Repository: exasol/integration-test-docker-environment (language: python)

Issue:
Test data not populated if  reuse_database_setup is set to true, but database not setup
## Background

If exaslct is used with ```--reuse-test-environment```, it sets the parameter reuse_database_setup=true.
This causes [PopulateEngineSmallTestDataToDatabase](https://github.com/exasol/integration-test-docker-environment/blob/0e240365cf81e112d47291aa0acdc5ac5d2105aa/exasol_integration_test_docker_environment/lib/test_environment/database_setup/populate_data.py#L26) to jump over population of test data, even if the database was setup from scratch.

## Acceptance Criteria

Test data must be populated, if database is setup from scratch, even if reuse_database_setup is set to true.


Discussion / hints:

Fix patch:
diff --git a/doc/changes/changelog.md b/doc/changes/changelog.md
index 446c89750..f2fb02745 100644
--- a/doc/changes/changelog.md
+++ b/doc/changes/changelog.md
@@ -1,5 +1,6 @@
 # Changes
 
+* [0.6.0](changes_0.6.0.md)
 * [0.5.0](changes_0.5.0.md)
 * [0.4.1](changes_0.4.1.md)
 * [0.4.0](changes_0.4.0.md)
diff --git a/doc/changes/changes_0.6.0.md b/doc/changes/changes_0.6.0.md
new file mode 100644
index 000000000..aa20d4d0b
--- /dev/null
+++ b/doc/changes/changes_0.6.0.md
@@ -0,0 +1,32 @@
+# Integration-Test-Docker-Environment 0.6.0, released t.b.d.
+
+Code name: t.b.d.
+
+## Summary
+
+t.b.d
+
+### Supported Exasol Versions
+
+* **6.2**: up to 6.2.17
+* **7.0**: up to 7.0.13
+* **7.1**: up to 7.1.1
+
+If you need further versions, please open an issue.
+
+### Tested Docker Runtimes
+
+- Docker Default Runtime
+- [NVIDIA Container Runtime](https://github.com/NVIDIA/nvidia-container-runtime) for GPU accelerated UDFs
+
+## Bug Fixes:
+
+- #120: Test data not populated if reuse_database_setup is set to true, but database not setup
+
+## Features / Enhancements:
+
+n/a
+
+## Refactoring:
+
+n/a
\ No newline at end of file


Test patch:
diff --git a/exasol_integration_test_docker_environment/cli/options/test_environment_options.py b/exasol_integration_test_docker_environment/cli/options/test_environment_options.py
index cff0aaa2a..1f13ddb30 100644
--- a/exasol_integration_test_docker_environment/cli/options/test_environment_options.py
+++ b/exasol_integration_test_docker_environment/cli/options/test_environment_options.py
@@ -10,8 +10,10 @@
 
 ]
 
+LATEST_DB_VERSION = """7.1.1"""
+
 docker_db_options = [
-    click.option('--docker-db-image-version', type=str, default="""7.1.1""",
+    click.option('--docker-db-image-version', type=str, default=LATEST_DB_VERSION,
                  show_default=True,
                  help="""Docker DB Image Version against which the tests should run."""),
     click.option('--docker-db-image-name', type=str, default="""exasol/docker-db""",
diff --git a/exasol_integration_test_docker_environment/lib/data/database_info.py b/exasol_integration_test_docker_environment/lib/data/database_info.py
index 5c202a83d..442bef957 100644
--- a/exasol_integration_test_docker_environment/lib/data/database_info.py
+++ b/exasol_integration_test_docker_environment/lib/data/database_info.py
@@ -5,8 +5,9 @@
 class DatabaseInfo(Info):
 
     def __init__(self, host: str, db_port: str, bucketfs_port: str,
-                 container_info: ContainerInfo = None):
+                 reused: bool, container_info: ContainerInfo = None):
         self.container_info = container_info
         self.bucketfs_port = bucketfs_port
         self.db_port = db_port
         self.host = host
+        self.reused = reused
diff --git a/exasol_integration_test_docker_environment/lib/test_environment/database_setup/populate_data.py b/exasol_integration_test_docker_environment/lib/test_environment/database_setup/populate_data.py
index 374ad48ad..526a7d53a 100644
--- a/exasol_integration_test_docker_environment/lib/test_environment/database_setup/populate_data.py
+++ b/exasol_integration_test_docker_environment/lib/test_environment/database_setup/populate_data.py
@@ -23,11 +23,11 @@ def __init__(self, *args, **kwargs):
         self._database_info = self.test_environment_info.database_info
 
     def run_task(self):
-        if not self.reuse_data:
-            self.populate_data()
-        else:
+        if self.reuse_data and self._database_info.reused:
             self.logger.warning("Reusing data")
             self.write_logs("Reused")
+        else:
+            self.populate_data()
 
     def populate_data(self):
         self.logger.warning("Uploading data")
diff --git a/exasol_integration_test_docker_environment/lib/test_environment/setup_external_database_host.py b/exasol_integration_test_docker_environment/lib/test_environment/setup_external_database_host.py
index dee2fa137..66c5405f3 100644
--- a/exasol_integration_test_docker_environment/lib/test_environment/setup_external_database_host.py
+++ b/exasol_integration_test_docker_environment/lib/test_environment/setup_external_database_host.py
@@ -28,9 +28,10 @@ def run_task(self):
                 self.external_exasol_db_host == "127.0.01":
             database_host = self.network_info.gateway
         self.setup_database()
-        database_info = DatabaseInfo(database_host,
-                                     self.external_exasol_db_port,
-                                     self.external_exasol_bucketfs_port)
+        database_info = DatabaseInfo(host=database_host,
+                                     db_port=self.external_exasol_db_port,
+                                     bucketfs_port=self.external_exasol_bucketfs_port,
+                                     reused=False)
         self.return_object(database_info)
 
     def setup_database(self):
diff --git a/exasol_integration_test_docker_environment/lib/test_environment/spawn_test_container.py b/exasol_integration_test_docker_environment/lib/test_environment/spawn_test_container.py
index 698fa72eb..f321ce133 100644
--- a/exasol_integration_test_docker_environment/lib/test_environment/spawn_test_container.py
+++ b/exasol_integration_test_docker_environment/lib/test_environment/spawn_test_container.py
@@ -48,10 +48,12 @@ def is_reuse_possible(self) -> bool:
                 self._client.containers.get(self.test_container_name)
         except Exception as e:
             pass
-        return self.network_info.reused and self.reuse_test_container and \
+        ret_val = self.network_info.reused and self.reuse_test_container and \
                test_container is not None and \
-               test_container.image == test_container_image_info.get_target_complete_name() and \
-               test_container_image_info.image_state == ImageState.USED_LOCAL
+               test_container_image_info.get_target_complete_name() in test_container.image.tags and \
+               test_container_image_info.image_state == ImageState.USED_LOCAL.name
+
+        return ret_val
 
     def run_task(self):
         subnet = netaddr.IPNetwork(self.network_info.subnet)
@@ -159,14 +161,16 @@ def _remove_container(self, container_name: str):
         try:
             container = self._client.containers.get(container_name)
             container.remove(force=True)
-            self.logger.info("Removed container %s", container_name)
+            self.logger.info(f"Removed container: name: '{container_name}', id: '{container.short_id}'")
         except Exception as e:
             pass
 
     def cleanup_task(self, success:bool):
+        self.logger.info(f"___________cleanup_task")
         if (success and not self.no_test_container_cleanup_after_success) or \
                 (not success and not self.no_test_container_cleanup_after_failure):
             try:
+                print(f"Cleaning up container %s", self.test_container_name)
                 self.logger.info(f"Cleaning up container %s", self.test_container_name)
                 self._remove_container(self.test_container_name)
             except Exception as e:
diff --git a/exasol_integration_test_docker_environment/lib/test_environment/spawn_test_database.py b/exasol_integration_test_docker_environment/lib/test_environment/spawn_test_database.py
index 2c99a5089..2bc41b2a7 100644
--- a/exasol_integration_test_docker_environment/lib/test_environment/spawn_test_database.py
+++ b/exasol_integration_test_docker_environment/lib/test_environment/spawn_test_database.py
@@ -62,7 +62,7 @@ def _try_to_reuse_database(self, db_ip_address: str) -> DatabaseInfo:
                          self.db_container_name)
         database_info = None
         try:
-            database_info = self._create_database_info(db_ip_address)
+            database_info = self._create_database_info(db_ip_address=db_ip_address, reused=True)
         except Exception as e:
             self.logger.warning("Tried to reuse database container %s, but got Exeception %s. "
                                 "Fallback to create new database.", self.db_container_name, e)
@@ -105,14 +105,14 @@ def _create_database_container(self, db_ip_address: str, db_private_network: str
         network_aliases = self._get_network_aliases()
         docker_network.connect(db_container, ipv4_address=db_ip_address, aliases=network_aliases)
         db_container.start()
-        database_info = self._create_database_info(db_ip_address)
+        database_info = self._create_database_info(db_ip_address=db_ip_address, reused=False)
         return database_info
 
     def _get_network_aliases(self):
         network_aliases = ["exasol_test_database", self.db_container_name]
         return network_aliases
 
-    def _create_database_info(self, db_ip_address: str) -> DatabaseInfo:
+    def _create_database_info(self, db_ip_address: str, reused: bool) -> DatabaseInfo:
         db_container = self._client.containers.get(self.db_container_name)
         if db_container.status != "running":
             raise Exception(f"Container {self.db_container_name} not running")
@@ -125,7 +125,7 @@ def _create_database_info(self, db_ip_address: str) -> DatabaseInfo:
                           volume_name=self._get_db_volume_name())
         database_info = \
             DatabaseInfo(host=db_ip_address, db_port=DB_PORT, bucketfs_port=BUCKETFS_PORT,
-                         container_info=container_info)
+                         reused=reused, container_info=container_info)
         return database_info
 
     def _pull_docker_db_images_if_necassary(self):
diff --git a/exasol_integration_test_docker_environment/test/test_test_container_reuse.py b/exasol_integration_test_docker_environment/test/test_test_container_reuse.py
index 351c589b1..7652acf4c 100644
--- a/exasol_integration_test_docker_environment/test/test_test_container_reuse.py
+++ b/exasol_integration_test_docker_environment/test/test_test_container_reuse.py
@@ -2,21 +2,19 @@
 import shutil
 import tempfile
 import unittest
-from datetime import datetime
-from multiprocessing import Process, Queue
 from pathlib import Path
-from typing import Callable
 
 import docker
 import luigi
 
+from exasol_integration_test_docker_environment.test.utils import process_spawn_utils
 from exasol_integration_test_docker_environment.cli.common import set_build_config, set_docker_repository_config
 from exasol_integration_test_docker_environment.lib.base.docker_base_task import DockerBaseTask
 from exasol_integration_test_docker_environment.lib.data.container_info import ContainerInfo
-from exasol_integration_test_docker_environment.lib.docker.images.clean.clean_images import CleanImagesStartingWith
 from exasol_integration_test_docker_environment.lib.test_environment.prepare_network_for_test_environment import \
     PrepareDockerNetworkForTestEnvironment
 from exasol_integration_test_docker_environment.lib.test_environment.spawn_test_container import SpawnTestContainer
+from exasol_integration_test_docker_environment.test.utils import luigi_utils
 
 
 class TestTask(DockerBaseTask):
@@ -53,27 +51,14 @@ def run_task(self):
 
         self.return_object({"container_id": container.image.id, "image_id": container.image.id})
 
-class TestContainerReuseTest(unittest.TestCase):
-
-    def set_job_id(self, task_cls):
-        strftime = datetime.now().strftime('%Y_%m_%d_%H_%M_%S')
-        job_id = f"{strftime}_{task_cls.__name__}"
-        config = luigi.configuration.get_config()
-        config.set('job_config', 'job_id', job_id)
-        return job_id
 
-    def clean(self):
-        jobid = self.set_job_id(CleanImagesStartingWith)
-        task = CleanImagesStartingWith(starts_with_pattern=self.docker_repository_name, jobid=jobid)
-        luigi.build([task], workers=1, local_scheduler=True, log_level="INFO")
-        if task._get_tmp_path_for_job().exists():
-            shutil.rmtree(str(task._get_tmp_path_for_job()))
+class TestContainerReuseTest(unittest.TestCase):
 
     def setUp(self):
         self.client = docker.from_env()
-        self.temp_directory = tempfile.mkdtemp()
         resource_directory = Path(Path(__file__).parent, "resources/test_test_container_reuse")
         print("resource_directory content", list(Path(resource_directory).iterdir()))
+        self.temp_directory = tempfile.mkdtemp()
         self.working_directory = shutil.copytree(resource_directory,
                                                  Path(self.temp_directory, "test_test_container_reuse"))
         print("working_directory",self.working_directory)
@@ -82,11 +67,11 @@ def setUp(self):
         print("working_directory content",list(Path(self.working_directory).iterdir()))
         self.docker_repository_name = self.__class__.__name__.lower()
         print("docker_repository_name",self.docker_repository_name)
-        self.clean()
+        luigi_utils.clean(self.docker_repository_name)
 
     def tearDown(self):
         os.chdir(self.old_working_directory)
-        self.clean()
+        luigi_utils.clean(self.docker_repository_name)
         shutil.rmtree(self.temp_directory)
         self.client.close()
 
@@ -110,7 +95,7 @@ def setup_luigi_config(self):
 
     def run1(self):
         self.setup_luigi_config()
-        self.set_job_id(SpawnTestContainer)
+        luigi_utils.set_job_id(SpawnTestContainer)
         task = TestTask(reuse=False, attempt=1)
         try:
             success = luigi.build([task], workers=1, local_scheduler=True, log_level="INFO")
@@ -126,7 +111,7 @@ def run1(self):
 
     def run2(self):
         self.setup_luigi_config()
-        self.set_job_id(SpawnTestContainer)
+        luigi_utils.set_job_id(SpawnTestContainer)
         task = TestTask(reuse=True, attempt=2)
         try:
             success = luigi.build([task], workers=1, local_scheduler=True, log_level="INFO")
@@ -139,37 +124,19 @@ def run2(self):
         finally:
             task.cleanup(False)
 
-    def process_main(self, queue: Queue, func: Callable):
-        try:
-            result = func()
-            queue.put(("result",result))
-        except Exception as e:
-            queue.put(("exception",e))
-
-    def run_in_process(self, func):
-        queue = Queue()
-        p1 = Process(target=self.process_main, args=(queue, func))
-        p1.start()
-        p1.join()
-        result = queue.get()
-        if result[0] == "result":
-            return result[1]
-        else:
-            raise result[1]
-
     def test_test_container_no_reuse_after_change(self):
-        p1 = self.run_in_process(self.run1)
+        p1 = process_spawn_utils.run_in_process(self.run1)
         dockerfile = Path(self.working_directory, "tests/Dockerfile")
         with dockerfile.open("a") as f:
             f.write("\n#Test\n")
-        p2 = self.run_in_process(self.run2)
+        p2 = process_spawn_utils.run_in_process(self.run2)
         print(p1)
         print(p2)
         assert p1 != p2
 
     def test_test_container_reuse(self):
-        p1 = self.run_in_process(self.run1)
-        p2 = self.run_in_process(self.run2)
+        p1 = process_spawn_utils.run_in_process(self.run1)
+        p2 = process_spawn_utils.run_in_process(self.run2)
         print(p1)
         print(p2)
         assert p1 == p2
diff --git a/exasol_integration_test_docker_environment/test/test_test_env_reuse.py b/exasol_integration_test_docker_environment/test/test_test_env_reuse.py
new file mode 100644
index 000000000..62e282575
--- /dev/null
+++ b/exasol_integration_test_docker_environment/test/test_test_env_reuse.py
@@ -0,0 +1,142 @@
+import os
+import unittest
+
+import docker
+import luigi
+
+from exasol_integration_test_docker_environment.lib.data.environment_type import EnvironmentType
+from exasol_integration_test_docker_environment.lib.test_environment.spawn_test_environment import SpawnTestEnvironment
+from exasol_integration_test_docker_environment.test.utils import process_spawn_utils
+from exasol_integration_test_docker_environment.cli.common import set_docker_repository_config
+from exasol_integration_test_docker_environment.test.utils import luigi_utils
+from exasol_integration_test_docker_environment.cli.options import test_environment_options
+
+
+class TestContainerReuseTest(unittest.TestCase):
+    '''
+    This test spawns a new test environment and, with parameters:
+    * reuse_database_setup=True,
+    * reuse_database=True,
+    * reuse_test_container=True
+    and verifies if the test data was populated to the docker db.
+    '''
+
+    def env_name(self):
+        return self.__class__.__name__.lower()
+
+    def setUp(self):
+        self._client = docker.from_env()
+        self._docker_repository_name = self.env_name()
+        print("docker_repository_name", self._docker_repository_name)
+        luigi_utils.clean(self._docker_repository_name)
+
+        self.docker_db_version_parameter = test_environment_options.LATEST_DB_VERSION
+        if "EXASOL_VERSION" in os.environ and os.environ["EXASOL_VERSION"] != "default":
+            self.docker_db_version_parameter = os.environ["EXASOL_VERSION"]
+
+    def tearDown(self):
+        luigi_utils.clean(self._docker_repository_name)
+        self._client.close()
+
+    def setup_luigi_config(self):
+        set_docker_repository_config(
+            docker_password=None,
+            docker_repository_name=self._docker_repository_name,
+            docker_username=None,
+            tag_prefix="",
+            kind="target"
+        )
+
+    def run_spawn_test_env_with_cleanup(self):
+        return self.run_spawn_test_env(cleanup=True)
+
+    def run_spawn_test_env_without_cleanup(self):
+        return self.run_spawn_test_env(cleanup=False)
+
+    def run_spawn_test_env(self, cleanup: bool):
+        result = None
+        self.setup_luigi_config()
+        luigi_utils.set_job_id(SpawnTestEnvironment)
+        task = SpawnTestEnvironment(reuse_database_setup=True,
+                                    reuse_database=True,
+                                    reuse_test_container=True,
+                                    no_test_container_cleanup_after_success=not cleanup,
+                                    no_database_cleanup_after_success=not cleanup,
+                                    external_exasol_xmlrpc_host="",
+                                    external_exasol_db_host="",
+                                    external_exasol_xmlrpc_port=0,
+                                    external_exasol_db_user="",
+                                    external_exasol_db_password="",
+                                    external_exasol_xmlrpc_user="",
+                                    external_exasol_xmlrpc_password="",
+                                    external_exasol_xmlrpc_cluster_name="",
+                                    external_exasol_bucketfs_write_password="",
+                                    environment_type=EnvironmentType.docker_db,
+                                    environment_name=self.env_name(),
+                                    docker_db_image_version=self.docker_db_version_parameter,
+                                    docker_db_image_name="exasol/docker-db"
+                                    )
+        try:
+            success = luigi.build([task], workers=1, local_scheduler=True, log_level="INFO")
+            if success:
+                result = task
+            else:
+                task.cleanup(False)
+                Exception("Task failed")
+        except Exception as e:
+            task.cleanup(False)
+        return result
+
+    def _create_exaplus_check_cmd(self, test_environment_info):
+        username = SpawnTestEnvironment.DEFAULT_DB_USER
+        password = SpawnTestEnvironment.DEFAULT_DATABASE_PASSWORD
+        database_host = test_environment_info.database_info.host
+        database_port = test_environment_info.database_info.db_port
+        q = "SELECT TABLE_NAME FROM SYS.EXA_ALL_TABLES WHERE TABLE_SCHEMA='TEST';"
+        return f"""$EXAPLUS -c '{database_host}:{database_port}' -u '{username}' -p '{password}' -sql \\\"{q}\\\""""
+
+    def _exec_cmd_in_test_container(self, test_environment_info, cmd):
+        bash_cmd = f"""bash -c "{cmd}" """
+        test_container = self._client.containers.get(test_environment_info.test_container_info.container_name)
+
+        exit_code, output = test_container.exec_run(cmd=bash_cmd)
+        self.assertEquals(exit_code, 0)
+        return output.decode('utf-8')
+
+    def _verify_test_data(self, test_environment_info):
+        cmd = self._create_exaplus_check_cmd(test_environment_info)
+        output_str = self._exec_cmd_in_test_container(test_environment_info, cmd)
+
+        # TODO read /tests/test/import.sql and apply a regular expression to
+        # get all table names and compare then one-by-one
+        self.assertIn("ENGINETABLE", [output_entry.strip() for output_entry in output_str.split(sep='\n')])
+
+    def test_initial_reuse_database_setup_populates_data(self):
+        task = process_spawn_utils.run_in_process(self.run_spawn_test_env_with_cleanup)
+        self._verify_test_data(task.get_return_object())
+        task.cleanup(True)
+
+    def get_instance_ids(self, test_environment_info):
+        test_container = self._client.containers.get(test_environment_info.test_container_info.container_name)
+        db_container = self._client.containers.get(test_environment_info.database_info.container_info.container_name)
+        network = self._client.networks.get(test_environment_info.network_info.network_name)
+        return test_container.id, db_container.id, network.id
+
+    def test_reuse_env_same_instances(self):
+        task = process_spawn_utils.run_in_process(self.run_spawn_test_env_without_cleanup)
+        test_environment_info = task.get_return_object()
+        old_instance_ids = self.get_instance_ids(test_environment_info)
+        # This clean is supposed to not remove docker instances
+        task.cleanup(True)
+
+        task = process_spawn_utils.run_in_process(self.run_spawn_test_env_with_cleanup)
+        test_environment_info = task.get_return_object()
+        new_instance_ids = self.get_instance_ids(test_environment_info)
+        self.assertEquals(old_instance_ids, new_instance_ids)
+        self._verify_test_data(test_environment_info)
+
+        task.cleanup(True)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/exasol_integration_test_docker_environment/test/utils/__init__.py b/exasol_integration_test_docker_environment/test/utils/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/exasol_integration_test_docker_environment/test/utils/luigi_utils.py b/exasol_integration_test_docker_environment/test/utils/luigi_utils.py
new file mode 100644
index 000000000..865772d8a
--- /dev/null
+++ b/exasol_integration_test_docker_environment/test/utils/luigi_utils.py
@@ -0,0 +1,22 @@
+import shutil
+from datetime import datetime
+
+import luigi
+
+from exasol_integration_test_docker_environment.lib.docker.images.clean.clean_images import CleanImagesStartingWith
+
+
+def set_job_id(task_cls):
+    strftime = datetime.now().strftime('%Y_%m_%d_%H_%M_%S')
+    job_id = f"{strftime}_{task_cls.__name__}"
+    config = luigi.configuration.get_config()
+    config.set('job_config', 'job_id', job_id)
+    return job_id
+
+
+def clean(docker_repository_name):
+    jobid = set_job_id(CleanImagesStartingWith)
+    task = CleanImagesStartingWith(starts_with_pattern=docker_repository_name, jobid=jobid)
+    luigi.build([task], workers=1, local_scheduler=True, log_level="INFO")
+    if task._get_tmp_path_for_job().exists():
+        shutil.rmtree(str(task._get_tmp_path_for_job()))
diff --git a/exasol_integration_test_docker_environment/test/utils/process_spawn_utils.py b/exasol_integration_test_docker_environment/test/utils/process_spawn_utils.py
new file mode 100644
index 000000000..0315ef907
--- /dev/null
+++ b/exasol_integration_test_docker_environment/test/utils/process_spawn_utils.py
@@ -0,0 +1,22 @@
+from multiprocessing import Process, Queue
+from typing import Callable
+
+
+def process_main(queue: Queue, func: Callable):
+    try:
+        result = func()
+        queue.put(("result", result))
+    except Exception as e:
+        queue.put(("exception", e))
+
+
+def run_in_process(func):
+    queue = Queue()
+    p1 = Process(target=process_main, args=(queue, func))
+    p1.start()
+    p1.join()
+    result = queue.get()
+    if result[0] == "result":
+        return result[1]
+    else:
+        raise result[1]
diff --git a/exasol_integration_test_docker_environment/test/utils.py b/exasol_integration_test_docker_environment/test/utils/utils.py
similarity index 96%
rename from exasol_integration_test_docker_environment/test/utils.py
rename to exasol_integration_test_docker_environment/test/utils/utils.py
index 6fc38360d..7f06af42f 100644
--- a/exasol_integration_test_docker_environment/test/utils.py
+++ b/exasol_integration_test_docker_environment/test/utils/utils.py
@@ -16,10 +16,10 @@
 
 from exasol_integration_test_docker_environment.lib.data.environment_info import EnvironmentInfo
 
+INTEGRATION_TEST_DOCKER_ENVIRONMENT_DEFAULT_BIN = "./start-test-env-without-poetry"
 
-INTEGRATION_TEST_DOCKER_ENVIRONMENT_DEFAULT_BIN="./start-test-env-without-poetry"
 
-class ExaslctDockerTestEnvironment():
+class ExaslctDockerTestEnvironment:
     def __init__(self, name: str, database_host: str,
                  db_username: str, db_password: str,
                  bucketfs_username: str, bucketfs_password: str,
@@ -43,7 +43,7 @@ def close(self):
         remove_docker_volumes([f"db_container_{self.name}_volume"])
 
 
-class ExaslctTestEnvironment():
+class ExaslctTestEnvironment:
 
     def __init__(self, test_object, executable="./exaslct", clean_images_at_close=True):
         self.clean_images_at_close = clean_images_at_close
@@ -84,9 +84,11 @@ def repository_prefix(self, value):
         self._update_attributes()
 
     def _update_attributes(self):
-        self.repository_name = f"{self._repository_prefix.lower()}/{self.name.lower()}"  # docker repository names must be lowercase
+        # docker repository names must be lowercase
+        self.repository_name = f"{self._repository_prefix.lower()}/{self.name.lower()}"
         self.flavor_path_argument = f"--flavor-path {self.get_test_flavor()}"
-        self.docker_repository_arguments = f"--source-docker-repository-name {self.repository_name} --target-docker-repository-name {self.repository_name}"
+        self.docker_repository_arguments = f"--source-docker-repository-name {self.repository_name} " \
+                                           f"--target-docker-repository-name {self.repository_name}"
         self.clean_docker_repository_arguments = f"--docker-repository-name {self.repository_name}"
         self.output_directory_arguments = f"--output-directory {self.temp_dir}"
         self.task_dependencies_argument = " ".join([f"--task-dependencies-dot-file {self.name}.dot", ])