def test_update_projects_week(self):
     """Test JOB update projects week works."""
     p = ProjectFactory.create()
     p.name = 'NewNameName'
     project_repository = ProjectRepository(db)
     project_repository.update(p)
     dashboard_update_projects_week()
     sql = "select * from dashboard_week_project_update;"
     results = db.session.execute(sql)
     for row in results:
         assert row.id == p.id
         assert row.name == p.name
         assert row.owner_id == p.owner_id
         assert row.u_name == p.owner.name
         assert row.email_addr == p.owner.email_addr
 def test_format_updated_projects(self):
     """Test format updated projects works."""
     p = ProjectFactory.create()
     p.name = 'NewNewNew'
     project_repo = ProjectRepository(db)
     project_repo.update(p)
     dashboard_update_projects_week()
     res = format_update_projects()
     day = datetime.utcnow().strftime('%Y-%m-%d')
     res = res[0]
     assert res['day'].strftime('%Y-%m-%d') == day, res['day']
     assert res['id'] == p.id
     assert res['short_name'] == p.short_name
     assert res['p_name'] == p.name
     assert res['email_addr'] == p.owner.email_addr
     assert res['owner_id'] == p.owner.id
     assert res['u_name'] == p.owner.name
Example #3
0
def setup_repositories():
    """Setup repositories."""
    from pybossa.repositories import UserRepository
    from pybossa.repositories import ProjectRepository
    from pybossa.repositories import BlogRepository
    from pybossa.repositories import TaskRepository
    from pybossa.repositories import AuditlogRepository
    global user_repo
    global project_repo
    global blog_repo
    global task_repo
    global auditlog_repo
    user_repo = UserRepository(db)
    project_repo = ProjectRepository(db)
    blog_repo = BlogRepository(db)
    task_repo = TaskRepository(db)
    auditlog_repo = AuditlogRepository(db)
Example #4
0
def setup_repositories(app):
    """Setup repositories."""
    from pybossa.repositories import UserRepository
    from pybossa.repositories import ProjectRepository
    from pybossa.repositories import ProjectStatsRepository
    from pybossa.repositories import AnnouncementRepository
    from pybossa.repositories import BlogRepository
    from pybossa.repositories import TaskRepository
    from pybossa.repositories import FlaggedTaskRepository
    from pybossa.repositories import AuditlogRepository
    from pybossa.repositories import WebhookRepository
    from pybossa.repositories import ResultRepository
    from pybossa.repositories import HelpingMaterialRepository
    from pybossa.repositories import PageRepository
    global user_repo
    global project_repo
    global project_stats_repo
    global announcement_repo
    global blog_repo
    global task_repo
    global flagged_task_repo
    global auditlog_repo
    global webhook_repo
    global result_repo
    global helping_repo
    global page_repo
    language = app.config.get('FULLTEXTSEARCH_LANGUAGE')
    user_repo = UserRepository(db)
    project_repo = ProjectRepository(db)
    project_stats_repo = ProjectStatsRepository(db)
    announcement_repo = AnnouncementRepository(db)
    blog_repo = BlogRepository(db)
    task_repo = TaskRepository(db, language)
    flagged_task_repo = FlaggedTaskRepository(db)
    auditlog_repo = AuditlogRepository(db)
    webhook_repo = WebhookRepository(db)
    result_repo = ResultRepository(db)
    helping_repo = HelpingMaterialRepository(db)
    page_repo = PageRepository(db)
Example #5
0
def setup_repositories(app):
    """Setup repositories."""
    from pybossa.repositories import UserRepository
    from pybossa.repositories import ProjectRepository
    from pybossa.repositories import ProjectStatsRepository
    from pybossa.repositories import AnnouncementRepository
    from pybossa.repositories import BlogRepository
    from pybossa.repositories import TaskRepository
    from pybossa.repositories import AuditlogRepository
    from pybossa.repositories import WebhookRepository
    from pybossa.repositories import ResultRepository
    from pybossa.repositories import HelpingMaterialRepository
    from pybossa.repositories import PerformanceStatsRepository
    global user_repo
    global project_repo
    global project_stats_repo
    global announcement_repo
    global blog_repo
    global task_repo
    global auditlog_repo
    global webhook_repo
    global result_repo
    global helping_repo
    global performance_stats_repo
    language = app.config.get('FULLTEXTSEARCH_LANGUAGE')
    rdancy_upd_exp = app.config.get('REDUNDANCY_UPDATE_EXPIRATION', 30)
    user_repo = UserRepository(db)
    project_repo = ProjectRepository(db)
    project_stats_repo = ProjectStatsRepository(db)
    announcement_repo = AnnouncementRepository(db)
    blog_repo = BlogRepository(db)
    task_repo = TaskRepository(db, language, rdancy_upd_exp)
    auditlog_repo = AuditlogRepository(db)
    webhook_repo = WebhookRepository(db)
    result_repo = ResultRepository(db)
    helping_repo = HelpingMaterialRepository(db)
    performance_stats_repo = PerformanceStatsRepository(db)
Example #6
0
def setup_repositories(app):
    """Setup repositories."""
    from pybossa.repositories import UserRepository
    from pybossa.repositories import ProjectRepository
    from pybossa.repositories import BlogRepository
    from pybossa.repositories import TaskRepository
    from pybossa.repositories import AuditlogRepository
    from pybossa.repositories import WebhookRepository
    from pybossa.repositories import ResultRepository
    global user_repo
    global project_repo
    global blog_repo
    global task_repo
    global auditlog_repo
    global webhook_repo
    global result_repo
    language = app.config.get('FULLTEXTSEARCH_LANGUAGE')
    user_repo = UserRepository(db)
    project_repo = ProjectRepository(db)
    blog_repo = BlogRepository(db)
    task_repo = TaskRepository(db, language)
    auditlog_repo = AuditlogRepository(db)
    webhook_repo = WebhookRepository(db)
    result_repo = ResultRepository(db)
Example #7
0
# along with PYBOSSA.  If not, see <http://www.gnu.org/licenses/>.
import json
from default import db, with_context
from nose.tools import assert_equal
from test_api import TestAPI
from mock import patch, call

from factories import ProjectFactory, TaskFactory, TaskRunFactory, UserFactory
from factories import AnonymousTaskRunFactory, ExternalUidTaskRunFactory

from pybossa.repositories import ProjectRepository
from pybossa.repositories import TaskRepository
from pybossa.repositories import ResultRepository
from pybossa.model.counter import Counter

project_repo = ProjectRepository(db)
task_repo = TaskRepository(db)
result_repo = ResultRepository(db)


class TestTaskAPI(TestAPI):
    def create_result(self,
                      n_results=1,
                      n_answers=1,
                      owner=None,
                      filter_by=False):
        if owner:
            owner = owner
        else:
            admin, owner, user = UserFactory.create_batch(3)
        project = ProjectFactory.create(owner=owner)
 def setup(self):
     super(TestCoowners, self).setUp()
     self.project_repo = ProjectRepository(db)
Example #9
0
 def setUp(self):
     super(TestProjectRepositoryForProjects, self).setUp()
     self.project_repo = ProjectRepository(db)
Example #10
0
class TestProjectRepositoryForCategories(Test):
    def setUp(self):
        super(TestProjectRepositoryForCategories, self).setUp()
        self.project_repo = ProjectRepository(db)

    @with_context
    def test_get_category_return_none_if_no_category(self):
        """Test get_category method returns None if there is no category with
        the specified id"""

        category = self.project_repo.get_category(200)

        assert category is None, category

    @with_context
    def test_get_category_returns_category(self):
        """Test get_category method returns a category if exists"""

        category = CategoryFactory.create()

        retrieved_category = self.project_repo.get_category(category.id)

        assert category == retrieved_category, retrieved_category

    @with_context
    def test_get_category_by(self):
        """Test get_category returns a category with the specified attribute"""

        category = CategoryFactory.create(name='My Cat', short_name='mycat')

        retrieved_category = self.project_repo.get_category_by(
            name=category.name)

        assert category == retrieved_category, retrieved_category

    @with_context
    def test_get_category_by_returns_none_if_no_category(self):
        """Test get_category returns None if no category matches the query"""

        CategoryFactory.create(name='My Project', short_name='mycategory')

        category = self.project_repo.get_by(name='no_name')

        assert category is None, category

    @with_context
    def get_all_returns_list_of_all_categories(self):
        """Test get_all_categories returns a list of all the existing categories"""

        categories = CategoryFactory.create_batch(3)

        retrieved_categories = self.project_repo.get_all_categories()

        assert isinstance(retrieved_categories, list)
        assert len(retrieved_categories) == len(
            categories), retrieved_categories
        for category in retrieved_categories:
            assert category in categories, category

    @with_context
    def test_filter_categories_by_no_matches(self):
        """Test filter_categories_by returns an empty list if no categories
        match the query"""

        CategoryFactory.create(name='My Project', short_name='mycategory')

        retrieved_categories = self.project_repo.filter_categories_by(
            name='no_name')

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

    @with_context
    def test_filter_categories_by_ownerid(self):
        """Test filter_categories_by removes ownerid from query."""

        CategoryFactory.create(name='My Project', short_name='mycategory')

        retrieved_categories = self.project_repo.filter_categories_by(
            short_name='mycategory', owner_id=1)

        assert isinstance(retrieved_categories, list)
        assert len(retrieved_categories) == 1, retrieved_categories

    @with_context
    def test_filter_categories_by_one_condition(self):
        """Test filter_categories_by returns a list of categories that meet
        the filtering condition"""

        CategoryFactory.create_batch(3, description='generic category')
        should_be_missing = CategoryFactory.create(
            description='other category')

        retrieved_categories = (self.project_repo.filter_categories_by(
            description='generic category'))

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

    @with_context
    def test_filter_categories_by_limit_offset(self):
        """Test that filter_categories_by supports limit and offset options"""

        CategoryFactory.create_batch(4)
        all_categories = self.project_repo.filter_categories_by()

        first_two = self.project_repo.filter_categories_by(limit=2)
        last_two = self.project_repo.filter_categories_by(limit=2, offset=2)

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

    @with_context
    def test_save_category(self):
        """Test save_category persist the category"""

        category = CategoryFactory.build()
        assert self.project_repo.get(category.id) is None

        self.project_repo.save_category(category)

        assert self.project_repo.get_category(
            category.id) == category, "Category not saved"

    @with_context
    def test_save_category_fails_if_integrity_error(self):
        """Test save_category raises a DBIntegrityError if the instance to be
       saved lacks a required value"""

        category = CategoryFactory.build(name=None)

        assert_raises(DBIntegrityError, self.project_repo.save_category,
                      category)

    @with_context
    def test_save_category_only_saves_categories(self):
        """Test save_category raises a WrongObjectError when an object which is
        not a Category instance is saved"""

        bad_object = ProjectFactory.build()

        assert_raises(WrongObjectError, self.project_repo.save_category,
                      bad_object)

    @with_context
    def test_update_category(self):
        """Test update_category persists the changes made to the category"""

        category = CategoryFactory.create(description='this is a category')
        category.description = 'the description has changed'

        self.project_repo.update_category(category)
        updated_category = self.project_repo.get_category(category.id)

        assert updated_category.description == 'the description has changed', updated_category

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

        category = CategoryFactory.create()
        category.name = None

        assert_raises(DBIntegrityError, self.project_repo.update_category,
                      category)

    @with_context
    def test_update_category_only_updates_categories(self):
        """Test update_category raises a WrongObjectError when an object which is
        not a Category instance is updated"""

        bad_object = ProjectFactory.build()

        assert_raises(WrongObjectError, self.project_repo.update_category,
                      bad_object)

    @with_context
    def test_delete_category(self):
        """Test delete_category removes the category instance"""

        category = CategoryFactory.create()

        self.project_repo.delete_category(category)
        deleted = self.project_repo.get_category(category.id)

        assert deleted is None, deleted

    @with_context
    def test_delete_category_only_deletes_categories(self):
        """Test delete_category raises a WrongObjectError if is requested to
        delete other than a category"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.project_repo.delete_category,
                      bad_object)
Example #11
0
class TestProjectRepositoryForProjects(Test):
    def setUp(self):
        super(TestProjectRepositoryForProjects, self).setUp()
        self.project_repo = ProjectRepository(db)

    @with_context
    def test_get_return_none_if_no_project(self):
        """Test get method returns None if there is no project with the
        specified id"""

        project = self.project_repo.get(2)

        assert project is None, project

    @with_context
    def test_get_returns_project(self):
        """Test get method returns a project if exists"""

        project = ProjectFactory.create()

        retrieved_project = self.project_repo.get(project.id)

        assert project == retrieved_project, retrieved_project

    @with_context
    def test_get_by_shortname_return_none_if_no_project(self):
        """Test get_by_shortname returns None when a project with the specified
        short_name does not exist"""

        project = self.project_repo.get_by_shortname('thisprojectdoesnotexist')

        assert project is None, project

    @with_context
    def test_get_by_shortname_returns_the_project(self):
        """Test get_by_shortname returns a project if exists"""

        project = ProjectFactory.create()

        retrieved_project = self.project_repo.get_by_shortname(
            project.short_name)

        assert project == retrieved_project, retrieved_project

    @with_context
    def test_get_by(self):
        """Test get_by returns a project with the specified attribute"""

        project = ProjectFactory.create(name='My Project',
                                        short_name='myproject')

        retrieved_project = self.project_repo.get_by(name=project.name)

        assert project == retrieved_project, retrieved_project

    @with_context
    def test_get_by_returns_none_if_no_project(self):
        """Test get_by returns None if no project matches the query"""

        ProjectFactory.create(name='My Project', short_name='myproject')

        project = self.project_repo.get_by(name='no_name')

        assert project is None, project

    @with_context
    def get_all_returns_list_of_all_projects(self):
        """Test get_all returns a list of all the existing projects"""

        projects = ProjectFactory.create_batch(3)

        retrieved_projects = self.project_repo.get_all()

        assert isinstance(retrieved_projects, list)
        assert len(retrieved_projects) == len(projects), retrieved_projects
        for project in retrieved_projects:
            assert project in projects, project

    @with_context
    def test_filter_by_no_matches(self):
        """Test filter_by returns an empty list if no projects match the query"""

        ProjectFactory.create(name='My Project', short_name='myproject')

        retrieved_projects = self.project_repo.filter_by(name='no_name')

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

    @with_context
    def test_filter_by_one_condition(self):
        """Test filter_by returns a list of projects that meet the filtering
        condition"""

        ProjectFactory.create_batch(3, allow_anonymous_contributors=False)
        should_be_missing = ProjectFactory.create(
            allow_anonymous_contributors=True)

        retrieved_projects = self.project_repo.filter_by(
            allow_anonymous_contributors=False)

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

    @with_context
    def test_filter_by_multiple_conditions(self):
        """Test filter_by supports multiple-condition queries"""

        ProjectFactory.create_batch(2,
                                    allow_anonymous_contributors=False,
                                    featured=False)
        project = ProjectFactory.create(allow_anonymous_contributors=False,
                                        featured=True)

        retrieved_projects = self.project_repo.filter_by(
            allow_anonymous_contributors=False, featured=True)

        assert len(retrieved_projects) == 1, retrieved_projects
        assert project in retrieved_projects, retrieved_projects

    @with_context
    def test_filter_by_limit_offset(self):
        """Test that filter_by supports limit and offset options"""

        ProjectFactory.create_batch(4)
        all_projects = self.project_repo.filter_by()

        first_two = self.project_repo.filter_by(limit=2)
        last_two = self.project_repo.filter_by(limit=2, offset=2)

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

    @with_context
    def test_save(self):
        """Test save persist the project"""

        project = ProjectFactory.build()
        assert self.project_repo.get(project.id) is None

        self.project_repo.save(project)

        assert self.project_repo.get(
            project.id) == project, "Project not saved"

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

        project = ProjectFactory.build(name=None)

        assert_raises(DBIntegrityError, self.project_repo.save, project)

    @with_context
    def test_save_only_saves_projects(self):
        """Test save raises a WrongObjectError when an object which is not
        a Project instance is saved"""

        bad_object = dict()

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

    @with_context
    def test_update(self):
        """Test update persists the changes made to the project"""

        project = ProjectFactory.create(description='this is a project')
        project.description = 'the description has changed'

        self.project_repo.update(project)
        updated_project = self.project_repo.get(project.id)

        assert updated_project.description == 'the description has changed', updated_project

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

        project = ProjectFactory.create()
        project.name = None

        assert_raises(DBIntegrityError, self.project_repo.update, project)

    @with_context
    def test_update_only_updates_projects(self):
        """Test update raises a WrongObjectError when an object which is not
        a Project instance is updated"""

        bad_object = dict()

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

    @with_context
    def test_delete(self):
        """Test delete removes the project instance"""

        project = ProjectFactory.create()

        self.project_repo.delete(project)
        deleted = self.project_repo.get(project.id)

        assert deleted is None, deleted

    @with_context
    def test_delete_also_removes_dependant_resources(self):
        """Test delete removes project tasks and taskruns too"""
        from factories import TaskFactory, TaskRunFactory, BlogpostFactory
        from pybossa.repositories import TaskRepository, BlogRepository

        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)
        taskrun = TaskRunFactory.create(task=task)
        blogpost = BlogpostFactory.create(project=project)

        self.project_repo.delete(project)
        deleted_task = TaskRepository(db).get_task(task.id)
        deleted_taskrun = TaskRepository(db).get_task_run(taskrun.id)
        deleted_blogpost = BlogRepository(db).get(blogpost.id)

        assert deleted_task is None, deleted_task
        assert deleted_taskrun is None, deleted_taskrun

    @with_context
    def test_delete_only_deletes_projects(self):
        """Test delete raises a WrongObjectError if is requested to delete other
        than a project"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.project_repo.delete, bad_object)
 def setUp(self):
     super(TestProjectRepositoryForProjects, self).setUp()
     self.project_repo = ProjectRepository(db)
class TestProjectRepositoryForProjects(Test):

    def setUp(self):
        super(TestProjectRepositoryForProjects, self).setUp()
        self.project_repo = ProjectRepository(db)


    def test_get_return_none_if_no_project(self):
        """Test get method returns None if there is no project with the
        specified id"""

        project = self.project_repo.get(2)

        assert project is None, project


    def test_get_returns_project(self):
        """Test get method returns a project if exists"""

        project = ProjectFactory.create()

        retrieved_project = self.project_repo.get(project.id)

        assert project == retrieved_project, retrieved_project


    def test_get_by_shortname_return_none_if_no_project(self):
        """Test get_by_shortname returns None when a project with the specified
        short_name does not exist"""

        project = self.project_repo.get_by_shortname('thisprojectdoesnotexist')

        assert project is None, project


    def test_get_by_shortname_returns_the_project(self):
        """Test get_by_shortname returns a project if exists"""

        project = ProjectFactory.create()

        retrieved_project = self.project_repo.get_by_shortname(project.short_name)

        assert project == retrieved_project, retrieved_project


    def test_get_by(self):
        """Test get_by returns a project with the specified attribute"""

        project = ProjectFactory.create(name='My Project', short_name='myproject')

        retrieved_project = self.project_repo.get_by(name=project.name)

        assert project == retrieved_project, retrieved_project


    def test_get_by_returns_none_if_no_project(self):
        """Test get_by returns None if no project matches the query"""

        ProjectFactory.create(name='My Project', short_name='myproject')

        project = self.project_repo.get_by(name='no_name')

        assert project is None, project


    def get_all_returns_list_of_all_projects(self):
        """Test get_all returns a list of all the existing projects"""

        projects = ProjectFactory.create_batch(3)

        retrieved_projects = self.project_repo.get_all()

        assert isinstance(retrieved_projects, list)
        assert len(retrieved_projects) == len(projects), retrieved_projects
        for project in retrieved_projects:
            assert project in projects, project


    def test_filter_by_no_matches(self):
        """Test filter_by returns an empty list if no projects match the query"""

        ProjectFactory.create(name='My Project', short_name='myproject')

        retrieved_projects = self.project_repo.filter_by(name='no_name')

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


    def test_filter_by_one_condition(self):
        """Test filter_by returns a list of projects that meet the filtering
        condition"""

        ProjectFactory.create_batch(3, allow_anonymous_contributors=False)
        should_be_missing = ProjectFactory.create(allow_anonymous_contributors=True)

        retrieved_projects = self.project_repo.filter_by(allow_anonymous_contributors=False)

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


    def test_filter_by_multiple_conditions(self):
        """Test filter_by supports multiple-condition queries"""

        ProjectFactory.create_batch(2, allow_anonymous_contributors=False, featured=False)
        project = ProjectFactory.create(allow_anonymous_contributors=False, featured=True)

        retrieved_projects = self.project_repo.filter_by(
                                            allow_anonymous_contributors=False,
                                            featured=True)

        assert len(retrieved_projects) == 1, retrieved_projects
        assert project in retrieved_projects, retrieved_projects


    def test_filter_by_limit_offset(self):
        """Test that filter_by supports limit and offset options"""

        ProjectFactory.create_batch(4)
        all_projects = self.project_repo.filter_by()

        first_two = self.project_repo.filter_by(limit=2)
        last_two = self.project_repo.filter_by(limit=2, offset=2)

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


    def test_save(self):
        """Test save persist the project"""

        project = ProjectFactory.build()
        assert self.project_repo.get(project.id) is None

        self.project_repo.save(project)

        assert self.project_repo.get(project.id) == project, "Project 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"""

        project = ProjectFactory.build(name=None)

        assert_raises(DBIntegrityError, self.project_repo.save, project)


    def test_save_only_saves_projects(self):
        """Test save raises a WrongObjectError when an object which is not
        a Project instance is saved"""

        bad_object = dict()

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


    def test_update(self):
        """Test update persists the changes made to the project"""

        project = ProjectFactory.create(description='this is a project')
        project.description = 'the description has changed'

        self.project_repo.update(project)
        updated_project = self.project_repo.get(project.id)

        assert updated_project.description == 'the description has changed', updated_project


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

        project = ProjectFactory.create()
        project.name = None

        assert_raises(DBIntegrityError, self.project_repo.update, project)


    def test_update_only_updates_projects(self):
        """Test update raises a WrongObjectError when an object which is not
        a Project instance is updated"""

        bad_object = dict()

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


    def test_delete(self):
        """Test delete removes the project instance"""

        project = ProjectFactory.create()

        self.project_repo.delete(project)
        deleted = self.project_repo.get(project.id)

        assert deleted is None, deleted


    def test_delete_also_removes_dependant_resources(self):
        """Test delete removes project tasks and taskruns too"""
        from factories import TaskFactory, TaskRunFactory, BlogpostFactory
        from pybossa.repositories import TaskRepository, BlogRepository

        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)
        taskrun = TaskRunFactory.create(task=task)
        blogpost = BlogpostFactory.create(project=project)

        self.project_repo.delete(project)
        deleted_task = TaskRepository(db).get_task(task.id)
        deleted_taskrun = TaskRepository(db).get_task_run(taskrun.id)
        deleted_blogpost = BlogRepository(db).get(blogpost.id)

        assert deleted_task is None, deleted_task
        assert deleted_taskrun is None, deleted_taskrun


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

        bad_object = dict()

        assert_raises(WrongObjectError, self.project_repo.delete, bad_object)
class TestProjectRepositoryForCategories(Test):

    def setUp(self):
        super(TestProjectRepositoryForCategories, self).setUp()
        self.project_repo = ProjectRepository(db)


    def test_get_category_return_none_if_no_category(self):
        """Test get_category method returns None if there is no category with
        the specified id"""

        category = self.project_repo.get_category(200)

        assert category is None, category


    def test_get_category_returns_category(self):
        """Test get_category method returns a category if exists"""

        category = CategoryFactory.create()

        retrieved_category = self.project_repo.get_category(category.id)

        assert category == retrieved_category, retrieved_category


    def test_get_category_by(self):
        """Test get_category returns a category with the specified attribute"""

        category = CategoryFactory.create(name='My Cat', short_name='mycat')

        retrieved_category = self.project_repo.get_category_by(name=category.name)

        assert category == retrieved_category, retrieved_category


    def test_get_category_by_returns_none_if_no_category(self):
        """Test get_category returns None if no category matches the query"""

        CategoryFactory.create(name='My Project', short_name='mycategory')

        category = self.project_repo.get_by(name='no_name')

        assert category is None, category


    def get_all_returns_list_of_all_categories(self):
        """Test get_all_categories returns a list of all the existing categories"""

        categories = CategoryFactory.create_batch(3)

        retrieved_categories = self.project_repo.get_all_categories()

        assert isinstance(retrieved_categories, list)
        assert len(retrieved_categories) == len(categories), retrieved_categories
        for category in retrieved_categories:
            assert category in categories, category


    def test_filter_categories_by_no_matches(self):
        """Test filter_categories_by returns an empty list if no categories
        match the query"""

        CategoryFactory.create(name='My Project', short_name='mycategory')

        retrieved_categories = self.project_repo.filter_categories_by(name='no_name')

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


    def test_filter_categories_by_one_condition(self):
        """Test filter_categories_by returns a list of categories that meet
        the filtering condition"""

        CategoryFactory.create_batch(3, description='generic category')
        should_be_missing = CategoryFactory.create(description='other category')

        retrieved_categories = (self.project_repo
            .filter_categories_by(description='generic category'))

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


    def test_filter_categories_by_limit_offset(self):
        """Test that filter_categories_by supports limit and offset options"""

        CategoryFactory.create_batch(4)
        all_categories = self.project_repo.filter_categories_by()

        first_two = self.project_repo.filter_categories_by(limit=2)
        last_two = self.project_repo.filter_categories_by(limit=2, offset=2)

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


    def test_save_category(self):
        """Test save_category persist the category"""

        category = CategoryFactory.build()
        assert self.project_repo.get(category.id) is None

        self.project_repo.save_category(category)

        assert self.project_repo.get_category(category.id) == category, "Category not saved"


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

        category = CategoryFactory.build(name=None)

        assert_raises(DBIntegrityError, self.project_repo.save_category, category)


    def test_save_category_only_saves_categories(self):
        """Test save_category raises a WrongObjectError when an object which is
        not a Category instance is saved"""

        bad_object = ProjectFactory.build()

        assert_raises(WrongObjectError, self.project_repo.save_category, bad_object)


    def test_update_category(self):
        """Test update_category persists the changes made to the category"""

        category = CategoryFactory.create(description='this is a category')
        category.description = 'the description has changed'

        self.project_repo.update_category(category)
        updated_category = self.project_repo.get_category(category.id)

        assert updated_category.description == 'the description has changed', updated_category


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

        category = CategoryFactory.create()
        category.name = None

        assert_raises(DBIntegrityError, self.project_repo.update_category, category)


    def test_update_category_only_updates_categories(self):
        """Test update_category raises a WrongObjectError when an object which is
        not a Category instance is updated"""

        bad_object = ProjectFactory.build()

        assert_raises(WrongObjectError, self.project_repo.update_category, bad_object)


    def test_delete_category(self):
        """Test delete_category removes the category instance"""

        category = CategoryFactory.create()

        self.project_repo.delete_category(category)
        deleted = self.project_repo.get_category(category.id)

        assert deleted is None, deleted


    def test_delete_category_only_deletes_categories(self):
        """Test delete_category raises a WrongObjectError if is requested to
        delete other than a category"""

        bad_object = dict()

        assert_raises(WrongObjectError, self.project_repo.delete_category, bad_object)
Example #15
0
class TestBaseAnalyst(Test):
    def setUp(self):
        super(TestBaseAnalyst, self).setUp()
        BaseAnalyst.__abstractmethods__ = frozenset()
        self.ctx = ContextFixtures()
        self.base_analyst = BaseAnalyst()
        self.project_repo = ProjectRepository(db)
        self.result_repo = ResultRepository(db)
        self.task_repo = TaskRepository(db)
        assert_dict_equal.__self__.maxDiff = None
        assert_equal.__self__.maxDiff = None

    @with_context
    @patch("pybossa_lc.analysis.base.BaseAnalyst.analyse")
    def test_analyse_all(self, mock_analyse):
        """Test that all results are analysed."""
        project = ProjectFactory()
        tasks = TaskFactory.create_batch(2, project=project, n_answers=1)
        for task in tasks:
            TaskRunFactory.create(task=task)
        result = self.result_repo.get_by(task_id=tasks[0].id)
        result.info = dict(annotations=[{}])
        self.result_repo.update(result)
        self.base_analyst.analyse_all(project.id)
        expected = [call(t.id, analyse_full=True) for t in tasks]
        assert_equal(mock_analyse.call_args_list, expected)

    @with_context
    @patch("pybossa_lc.analysis.base.BaseAnalyst.analyse")
    def test_analyse_empty(self, mock_analyse):
        """Test that empty results are analysed."""
        project = ProjectFactory()
        tasks = TaskFactory.create_batch(2, project=project, n_answers=1)
        for task in tasks:
            TaskRunFactory.create(task=task)
        result = self.result_repo.get_by(task_id=tasks[0].id)
        result.info = dict(annotations=[{}])
        self.result_repo.update(result)
        all_results = self.result_repo.filter_by(project_id=project.id)
        self.base_analyst.analyse_empty(project.id)
        expected = [call(r.task_id) for r in all_results if not r.info]
        assert_equal(mock_analyse.call_args_list, expected)

    @with_context
    def test_key_dropped(self):
        """Test the correct keys are dropped."""
        data = [{'foo': None, 'bar': None}]
        df = pandas.DataFrame(data, range(len(data)))
        excluded = ['foo']
        df = self.base_analyst.drop_keys(df, excluded)
        assert_not_in('foo', df.keys())
        assert_in('bar', df.keys())

    @with_context
    def test_empty_rows_dropped(self):
        """Test empty rows are dropped."""
        data = [{'foo': 'bar'}, {'foo': None}]
        df = pandas.DataFrame(data, range(len(data)))
        df = self.base_analyst.drop_empty_rows(df)
        assert_equals(df['foo'].tolist(), ['bar'])

    @with_context
    def test_partial_rows_not_dropped(self):
        """Test partial rows are not dropped."""
        data = [{'foo': 'bar', 'baz': None}]
        df = pandas.DataFrame(data, range(len(data)))
        df = self.base_analyst.drop_empty_rows(df)
        expected = {'foo': {0: 'bar'}, 'baz': {0: None}}
        assert_dict_equal(df.to_dict(), expected)

    @with_context
    def test_match_fails_when_percentage_not_met(self):
        """Test False is returned when min answers not met."""
        data = [{'foo': 'bar', 'baz': None}]
        df = pandas.DataFrame(data, range(len(data)))
        min_answers = 2
        has_matches = self.base_analyst.has_n_matches(min_answers, df)
        assert_equal(has_matches, False)

    @with_context
    def test_match_fails_when_nan_cols(self):
        """Test False is returned when NaN columns only."""
        data = [{'foo': None}]
        df = pandas.DataFrame(data, range(len(data)))
        df = df.replace('', numpy.nan)
        min_answers = 2
        has_matches = self.base_analyst.has_n_matches(min_answers, df)
        assert_equal(has_matches, False)

    @with_context
    def test_match_succeeds_when_percentage_met(self):
        """Test True returned when match percentage met."""
        data = [{'foo': 'bar'}, {'foo': 'bar'}]
        df = pandas.DataFrame(data, range(len(data)))
        min_answers = 2
        has_matches = self.base_analyst.has_n_matches(min_answers, df)
        assert_equal(has_matches, True)

    @with_context
    def test_get_dataframe_with_dict(self):
        """Test the task run dataframe with a dict as the info."""
        info = {'foo': 'bar'}
        n_task_runs = 2
        task = TaskFactory()
        taskruns = TaskRunFactory.create_batch(n_task_runs,
                                               task=task,
                                               info=info)
        df = self.base_analyst.get_task_run_df(task, taskruns)
        assert_equal(df['foo'].tolist(), [info['foo']] * n_task_runs)
        assert_equal(df['info'].tolist(), [info] * n_task_runs)

    @with_context
    def test_get_dataframe_with_list(self):
        """Test the task run dataframe with a list as the info."""
        info = [{'foo': 'bar'}, {'baz': 'qux'}]
        n_task_runs = 2
        task = TaskFactory()
        taskruns = TaskRunFactory.create_batch(n_task_runs,
                                               task=task,
                                               info=info)
        df = self.base_analyst.get_task_run_df(task, taskruns)
        assert_equal(df['info'].tolist(), [info] * n_task_runs)

    @with_context
    def test_protected_keys_prefixed_when_exploded(self):
        """Test that protected info keys are prefixed."""
        info = {'foo': 'bar', 'info': 'baz'}
        task = TaskFactory()
        taskrun = TaskRunFactory.create(task=task, info=info)
        df = self.base_analyst.get_task_run_df(task, [taskrun])
        assert_equal(df['_info'].tolist(), [info['info']])

    @with_context
    def test_user_ids_in_task_run_dataframe(self):
        """Test that user IDs are included in the task run dataframe."""
        task = TaskFactory()
        taskruns = TaskRunFactory.create_batch(2, task=task)
        df = self.base_analyst.get_task_run_df(task, taskruns)
        assert_equal(df['user_id'].tolist(), [tr.user_id for tr in taskruns])

    def test_titlecase_normalisation(self):
        """Test titlecase normalisation."""
        rules = dict(case='title')
        norm = self.base_analyst.normalise_transcription('Some words', rules)
        assert_equal(norm, 'Some Words')

    def test_lowercase_normalisation(self):
        """Test lowercase normalisation."""
        rules = dict(case='lower')
        norm = self.base_analyst.normalise_transcription('Some words', rules)
        assert_equal(norm, 'some words')

    def test_uppercase_normalisation(self):
        """Test uppercase normalisation."""
        rules = dict(case='upper')
        norm = self.base_analyst.normalise_transcription('Some words', rules)
        assert_equal(norm, 'SOME WORDS')

    def test_whitespace_normalisation(self):
        """Test whitespace normalisation."""
        rules = dict(whitespace='normalise')
        norm = self.base_analyst.normalise_transcription(' Two  Words', rules)
        assert_equal(norm, 'Two Words')

    def test_whitespace_replace_underscore(self):
        """Test replacing whitespace with underscore normalisation."""
        rules = dict(whitespace='underscore')
        norm = self.base_analyst.normalise_transcription(' Two  Words', rules)
        assert_equal(norm, 'Two_Words')

    def test_whitespace_replace_full_stop(self):
        """Test replacing whitespace with full stop normalisation."""
        rules = dict(whitespace='full_stop')
        norm = self.base_analyst.normalise_transcription(' Two  Words', rules)
        assert_equal(norm, 'Two.Words')

    def test_trim_punctuation_normalisation(self):
        """Test trim punctuation normalisation."""
        rules = dict(trim_punctuation=True)
        norm = self.base_analyst.normalise_transcription(':Oh, a word.', rules)
        assert_equal(norm, 'Oh, a word')

    def test_date_not_normalised_if_rule_inactive(self):
        """Test date conversion not applied of rule not activate."""
        norm = self.base_analyst.normalise_transcription('foo', {})
        assert_equal(norm, 'foo')

    def test_date_conversion_with_slash(self):
        """Test date conversion with slash seperators."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('19/11/1984', rules)
        assert_equal(norm, '1984-11-19')

    def test_date_conversion_with_hyphen(self):
        """Test date conversion with hyphen seperator."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('19-11-1984', rules)
        assert_equal(norm, '1984-11-19')

    def test_date_conversion_with_no_seperator(self):
        """Test date conversion with no seperator."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('19111984', rules)
        assert_equal(norm, '')

    def test_date_conversion_with_no_year_and_year_last(self):
        """Test date conversion with no year and year last."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('19/11', rules)
        assert_equal(norm, '-11-19')

    def test_date_conversion_with_no_year_and_year_first(self):
        """Test date conversion with no year and year first."""
        rules = dict(date_format=True, yearfirst=True)
        norm = self.base_analyst.normalise_transcription('11/19', rules)
        assert_equal(norm, '-11-19')

    def test_date_conversion_with_invalid_string(self):
        """Test date conversion with invalid string."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('No date', rules)
        assert_equal(norm, '')

    def test_date_conversion_with_zero(self):
        """Test date conversion with zero."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('0', rules)
        assert_equal(norm, '')

    def test_date_conversion_with_non_zero_integer(self):
        """Test date conversion with non-zero integer."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('1', rules)
        assert_equal(norm, '')

    def test_date_conversion_with_trailing_punctuation(self):
        """Test date conversion with trailing punctuation."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('19/11/', rules)
        assert_equal(norm, '-11-19')

    def test_date_conversion_with_trailing_whitespace(self):
        """Test date conversion with trailing whitespace."""
        rules = dict(date_format=True, dayfirst=True)
        norm = self.base_analyst.normalise_transcription('19/11/1984 ', rules)
        assert_equal(norm, '1984-11-19')

    @with_context
    def test_n_answers_increased_when_task_complete(self):
        """Test n answers required for a task is updated."""
        n_original_answers = 1
        task = TaskFactory.create(n_answers=n_original_answers)
        TaskRunFactory.create(task=task)
        self.base_analyst.update_n_answers_required(task, False)
        assert_equal(task.n_answers, n_original_answers + 1)
        assert_equal(task.state, 'ongoing')

    @with_context
    def test_n_answers_not_increased_when_still_task_runs(self):
        """Test n answers not updated when task runs still required."""
        n_original_answers = 2
        task = TaskFactory.create(n_answers=n_original_answers)
        TaskRunFactory.create(task=task)
        self.base_analyst.update_n_answers_required(task, False)
        assert_equal(task.n_answers, n_original_answers)
        assert_equal(task.state, 'ongoing')

    @with_context
    def test_n_answers_not_increased_when_max_answers_reached(self):
        """Test n answers not updated when max answers reached."""
        n_answers = 3
        task = TaskFactory.create(n_answers=n_answers)
        TaskRunFactory.create_batch(n_answers, task=task)
        self.base_analyst.update_n_answers_required(task,
                                                    False,
                                                    max_answers=n_answers)
        assert_equal(task.n_answers, n_answers)
        assert_equal(task.state, 'completed')

    @with_context
    def test_n_answers_reduced_when_task_complete(self):
        """Test n answers reduced to number of task runs when task complete."""
        n_answers = 3
        task = TaskFactory.create(n_answers=n_answers)
        TaskRunFactory.create_batch(n_answers - 1, task=task)
        self.base_analyst.update_n_answers_required(task,
                                                    True,
                                                    max_answers=n_answers)
        assert_equal(task.n_answers, n_answers - 1)
        assert_equal(task.state, 'completed')

    def test_overlap_ratio_is_1_with_equal_rects(self):
        """Test for an overlap ratio of 1."""
        rect = {'x': 100, 'y': 100, 'w': 100, 'h': 100}
        overlap = self.base_analyst.get_overlap_ratio(rect, rect)
        assert_equal(overlap, 1)

    def test_overlap_ratio_is_0_with_adjacent_rects(self):
        """Test for an overlap ratio of 0."""
        r1 = {'x': 100, 'y': 100, 'w': 100, 'h': 100}
        r2 = {'x': 100, 'y': 201, 'w': 100, 'h': 100}
        overlap = self.base_analyst.get_overlap_ratio(r1, r2)
        assert_equal(overlap, 0)

    def test_overlap_ratio_with_partially_overlapping_rects(self):
        """Test for an overlap ratio of 0.33."""
        r1 = {'x': 100, 'y': 100, 'w': 100, 'h': 100}
        r2 = {'x': 150, 'y': 100, 'w': 100, 'h': 100}
        overlap = self.base_analyst.get_overlap_ratio(r1, r2)
        assert_equal('{:.2f}'.format(overlap), '0.33')

    def test_overlap_ratio_where_union_is_zero(self):
        """Test for an overlap ratio where the union is zero."""
        r1 = {'x': 0, 'y': 0, 'w': 100, 'h': 100}
        r2 = {'x': 101, 'y': 0, 'w': 100, 'h': 100}
        overlap = self.base_analyst.get_overlap_ratio(r1, r2)
        assert_equal(overlap, 0)

    def test_rect_from_selection(self):
        """Test that we get the correct rect."""
        coords = dict(x=400, y=200, w=100, h=150)
        coords_str = '{0},{1},{2},{3}'.format(coords['x'], coords['y'],
                                              coords['w'], coords['h'])
        fake_anno = {
            'target': {
                'selector': {
                    'value': '?xywh={}'.format(coords_str)
                }
            }
        }
        rect = self.base_analyst.get_rect_from_selection_anno(fake_anno)
        assert_dict_equal(rect, coords)

    def test_rect_from_selection_with_floats(self):
        """Test that we get the correct rect with rounded coordinates."""
        coords = dict(x=400.001, y=200.499, w=100.501, h=150.999)
        coords_str = '{0},{1},{2},{3}'.format(coords['x'], coords['y'],
                                              coords['w'], coords['h'])
        fake_anno = {
            'target': {
                'selector': {
                    'value': '?xywh={}'.format(coords_str)
                }
            }
        }
        rect = self.base_analyst.get_rect_from_selection_anno(fake_anno)
        assert_dict_equal(rect, {'x': 400, 'y': 200, 'w': 101, 'h': 151})

    @with_context
    def test_get_project_template(self):
        """Test that the correct template is returned."""
        category = CategoryFactory()
        tmpl_fixtures = TemplateFixtures(category)
        tmpl1 = tmpl_fixtures.create()
        tmpl2 = tmpl_fixtures.create()
        fake_templates = [tmpl1, tmpl2]
        category.info = dict(templates=fake_templates)
        self.project_repo.update_category(category)
        project_info = dict(template_id=tmpl1['id'])
        project = ProjectFactory(category=category, info=project_info)
        ret_tmpl = self.base_analyst.get_project_template(project)
        assert_equal(ret_tmpl, tmpl1)

    @with_context
    @raises(ValueError)
    def test_get_invalid_project_template(self):
        """Test that getting an invalid template throws an error."""
        fake_templates = [{'id': 'foo'}]
        user_info = dict(templates=fake_templates)
        project_info = dict(template_id='bar')
        UserFactory.create(info=user_info)
        project = ProjectFactory(info=project_info)
        self.base_analyst.get_project_template(project)

    @with_context
    @raises(ValueError)
    def test_get_non_existant_project_template(self):
        """Test that getting a non-existant template throws an error."""
        project = ProjectFactory()
        self.base_analyst.get_project_template(project)

    def test_dataframe_keys_replaced(self):
        """Test that dataframe keys are replaced and columns merged."""
        data = [{'foo': '你好', 'baz': 'qux'}, {'foo': 1, 'quux': 'qux'}]
        old_df = pandas.DataFrame(data, range(len(data)))
        new_df = self.base_analyst.replace_df_keys(old_df, quux='baz')
        assert_dict_equal(new_df.to_dict(), {
            'foo': {
                0: '你好',
                1: 1
            },
            'baz': {
                0: 'qux',
                1: 'qux'
            }
        })

    @with_context
    @patch('pybossa_lc.analysis.base.send_mail')
    @patch('pybossa_lc.analysis.base.render_template')
    @patch('pybossa_lc.analysis.base.Queue.enqueue')
    def test_comment_annotations_emailed(self, mock_enqueue, mock_render,
                                         mock_send_mail):
        """Test that comment annotation emails are sent."""
        mock_render.return_value = True
        comment = 'foo'
        creator = 'bar'
        target = 'example.com'
        fake_anno = {
            'creator': {
                'id': 'example.com/user1',
                'type': 'Person',
                'name': creator,
                'nickname': 'nick'
            },
            'body': {
                'type': 'TextualBody',
                'purpose': 'commenting',
                'value': comment,
                'format': 'text/plain'
            }
        }
        task = self.ctx.create_task(1, target)
        json_anno = json.dumps(fake_anno, indent=2, sort_keys=True)
        self.base_analyst.email_comment_anno(task, fake_anno)

        expected_render_args = [
            call('/account/email/new_comment_anno.md',
                 annotation=json_anno,
                 creator=creator,
                 comment=comment,
                 raw_image=None,
                 link=None),
            call('/account/email/new_comment_anno.html',
                 annotation=json_anno,
                 creator=creator,
                 comment=comment,
                 raw_image=None,
                 link=None)
        ]
        assert_equal(mock_render.call_args_list, expected_render_args)

        expected_msg = {
            'body': True,
            'html': True,
            'subject': 'New Comment Annotation',
            'recipients': flask_app.config.get('ADMINS')
        }
        mock_enqueue.assert_called_once_with(mock_send_mail, expected_msg)

    @with_context
    @patch('pybossa_lc.model.base.wa_client')
    def test_modified_results_not_updated(self, mock_client):
        """Test results are not updated if an Annotation has been modified."""
        task = self.ctx.create_task(1)
        TaskRunFactory(task=task)
        result = self.result_repo.get_by(task_id=task.id)
        self.base_analyst.analyse(result.id)
        mock_client.search_annotations.return_value = [{
            'modified': 'fake-time'
        }]
        assert_equal(mock_client.create_annotation.called, False)

    @with_context
    @patch('pybossa_lc.model.base.wa_client')
    def test_parent_results_not_updated(self, mock_client):
        """Test results are not updated if an Annotation has children."""
        task = self.ctx.create_task(1)
        TaskRunFactory(task=task)
        result = self.result_repo.get_by(task_id=task.id)
        result.info = dict(has_children=True)
        self.result_repo.update(result)
        self.base_analyst.analyse(result.id)
        assert_equal(mock_client.create_annotation.called, False)

    @with_context
    @patch('pybossa_lc.model.base.wa_client')
    def test_result_with_child_not_updated(self, mock_client):
        """Test that a result is not updated when it has a child."""
        task = self.ctx.create_task(1)
        TaskRunFactory(task=task)
        result = self.result_repo.get_by(task_id=task.id)
        info = dict(annotations='foo', has_children=True)
        result.info = info
        self.result_repo.update(result)
        self.base_analyst.analyse(result.id)
        assert_equal(result.info, info)

    @with_context
    def test_analysis_exception_if_no_annotation_collection(self):
        """Test that AnnotationCollection must be setup."""
        task = self.ctx.create_task(1, 'example.com', anno_collection=None)
        TaskRunFactory.create(task=task)
        result = self.result_repo.filter_by(project_id=task.project_id)[0]
        assert_raises(AnalysisException, self.base_analyst.analyse, result.id)