def command(): """Run the program. Command line parse and dispatch. """ args = command_line_args() # Run GUI if not args.import_csv: return main() # An empty string is a valid SQLAlchemy non-default value for the database name. non_default_database = args.database == '' or args.database if args.verbosity >= 1: print(f"Running {__file__}") print(f'Loading movies from {args.import_csv}') if non_default_database: print(f"Adding movies to database '{args.database}'.") else: print("Adding movies to the default database.") if non_default_database: database.connect_to_database(args.database) else: database.connect_to_database() try: impexp.import_movies(args.import_csv) except impexp.MoviedbInvalidImportData as exc: print(exc)
def test_row_length_validation(path): """Test validation of correct number of fields in data row.""" expected = ("title,year\n" "Row has too many or too few items.\n" "Hamlet,1996,Branagh,242,this always will be,garbage,\n") bad_field_fn = path / 'bad_field.csv' bad_field_fn.write(BAD_FIELD) reject_fn = path / 'bad_field_reject.csv' with pytest.raises(impexp.MoviedbInvalidImportData): impexp.import_movies(bad_field_fn) assert reject_fn.read() == expected
def test_add_movie_called(path, monkeypatch): """Test database.add_movie called.""" expected = [dict(title='Hamlet', year='1996', minutes='242', notes=''), dict(title='Revanche', year='2008', minutes='122', notes='Oscar nominated')] calls = [] def mock_add_movie(movie: dict): """Accumulate the arguments of each call in an external list. """ calls.append(movie) monkeypatch.setattr(impexp.database, 'add_movie', mock_add_movie, raising=True) good_data_fn = path / 'good_data.csv' good_data_fn.write(GOOD_DATA) impexp.import_movies(good_data_fn) assert calls == expected
def import_movies(): """Open a csv file and load the contents into the database.""" csv_fn = guiwidgets_2.gui_askopenfilename(parent=config.app.tk_root, filetypes=(('Movie import files', '*.csv'), )) # Exit if the user clicked askopenfilename's cancel button if csv_fn == '': return try: impexp.import_movies(csv_fn) except impexp.MoviedbInvalidImportData as exc: guiwidgets.gui_messagebox( config.app.tk_root, message='Errors were found in the input file.', detail=exc.args[0], icon='warning')
def test_invalid_row_values(path, monkeypatch): """Test database integrity violation causes record rejection.""" error_msg = 'Hid behind tapestry.' expected = ('title,year,notes\n' f'ValueError: {error_msg}\n' 'Hamlet,1996,1\n') # noinspection PyUnusedLocal def mock_add_movie(movie: dict): """Force add_movie call to raise ValueError.""" raise ValueError(error_msg) monkeypatch.setattr(impexp.database, 'add_movie', mock_add_movie, raising=True) violation_data_fn = path / 'violation_data.csv' violation_data_fn.write(BAD_ROW_DATA) reject_fn = path / 'violation_data_reject.csv' with pytest.raises(impexp.MoviedbInvalidImportData): impexp.import_movies(violation_data_fn) assert reject_fn.read() == expected
def test_column_heading_validation(path, monkeypatch): """Test validation of invalid field.""" expected = ('title,year,garbage\n' '"TypeError: The header row is bad.\n' 'It is missing a required column, has an invalid column, ' 'or has a blank column.\n' 'Note that only the first error is reported.\n' 'test error message"\n""\n') # noinspection PyUnusedLocal def mock_add_movie(movie: dict): """Test dummy: Raise error""" raise TypeError("test error message") monkeypatch.setattr(impexp.database, 'add_movie', mock_add_movie, raising=True) bad_column_fn = path / 'bad_column.csv' bad_column_fn.write(BAD_COLUMN) with pytest.raises(impexp.MoviedbInvalidImportData): impexp.import_movies(bad_column_fn) reject_fn = path / 'bad_column_reject.csv' assert reject_fn.read() == expected
def test_create_reject_file(path, monkeypatch): error_msg = 'Unsuccessful bank robbery' expected = ("title,year,minutes,notes\n" f"ValueError: {error_msg}\n" "Hamlet,1996,242,\n" f"ValueError: {error_msg}\n" "Revanche,2008,122,Oscar nominated\n") # noinspection PyUnusedLocal def mock_add_movie(movie: dict): """Force add_movie call to raise ValueError.""" raise ValueError(error_msg) monkeypatch.setattr(impexp.database, 'add_movie', mock_add_movie, raising=True) data_fn = path / 'data.csv' data_fn.write(GOOD_DATA) reject_fn = path / 'data_reject.csv' with pytest.raises(impexp.MoviedbInvalidImportData): impexp.import_movies(data_fn) assert reject_fn.read() == expected
def test_database_integrity_violation(path, monkeypatch): """Test database integrity violation causes record rejection.""" expected_left = ('title,year,notes\n"(builtins.int) 3\n[SQL: 1]\n[parameters: 2]\n' '(Background on this error at: ') expected_right = 'Hamlet,1996,2\n' calls = [] def mock_add_movie(movie: dict): """Accumulate the arguments of each call in an external list. """ calls.append(movie) if len(calls) > 1: raise impexp.database.sqlalchemy.exc.IntegrityError(1, 2, 3) monkeypatch.setattr(impexp.database, 'add_movie', mock_add_movie, raising=True) violation_data_fn = path / 'violation_data.csv' violation_data_fn.write(VIOLATION_DATA) reject_fn = path / 'violation_data_reject.csv' with pytest.raises(impexp.MoviedbInvalidImportData): impexp.import_movies(violation_data_fn) assert reject_fn.read()[:90] == expected_left assert reject_fn.read()[-14:] == expected_right