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()
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_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
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
def test_save_chart_image(self, request, database_backend, test_full_class, tmpdir): """ Verify API works. NB No db verification in API test, as API for verifying does not exist. TODO: Verify db saved chart contents when load/edit features added. """ test_database = request.getfixturevalue(database_backend) test_existing_class = NewClass.from_dict(test_full_class.json_dict()) for student in test_existing_class: if student.avatar_id: Path(test_existing_class.temp_avatars_dir, student.avatar_id).write_text(student.avatar_id) # Create class in db: test_database.create_class(test_existing_class) # Find class id to load: classes = test_database.get_classes() test_class_id = classes[0].id # test_class = Class.from_dict(test_full_class_data_set['json_dict_rep']) test_class = test_database.load_class(test_class_id) test_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': { "some": "chart", "default": "params" }, 'score-students_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 }, } # Create chart in db: test_database.create_chart(test_data_dict) mock_plt = plt.figure(figsize=(19.20, 10.80)) test_image = io.BytesIO() # Images must both be saved as '.png' for comparison. test_image_path = Path(tmpdir, 'test image.png') mock_plt.savefig(test_image_path, format='png', dpi=300) test_image.seek(0) # Return pointer to start of binary stream. save_chart_path = test_database.save_chart_image( test_data_dict, mock_plt) # Return pointer: test_image.seek(0) # Return pointer to start of binary stream. # Path exists ad image at path is expected data: assert save_chart_path.exists() compare_images(save_chart_path, test_image_path, 0.0001)
class TestMoveAvatarsToClassData: @pytest.mark.parametrize( 'test_new_class, expected_moved_avatars', [ (NewClass('test empty class'), []), # No students # All students have avatar_id (NewClass.from_dict({ 'name': 'test_class', 'students': [ { 'name': 'Cali', 'avatar_id': 'Cali_avatar.png' }, { 'name': 'Zach', 'avatar_id': 'Zach_avatar.png' }, { 'name': 'Ashley', 'avatar_id': 'Ashley_avatar.png' }, { 'name': 'Danielle', 'avatar_id': 'Danielle_avatar.png' }, ] }), [ 'Cali_avatar.png', 'Zach_avatar.png', 'Ashley_avatar.png', 'Danielle_avatar.png', ]), # Some students have avatar_id (NewClass.from_dict(test_full_class_data_set['json_dict_rep']), [ 'Cali_avatar.png', 'Zach_avatar.png', 'Ashley_avatar.png', 'Danielle_avatar.png', ]), # No students have avatar_id (NewClass.from_dict({ 'name': 'test_class', 'students': [ { 'name': 'Cali' }, { 'name': 'Zach' }, { 'name': 'Ashley' }, { 'name': 'Danielle' }, ] }), []), ]) def test_move_avatars_to_class_data(self, empty_json_database, test_new_class, expected_moved_avatars): """Avatar files copied from original locations to class data.""" test_json_database = empty_json_database moved_avatars = [] def mock_move_avatar_to_class_data(test_class: NewClass, avatar_filename: str): assert test_class is test_new_class moved_avatars.append(avatar_filename) empty_json_database._move_avatar_to_class_data = mock_move_avatar_to_class_data assert test_json_database._move_avatars_to_class_data( test_new_class) is None assert moved_avatars == expected_moved_avatars
def test_generate_avatar_coords_backends(self, request, monkeypatch, database_backend): test_database = request.getfixturevalue(database_backend) test_database.default_avatar_path = 'mocked_default_avatar_path' test_existing_class = NewClass.from_dict( test_full_class_data_set['json_dict_rep']) for student in test_existing_class: if student.avatar_id: Path(test_existing_class.temp_avatars_dir, student.avatar_id).write_text(student.avatar_id) # Create class in db: test_database.create_class(test_existing_class) # Find class id to load: classes = test_database.get_classes() test_class_id = classes[0].id # test_class = Class.from_dict(test_full_class_data_set['json_dict_rep']) test_class = test_database.load_class(test_class_id) monkeypatch.setattr(process_chart_data.definitions, 'DATABASE', test_database) # student_score_entry_sequence = [0, 1, 3, None, 50, 99, 100, 1, 2, 3, 4, None, 6, 7, 8] 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 } # Vary calls for actual avatars based on backend. test_generate_avatar_coords_result = { **{ 'mocked_default_avatar_path': [(0.0, 15), (0.0, 25), (0.0, 45), (0.0, 55), (0.0, 65), (10.0, 15), (10.0, 25), (50.0, 5), (100.0, 5), (100.0, 15)], }, **({ test_database.get_avatar_path_class_filename( test_class.id, test_class.students[8].avatar_id): [(0.0, 35)], # Ashley test_database.get_avatar_path_class_filename( test_class.id, test_class.students[0].avatar_id): [(0.0, 5)], # Cali test_database.get_avatar_path_class_filename( test_class.id, test_class.students[12].avatar_id): [(10.0, 5)], # Danielle } if isinstance(test_database, JSONDatabase) else { test_database.get_avatar_path(test_class.students[8].avatar_id): [(0.0, 35)], # Ashley test_database.get_avatar_path(test_class.students[0].avatar_id): [(0.0, 5)], # Cali test_database.get_avatar_path(test_class.students[12].avatar_id): [(10.0, 5)], # Danielle }), } assert generate_avatar_coords( test_student_scores_dict, test_class.id) == test_generate_avatar_coords_result
def test_save_chart_image(self, empty_sqlite_database, test_full_class): test_database = empty_sqlite_database test_existing_class = NewClass.from_dict(test_full_class.json_dict()) for student in test_existing_class: if student.avatar_id: Path(test_existing_class.temp_avatars_dir, student.avatar_id).write_text(student.avatar_id) # Create class in db: test_database.create_class(test_existing_class) # Find class id to load: classes = test_database.get_classes() test_class_id = classes[0].id # test_class = Class.from_dict(test_full_class_data_set['json_dict_rep']) test_class = test_database.load_class(test_class_id) test_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': { "some": "chart", "default": "params" }, 'score-students_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 }, } # Create chart in db: test_database.create_chart(test_data_dict) mock_plt = plt.figure(figsize=(19.20, 10.80)) test_image = io.BytesIO() mock_plt.savefig(test_image, format='png', dpi=300) test_image.seek(0) # Return pointer to start of binary stream. save_chart_path = test_database.save_chart_image( test_data_dict, mock_plt) # Return pointer: test_image.seek(0) # Return pointer to start of binary stream. # Path exists ad image at path is expected data: assert save_chart_path.exists() assert save_chart_path.read_bytes() == test_image.read1( ) # size arg can be omitted on 3.7+