class TestComposeClasslistDialogue:
    @pytest.mark.parametrize(
        'class_data, create_blank_class',
        [
            ([Class.from_dict(test_full_class_data_set['json_dict_rep'])], []),
            ([Class(name='Empty class with no students')
              ], [True]),  # Empty class created
            pytest.param(
                [Class(name='class with no students')], [],
                marks=pytest.mark.xfail(
                    reason="No values left to return from blank_class_dialogue."
                )),
            (
                [
                    Class(name=Class.from_dict(
                        test_full_class_data_set['json_dict_rep']).name
                          ),  # Empty class, then full class.
                    Class.from_dict(test_full_class_data_set['json_dict_rep'])
                ],
                [False]),
            ([Class(name="Empty class"),
              Class(name="Empty class")
              ], [False, True]),  # Empty class refused then accepted.
        ])
    def test_compose_classlist_dialogue_full_class(
        self,
        monkeypatch,
        class_data,
        create_blank_class,
        test_full_class,
    ):
        class_data_to_return = (test_class for test_class in class_data)

        def mocked_take_class_data_input(class_name):
            if class_name not in [
                    test_class.name for test_class in class_data
            ]:
                raise ValueError
            return next(class_data_to_return)

        blank_class_returns = (chosen_option
                               for chosen_option in create_blank_class)

        def mocked_blank_class_dialogue():
            # Will raise StopIteration if no values left to return (or none to begin with).
            return next(blank_class_returns)

        def mocked_class_data_feedback(test_class):
            if test_class not in class_data:
                raise ValueError

        monkeypatch.setattr(class_functions, 'take_class_data_input',
                            mocked_take_class_data_input)
        monkeypatch.setattr(class_functions, 'blank_class_dialogue',
                            mocked_blank_class_dialogue)
        monkeypatch.setattr(class_functions, 'class_data_feedback',
                            mocked_class_data_feedback)
        assert compose_classlist_dialogue(
            class_data[0].name).json_dict() == class_data[-1].json_dict()
Example #2
0
    def test_load_class(self, request, database_backend, class_data):
        """Class loaded has same data as that saved in db, with class/student ids."""
        test_database = request.getfixturevalue(database_backend)
        preexisting_class = request.getfixturevalue(class_data)
        # Create test NewClass object, mocking avatar_files.
        preexisting_class = NewClass.from_dict(preexisting_class.json_dict())
        for student in preexisting_class:
            if student.avatar_id:
                Path(preexisting_class.temp_avatars_dir,
                     student.avatar_id).write_text(student.avatar_id)
        # Create class in db:
        test_database.create_class(preexisting_class)

        # Find class id, load class to verify:
        classes = test_database.get_classes()
        test_full_class_id = classes[
            0].id  # As the only class will be first item.

        # Loaded class will have ids:
        test_loaded_class_with_student_ids = Class.from_dict(
            preexisting_class.json_dict())
        if isinstance(test_database, JSONDatabase):
            for student in test_loaded_class_with_student_ids.students:
                student.id = student.name
        if not isinstance(test_database, JSONDatabase):
            # This should be accurate for most sql databases.
            for test_id, student in enumerate(
                    test_loaded_class_with_student_ids.students, start=1):
                student.id = test_id

        assert test_database.load_class(test_full_class_id).json_dict(
        ) == test_loaded_class_with_student_ids.json_dict()
Example #3
0
class TestClassStr:
    @pytest.mark.parametrize(
        'class_object,'
        'expected_str', [
            (Class(name='name_only_class'),
             f"Class {'name_only_class'}, with id=None, containing 0 students."
             ),
            (Class(class_id='some class id', name='name_only_class with id'),
             f"Class {'name_only_class with id'}, with id={'some class id'}, containing 0 students."
             ),
            (Class.from_dict(test_full_class_data_set['json_dict_rep']),
             f"Class {Class.from_dict(test_full_class_data_set['json_dict_rep']).name}, "
             f"with id={Class.from_dict(test_full_class_data_set['json_dict_rep']).id}, "
             f"containing {len(Class.from_dict(test_full_class_data_set['json_dict_rep']).students)} students, "
             f"with names: {', '.join([student.name for student in Class.from_dict(test_full_class_data_set['json_dict_rep']).students])}."
             ),
            (Class(class_id='some class id',
                   name='small_class with id',
                   students=[Student(name='one'),
                             Student(name='two')
                             ]), f"Class {'small_class with id'}, "
             f"with id={'some class id'}, "
             f"containing 2 students, "
             f"with names: one, two."),
        ])
    def test_str(self, class_object, expected_str):
        assert str(class_object) == expected_str
Example #4
0
    def test_create_class(self, request, empty_sqlite_database, class_data):
        test_database = empty_sqlite_database
        test_class_data = request.getfixturevalue(class_data)
        # Create test NewClass object, mocking avatar_files.
        test_class = NewClass.from_dict(test_class_data.json_dict())
        for student in test_class:
            if student.avatar_id:
                Path(test_class.temp_avatars_dir,
                     student.avatar_id).write_text(student.avatar_id)

        # no students or class in empty db:
        assert not test_database._connection().cursor().execute(
            """SELECT * FROM class""").fetchall()
        assert not test_database._connection().cursor().execute(
            """SELECT * FROM student""").fetchall()

        # Create class in db:
        assert test_database.create_class(test_class) is None

        # Find class id, load class to verify:
        classes = test_database.get_classes()
        test_class_id = classes[0].id

        # Class will have ids:
        test_loaded_class_with_student_ids = Class.from_dict(
            test_class.json_dict()).json_dict()
        for test_id, student in enumerate(
                test_loaded_class_with_student_ids['students'], start=1):
            student['id'] = test_id

        assert test_database.load_class(  # NB Returned object will be Class, not NewClass:
            test_class_id).json_dict() == test_loaded_class_with_student_ids
Example #5
0
class TestAssembleChartData:
    @pytest.mark.parametrize('class_from_create_class',
                             [Class.from_dict(test_full_class_data_set['json_dict_rep']),  # Pass in test_class
                              NewClass.from_dict(test_full_class_data_set['json_dict_rep'])  # NewClass obj
                              ])
    def test_assemble_chart_data(self, monkeypatch, class_from_create_class):
        test_chart_name = 'my_chart'
        test_chart_filename = test_chart_name
        mock_score_avatar_dict = {'scores': 'list of avatars'}
        mock_chart_params = {'some': 'chart_params'}

        def mocked_take_score_data(class_obj):
            assert class_obj is class_from_create_class
            return mock_score_avatar_dict

        def mocked_take_chart_name():
            return test_chart_name

        def mocked_clean_for_filename(chart_name):
            assert chart_name == test_chart_name
            return test_chart_name

        def mocked_set_chart_params():
            return mock_chart_params

        monkeypatch.setattr(create_chart, 'take_score_data', mocked_take_score_data)
        monkeypatch.setattr(create_chart, 'take_chart_name', mocked_take_chart_name)
        monkeypatch.setattr(create_chart, 'clean_for_filename', mocked_clean_for_filename)
        monkeypatch.setattr(create_chart, 'set_chart_params', mocked_set_chart_params)

        assert assemble_chart_data(class_from_create_class) == (
            test_chart_name, test_chart_filename, mock_score_avatar_dict, mock_chart_params)
    def test_take_score_data(self, monkeypatch):
        test_class = Class.from_dict(test_full_class_data_set['json_dict_rep'])

        mock_score_avatar_dict = {'scores': 'list of avatars'}

        def mocked_take_student_scores(scored_class):
            assert scored_class == test_class
            return mock_score_avatar_dict

        monkeypatch.setattr(take_chart_data_UI, 'take_student_scores',
                            mocked_take_student_scores)

        assert take_score_data(test_class) == mock_score_avatar_dict
Example #7
0
class TestClassRepr:
    @pytest.mark.parametrize('class_object', [
        Class(name='name_only_class'),
        Class(name='name only class with id', class_id='a class id'),
        Class.from_dict(test_full_class_data_set['json_dict_rep']),
    ])
    def test_repr(self, class_object):
        assert repr(class_object) == (
            f'{class_object.__class__.__module__}.{class_object.__class__.__name__}('
            f'id={class_object.id if class_object.id else None !r}, '
            f'name={class_object._name!r}, '
            f'path_safe_name={class_object._path_safe_name!r}, '
            f'students={class_object.students!r}'
            f')')
Example #8
0
    def setUp(self):
        self.test_class = Class.from_dict(
            test_full_class_data_set['json_dict_rep'])

        self.score_entry_instruction = (
            f"\nEnter student scores for {self.test_class.name}: \n"
            f"Type score for each student, or '_' to exclude student, and press enter."
        )
        self.newline_after_entry = '\n'
        self.print_calls = [
            self.score_entry_instruction, self.newline_after_entry
        ]

        self.mock_score_avatar_dict = {'scores': 'list of avatars'}
Example #9
0
    def test_assemble_chart_data(self, monkeypatch):
        test_class = Class.from_dict(test_full_class_data_set['json_dict_rep'])
        test_class_name = test_class.name
        test_chart_name = 'my_chart'
        test_chart_filename = test_chart_name
        mock_score_avatar_dict = {'scores': 'list of avatars'}
        mock_chart_params = {'some': 'chart_params'}

        def mocked_select_classlist():
            return test_class_name

        def mocked_load_class_from_disk(class_name):
            if class_name != test_class_name:
                raise ValueError
            return test_class

        def mocked_take_score_data(class_obj):
            if class_obj is not test_class:
                raise ValueError
            return mock_score_avatar_dict

        def mocked_take_chart_name():
            return test_chart_name

        def mocked_clean_for_filename(chart_name):
            if chart_name != test_chart_name:
                raise ValueError
            return test_chart_name

        def mocked_set_chart_params():
            return mock_chart_params

        monkeypatch.setattr(create_chart, 'select_classlist',
                            mocked_select_classlist)
        monkeypatch.setattr(create_chart, 'load_class_from_disk',
                            mocked_load_class_from_disk)
        monkeypatch.setattr(create_chart, 'take_score_data',
                            mocked_take_score_data)
        monkeypatch.setattr(create_chart, 'take_chart_name',
                            mocked_take_chart_name)
        monkeypatch.setattr(create_chart, 'clean_for_filename',
                            mocked_clean_for_filename)
        monkeypatch.setattr(create_chart, 'set_chart_params',
                            mocked_set_chart_params)

        assert assemble_chart_data() == (test_class_name, test_chart_name,
                                         test_chart_filename,
                                         mock_score_avatar_dict,
                                         mock_chart_params)
Example #10
0
    def setUp(self):
        self.mock_CLASSLIST_DATA_PATH = Path('.')
        self.mock_CLASSLIST_DATA_FILE_TYPE = '.class_data_file'

        self.test_class_json_dict = test_full_class_data_set['json_dict_rep']
        self.test_class_name = self.test_class_json_dict['name']

        self.test_class_object = Class.from_dict(self.test_class_json_dict)

        # Build save file path
        self.test_class_filename = self.test_class_name + self.mock_CLASSLIST_DATA_FILE_TYPE
        self.test_class_data_path = self.mock_CLASSLIST_DATA_PATH.joinpath(
            self.test_class_name)
        self.test_class_data_file_path = self.test_class_data_path.joinpath(
            self.test_class_filename)
    def test_take_student_scores(self, monkeypatch):
        """
        Score data returned.

        Test with generic database.
        """

        test_class = Class.from_dict(test_full_class_data_set['json_dict_rep'])

        # Gives no score to one student with and without an avatar.
        mocked_take_score_entry_return_values = [
            0, 1, 3, None, 50, 99, 100, 1, 2, 3, 4, None, 6, 7, 8
        ]

        test_take_student_scores_return_value = {
            0: [test_class.students[0]],  # Cali
            1: [
                test_class.students[1],  # Monty
                test_class.students[7]
            ],  # Regina
            3: [
                test_class.students[2],  # Abby
                test_class.students[9]
            ],  # Alex
            # No score, not returned: None: [test_class.students[3],  # Zach
            #                                test_class.students[11]],  # Edgar
            50: [test_class.students[4]],  # Janell
            99: [test_class.students[5]],  # Matthew
            100: [test_class.students[6]],  # Olivia
            2: [test_class.students[8]],  # Ashley
            4: [test_class.students[10]],  # Melissa
            6: [test_class.students[12]],  # Danielle
            7: [test_class.students[13]],  # Kayla
            8: [test_class.students[14]],  # Jaleigh
        }

        score = (score for score in mocked_take_score_entry_return_values)

        def mocked_take_score_entry(student_name):
            return next(score)

        monkeypatch.setattr(take_chart_data_UI, 'take_score_entry',
                            mocked_take_score_entry)

        assert take_student_scores(
            test_class) == test_take_student_scores_return_value
Example #12
0
    def setUp(self):
        self.mock_DEFAULT_AVATAR_PATH = 'mocked_default_avatar_path'

        self.test_class = Class.from_dict(
            test_full_class_data_set['json_dict_rep'])

        # NB If data other than avatar in dict values, this test implementation may need to change.
        self.avatar_paths = [
            f'path to {student.avatar_filename}' if student.avatar_filename
            is not None else self.mock_DEFAULT_AVATAR_PATH
            for student in self.test_class.students
        ]

        # Gives no score to one student with and without an avatar.
        self.mocked_take_score_entry_return_values = [
            0, 1, 3, None, 50, 99, 100, 1, 2, 3, 4, None, 6, 7, 8
        ]
        self.mocked_get_avatar_path_return_values = [
            self.avatar_paths[self.mocked_take_score_entry_return_values.index(
                score)] for score in self.mocked_take_score_entry_return_values
            if score is not None
        ]

        self.test_take_student_scores_return_value = {
            0: ['path to Cali_avatar.png'],
            1: [self.mock_DEFAULT_AVATAR_PATH, self.mock_DEFAULT_AVATAR_PATH],
            3: [self.mock_DEFAULT_AVATAR_PATH, self.mock_DEFAULT_AVATAR_PATH],
            # No score, not returned: None: ['Zach_avatar.png', None]
            50: [self.mock_DEFAULT_AVATAR_PATH],
            99: [self.mock_DEFAULT_AVATAR_PATH],
            100: [self.mock_DEFAULT_AVATAR_PATH],
            2: ['path to Ashley_avatar.png'],
            4: [self.mock_DEFAULT_AVATAR_PATH],
            6: ['path to Danielle.png'],
            7: [self.mock_DEFAULT_AVATAR_PATH],
            8: [self.mock_DEFAULT_AVATAR_PATH]
        }
Example #13
0
class TestNewChart:
    @pytest.mark.parametrize('user_wants_to_save', [True, False], ids=['User saving.', 'User not saving.'])
    @pytest.mark.parametrize('class_from_create_class',
                             [None,  # Test Full class fixture
                              Class.from_dict(test_full_class_data_set['json_dict_rep']),  # Pass in test_class
                              NewClass.from_dict(test_full_class_data_set['json_dict_rep'])  # NewClass obj
                              ])
    def test_new_chart(self, monkeypatch, empty_generic_database,
                       class_from_create_class, test_full_class,
                       user_wants_to_save):
        # Test class either passed, or instantiated if None is passed.
        test_class = class_from_create_class or test_full_class

        test_chart_name = 'test_chart_name'
        test_chart_default_filename = 'test_chart_default_filename'
        test_chart_params = {'test_chart_params': 'some chart params'}
        test_score_avatar_dict = {'test_student_scores': 'test student avatars'}

        test_chart_data_dict = {'class_id': test_class.id,
                                'class_name': test_class.name,
                                'chart_name': test_chart_name,
                                'chart_default_filename': test_chart_default_filename,
                                'chart_params': test_chart_params,
                                'score-students_dict': test_score_avatar_dict,
                                }

        test_chart_image_location = 'some image location'

        def mocked_select_classlist():
            if class_from_create_class:
                raise ValueError('select_classlist should not be called if a class is passed.')
            return test_full_class.name

        def mocked_get_classes():
            if class_from_create_class:
                raise ValueError('Function should not be called if class is passed.')
            return test_class.name

        def mocked_load_class(class_name):
            if class_from_create_class:
                raise ValueError('Function should not be called if class is passed.')
            return test_class

        def mocked_assemble_chart_data(class_obj):
            return (test_chart_name,
                    test_chart_default_filename,
                    test_score_avatar_dict,
                    test_chart_params)

        def mocked_create_chart(chart_data_dict):
            assert chart_data_dict == test_chart_data_dict

        def mocked_generate_chart_image(chart_data_dict):
            assert chart_data_dict == test_chart_data_dict
            return test_chart_image_location

        def mocked_show_image(chart_image_location):
            assert chart_image_location == test_chart_image_location
            return user_wants_to_save

        user_save_chart_image_mock = {'called': False}

        def mocked_user_save_chart_image(chart_data_dict, chart_image_location):
            assert chart_data_dict == test_chart_data_dict
            assert chart_image_location == test_chart_image_location
            user_save_chart_image_mock['called'] = True
            if not user_wants_to_save:
                raise ValueError('Should not be called if user did not want to save.')

        test_database = empty_generic_database
        test_database.load_class = mocked_load_class
        test_database.get_classes = mocked_get_classes
        test_database.create_chart = mocked_create_chart

        monkeypatch.setattr(definitions, 'DATABASE', test_database)
        monkeypatch.setattr(create_chart, 'select_classlist', mocked_select_classlist)
        monkeypatch.setattr(create_chart, 'assemble_chart_data', mocked_assemble_chart_data)
        monkeypatch.setattr(create_chart, 'generate_chart_image', mocked_generate_chart_image)
        monkeypatch.setattr(create_chart, 'show_image', mocked_show_image)
        monkeypatch.setattr(create_chart, 'user_save_chart_image', mocked_user_save_chart_image)

        assert new_chart(class_from_create_class) is None

        assert user_save_chart_image_mock['called'] is user_wants_to_save
Example #14
0
    def test_generate_avatar_coords_generic_api(self, monkeypatch,
                                                empty_generic_database):
        test_database = empty_generic_database
        test_database.default_avatar_path = 'mocked_default_avatar_path'

        test_class = Class.from_dict(test_full_class_data_set['json_dict_rep'])
        student_score_entry_sequence = [
            0, 1, 3, None, 50, 99, 100, 1, 2, 3, 4, None, 6, 7, 8
        ]

        # Mock out avatar_paths with readable strings.
        avatar_paths = [
            f'path to {student.avatar_id}' if student.avatar_id is not None
            else test_database.default_avatar_path
            for student in test_class.students
        ]
        # Format those avatar_paths to remove students who did not submit a score:
        mocked_get_avatar_path_return_values = [
            avatar_paths[student_score_entry_sequence.index(score)]
            for score in student_score_entry_sequence if score is not None
        ]
        avatar_path = (path for path in mocked_get_avatar_path_return_values)

        avatar_ids = [student.avatar_id for student in test_class]

        def mocked_get_avatar_path(avatar_id):
            """
            Strictly speaking does not need a mock, as should raise error, but
            re-mocking method for clarity.
            """
            assert avatar_id in avatar_ids
            #  deepcode ignore unguarded~next~call: No guard - let error propagate, should not reach StopIteration.
            return next(avatar_path)

        test_database.get_avatar_path = mocked_get_avatar_path

        monkeypatch.setattr(process_chart_data.definitions, 'DATABASE',
                            test_database)

        test_student_scores_dict = {
            0: [test_class.students[0]],  # Cali
            1: [
                test_class.students[1],  # Monty
                test_class.students[7]
            ],  # Regina
            3: [
                test_class.students[2],  # Abby
                test_class.students[9]
            ],  # Alex
            # No score, not returned: None: [test_class.students[3],  # Zach
            #                                test_class.students[11]],  # Edgar
            50: [test_class.students[4]],  # Janell
            99: [test_class.students[5]],  # Matthew
            100: [test_class.students[6]],  # Olivia
            2: [test_class.students[8]],  # Ashley
            4: [test_class.students[10]],  # Melissa
            6: [test_class.students[12]],  # Danielle
            7: [test_class.students[13]],  # Kayla
            8: [test_class.students[14]],  # Jaleigh
        }

        test_generate_avatar_coords_result = {
            'mocked_default_avatar_path': [(0.0, 15), (0.0, 25), (0.0, 35),
                                           (0.0, 45), (0.0, 55), (0.0, 65),
                                           (10.0, 15), (10.0, 25), (50.0, 5),
                                           (100.0, 5)],
            'path to Ashley_avatar.png': [(100.0, 15)],
            'path to Cali_avatar.png': [(0.0, 5)],
            'path to Danielle_avatar.png': [(10.0, 5)]
        }

        assert generate_avatar_coords(
            test_student_scores_dict,
            test_class.id) == test_generate_avatar_coords_result
Example #15
0
 def mock_from_file(class_path):
     assert class_path == Path(
         test_json_database.class_data_path, test_class_name,
         f'{test_class_name}{test_json_database.class_data_file_type}')
     return Class.from_dict(test_full_class.json_dict())
Example #16
0
 def setUp(self) -> None:
     self.full_class_return = Class.from_dict(
         test_full_class_data_set['json_dict_rep'])
     self.empty_class_return = Class(name=self.full_class_return.name)
Example #17
0
 def setUp(self):
     self.test_class_json_dict = test_full_class_data_set['json_dict_rep']
     self.test_classname = self.test_class_json_dict['name']
     self.test_class_object = Class.from_dict(self.test_class_json_dict)