def setUp(self): alchemist = AlchemyHandler() alchemist.username = "******" alchemist.password = "******" alchemist.database = "test_db" alchemist.connect() alchemist.build_graph() self.alchemist = alchemist self.db_filter = Filter(alchemist=self.alchemist) phageid = self.alchemist.get_column("phage.PhageID") self.phageid = phageid
def main(unparsed_args_list): """Uses parsed args to run the entirety of the file export pipeline. :param unparsed_args_list: Input a list of command line args. :type unparsed_args_list: list[str] """ #Returns after printing appropriate error message from parsing/connecting. args = parse_export(unparsed_args_list) alchemist = AlchemyHandler(database=args.database) alchemist.connect(ask_database=True, pipeline=True) alchemist.build_graph() # Exporting as a SQL file is not constricted by schema version. if args.pipeline != "sql": mysqldb.check_schema_compatibility(alchemist.engine, "export") values = [] if args.pipeline in FILTERABLE_PIPELINES: values = parse_value_input(args.input) if not args.pipeline in PIPELINES: print("ABORTED EXPORT: Unknown pipeline option discrepency.\n" "Pipeline parsed from command line args is not supported") sys.exit(1) if args.pipeline != "I": execute_export(alchemist, args.folder_path, args.folder_name, args.pipeline, table=args.table, values=values, filters=args.filters, groups=args.groups, sort=args.sort, include_columns=args.include_columns, exclude_columns=args.exclude_columns, sequence_columns=args.sequence_columns, raw_bytes=args.raw_bytes, concatenate=args.concatenate, verbose=args.verbose) else: pass
class TestAlchemyHandler(unittest.TestCase): def setUp(self): self.alchemist = AlchemyHandler() def test_constructor_1(self): self.assertEqual(self.alchemist._database, None) self.assertEqual(self.alchemist._username, None) self.assertEqual(self.alchemist._password, None) def test_constructor_2(self): self.assertEqual(self.alchemist._engine, None) self.assertEqual(self.alchemist.metadata, None) self.assertEqual(self.alchemist.graph, None) self.assertEqual(self.alchemist.session, None) def test_constructor_3(self): self.assertFalse(self.alchemist.connected) self.assertFalse(self.alchemist.has_database) self.assertFalse(self.alchemist.has_credentials) def test_database_1(self): self.alchemist.database = "Test" self.assertTrue(self.alchemist.has_database) self.assertFalse(self.alchemist.connected_database) def test_username_1(self): self.alchemist.username = "******" self.assertFalse(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) def test_username_2(self): self.alchemist.password = "******" self.alchemist.username = "******" self.assertTrue(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) def test_password_1(self): self.alchemist.password ="******" self.assertFalse(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) def test_password_2(self): self.alchemist.username = "******" self.alchemist.password = "******" self.assertTrue(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) def test_engine_1(self): self.alchemist.connected = True self.alchemist.engine = None self.assertFalse(self.alchemist.connected) def test_engine_2(self): with self.assertRaises(TypeError): self.alchemist.engine = "Test" @patch("pdm_utils.classes.alchemyhandler.input") def test_ask_database_1(self, Input): self.alchemist.ask_database() Input.assert_called() @patch("pdm_utils.classes.alchemyhandler.input") def test_ask_database_2(self, Input): self.alchemist.has_database = False self.alchemist.connected = True self.alchemist.ask_database() self.assertTrue(self.alchemist.has_database) self.assertFalse(self.alchemist.connected) @patch("pdm_utils.classes.alchemyhandler.getpass") def test_ask_credentials_1(self, GetPass): self.alchemist.ask_credentials() GetPass.assert_called() @patch("pdm_utils.classes.alchemyhandler.getpass") def test_ask_credentials_2(self, GetPass): self.alchemist.has_credentials = False self.alchemist.connected = True self.alchemist.ask_credentials() self.assertTrue(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) def test_validate_database_1(self): MockEngine = Mock() MockProxy = Mock() MockEngine.execute.return_value = MockProxy MockProxy.fetchall.return_value = [("test_db",), ("Actinobacteriophage",)] self.alchemist.database = "test_db" self.alchemist._engine = MockEngine self.alchemist.validate_database() MockEngine.execute.assert_called_with("SHOW DATABASES") MockProxy.fetchall.assert_called() def test_validate_database_2(self): with self.assertRaises(IndexError): self.alchemist.validate_database() def test_validate_database_3(self): MockEngine = Mock() MockProxy = Mock() MockEngine.execute.return_value = MockProxy MockProxy.fetchall.return_value = [] self.alchemist.database = "test db" self.alchemist._engine = MockEngine with self.assertRaises(ValueError): self.alchemist.validate_database() MockEngine.execute.assert_called_with("SHOW DATABASES") MockProxy.fetchall.assert_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_1(self, CreateEngine, AskCredentials): self.alchemist.engine = None self.alchemist.connected = True self.alchemist.build_engine() CreateEngine.assert_not_called() AskCredentials.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_2(self, CreateEngine, AskCredentials): self.alchemist.username = "******" self.alchemist.password = "******" self.alchemist.has_credentials = False self.alchemist.build_engine() AskCredentials.assert_called() login_string = "mysql+pymysql://user:pass@localhost/" CreateEngine.assert_called_with(login_string) @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.validate_database") @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_3(self, CreateEngine, ValidateDatabase): self.alchemist.username = "******" self.alchemist.password = "******" self.alchemist.database = "database" self.alchemist.build_engine() login_string = "mysql+pymysql://user:pass@localhost/" db_login_string = "mysql+pymysql://user:pass@localhost/database" CreateEngine.assert_any_call(login_string) CreateEngine.assert_any_call(db_login_string) @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_4(self, CreateEngine, AskCredentials): self.alchemist.has_credentials = True self.alchemist.connected = False self.alchemist.metadata = "Test" self.alchemist.graph = "Test" self.alchemist.build_engine() self.alchemist.connected = True self.assertEqual(self.alchemist.metadata, None) self.assertEqual(self.alchemist.graph, None) @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_connect_1(self, BuildEngine, AskDatabase, AskCredentials): self.alchemist.has_credentials = True self.alchemist.connect() BuildEngine.assert_called() AskDatabase.assert_not_called() AskCredentials.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_connect_2(self, BuildEngine, AskDatabase, AskCredentials): self.alchemist.connect(ask_database=True) BuildEngine.assert_called() AskDatabase.assert_called() AskCredentials.assert_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_connect_3(self, BuildEngine, AskDatabase, AskCredentials): self.alchemist.connected = False BuildEngine.side_effect = OperationalError("", "", "") with self.assertRaises(ValueError): self.alchemist.connect() BuildEngine.assert_called() AskDatabase.assert_not_called() AskCredentials.assert_called() def mock_build_engine(self, mock_engine): self.alchemist._engine = mock_engine @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_execute_1(self, BuildEngine): MockEngine = Mock() MockProxy = Mock() MockEngine.execute.return_value = MockProxy MockProxy.fetchall.return_value = [] self.alchemist._engine = MockEngine self.alchemist.execute("Executable") MockEngine.execute.assert_called_with("Executable") MockProxy.fetchall.assert_called() BuildEngine.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_scalar_1(self, BuildEngine): MockEngine = Mock() MockProxy = Mock() MockEngine.execute.return_value = MockProxy MockProxy.scalar.return_value = "Scalar" self.alchemist._engine = MockEngine self.alchemist.scalar("Executable") MockEngine.execute.assert_called_with("Executable") MockProxy.scalar.assert_called() BuildEngine.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.MetaData") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") def test_build_metadata_1(self, AskDatabase, BuildEngine, MetaData): self.alchemist.has_database = False self.alchemist.connected = False self.alchemist.build_metadata() AskDatabase.assert_called() BuildEngine.assert_called() MetaData.assert_called() @patch("pdm_utils.classes.alchemyhandler.MetaData") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") def test_build_metadata_2(self, AskDatabase, BuildEngine, MetaData): self.alchemist.has_database = True self.alchemist.connected = True self.alchemist.build_metadata() AskDatabase.assert_not_called() BuildEngine.assert_not_called() MetaData.assert_called() @patch("pdm_utils.classes.alchemyhandler.parsing.translate_table") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_translate_table_1(self, BuildMetadata, TranslateTable): self.alchemist.metadata = "Metadata" self.alchemist.translate_table("Test") TranslateTable.assert_called_with("Metadata", "Test") BuildMetadata.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.parsing.translate_table") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_translate_table_2(self, BuildMetadata, TranslateTable): self.alchemist.metadata = None self.alchemist.translate_table("Test") TranslateTable.assert_called_with(None, "Test") BuildMetadata.assert_called() @patch("pdm_utils.classes.alchemyhandler.parsing.translate_column") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_translate_column_1(self, BuildMetadata, TranslateColumn): self.alchemist.metadata = "Metadata" self.alchemist.translate_column("Test") TranslateColumn.assert_called_with("Metadata", "Test") BuildMetadata.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.parsing.translate_column") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_translate_column_2(self, BuildMetadata, TranslateColumn): self.alchemist.metadata = None self.alchemist.translate_column("Test") TranslateColumn.assert_called_with(None, "Test") BuildMetadata.assert_called() @patch("pdm_utils.classes.alchemyhandler.querying.get_table") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_get_table_1(self, BuildMetadata, GetTable): self.alchemist.metadata = "Metadata" self.alchemist.get_table("Test") GetTable.assert_called_with("Metadata", "Test") BuildMetadata.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.querying.get_table") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_get_table_2(self, BuildMetadata, GetTable): self.alchemist.metadata = None self.alchemist.get_table("Test") GetTable.assert_called_with(None, "Test") BuildMetadata.assert_called() @patch("pdm_utils.classes.alchemyhandler.querying.get_column") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_get_column_1(self, BuildMetadata, GetColumn): self.alchemist.metadata = "Metadata" self.alchemist.get_column("Test") GetColumn.assert_called_with("Metadata", "Test") BuildMetadata.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.querying.get_column") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_get_column_2(self, BuildMetadata, GetColumn): self.alchemist.metadata = None self.alchemist.get_column("Test") GetColumn.assert_called_with(None, "Test") BuildMetadata.assert_called() @patch("pdm_utils.classes.alchemyhandler.querying.build_graph") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_build_graph_1(self, BuildMetadata, BuildGraph): BuildGraph.return_value = "Graph" self.alchemist.metadata = "Metadata" self.alchemist.build_graph() BuildMetadata.assert_not_called() BuildGraph.assert_called_with("Metadata") self.assertEqual(self.alchemist.graph, "Graph") @patch("pdm_utils.classes.alchemyhandler.querying.build_graph") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_build_graph_2(self, BuildMetadata, BuildGraph): BuildGraph.return_value = "Graph" self.alchemist.metadata = None self.alchemist.build_graph() BuildMetadata.assert_called() BuildGraph.assert_called_with(None) self.assertEqual(self.alchemist.graph, "Graph") @patch("pdm_utils.classes.alchemyhandler.cartography.get_map") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_get_map_1(self, BuildMetadata, GetMap): self.alchemist.metadata = "Metadata" self.alchemist.get_map("Test") BuildMetadata.assert_not_called() GetMap.assert_called_with("Metadata", "Test") @patch("pdm_utils.classes.alchemyhandler.cartography.get_map") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_get_map_2(self, BuildMetadata, GetMap): self.alchemist.metadata = None self.alchemist.get_map("Test") BuildMetadata.assert_called() GetMap.assert_called_with(None, "Test")
class TestAlchemyHandler(unittest.TestCase): def setUp(self): self.alchemist = AlchemyHandler() def test_constructor_1(self): """Verify AlchemyHandler credentials are initialized as None. """ self.assertEqual(self.alchemist._database, None) self.assertEqual(self.alchemist._username, None) self.assertEqual(self.alchemist._password, None) def test_constructor_2(self): """Verify AlchemyHandler data objects are initialized as None. """ self.assertEqual(self.alchemist._engine, None) self.assertEqual(self.alchemist._metadata, None) self.assertEqual(self.alchemist._graph, None) self.assertEqual(self.alchemist._session, None) def test_constructor_3(self): """Verify AlchemyHandler data booleans are initialized as False. """ self.assertFalse(self.alchemist.connected) self.assertFalse(self.alchemist.has_database) self.assertFalse(self.alchemist.has_credentials) def test_database_1(self): """Verify database property sets has_database. """ self.alchemist.database = "Test" self.assertTrue(self.alchemist.has_database) self.assertFalse(self.alchemist.connected_database) def test_username_1(self): """Verify username property conserves has_credentials and connected. """ self.alchemist.username = "******" self.assertFalse(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) def test_username_2(self): """Verify username property sets has_credentials with valid password. """ self.alchemist.password = "******" self.alchemist.username = "******" self.assertTrue(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.clear") def test_username_3(self, clear_mock): """Verify changing usrename property calls clear(). """ self.alchemist.username = "******" clear_mock.assert_called() def test_password_1(self): """Verify password property conserves has_credentials and connected. """ self.alchemist.password = "******" self.assertFalse(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) def test_password_2(self): """Verify password property sets has_credentials with valid username. """ self.alchemist.username = "******" self.alchemist.password = "******" self.assertTrue(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.clear") def test_password_3(self, clear_mock): """Verify changing password property calls clear(). """ self.alchemist.password = "******" clear_mock.assert_called() def test_construct_engine_string_1(self): """Verify construct_engine_string generates an expected URI. """ URI = self.alchemist.construct_engine_string(username="******", password="******") self.assertEqual(URI, "mysql+pymysql://pdm_user:pdm_pass@localhost/") def test_construct_engine_string_2(self): """Verify construct_engine_string accepts use of different drivers. """ URI = self.alchemist.construct_engine_string(driver="mysqlconnector", username="******", password="******") self.assertEqual(URI, "mysql+mysqlconnector://pdm_user:pdm_pass@localhost/") def test_engine_1(self): """Verify engine property sets connected. """ self.alchemist.connected = True self.alchemist.engine = None self.assertFalse(self.alchemist.connected) def test_engine_2(self): """Verify engine property raises TypeError on bad engine input. """ with self.assertRaises(TypeError): self.alchemist.engine = "Test" @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_engine_3(self, build_engine_mock): """Verify engine property calls build_engine() selectively. """ mock_engine = Mock() build_engine_mock.return_value = mock_engine self.alchemist._engine = "Test" self.assertEqual(self.alchemist.engine, "Test") build_engine_mock.assert_not_called() self.alchemist._engine = None self.alchemist.engine build_engine_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler" ".extract_engine_credentials") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.get_mysql_dbs") def test_engine_4(self, get_mysql_dbs_mock, extract_engine_credentials_mock): """Verify call structure of engine property setter. """ mock_engine = Mock(spec=Engine) self.alchemist.engine = mock_engine get_mysql_dbs_mock.assert_called() extract_engine_credentials_mock.assert_called_with(mock_engine) @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_metadata_1(self, build_metadata_mock): """Verify metadata property calls build_metadata() selectively. """ self.alchemist._metadata = "Test" self.alchemist.metadata build_metadata_mock.assert_not_called() self.alchemist._metadata = None self.alchemist.metadata build_metadata_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_graph") def test_graph_1(self, build_graph_mock): """Verify graph property calls build_graph() selectively. """ self.alchemist._graph = "Test" self.alchemist.graph build_graph_mock.assert_not_called() self.alchemist._graph = None self.alchemist.graph build_graph_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_session") def test_session_1(self, build_session_mock): """Verify session property calls build_session() selectively. """ self.alchemist._session = "Test" self.alchemist.session build_session_mock.assert_not_called() self.alchemist._session = None self.alchemist.session build_session_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_mapper") def test_mapper_1(self, build_mapper_mock): """Verify mapper property calls build_mapper() selectively. """ self.alchemist._mapper = "Test" self.alchemist.mapper build_mapper_mock.assert_not_called() self.alchemist._mapper = None self.alchemist.mapper build_mapper_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.input") def test_ask_database_1(self, Input): """Verify ask_database() calls input(). """ self.alchemist.ask_database() Input.assert_called() @patch("pdm_utils.classes.alchemyhandler.input") def test_ask_database_2(self, Input): """Verify ask_database() sets has_database. """ self.alchemist.has_database = False self.alchemist.connected = True self.alchemist.ask_database() self.assertTrue(self.alchemist.has_database) self.assertFalse(self.alchemist.connected) @patch("pdm_utils.classes.alchemyhandler.getpass") def test_ask_credentials_1(self, GetPass): """Verify ask_credentials() calls getpass(). """ self.alchemist.ask_credentials() GetPass.assert_called() @patch("pdm_utils.classes.alchemyhandler.getpass") def test_ask_credentials_2(self, GetPass): """Verify ask_credentials() sets has_credentials. """ self.alchemist.has_credentials = False self.alchemist.connected = True self.alchemist.ask_credentials() self.assertTrue(self.alchemist.has_credentials) self.assertFalse(self.alchemist.connected) def test_validate_database_1(self): """Verify function structure of validate_database(). """ mock_engine = Mock() mock_proxy = Mock() mock_engine.execute.return_value = mock_proxy mock_proxy.fetchall.return_value = [("pdm_test_db",), ("Actinobacteriophage",)] self.alchemist.connected = True self.alchemist.database = "pdm_test_db" self.alchemist._engine = mock_engine self.alchemist.validate_database() mock_engine.execute.assert_called_once() mock_proxy.fetchall.assert_called() def test_validate_database_2(self): """Verify validate_database() raises IndexError without database. """ self.alchemist.connected = True with self.assertRaises(AttributeError): self.alchemist.validate_database() def test_validate_database_3(self): """Verify validate_database() raises ValueError from bad database input. """ mock_engine = Mock() mock_proxy = Mock() mock_engine.execute.return_value = mock_proxy mock_proxy.fetchall.return_value = [] self.alchemist.connected = True self.alchemist.database = "test db" self.alchemist._engine = mock_engine with self.assertRaises(MySQLDatabaseError): self.alchemist.validate_database() mock_engine.execute.assert_called_once() mock_proxy.fetchall.assert_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_1(self, create_engine_mock, ask_credentials_mock): """Verify build_engine() returns if connected already. """ self.alchemist.engine = None self.alchemist.connected = True self.alchemist.build_engine() create_engine_mock.assert_not_called() ask_credentials_mock.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_2(self, create_engine_mock, ask_credentials_mock): """Verify build_engine() raises attribute error without credentials. """ self.alchemist.username = "******" self.alchemist.password = "******" self.alchemist.has_credentials = False with self.assertRaises(AttributeError): self.alchemist.build_engine() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.validate_database") @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_3(self, create_engine_mock, validate_database_mock): """Verify build_engine() calls create_engine() with db engine string. """ self.alchemist.username = "******" self.alchemist.password = "******" self.alchemist.database = "database" self.alchemist.build_engine() login_string = "mysql+pymysql://user:pass@localhost/" db_login_string = "mysql+pymysql://user:pass@localhost/database" create_engine_mock.assert_any_call(login_string, echo=False) create_engine_mock.assert_any_call(db_login_string, echo=False) @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_4(self, create_engine_mock, ask_credentials_mock): """Verify build_engine() sets has_credentials. """ self.alchemist.has_credentials = True self.alchemist.connected = False self.alchemist._metadata = "Test" self.alchemist._graph = "Test" self.alchemist.build_engine() self.alchemist.connected = True self.assertEqual(self.alchemist._metadata, None) self.assertEqual(self.alchemist._graph, None) @patch("pdm_utils.classes.alchemyhandler.sqlalchemy.create_engine") def test_build_engine_5(self, create_engine_mock): """Verify AlchemyHandler echo property controls create_engine() parameters. """ self.alchemist.username = "******" self.alchemist.password = "******" self.alchemist.build_engine() login_string = "mysql+pymysql://user:pass@localhost/" create_engine_mock.assert_any_call(login_string, echo=False) self.alchemist.echo = True self.alchemist.connected = False self.alchemist.build_engine() create_engine_mock.assert_any_call(login_string, echo=True) @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_connect_1(self, build_engine_mock, ask_database_mock, AskCredentials): """Verify connect() returns if build_engine() does not complain. """ self.alchemist.has_credentials = True self.alchemist.connected = True self.alchemist.connect() build_engine_mock.assert_called() ask_database_mock.assert_not_called() AskCredentials.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_connect_2(self, build_engine_mock, ask_database_mock, AskCredentials): """Verify connect() AlchemyHandler properties control function calls. """ self.alchemist.connected = True self.alchemist.connected_database = True self.alchemist.has_credentials = True self.alchemist.connect(ask_database=True) build_engine_mock.assert_called() ask_database_mock.assert_not_called() AskCredentials.assert_not_called() @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler." "ask_credentials") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") def test_connect_3(self, build_engine_mock, ask_database_mock, AskCredentials): """Verify connect() depends on build_engine() to raise ValueError. """ self.alchemist.connected = False build_engine_mock.side_effect = OperationalError("", "", "") with self.assertRaises(SQLCredentialsError): self.alchemist.connect() build_engine_mock.assert_called() ask_database_mock.assert_not_called() AskCredentials.assert_called() def build_engine_side_effect(self, mock_engine): """Helper function for side effect usage. """ self.alchemist._engine = mock_engine @patch("pdm_utils.classes.alchemyhandler.MetaData") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") def test_build_metadata_1(self, ask_database_mock, build_engine_mock, metadata_mock): """Verify build_metadata() relies on AlchemyHandler properties. """ self.alchemist.has_database = False self.alchemist.connected = False self.alchemist.build_metadata() ask_database_mock.assert_called() build_engine_mock.assert_called() metadata_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.MetaData") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") def test_build_metadata_2(self, ask_database_mock, build_engine_mock, metadata_mock): """Verify build_metadata() calls ask_database() and build_engine(). """ self.alchemist.has_database = True self.alchemist.connected = True self.alchemist.connected_database = True self.alchemist.build_metadata() ask_database_mock.assert_not_called() build_engine_mock.assert_not_called() metadata_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.querying.build_graph") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_build_graph_1(self, build_metadata_mock, build_graph_mock): """Verify build_graph() calls querying.build_graph(). """ build_graph_mock.return_value = "Graph" self.alchemist._metadata = "Metadata" self.alchemist.build_graph() build_metadata_mock.assert_not_called() build_graph_mock.assert_called_with("Metadata") self.assertEqual(self.alchemist._graph, "Graph") @patch("pdm_utils.classes.alchemyhandler.querying.build_graph") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_build_graph_2(self, build_metadata_mock, build_graph_mock): """Verify build_graph() calls build_metadata(). """ build_graph_mock.return_value = "Graph" self.alchemist._metadata = None self.alchemist.build_graph() build_metadata_mock.assert_called() build_graph_mock.assert_called_with(None) self.assertEqual(self.alchemist._graph, "Graph") @patch("pdm_utils.classes.alchemyhandler.sessionmaker") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") def test_build_session_1(self, ask_database_mock, build_engine_mock, sessionmaker_mock): """Verify build_session() relies on AlchemyHandler properties. """ self.alchemist.has_database = False self.alchemist.connected = False self.alchemist.build_session() ask_database_mock.assert_called() build_engine_mock.assert_called() sessionmaker_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.sessionmaker") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_engine") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.ask_database") def test_build_session_2(self, ask_database_mock, build_engine_mock, sessionmaker_mock): """Verify build_session() calls ask_database() and build_engine(). """ self.alchemist.has_database = True self.alchemist.connected = True self.alchemist.build_session() ask_database_mock.assert_not_called() build_engine_mock.assert_not_called() sessionmaker_mock.assert_called() @patch("pdm_utils.classes.alchemyhandler.automap_base") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_build_mapper_1(self, build_metadata_mock, automap_base_mock): """Verify build_mapper() calls automap_base(). """ base_mock = Mock() automap_base_mock.return_value = base_mock self.alchemist._metadata = "Metadata" self.alchemist.build_mapper() build_metadata_mock.assert_not_called() automap_base_mock.assert_called_with(metadata="Metadata") self.assertEqual(self.alchemist._mapper, base_mock) @patch("pdm_utils.classes.alchemyhandler.automap_base") @patch("pdm_utils.classes.alchemyhandler.AlchemyHandler.build_metadata") def test_build_mapper_2(self, build_metadata_mock, automap_base_mock): """Verify build_mapper() calls build_metadata(). """ base_mock = Mock() automap_base_mock.return_value = base_mock self.alchemist._metadata = None self.alchemist.build_mapper() build_metadata_mock.assert_called() automap_base_mock.assert_called_with(metadata=None) self.assertEqual(self.alchemist._mapper, base_mock)
class TestFileExport(unittest.TestCase): @classmethod def setUpClass(self): test_db_utils.create_filled_test_db() self.test_dir = Path(TEST_DIR) if self.test_dir.is_dir(): shutil.rmtree(TEST_DIR) self.test_dir.mkdir() @classmethod def tearDownClass(self): test_db_utils.remove_db() shutil.rmtree(TEST_DIR) def setUp(self): self.alchemist = AlchemyHandler() self.alchemist.username=USER self.alchemist.password=PWD self.alchemist.database=DB self.alchemist.connect(ask_database=True, login_attempts=0) self.alchemist.build_graph() self.db_filter = Filter(alchemist=self.alchemist) self.export_test_dir = self.test_dir.joinpath("export_test_dir") def tearDown(self): if self.export_test_dir.is_dir(): shutil.rmtree(str(self.export_test_dir)) def test_execute_export_1(self): """Verify execute_export() creates new directory as expected. """ for pipeline in export_db.PIPELINES: with self.subTest(pipeline=pipeline): export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, pipeline) self.assertTrue(self.export_test_dir.is_dir()) shutil.rmtree(str(self.export_test_dir)) def test_execute_export_2(self): """Verify execute_export() 'sql' pipeline functions as expected. """ export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "sql") self.assertTrue(self.export_test_dir.is_dir()) sql_file_path = self.export_test_dir.joinpath( f"{self.alchemist.database}.sql") self.assertTrue(sql_file_path.is_file()) def test_execute_export_3(self): """Verify execute_export() 'csv' pipeline functions as expected. """ for table in export_db.TABLES: with self.subTest(table=table): export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "csv", table=table) self.assertTrue(self.export_test_dir.is_dir()) csv_file_path = self.export_test_dir.joinpath( f"{table}.csv") self.assertTrue(csv_file_path.is_file()) shutil.rmtree(str(self.export_test_dir)) def test_execute_export_4(self): """Verify execute_export() SeqRecord pipelines function as expected. """ for file_type in export_db.BIOPYTHON_PIPELINES: with self.subTest(file_type=file_type): export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, file_type) self.assertTrue(self.export_test_dir.is_dir()) flat_file_path = self.export_test_dir.joinpath( f"Trixie.{file_type}") self.assertTrue(flat_file_path.is_file()) shutil.rmtree(str(self.export_test_dir)) def test_execute_export_5(self): """Verify execute_export() filter parameter functions as expected. """ filters = "phage.PhageID!=Trixie AND phage.Cluster=A" export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "fasta", filters=filters) D29_file_path = self.export_test_dir.joinpath("D29.fasta") Trixie_file_path = self.export_test_dir.joinpath("Trixie.fasta") self.assertTrue(D29_file_path.is_file()) self.assertFalse(Trixie_file_path.is_file()) def test_execute_export_6(self): """Verify execute_export() group parameter functions as expected. """ groups = ["phage.Cluster", "phage.Subcluster"] export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "fasta", groups=groups) A_path = self.export_test_dir.joinpath("A") C_path = self.export_test_dir.joinpath("C") A2_path = A_path.joinpath("A2") C1_path = C_path.joinpath("C1") C2_path = C_path.joinpath("C2") Trixie_path = A2_path.joinpath("Trixie.fasta") D29_path = A2_path.joinpath("D29.fasta") Alice_path = C1_path.joinpath("Alice.fasta") Myrna_path = C2_path.joinpath("Myrna.fasta") self.assertTrue(A_path.is_dir()) self.assertTrue(C_path.is_dir()) self.assertTrue(A2_path.is_dir()) self.assertTrue(C1_path.is_dir()) self.assertTrue(C2_path.is_dir()) self.assertTrue(Trixie_path.is_file()) self.assertTrue(D29_path.is_file()) self.assertTrue(Alice_path.is_file()) self.assertTrue(Myrna_path.is_file()) def test_execute_export_7(self): """Verify execute_export() sort parameter is functional. """ sort_columns = ["phage.Subcluster"] export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "csv", sort=sort_columns) def test_execute_export_8(self): """Verify execute_export() concatenate parameter functions as expected. """ export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "fasta", concatenate=True) fasta_path = self.export_test_dir.joinpath( f"{self.export_test_dir.name}.fasta") self.assertTrue(fasta_path.is_file()) def test_execute_export_9(self): """Verify execute_export() include_columns functions as expected. """ include_columns = ["phage.Cluster"] export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "csv", table="gene", include_columns=include_columns) csv_path = self.export_test_dir.joinpath( f"gene.csv") with open(csv_path) as csv_handle: reader = csv.reader(csv_handle) headers = next(reader) self.assertTrue("Cluster" in headers) self.assertEqual("GeneID", headers[0]) self.assertFalse("Translation" in headers) def test_execute_export_10(self): """Verify execute_export() exclude_columns functions as expected. """ exclude_columns = ["phage.Subcluster"] export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "csv", exclude_columns=exclude_columns) csv_path = self.export_test_dir.joinpath( f"phage.csv") with open(csv_path) as csv_handle: reader = csv.reader(csv_handle) headers = next(reader) self.assertTrue("Cluster" in headers) self.assertEqual("PhageID", headers[0]) self.assertFalse("Subcluster" in headers) self.assertFalse("Sequence" in headers) def test_execute_export_11(self): """Verify execute_export() sequence_columns functions as expected. """ export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, "csv", sequence_columns=True) csv_path = self.export_test_dir.joinpath( f"phage.csv") with open(csv_path) as csv_handle: reader = csv.reader(csv_handle) headers = next(reader) self.assertTrue("Cluster" in headers) self.assertEqual("PhageID", headers[0]) self.assertTrue("Sequence" in headers) def test_execute_export_12(self): """Verify execute_export() SeqRecord pipeline functions as expected. """ for file_type in export_db.BIOPYTHON_PIPELINES: with self.subTest(file_type=file_type): export_db.execute_export(self.alchemist, self.test_dir, self.export_test_dir.name, file_type, table="gene") self.assertTrue(self.export_test_dir.is_dir()) flat_file_path = self.export_test_dir.joinpath( f"Trixie_CDS_70.{file_type}") self.assertTrue(flat_file_path.is_file()) shutil.rmtree(str(self.export_test_dir))
class TestFileIO(unittest.TestCase): @classmethod def setUpClass(self): base_dir = Path(TMPDIR_BASE) self.test_dir = base_dir.joinpath(TMPDIR_PREFIX) test_db_utils.create_filled_test_db() if self.test_dir.is_dir(): shutil.rmtree(self.test_dir) self.test_dir.mkdir() self.test_import_table_1 = Path(test_file_dir, "test_import_table_1.csv") self.tkt_dict1 = {"phage_id": "L5", "host_genus": "Mycobacterium"} self.tkt_dict2 = {"phage_id": "Trixie", "host_genus": "Mycobacterium"} self.test_fasta_file_1 = Path(test_file_dir, "test_fasta_file_1.fasta") self.test_fasta_file_2 = Path(test_file_dir, "test_fasta_file_2.fasta") self.test_fa_1_gs_to_ts = {} self.test_fa_2_gs_to_ts = {} with self.test_fasta_file_1.open(mode="r") as filehandle: for record in SeqIO.parse(filehandle, "fasta"): self.test_fa_1_gs_to_ts[record.id] = str(record.seq) self.test_fa_2_gs_to_ts[record.id] = str(record.seq) self.test_fa_1_ts_to_gs = {} for seq_id, trans in self.test_fa_1_gs_to_ts.items(): seq_ids = self.test_fa_1_ts_to_gs.get(trans, []) seq_ids.append(seq_id) self.test_fa_1_ts_to_gs[trans] = seq_ids self.test_fa_2_ts_to_gs = {} for seq_id, trans in self.test_fa_2_gs_to_ts.items(): seq_ids = self.test_fa_2_ts_to_gs.get(trans, []) seq_ids.append(seq_id) self.test_fa_2_ts_to_gs[trans] = seq_ids self.fasta_dict_1 = { "Trixie_CDS_11": ("MASIQGKLIALVLKYGISYLRKHPELLKEI" "SKHIPGKVDDLVLEVLAKLLGV") } self.fasta_dict_2 = { "TRIXIE_CDS_3": ("MSGFDDKIVDQAQAIVPADDYDALPLAGPGR" "WAHVPGGLTLYTNDDTVLFAQGDMSTIESSY" "LFQAMEKLRLAGKTASQAFDILRLEADAISG" "DLSELAEE"), "L5_CDS_3": ("MAQMQATHTIEGFLAVEVAPRAFVAENGHVL" "TRLSATKWGGGEGLEILNYEGPGTVEVSDEK" "LAEAQRASEVEAELRREVGKE") } @classmethod def tearDownClass(self): test_db_utils.remove_db() shutil.rmtree(self.test_dir) def setUp(self): self.alchemist = AlchemyHandler() self.alchemist.username = USER self.alchemist.password = PWD self.alchemist.database = DB self.alchemist.connect(ask_database=True, login_attempts=0) self.alchemist.build_graph() self.fileio_test_dir = self.test_dir.joinpath("fileio_test_dir") self.fileio_test_dir.mkdir() self.data_dict_file = self.fileio_test_dir.joinpath("table.csv") self.fasta_file = self.fileio_test_dir.joinpath("translations.fasta") def tearDown(self): shutil.rmtree(self.fileio_test_dir) def test_retrieve_data_dict_1(self): """Verify a correctly structured file can be opened.""" list_of_data_dicts = \ fileio.retrieve_data_dict(self.test_import_table_1) self.assertEqual(len(list_of_data_dicts), 2) def test_export_data_dict_1(self): """Verify data is exported correctly.""" list_of_data = [self.tkt_dict1, self.tkt_dict2] headers = ["type", "phage_id", "host_genus", "cluster"] fileio.export_data_dict(list_of_data, self.data_dict_file, headers, include_headers=True) exp_success_tkts = [] with open(self.data_dict_file, 'r') as file: file_reader = csv.DictReader(file) for dict in file_reader: exp_success_tkts.append(dict) with self.subTest(): self.assertEqual(len(exp_success_tkts), 2) with self.subTest(): self.assertEqual(set(exp_success_tkts[0].keys()), set(headers)) def test_write_fasta_1(self): """Verify write_fasta() creates readable fasta formatted file""" fileio.write_fasta(self.fasta_dict_1, self.fasta_file) record = SeqIO.read(self.fasta_file, "fasta") id = list(self.fasta_dict_1.keys())[0] seq = self.fasta_dict_1[id] self.assertEqual(record.id, id) self.assertEqual(str(record.seq), seq) def test_write_fasta_2(self): """Verify write_fasta() can properly concatenate fasta files""" fileio.write_fasta(self.fasta_dict_2, self.fasta_file) records = SeqIO.parse(self.fasta_file, "fasta") keys = list(self.fasta_dict_2.keys()) for record in records: self.assertTrue(record.id in keys) seq = self.fasta_dict_2[record.id] self.assertEqual(str(record.seq), seq) def test_reintroduce_fasta_duplicates_1(self): """Verify reintroduce_duplicates() copies fastas without duplicates""" fileio.write_fasta(self.test_fa_1_gs_to_ts, self.fasta_file) fileio.reintroduce_fasta_duplicates(self.test_fa_1_ts_to_gs, self.fasta_file) with self.fasta_file.open(mode="r") as filehandle: for record in SeqIO.parse(filehandle, "fasta"): with self.subTest(seq_id=record.id): translation = self.test_fa_1_gs_to_ts[record.id] self.assertTrue(translation is not None) self.assertEqual(str(record.seq), translation) def test_reintroduce_fasta_duplicates_2(self): """Verify reintroduce_duplicates() recognizes duplicate sequences""" fileio.write_fasta(self.test_fa_1_gs_to_ts, self.fasta_file) fileio.reintroduce_fasta_duplicates(self.test_fa_2_ts_to_gs, self.fasta_file) with self.fasta_file.open(mode="r") as filehandle: for record in SeqIO.parse(filehandle, "fasta"): with self.subTest(seq_id=record.id): translation = self.test_fa_2_gs_to_ts[record.id] self.assertTrue(translation is not None) self.assertEqual(str(record.seq), translation) def test_reintroduce_fasta_duplicates_3(self): """Verify reintroduce_duplicates() preserves unrecognized translations """ fileio.write_fasta(self.test_fa_2_gs_to_ts, self.fasta_file) fileio.reintroduce_fasta_duplicates(self.test_fa_1_ts_to_gs, self.fasta_file) with self.fasta_file.open(mode="r") as filehandle: for record in SeqIO.parse(filehandle, "fasta"): with self.subTest(seq_id=record.id): translation = self.test_fa_2_gs_to_ts[record.id] self.assertTrue(translation is not None) self.assertEqual(str(record.seq), translation)