Beispiel #1
0
class TestTaskRepositoryForTaskrunQueries(Test):
    def setUp(self):
        super(TestTaskRepositoryForTaskrunQueries, self).setUp()
        self.task_repo = TaskRepository(db)

    def test_get_task_run_return_none_if_no_task_run(self):
        """Test get_task_run method returns None if there is no taskrun with the
        specified id"""

        taskrun = self.task_repo.get_task_run(200)

        assert taskrun is None, taskrun

    def test_get_task_run_returns_task_run(self):
        """Test get_task_run method returns a taskrun if exists"""

        taskrun = TaskRunFactory.create()

        retrieved_taskrun = self.task_repo.get_task_run(taskrun.id)

        assert taskrun == retrieved_taskrun, retrieved_taskrun

    def test_get_task_run_by(self):
        """Test get_task_run_by returns a taskrun with the specified attribute"""

        taskrun = TaskRunFactory.create(info='info')

        retrieved_taskrun = self.task_repo.get_task_run_by(info=taskrun.info)

        assert taskrun == retrieved_taskrun, retrieved_taskrun

    def test_get_task_run_by_returns_none_if_no_task_run(self):
        """Test get_task_run_by returns None if no taskrun matches the query"""

        TaskRunFactory.create(info='info')

        taskrun = self.task_repo.get_task_run_by(info='other info')

        assert taskrun is None, taskrun

    def test_filter_task_runs_by_no_matches(self):
        """Test filter_task_runs_by returns an empty list if no taskruns match
        the query"""

        TaskRunFactory.create(info='info')

        retrieved_taskruns = self.task_repo.filter_task_runs_by(info='other')

        assert isinstance(retrieved_taskruns, list)
        assert len(retrieved_taskruns) == 0, retrieved_taskruns

    def test_filter_task_runs_by_one_condition(self):
        """Test filter_task_runs_by returns a list of taskruns that meet the
        filtering condition"""

        TaskRunFactory.create_batch(3, info='info')
        should_be_missing = TaskFactory.create(info='other info')

        retrieved_taskruns = self.task_repo.filter_task_runs_by(info='info')

        assert len(retrieved_taskruns) == 3, retrieved_taskruns
        assert should_be_missing not in retrieved_taskruns, retrieved_taskruns

    def test_filter_task_runs_by_multiple_conditions(self):
        """Test filter_task_runs_by supports multiple-condition queries"""

        TaskRunFactory.create(info='info', user_ip='8.8.8.8')
        taskrun = TaskRunFactory.create(info='info', user_ip='1.1.1.1')

        retrieved_taskruns = self.task_repo.filter_task_runs_by(
            info='info', user_ip='1.1.1.1')

        assert len(retrieved_taskruns) == 1, retrieved_taskruns
        assert taskrun in retrieved_taskruns, retrieved_taskruns

    def test_filter_task_runs_support_yield_option(self):
        """Test that filter_task_runs_by with the yielded=True option returns
        the results as a generator"""

        task_runs = TaskRunFactory.create_batch(2, info='info')

        yielded_task_runs = self.task_repo.filter_task_runs_by(info='info',
                                                               yielded=True)

        import types
        assert isinstance(yielded_task_runs.__iter__(), types.GeneratorType)
        for taskrun in yielded_task_runs:
            assert taskrun in task_runs

    def test_filter_tasks_limit_offset(self):
        """Test that filter_tasks_by supports limit and offset options"""

        TaskRunFactory.create_batch(4)
        all_task_runs = self.task_repo.filter_task_runs_by()

        first_two = self.task_repo.filter_task_runs_by(limit=2)
        last_two = self.task_repo.filter_task_runs_by(limit=2, offset=2)

        assert len(first_two) == 2, first_two
        assert len(last_two) == 2, last_two
        assert first_two == all_task_runs[:2]
        assert last_two == all_task_runs[2:]

    def test_count_task_runs_with_no_matches(self):
        """Test count_task_runs_with returns 0 if no taskruns match the query"""

        TaskRunFactory.create(info='info')

        count = self.task_repo.count_task_runs_with(info='other info')

        assert count == 0, count

    def test_count_task_runs_with_one_condition(self):
        """Test count_task_runs_with returns the number of taskruns that meet the
        filtering condition"""

        TaskRunFactory.create_batch(3, info='info')
        should_be_missing = TaskRunFactory.create(info='other info')

        count = self.task_repo.count_task_runs_with(info='info')

        assert count == 3, count

    def test_count_task_runs_with_multiple_conditions(self):
        """Test count_task_runs_with supports multiple-condition queries"""

        TaskRunFactory.create(info='info', user_ip='8.8.8.8')
        taskrun = TaskRunFactory.create(info='info', user_ip='1.1.1.1')

        count = self.task_repo.count_task_runs_with(info='info',
                                                    user_ip='1.1.1.1')

        assert count == 1, count
class TestTaskRepositorySaveDeleteUpdate(Test):

    def setUp(self):
        super(TestTaskRepositorySaveDeleteUpdate, self).setUp()
        self.task_repo = TaskRepository(db)


    def test_save_saves_tasks(self):
        """Test save persists Task instances"""

        task = TaskFactory.build()
        assert self.task_repo.get_task(task.id) is None

        self.task_repo.save(task)

        assert self.task_repo.get_task(task.id) == task, "Task not saved"


    def test_save_saves_taskruns(self):
        """Test save persists TaskRun instances"""

        taskrun = TaskRunFactory.build()
        assert self.task_repo.get_task_run(taskrun.id) is None

        self.task_repo.save(taskrun)

        assert self.task_repo.get_task_run(taskrun.id) == taskrun, "TaskRun not saved"


    def test_save_fails_if_integrity_error(self):
        """Test save raises a DBIntegrityError if the instance to be saved lacks
        a required value"""

        task = TaskFactory.build(project_id=None, project=None)

        assert_raises(DBIntegrityError, self.task_repo.save, task)


    def test_save_only_saves_tasks_and_taskruns(self):
        """Test save raises a WrongObjectError when an object which is neither
        a Task nor a Taskrun instance is saved"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.task_repo.save, bad_object)


    def test_update_task(self):
        """Test update persists the changes made to Task instances"""

        task = TaskFactory.create(state='ongoing')
        task.state = 'done'

        self.task_repo.update(task)
        updated_task = self.task_repo.get_task(task.id)

        assert updated_task.state == 'done', updated_task


    def test_update_taskrun(self):
        """Test update persists the changes made to TaskRun instances"""

        taskrun = TaskRunFactory.create(info='info')
        taskrun.info = 'updated info!'

        self.task_repo.update(taskrun)
        updated_taskrun = self.task_repo.get_task_run(taskrun.id)

        assert updated_taskrun.info == 'updated info!', updated_taskrun


    def test_update_fails_if_integrity_error(self):
        """Test update raises a DBIntegrityError if the instance to be updated
        lacks a required value"""

        task = TaskFactory.create()
        task.project_id = None

        assert_raises(DBIntegrityError, self.task_repo.update, task)


    def test_update_only_updates_tasks_and_taskruns(self):
        """Test update raises a WrongObjectError when an object which is neither
        a Task nor a TaskRun instance is updated"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.task_repo.update, bad_object)


    def test_delete_task(self):
        """Test delete removes the Task instance"""

        task = TaskFactory.create()

        self.task_repo.delete(task)
        deleted = self.task_repo.get_task(task.id)

        assert deleted is None, deleted


    def test_delete_task_deletes_dependent_taskruns(self):
        """Test delete removes the dependent TaskRun instances"""

        task = TaskFactory.create()
        taskrun = TaskRunFactory.create(task=task)

        self.task_repo.delete(task)
        deleted = self.task_repo.get_task_run(taskrun.id)

        assert deleted is None, deleted


    def test_delete_taskrun(self):
        """Test delete removes the TaskRun instance"""

        taskrun = TaskRunFactory.create()

        self.task_repo.delete(taskrun)
        deleted = self.task_repo.get_task_run(taskrun.id)

        assert deleted is None, deleted


    def test_delete_only_deletes_tasks(self):
        """Test delete raises a WrongObjectError if is requested to delete other
        than a task"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.task_repo.delete, bad_object)


    def test_delete_valid_from_project_deletes_many_tasks(self):
        """Test delete_valid_from_project deletes many tasks at once"""

        tasks = TaskFactory.create_batch(2)

        project = project_repo.get(tasks[0].project_id)

        self.task_repo.delete_valid_from_project(project)

        tasks = self.task_repo.filter_tasks_by(project_id=project.id)

        assert len(tasks) == 0, len(tasks)


    def test_delete_valid_from_project_deletes_dependent(self):
        """Test delete_valid_from_project deletes dependent taskruns too"""

        task = TaskFactory.create()
        taskrun = TaskRunFactory.create(task=task)
        task_run_id = taskrun.id
        project = project_repo.get(task.project_id)

        self.task_repo.delete_valid_from_project(project)
        deleted = self.task_repo.get_task_run(id=task_run_id)

        assert deleted is None, deleted


    def test_delete_valid_from_project_deletes_dependent_without_result(self):
        """Test delete_valid_from_project deletes dependent taskruns without result"""

        task = TaskFactory.create(n_answers=1)
        project = project_repo.get(task.project_id)
        taskrun = TaskRunFactory.create(task=task)
        task2 = TaskFactory.create(project=project)
        TaskRunFactory.create(task=task2)

        self.task_repo.delete_valid_from_project(project)
        non_deleted = self.task_repo.filter_tasks_by(project_id=project.id)

        err_msg = "There should be one task, as it belongs to a result"
        assert len(non_deleted) == 1, err_msg
        assert non_deleted[0].id == task.id, err_msg

        non_deleted = self.task_repo.filter_task_runs_by(project_id=project.id)

        err_msg = "There should be one task_run, as it belongs to a result"
        assert len(non_deleted) == 1, err_msg
        assert non_deleted[0].id == taskrun.id, err_msg


    def test_delete_taskruns_from_project_deletes_taskruns(self):
        task = TaskFactory.create()
        project = project_repo.get(task.project_id)
        taskrun = TaskRunFactory.create(task=task)

        self.task_repo.delete_taskruns_from_project(project)
        taskruns = self.task_repo.filter_task_runs_by(project_id=project.id)

        assert taskruns == [], taskruns


    def test_update_tasks_redundancy_changes_all_project_tasks_redundancy(self):
        """Test update_tasks_redundancy updates the n_answers value for every
        task in the project"""

        project = ProjectFactory.create()
        TaskFactory.create_batch(2, project=project, n_answers=1)

        self.task_repo.update_tasks_redundancy(project, 2)
        tasks = self.task_repo.filter_tasks_by(project_id=project.id)

        for task in tasks:
            assert task.n_answers == 2, task.n_answers


    def test_update_tasks_redundancy_updates_state_when_incrementing(self):
        """Test update_tasks_redundancy changes 'completed' tasks to 'ongoing'
        if n_answers is incremented enough"""

        project = ProjectFactory.create()
        tasks = TaskFactory.create_batch(2, project=project, n_answers=2)
        TaskRunFactory.create_batch(2, task=tasks[0])
        tasks[0].state = 'completed'
        self.task_repo.update(tasks[0])

        assert tasks[0].state == 'completed', tasks[0].state
        assert tasks[1].state == 'ongoing', tasks[1].state

        self.task_repo.update_tasks_redundancy(project, 3)
        tasks = self.task_repo.filter_tasks_by(project_id=project.id)

        for task in tasks:
            assert task.state == 'ongoing', task.state


    def test_update_tasks_redundancy_updates_state_when_decrementing(self):
        """Test update_tasks_redundancy changes 'ongoing' tasks to 'completed'
        if n_answers is decremented enough"""

        project = ProjectFactory.create()
        tasks = TaskFactory.create_batch(2, project=project, n_answers=2)
        TaskRunFactory.create_batch(2, task=tasks[0])
        TaskRunFactory.create(task=tasks[1])
        tasks[0].state = 'completed'
        self.task_repo.update(tasks[0])

        assert tasks[0].state == 'completed', tasks[0].state
        assert tasks[1].state == 'ongoing', tasks[1].state

        self.task_repo.update_tasks_redundancy(project, 1)
        tasks = self.task_repo.filter_tasks_by(project_id=project.id)

        for task in tasks:
            assert task.state == 'completed', task.state
class TestTaskRepositorySaveDeleteUpdate(Test):
    def setUp(self):
        super(TestTaskRepositorySaveDeleteUpdate, self).setUp()
        self.task_repo = TaskRepository(db)

    def test_save_saves_tasks(self):
        """Test save persists Task instances"""

        task = TaskFactory.build()
        assert self.task_repo.get_task(task.id) is None

        self.task_repo.save(task)

        assert self.task_repo.get_task(task.id) == task, "Task not saved"

    def test_save_saves_taskruns(self):
        """Test save persists TaskRun instances"""

        taskrun = TaskRunFactory.build()
        assert self.task_repo.get_task_run(taskrun.id) is None

        self.task_repo.save(taskrun)

        assert self.task_repo.get_task_run(
            taskrun.id) == taskrun, "TaskRun not saved"

    def test_save_fails_if_integrity_error(self):
        """Test save raises a DBIntegrityError if the instance to be saved lacks
        a required value"""

        task = TaskFactory.build(project_id=None, project=None)

        assert_raises(DBIntegrityError, self.task_repo.save, task)

    def test_save_only_saves_tasks_and_taskruns(self):
        """Test save raises a WrongObjectError when an object which is neither
        a Task nor a Taskrun instance is saved"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.task_repo.save, bad_object)

    def test_update_task(self):
        """Test update persists the changes made to Task instances"""

        task = TaskFactory.create(state='ongoing')
        task.state = 'done'

        self.task_repo.update(task)
        updated_task = self.task_repo.get_task(task.id)

        assert updated_task.state == 'done', updated_task

    def test_update_taskrun(self):
        """Test update persists the changes made to TaskRun instances"""

        taskrun = TaskRunFactory.create(info='info')
        taskrun.info = 'updated info!'

        self.task_repo.update(taskrun)
        updated_taskrun = self.task_repo.get_task_run(taskrun.id)

        assert updated_taskrun.info == 'updated info!', updated_taskrun

    def test_update_fails_if_integrity_error(self):
        """Test update raises a DBIntegrityError if the instance to be updated
        lacks a required value"""

        task = TaskFactory.create()
        task.project_id = None

        assert_raises(DBIntegrityError, self.task_repo.update, task)

    def test_update_only_updates_tasks_and_taskruns(self):
        """Test update raises a WrongObjectError when an object which is neither
        a Task nor a TaskRun instance is updated"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.task_repo.update, bad_object)

    def test_delete_task(self):
        """Test delete removes the Task instance"""

        task = TaskFactory.create()

        self.task_repo.delete(task)
        deleted = self.task_repo.get_task(task.id)

        assert deleted is None, deleted

    def test_delete_task_deletes_dependent_taskruns(self):
        """Test delete removes the dependent TaskRun instances"""

        task = TaskFactory.create()
        taskrun = TaskRunFactory.create(task=task)

        self.task_repo.delete(task)
        deleted = self.task_repo.get_task_run(taskrun.id)

        assert deleted is None, deleted

    def test_delete_taskrun(self):
        """Test delete removes the TaskRun instance"""

        taskrun = TaskRunFactory.create()

        self.task_repo.delete(taskrun)
        deleted = self.task_repo.get_task_run(taskrun.id)

        assert deleted is None, deleted

    def test_delete_only_deletes_tasks(self):
        """Test delete raises a WrongObjectError if is requested to delete other
        than a task"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.task_repo.delete, bad_object)

    def test_delete_valid_from_project_deletes_many_tasks(self):
        """Test delete_valid_from_project deletes many tasks at once"""

        tasks = TaskFactory.create_batch(2)

        project = project_repo.get(tasks[0].project_id)

        self.task_repo.delete_valid_from_project(project)

        tasks = self.task_repo.filter_tasks_by(project_id=project.id)

        assert len(tasks) == 0, len(tasks)

    def test_delete_valid_from_project_deletes_dependent(self):
        """Test delete_valid_from_project deletes dependent taskruns too"""

        task = TaskFactory.create()
        taskrun = TaskRunFactory.create(task=task)
        task_run_id = taskrun.id
        project = project_repo.get(task.project_id)

        self.task_repo.delete_valid_from_project(project)
        deleted = self.task_repo.get_task_run(id=task_run_id)

        assert deleted is None, deleted

    def test_delete_valid_from_project_deletes_dependent_without_result(self):
        """Test delete_valid_from_project deletes dependent taskruns without result"""

        task = TaskFactory.create(n_answers=1)
        project = project_repo.get(task.project_id)
        taskrun = TaskRunFactory.create(task=task)
        task2 = TaskFactory.create(project=project)
        TaskRunFactory.create(task=task2)

        self.task_repo.delete_valid_from_project(project)
        non_deleted = self.task_repo.filter_tasks_by(project_id=project.id)

        err_msg = "There should be one task, as it belongs to a result"
        assert len(non_deleted) == 1, err_msg
        assert non_deleted[0].id == task.id, err_msg

        non_deleted = self.task_repo.filter_task_runs_by(project_id=project.id)

        err_msg = "There should be one task_run, as it belongs to a result"
        assert len(non_deleted) == 1, err_msg
        assert non_deleted[0].id == taskrun.id, err_msg

    def test_delete_taskruns_from_project_deletes_taskruns(self):
        task = TaskFactory.create()
        project = project_repo.get(task.project_id)
        taskrun = TaskRunFactory.create(task=task)

        self.task_repo.delete_taskruns_from_project(project)
        taskruns = self.task_repo.filter_task_runs_by(project_id=project.id)

        assert taskruns == [], taskruns

    def test_update_tasks_redundancy_changes_all_project_tasks_redundancy(
            self):
        """Test update_tasks_redundancy updates the n_answers value for every
        task in the project"""

        project = ProjectFactory.create()
        TaskFactory.create_batch(2, project=project, n_answers=1)

        self.task_repo.update_tasks_redundancy(project, 2)
        tasks = self.task_repo.filter_tasks_by(project_id=project.id)

        for task in tasks:
            assert task.n_answers == 2, task.n_answers

    def test_update_tasks_redundancy_updates_state_when_incrementing(self):
        """Test update_tasks_redundancy changes 'completed' tasks to 'ongoing'
        if n_answers is incremented enough"""

        project = ProjectFactory.create()
        tasks = TaskFactory.create_batch(2, project=project, n_answers=2)
        TaskRunFactory.create_batch(2, task=tasks[0])
        tasks[0].state = 'completed'
        self.task_repo.update(tasks[0])

        assert tasks[0].state == 'completed', tasks[0].state
        assert tasks[1].state == 'ongoing', tasks[1].state

        self.task_repo.update_tasks_redundancy(project, 3)
        tasks = self.task_repo.filter_tasks_by(project_id=project.id)

        for task in tasks:
            assert task.state == 'ongoing', task.state

    def test_update_tasks_redundancy_updates_state_when_decrementing(self):
        """Test update_tasks_redundancy changes 'ongoing' tasks to 'completed'
        if n_answers is decremented enough"""

        project = ProjectFactory.create()
        tasks = TaskFactory.create_batch(2, project=project, n_answers=2)
        TaskRunFactory.create_batch(2, task=tasks[0])
        TaskRunFactory.create(task=tasks[1])
        tasks[0].state = 'completed'
        self.task_repo.update(tasks[0])

        assert tasks[0].state == 'completed', tasks[0].state
        assert tasks[1].state == 'ongoing', tasks[1].state

        self.task_repo.update_tasks_redundancy(project, 1)
        tasks = self.task_repo.filter_tasks_by(project_id=project.id)

        for task in tasks:
            assert task.state == 'completed', task.state
class TestTaskRepositoryForTaskrunQueries(Test):

    def setUp(self):
        super(TestTaskRepositoryForTaskrunQueries, self).setUp()
        self.task_repo = TaskRepository(db)


    def test_get_task_run_return_none_if_no_task_run(self):
        """Test get_task_run method returns None if there is no taskrun with the
        specified id"""

        taskrun = self.task_repo.get_task_run(200)

        assert taskrun is None, taskrun


    def test_get_task_run_returns_task_run(self):
        """Test get_task_run method returns a taskrun if exists"""

        taskrun = TaskRunFactory.create()

        retrieved_taskrun = self.task_repo.get_task_run(taskrun.id)

        assert taskrun == retrieved_taskrun, retrieved_taskrun


    def test_get_task_run_by(self):
        """Test get_task_run_by returns a taskrun with the specified attribute"""

        taskrun = TaskRunFactory.create(info='info')

        retrieved_taskrun = self.task_repo.get_task_run_by(info=taskrun.info)

        assert taskrun == retrieved_taskrun, retrieved_taskrun

    def test_get_task_run_by_info_json(self):
        """Test get_task_run_by with JSON returns a
        taskrun with the specified attribute"""

        data = {'foo': 'bar'}
        taskrun = TaskRunFactory.create(info=data)

        info = 'foo::bar'
        retrieved_taskrun = self.task_repo.get_task_run_by(info=info)

        assert taskrun == retrieved_taskrun, retrieved_taskrun

    def test_get_task_run_by_info_json_fulltext(self):
        """Test get_task_run_by with JSON and fulltext returns a
        taskrun with the specified attribute"""

        data = {'foo': 'bar'}
        taskrun = TaskRunFactory.create(info=data)

        info = 'foo::bar'
        retrieved_taskrun = self.task_repo.get_task_run_by(info=info,
                                                           fulltextsearch='1')

        assert taskrun == retrieved_taskrun, retrieved_taskrun



    def test_get_task_run_by_returns_none_if_no_task_run(self):
        """Test get_task_run_by returns None if no taskrun matches the query"""

        TaskRunFactory.create(info='info')

        taskrun = self.task_repo.get_task_run_by(info='other info')

        assert taskrun is None, taskrun


    def test_filter_task_runs_by_no_matches(self):
        """Test filter_task_runs_by returns an empty list if no taskruns match
        the query"""

        TaskRunFactory.create(info='info')

        retrieved_taskruns = self.task_repo.filter_task_runs_by(info='other')

        assert isinstance(retrieved_taskruns, list)
        assert len(retrieved_taskruns) == 0, retrieved_taskruns


    def test_filter_task_runs_by_one_condition(self):
        """Test filter_task_runs_by returns a list of taskruns that meet the
        filtering condition"""

        TaskRunFactory.create_batch(3, info='info')
        should_be_missing = TaskFactory.create(info='other info')

        retrieved_taskruns = self.task_repo.filter_task_runs_by(info='info')

        assert len(retrieved_taskruns) == 3, retrieved_taskruns
        assert should_be_missing not in retrieved_taskruns, retrieved_taskruns


    def test_filter_task_runs_by_multiple_conditions(self):
        """Test filter_task_runs_by supports multiple-condition queries"""

        TaskRunFactory.create(info='info', user_ip='8.8.8.8')
        taskrun = TaskRunFactory.create(info='info', user_ip='1.1.1.1')

        retrieved_taskruns = self.task_repo.filter_task_runs_by(info='info',
                                                                user_ip='1.1.1.1')

        assert len(retrieved_taskruns) == 1, retrieved_taskruns
        assert taskrun in retrieved_taskruns, retrieved_taskruns


    def test_filter_task_runs_by_multiple_conditions_fulltext(self):
        """Test filter_task_runs_by supports multiple-condition
        fulltext queries"""

        text = 'you agent something word'
        data = {'foo': 'bar', 'bar': text}
        TaskRunFactory.create(info=data, user_ip='8.8.8.8')
        taskrun = TaskRunFactory.create(info=data, user_ip='1.1.1.1')

        info = 'foo::bar|bar::agent'
        retrieved_taskruns = self.task_repo.filter_task_runs_by(info=info,
                                                                user_ip='1.1.1.1',
                                                                fulltextsearch='1')

        assert len(retrieved_taskruns) == 1, retrieved_taskruns
        assert taskrun in retrieved_taskruns, retrieved_taskruns

        retrieved_taskruns = self.task_repo.filter_task_runs_by(info=info,
                                                                user_ip='1.1.1.1')
        assert len(retrieved_taskruns) == 0, retrieved_taskruns

    def test_filter_task_runs_support_yield_option(self):
        """Test that filter_task_runs_by with the yielded=True option returns
        the results as a generator"""

        task_runs = TaskRunFactory.create_batch(2, info='info')

        yielded_task_runs = self.task_repo.filter_task_runs_by(info='info',
                                                               yielded=True)

        import types
        assert isinstance(yielded_task_runs.__iter__(), types.GeneratorType)
        for taskrun in yielded_task_runs:
            assert taskrun in task_runs


    def test_filter_tasks_runs_limit_offset(self):
        """Test that filter_tasks_by supports limit and offset options"""

        TaskRunFactory.create_batch(4)
        all_task_runs = self.task_repo.filter_task_runs_by()

        first_two = self.task_repo.filter_task_runs_by(limit=2)
        last_two = self.task_repo.filter_task_runs_by(limit=2, offset=2)

        assert len(first_two) == 2, first_two
        assert len(last_two) == 2, last_two
        assert first_two == all_task_runs[:2]
        assert last_two == all_task_runs[2:]


    def test_count_task_runs_with_no_matches(self):
        """Test count_task_runs_with returns 0 if no taskruns match the query"""

        TaskRunFactory.create(info='info')

        count = self.task_repo.count_task_runs_with(info='other info')

        assert count == 0, count


    def test_count_task_runs_with_one_condition(self):
        """Test count_task_runs_with returns the number of taskruns that meet the
        filtering condition"""

        TaskRunFactory.create_batch(3, info='info')
        should_be_missing = TaskRunFactory.create(info='other info')

        count = self.task_repo.count_task_runs_with(info='info')

        assert count == 3, count


    def test_count_task_runs_with_multiple_conditions(self):
        """Test count_task_runs_with supports multiple-condition queries"""

        TaskRunFactory.create(info='info', user_ip='8.8.8.8')
        taskrun = TaskRunFactory.create(info='info', user_ip='1.1.1.1')

        count = self.task_repo.count_task_runs_with(info='info',
                                                    user_ip='1.1.1.1')

        assert count == 1, count