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

Issue:
Improve error message when docker socket can't be found
```
291       File "/builds/Dudanski/exasol-testautomatisierung/integration-test-docker-environment/src/lib/test_environment/prepare_network_for_test_environment.py", line 27, in run_task
292         self.network_info = self.create_docker_network()
293       File "/builds/Dudanski/exasol-testautomatisierung/integration-test-docker-environment/src/lib/test_environment/prepare_network_for_test_environment.py", line 37, in create_docker_network
294         self.remove_container(self.test_container_name)
295       File "/builds/Dudanski/exasol-testautomatisierung/integration-test-docker-environment/src/lib/test_environment/prepare_network_for_test_environment.py", line 72, in remove_container
296         container = self._client.containers.get(container_name)
297       File "/venv/lib/python3.6/site-packages/docker/models/containers.py", line 880, in get
298         resp = self.client.api.inspect_container(container_id)
299       File "/venv/lib/python3.6/site-packages/docker/utils/decorators.py", line 19, in wrapped
300         return f(self, resource_id, *args, **kwargs)
301       File "/venv/lib/python3.6/site-packages/docker/api/container.py", line 758, in inspect_container
302         self._get(self._url("/containers/{0}/json", container)), True
303       File "/venv/lib/python3.6/site-packages/docker/utils/decorators.py", line 46, in inner
304         return f(self, *args, **kwargs)
305       File "/venv/lib/python3.6/site-packages/docker/api/client.py", line 230, in _get
306         return self.get(url, **self._set_request_timeout(kwargs))
307       File "/venv/lib/python3.6/site-packages/requests/sessions.py", line 543, in get
308         return self.request('GET', url, **kwargs)
309       File "/venv/lib/python3.6/site-packages/requests/sessions.py", line 530, in request
310         resp = self.send(prep, **send_kwargs)
311       File "/venv/lib/python3.6/site-packages/requests/sessions.py", line 643, in send
312         r = adapter.send(request, **kwargs)
313       File "/venv/lib/python3.6/site-packages/requests/adapters.py", line 498, in send
314         raise ConnectionError(err, request=request)
315     requests.exceptions.ConnectionError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))
```


Discussion / hints:
Situation: 

Currently, we don't check if docker is available on the machine and only recognize the problem deep inside the stack trace with a not so useful error message.

Fix:

Check if we can connect to the Docker daemon very early in the process and if we can't reach throw a useful error message.

Fix patch:
diff --git a/README.md b/README.md
index 922e1d181..045963259 100644
--- a/README.md
+++ b/README.md
@@ -123,6 +123,41 @@ You can look at them on the commandline with:
 ./start-test-env spawn-test-environment --help 
 ```
 
+### The integration-test-docker-environment command line tool
+Besides, the already mentioned command `spawn-test-environment`, the integration-test-docker-environemnt
+command line tool provides a couple of other helpful tools.
+
+Run `main.py --help`, to get a list of the available commands:
+```console
+Usage: main.py [OPTIONS] COMMAND [ARGS]...
+
+Options:
+  --help  Show this message and exit.
+
+Commands:
+  build-test-container    This command builds all stages of the test...
+  health                  Check the health of the execution environment.
+  push-test-container     This command pushs all stages of the test...
+  spawn-test-environment  This command spawn a test environment with a...
+```
+
+To get more details on a specific command run `main.py <command> --help`,
+e.g. `main.py health --help`:
+
+```console
+Usage: main.py health [OPTIONS]
+
+  Check the health of the execution environment.
+
+  If no issues have been found, using the library or executing the test should
+  work just fine. For all found issues there will be a proposed fix/solution.
+
+  If the environment was found to be healthy the exit code will be 0.
+
+Options:
+  --help  Show this message and exit.
+```
+
 ### Default Credentials
 
 The default credentials for the database are
diff --git a/README.rst b/README.rst
deleted file mode 100644
index 3259e9155..000000000
--- a/README.rst
+++ /dev/null
@@ -1,214 +0,0 @@
-
-Integration Test Docker Environment
-===================================
-
-About
------
-
-This project provides a command line interface to start a test environment with an `Exasol Docker-DB <https://hub.docker.com/r/exasol/docker-db>`_. It starts an Exasol Docker-DB container and an associated test container where `EXAPlus CLI <https://docs.exasol.com/connect_exasol/sql_clients/exaplus_cli/exaplus_cli.htm>`_ and  the `Exasol ODBC driver <https://docs.exasol.com/connect_exasol/drivers/odbc.htm>`_ are already installed.
-
-Both containers exist in the same Docker network. This allows you to connect from the test container to the Docker-DB container. Furthermore, the database gets populated with some test data. You can find the test data under ``tests/test/enginedb_small/import.sql``. Besides the test container, you can also access the Exasol database and the Bucket-FS from the host via forwarded ports.
-
-Comparison to Docker-DB and the Exasol Testcontainers
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-
-* This project uses the `Docker-DB <https://hub.docker.com/r/exasol/docker-db>`_\ , but it does the configuration, setup and startup for you. For example, it waits until the Database and the Bucket-FS accept connections. It also populates the database with test data and provides with the test container as an environment to access the database.
-* The `Exasol Testcontainers <https://github.com/exasol/exasol-testcontainers/>`_ provide similar features for Java integration tests, so if you have an Java project use the Exasol Testcontainer, because they are more integrated in the Java ecosystem then this project. Testcontainers are designed to integrate with popular unit testing frameworks like `JUnit4 <https://www.testcontainers.org/test_framework_integration/junit_4/>`_\ , `JUnit5 <https://www.testcontainers.org/test_framework_integration/junit_5/>`_ and `Spock <https://www.testcontainers.org/test_framework_integration/spock/>`_. Most notably, lifecycle management of containers controlled by the tests lifecycle.
-
-However, if you have a project in any other language you can use this project to start a test Exasol database via a command line interface.
-
-Prerequisites
--------------
-
-In order to start a Docker-DB Test Environment, you need:
-
-
-* Tested Operating System:
-
-  * Linux
-  * Mac OS X with `Docker Desktop on Mac <https://docs.docker.com/docker-for-mac/install/>`_ and Intel processor
-  * Windows is currently **not supported**
-
-* Docker with privileged mode
-* At least 2 GiB RAM
-* We recommend at least 15 GB free disk space on the partition 
-  where Docker stores its images and containers. On Linux Docker typically stores 
-  the images under ``/var/lib/docker``.
-
-Getting started
----------------
-
-Clone the repository
-
-.. code-block::
-
-   git clone https://github.com/exasol/integration-test-docker-environment
-
-Starting the test environment:
-
-.. code-block::
-
-   ./start-test-env spawn-test-environment --environment-name <NAME>
-
-or if you work on the code of the Test Environment (requires Python >=3.6 with pip):
-
-.. code-block::
-
-   ./start-test-env-without-docker-runner spawn-test-environment --environment-name <NAME>
-
-Shutdown of the test environment is currently done manual.
-
-Options
-^^^^^^^
-
-The following options are available to customize the test environment. 
-
-.. code-block::
-
-   Usage: main.py spawn-test-environment [OPTIONS]
-
-     This command spawn a test environment with a docker-db container and a
-     connected test-container. The test-container is reachable by the database
-     for output redirects of UDFs.
-
-   Options:
-     --environment-name TEXT         Name of the docker environment. This name
-                                     gets used as suffix for the container
-                                     db_container_<name> and
-                                     test_container_<name>  [required]
-
-     --database-port-forward INTEGER
-                                     Host port to which the database port gets
-                                     forwarded
-
-     --bucketfs-port-forward INTEGER
-                                     Host port to which the bucketfs port gets
-                                     forwarded
-
-     --db-mem-size TEXT              The main memory used by the database. Format
-                                     <number> <unit>, e.g. 1 GiB. The minimum
-                                     size is 1 GB, below that the database will
-                                     not start.  [default: 2 GiB]
-
-     --db-disk-size TEXT             The disk size available for the database.
-                                     Format <number> <unit>, e.g. 1 GiB. The
-                                     minimum size is 100 MiB. However, the setup
-                                     creates volume files with at least 2 GB
-                                     larger size, because the database needs at
-                                     least so much more disk.  [default: 2 GiB]
-
-     --deactivate-database-setup / --no-deactivate-database-setup
-                                     Deactivates the setup of the spawned
-                                     database, this means no data get populated
-                                     and no jdbc drivers get uploaded. This can
-                                     be used either to save time or as a
-                                     workaround for MacOSX where the
-                                     test_container seems not to be able to
-                                     access the tests directory  [default: False]
-
-     --docker-runtime TEXT           The docker runtime used to start all
-                                     containers
-
-     --docker-db-image-version TEXT  Docker DB Image Version against which the
-                                     tests should run.  [default: 7.1.5]
-
-     --docker-db-image-name TEXT     Docker DB Image Name against which the tests
-                                     should run.  [default: exasol/docker-db]
-
-You can look at them on the commandline with:
-
-.. code-block::
-
-   ./start-test-env spawn-test-environment --help
-
-Default Credentials
-^^^^^^^^^^^^^^^^^^^
-
-The default credentials for the database are
-
-
-* User: ``sys``
-* Password: ``exasol``
-
-and for the Bucket-FS:
-
-
-* User: ``w``
-* Password: ``write``
-
-or
-
-
-* User: ``r``
-* Password: ``read``
-
-Accessing the Environment Information
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The python setup script creates configuration files on the host and in the test container.
-
-On the host the container information get stored in the build output directory usually under ``.build_output/cache/<ENVIRONMENT_NAME>/*``. In the test container the config file is stored at the root directory ``/``.
-
-The following config files are available:
-
-
-* 
-  environment_info.sh: This file is meant to be source by the bash and then provides the information as environment variables. Here an example for the content:
-
-  .. code-block::
-
-     export ENVIRONMENT_NAME=test
-     export ENVIRONMENT_TYPE=EnvironmentType.docker_db
-
-     # Database IP in environment docker network
-     export ENVIRONMENT_DATABASE_HOST=172.21.0.2
-     export ENVIRONMENT_DATABASE_DB_PORT=8888
-     export ENVIRONMENT_DATABASE_BUCKETFS_PORT=6583
-     export ENVIRONMENT_DATABASE_CONTAINER_NAME=db_container_test
-     export ENVIRONMENT_DATABASE_CONTAINER_NETWORK_ALIASES="exasol_test_database db_container_test"
-     # Database IP in the environment docker network
-     export ENVIRONMENT_DATABASE_CONTAINER_IP_ADDRESS=172.21.0.2
-     export ENVIRONMENT_DATABASE_CONTAINER_VOLUMNE_NAME=db_container_test_volume
-     # Database IP on the docker default bridge which under Linux available from the host
-     export ENVIRONMENT_DATABASE_CONTAINER_DEFAULT_BRIDGE_IP_ADDRESS=172.17.0.3
-
-     export ENVIRONMENT_TEST_CONTAINER_NAME=test_container_test
-     export ENVIRONMENT_TEST_CONTAINER_NETWORK_ALIASES="test_container test_container_test"
-     # Test Container IP in the environment docker network
-     export ENVIRONMENT_TEST_CONTAINER_IP_ADDRESS=172.21.0.3
-
-* environment_info.json: Contains the EnvironmentInfo objects pickled with JsonPickle
-
-Currently supported Exasol Versions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-
-* **6.0**\ : 6.0.12, 6.0.13, 6.0.16
-* **6.1**\ : 6.1.1, 6.1.6, 6.1.7, 6.1.8, 6.1.9, 6.1.10, 6.1.11
-* **6.2**\ : 6.2.4, 6.2.0, 6.2.1, 6.2.3, 6.2.5, 6.2.6, 6.2.7, 6.2.8, 6.2.9
-* **7.0**\ : 7.0.0, 7.0.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
-
-Mac OS X Support
-----------------
-
-What do I need to do to start the Test Environment with Mac OS X
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The Exasol Docker-DB needs per default a bit more than 2 GB of RAM, however the Docker VM on Mac OS X provides often not enough RAM to accommodate this. You should increase the RAM of the Docker VM to at least 4.25 GB or reduce the DB Mem Size for the Exasol Docker-DB to less than 2 GB with ``--db-mem-size 1 GiB``.
-
-What happens under the hood
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Mac OS X with Docker Desktop for Mac uses a lightweight virtual machine with linux in which the docker daemon runs and the containers get started. This makes `networking <https://docs.docker.com/docker-for-mac/networking/>`_ and `shared directories <https://docs.docker.com/docker-for-mac/osxfs/>`_ more complicated then on Linux.
-
-We start the python setup script for the test environment in its own Docker container, lets call it ``docker runner``\ , because the library `Luigi <https://luigi.readthedocs.io/en/stable/>`_ can have problems with Mac OS X and to avoid the installation of further dependencies. To support Mac OS X, the ``start-test-env`` script starts the ``docker runner`` container and mounts the docker socket at ``/var/run/docker.sock`` and the directory of the test environment from the Mac OS X host to the container. Then, it starts ``start-test-env-without-docker`` which then starts the python script. It is important, that the repository gets cloned to the Mac OS X host and not to a docker container, because the python scripts tries to start further docker container which use host mounts to share the tests directory of the test environment with the docker container.
diff --git a/doc/changes/changes_0.9.0.md b/doc/changes/changes_0.9.0.md
index f507c00e6..764c4d6e5 100644
--- a/doc/changes/changes_0.9.0.md
+++ b/doc/changes/changes_0.9.0.md
@@ -26,7 +26,7 @@ If you need further versions, please open an issue.
 
 ## Features / Enhancements:
 
-n/a
+ - #17: Improve error message when docker socket can't be found 
 
 ## Refactoring:
 
diff --git a/scripts/build/check_release.py b/scripts/build/check_release.py
index 5ae278ea0..4a6d5aa41 100644
--- a/scripts/build/check_release.py
+++ b/scripts/build/check_release.py
@@ -1,4 +1,3 @@
-import os
 import re
 from pathlib import Path
 
diff --git a/scripts/health.sh b/scripts/health.sh
new file mode 100755
index 000000000..fce459c72
--- /dev/null
+++ b/scripts/health.sh
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+# Check the health status of the current environment
+# If this script executed successfully, ware all set to run.
+set -u
+
+MAJOR_MINIMUM_VERSION_DOCKER="17"
+MINOR_MINIMUM_VERSION_DOCKER="05"
+
+help() {
+  if [ "$1" == "docker" ]; then
+    echo "Please follow the installation instructions on https://docs.docker.com/get-docker/"
+    echo "or for a quick installation for non production linux machines the instruction on https://github.com/docker/docker-install"
+  else
+    echo "There is no suggestion for the issue at hand, please contact your administrator or support"
+  fi
+}
+
+is_command_available () {
+  command -v "$1" > /dev/null
+}
+
+is_version_compatible() {
+  local min_major="$1" # $1 - expected min major version
+  local min_minor="$2" # $2 - expected min minor version
+  local major="$3"     # $3 - actual major version
+  local minor="$4"     # $4 - actual minor version
+  if [ "$major" -lt "$min_major" ]; then
+    return 1
+  fi
+  if [ "$major" -eq "$min_major" ] && [ "$minor" -lt "$min_minor" ]; then
+    return 1
+  fi
+  return 0
+}
+
+require() {
+  # check if a command is available, otherwise print an error and exit
+  if ! is_command_available "$1"; then
+    echo "Could not find '$1'"
+    echo
+    help "$1"
+    exit 1
+  fi
+}
+
+# Why is this check needed?
+# If docker is installed, the client part of it usually works just fine (cli frontend).
+# Unfortunately this does not mean that docker will work.
+# Another crucial part of docker to work properly is, that the server (backend) part works too.
+# If the docker server does not work properly various commands will fail, so will `docker info`
+# (Because it is requesting information from the docker server).
+# Therefore we need this check to be confident docker is operational.
+check_docker_info () {
+    local docker_cmd="$1"
+    local details
+    details=$("$docker_cmd" info)
+    # we want to store the details of the command, for error reporting. Therefore we won't check within the if.
+    # shellcheck disable=SC2181
+    if [ "$?" -ne 0 ]; then
+      echo "ERROR: Docker does not seem to be configured correctly!"
+      echo "Details:"
+      echo
+      echo "$details"
+      return 1
+    fi
+}
+
+docker_version () {
+    local docker_cmd="$1"
+    local version
+    version=$("$docker_cmd" info | grep  "Server Version: " | cut -f2 -d ":" | tr -d '[:space:]')
+    echo "$version"
+}
+
+docker_major_version () {
+    local docker_cmd="$1"
+    local version
+    version=$(docker_version "$docker_cmd")
+    echo "$version" | cut -f1 -d "."
+}
+
+docker_minor_version () {
+    local docker_cmd="$1"
+    local version
+    version=$(docker_version "$docker_cmd")
+    echo "$version" | cut -f2 -d "."
+}
+
+docker_check_version () {
+  local docker_cmd=$1
+  local actual_major_version
+  actual_major_version=$(docker_major_version "$docker_cmd")
+  local actual_minor_version
+  actual_minor_version=$(docker_minor_version "$docker_cmd")
+
+  if ! is_version_compatible "$MAJOR_MINIMUM_VERSION_DOCKER" "$MINOR_MINIMUM_VERSION_DOCKER" "$actual_major_version" "$actual_minor_version"; then
+    echo "The currently installed docker version $actual_major_version.$actual_minor_version version is not compatible"
+    help "$docker_cmd"
+    return 1
+  fi
+}
+
+docker_check_pull () {
+  local docker_cmd=$1
+  local details
+  details=$("docker" pull ubuntu:18.04 2>&1)
+  # We want to store the details of the command, for error reporting. Therefore we won't check within the if.
+  # shellcheck disable=SC2181
+  if [ $? -ne 0 ]; then
+    echo "Could not pull images from docker registry"
+    echo "details:"
+    echo "$details"
+    return 1
+  fi
+}
+
+docker_check_connectivity () {
+  local docker_cmd=$1
+  local details
+  details=$(docker run --rm ubuntu:18.04 bash -c ": >/dev/tcp/1.1.1.1/53")
+  # We want to store the details of the command, for error reporting. Therefore we won't check within the if.
+  # shellcheck disable=SC2181
+  if [ $? -ne 0 ]; then
+    echo "The docker machine does not seem to have connectivity"
+    echo "details:"
+    echo "$details"
+    return 1
+  fi
+}
+
+health_check_docker () {
+  local docker_cmd="docker"
+  require "$docker_cmd"
+
+  if ! check_docker_info "$docker_cmd"; then
+    return 1
+  fi
+
+  if ! docker_check_version "$docker_cmd"; then
+    return 1
+  fi
+
+  if ! docker_check_pull "$docker_cmd"; then
+    return 1
+  fi
+
+  if ! docker_check_connectivity "$docker_cmd"; then
+    return 1
+  fi
+}
+
+main() {
+  if [ "$1" != "run" ]; then return 0; fi
+  if ! health_check_docker; then
+    exit 1
+  fi
+}
+
+# run all health checks
+main "$1"
diff --git a/setup.py b/setup.py
index 588a14883..fc1496f39 100644
--- a/setup.py
+++ b/setup.py
@@ -68,7 +68,7 @@
     'name': 'exasol-integration-test-docker-environment',
     'version': '0.9.0',
     'description': 'Integration Test Docker Environment for Exasol',
-    'long_description': '# Integration Test Docker Environment\n\n## About\n\nThis project provides a command line interface to start a test environment with an [Exasol Docker-DB](https://hub.docker.com/r/exasol/docker-db). It starts an Exasol Docker-DB container and an associated test container where [EXAPlus CLI](https://docs.exasol.com/connect_exasol/sql_clients/exaplus_cli/exaplus_cli.htm) and  the [Exasol ODBC driver](https://docs.exasol.com/connect_exasol/drivers/odbc.htm) are already installed.\n\nBoth containers exist in the same Docker network. This allows you to connect from the test container to the Docker-DB container. Furthermore, the database gets populated with some test data. You can find the test data under `tests/test/enginedb_small/import.sql`. Besides the test container, you can also access the Exasol database and the Bucket-FS from the host via forwarded ports.\n\n### Comparison to Docker-DB and the Exasol Testcontainers\n\n* This project uses the [Docker-DB](https://hub.docker.com/r/exasol/docker-db), but it does the configuration, setup and startup for you. For example, it waits until the Database and the Bucket-FS accept connections. It also populates the database with test data and provides with the test container as an environment to access the database.\n* The [Exasol Testcontainers](https://github.com/exasol/exasol-testcontainers/) provide similar features for Java integration tests, so if you have an Java project use the Exasol Testcontainer, because they are more integrated in the Java ecosystem then this project. Testcontainers are designed to integrate with popular unit testing frameworks like [JUnit4](https://www.testcontainers.org/test_framework_integration/junit_4/), [JUnit5](https://www.testcontainers.org/test_framework_integration/junit_5/) and [Spock](https://www.testcontainers.org/test_framework_integration/spock/). Most notably, lifecycle management of containers controlled by the tests lifecycle.\n\nHowever, if you have a project in any other language you can use this project to start a test Exasol database via a command line interface.\n\n## Prerequisites\n\nIn order to start a Docker-DB Test Environment, you need:\n\n* Tested Operating System:\n  * Linux\n  * Mac OS X with [Docker Desktop on Mac](https://docs.docker.com/docker-for-mac/install/) and Intel processor\n  * Windows is currently **not supported**\n* Docker with privileged mode\n* At least 2 GiB RAM\n* We recommend at least 15 GB free disk space on the partition \n  where Docker stores its images and containers. On Linux Docker typically stores \n  the images under `/var/lib/docker`.\n\n## Getting started\n\nClone the repository\n\n```\ngit clone https://github.com/exasol/integration-test-docker-environment\n```\n\nStarting the test environment:\n\n```\n./start-test-env spawn-test-environment --environment-name <NAME>\n```\nor if you work on the code of the Test Environment (requires Python >=3.6 with [poetry](https://python-poetry.org/)):\n\n```\n./start-test-env-with-poetry spawn-test-environment --environment-name <NAME>\n```\n\nShutdown of the test environment is currently done manual.\n\n### Options\n\nThe following options are available to customize the test environment. \n\n```\nUsage: main.py spawn-test-environment [OPTIONS]\n\n  This command spawn a test environment with a docker-db container and a\n  connected test-container. The test-container is reachable by the database\n  for output redirects of UDFs.\n\nOptions:\n  --environment-name TEXT         Name of the docker environment. This name\n                                  gets used as suffix for the container\n                                  db_container_<name> and\n                                  test_container_<name>  [required]\n\n  --database-port-forward INTEGER\n                                  Host port to which the database port gets\n                                  forwarded\n\n  --bucketfs-port-forward INTEGER\n                                  Host port to which the BucketFS port gets\n                                  forwarded\n\n  --db-mem-size TEXT              The main memory used by the database. Format\n                                  <number> <unit>, e.g. 1 GiB. The minimum\n                                  size is 1 GB, below that the database will\n                                  not start.  [default: 2 GiB]\n\n  --db-disk-size TEXT             The disk size available for the database.\n                                  Format <number> <unit>, e.g. 1 GiB. The\n                                  minimum size is 100 MiB. However, the setup\n                                  creates volume files with at least 2 GB\n                                  larger size, because the database needs at\n                                  least so much more disk.  [default: 2 GiB]\n\n  --nameserver TEXT               Add a nameserver to the list of DNS\n                                  nameservers which the docker-db should use\n                                  for resolving domain names. You can repeat\n                                  this option to add further nameservers.\n\n  --deactivate-database-setup / --no-deactivate-database-setup\n                                  Deactivates the setup of the spawned\n                                  database, this means no data get populated\n                                  and no JDBC drivers get uploaded. This can\n                                  be used either to save time or as a\n                                  workaround for MacOSX where the\n                                  test_container seems not to be able to\n                                  access the tests directory  [default: False]\n\n  --docker-runtime TEXT           The docker runtime used to start all\n                                  containers\n\n  --docker-db-image-version TEXT  Docker DB Image Version against which the\n                                  tests should run.  [default: 7.1.5]\n\n  --docker-db-image-name TEXT     Docker DB Image Name against which the tests\n                                  should run.  [default: exasol/docker-db]\n\n  --output-directory DIRECTORY    Output directory where the system stores all\n                                  output and log files.  [default:\n                                  .build_output]\n\n  --temporary-base-directory DIRECTORY\n                                  Directory where the system creates temporary\n                                  directories.  [default: /tmp]\n```\n\nYou can look at them on the commandline with:\n\n```\n./start-test-env spawn-test-environment --help \n```\n\n### Default Credentials\n\nThe default credentials for the database are\n\n  * User: `sys`\n  * Password: `exasol`\n  \nand for the Bucket-FS:\n\n  * User: `w`\n  * Password: `write`\n  \nor\n\n  * User: `r`\n  * Password: `read`\n\n### Accessing the Environment Information\n\nThe python setup script creates configuration files on the host and in the test container.\n\nOn the host the container information get stored in the build output directory usually under `.build_output/cache/<ENVIRONMENT_NAME>/*`. In the test container the config file is stored at the root directory `/`.\n\nThe following config files are available:\n\n- environment_info.sh: This file is meant to be source by the bash and then provides the information as environment variables. Here an example for the content:\n\n  ```\n  export ENVIRONMENT_NAME=test\n  export ENVIRONMENT_TYPE=EnvironmentType.docker_db\n\n  # Database IP in environment docker network\n  export ENVIRONMENT_DATABASE_HOST=172.21.0.2\n  export ENVIRONMENT_DATABASE_DB_PORT=8888\n  export ENVIRONMENT_DATABASE_BUCKETFS_PORT=6583\n  export ENVIRONMENT_DATABASE_CONTAINER_NAME=db_container_test\n  export ENVIRONMENT_DATABASE_CONTAINER_NETWORK_ALIASES="exasol_test_database db_container_test"\n  # Database IP in the environment docker network\n  export ENVIRONMENT_DATABASE_CONTAINER_IP_ADDRESS=172.21.0.2\n  export ENVIRONMENT_DATABASE_CONTAINER_VOLUMNE_NAME=db_container_test_volume\n  # Database IP on the docker default bridge which under Linux available from the host\n  export ENVIRONMENT_DATABASE_CONTAINER_DEFAULT_BRIDGE_IP_ADDRESS=172.17.0.3\n\n  export ENVIRONMENT_TEST_CONTAINER_NAME=test_container_test\n  export ENVIRONMENT_TEST_CONTAINER_NETWORK_ALIASES="test_container test_container_test"\n  # Test Container IP in the environment docker network\n  export ENVIRONMENT_TEST_CONTAINER_IP_ADDRESS=172.21.0.3\n  ```\n- environment_info.json: Contains the EnvironmentInfo objects pickled with JsonPickle\n  \n### Currently supported Exasol Versions\n\n* **7.0**: up to 7.0.15 **except 7.0.5**\n* **7.1**: up to 7.1.5\n\n\nIf you need further versions, please open an issue.\n\n### Tested Docker Runtimes\n\n- Docker Default Runtime\n- [NVIDIA Container Runtime](https://github.com/NVIDIA/nvidia-container-runtime) for GPU accelerated UDFs\n\n## Mac OS X Support\n\n### What do I need to do to start the Test Environment with Mac OS X\n\nThe Exasol Docker-DB needs per default a bit more than 2 GB of RAM, however the Docker VM on Mac OS X provides often not enough RAM to accommodate this. You should increase the RAM of the Docker VM to at least 4.25 GB or reduce the DB Mem Size for the Exasol Docker-DB to less than 2 GB with `--db-mem-size 1 GiB`.\n\n### What happens under the hood\n\nMac OS X with Docker Desktop for Mac uses a lightweight virtual machine with linux in which the docker daemon runs and the containers get started. This makes [networking](https://docs.docker.com/docker-for-mac/networking/) and [shared directories](https://docs.docker.com/docker-for-mac/osxfs/) more complicated then on Linux.\n\nWe start the python setup script for the test environment in its own Docker container, lets call it `docker runner`, because the library [Luigi](https://luigi.readthedocs.io/en/stable/) can have problems with Mac OS X and to avoid the installation of further dependencies. To support Mac OS X, the `start-test-env` script starts the `docker runner` container and mounts the docker socket at `/var/run/docker.sock` and the directory of the test environment from the Mac OS X host to the container. Then, it starts `start-test-env-without-docker` which then starts the python script. It is important, that the repository gets cloned to the Mac OS X host and not to a docker container, because the python scripts tries to start further docker container which use host mounts to share the tests directory of the test environment with the docker container.\n',
+    'long_description': '# Integration Test Docker Environment\n\n## About\n\nThis project provides a command line interface to start a test environment with an [Exasol Docker-DB](https://hub.docker.com/r/exasol/docker-db). It starts an Exasol Docker-DB container and an associated test container where [EXAPlus CLI](https://docs.exasol.com/connect_exasol/sql_clients/exaplus_cli/exaplus_cli.htm) and  the [Exasol ODBC driver](https://docs.exasol.com/connect_exasol/drivers/odbc.htm) are already installed.\n\nBoth containers exist in the same Docker network. This allows you to connect from the test container to the Docker-DB container. Furthermore, the database gets populated with some test data. You can find the test data under `tests/test/enginedb_small/import.sql`. Besides the test container, you can also access the Exasol database and the Bucket-FS from the host via forwarded ports.\n\n### Comparison to Docker-DB and the Exasol Testcontainers\n\n* This project uses the [Docker-DB](https://hub.docker.com/r/exasol/docker-db), but it does the configuration, setup and startup for you. For example, it waits until the Database and the Bucket-FS accept connections. It also populates the database with test data and provides with the test container as an environment to access the database.\n* The [Exasol Testcontainers](https://github.com/exasol/exasol-testcontainers/) provide similar features for Java integration tests, so if you have an Java project use the Exasol Testcontainer, because they are more integrated in the Java ecosystem then this project. Testcontainers are designed to integrate with popular unit testing frameworks like [JUnit4](https://www.testcontainers.org/test_framework_integration/junit_4/), [JUnit5](https://www.testcontainers.org/test_framework_integration/junit_5/) and [Spock](https://www.testcontainers.org/test_framework_integration/spock/). Most notably, lifecycle management of containers controlled by the tests lifecycle.\n\nHowever, if you have a project in any other language you can use this project to start a test Exasol database via a command line interface.\n\n## Prerequisites\n\nIn order to start a Docker-DB Test Environment, you need:\n\n* Tested Operating System:\n  * Linux\n  * Mac OS X with [Docker Desktop on Mac](https://docs.docker.com/docker-for-mac/install/) and Intel processor\n  * Windows is currently **not supported**\n* Docker with privileged mode\n* At least 2 GiB RAM\n* We recommend at least 15 GB free disk space on the partition \n  where Docker stores its images and containers. On Linux Docker typically stores \n  the images under `/var/lib/docker`.\n\n## Getting started\n\nClone the repository\n\n```\ngit clone https://github.com/exasol/integration-test-docker-environment\n```\n\nStarting the test environment:\n\n```\n./start-test-env spawn-test-environment --environment-name <NAME>\n```\nor if you work on the code of the Test Environment (requires Python >=3.6 with [poetry](https://python-poetry.org/)):\n\n```\n./start-test-env-with-poetry spawn-test-environment --environment-name <NAME>\n```\n\nShutdown of the test environment is currently done manual.\n\n### Options\n\nThe following options are available to customize the test environment. \n\n```\nUsage: main.py spawn-test-environment [OPTIONS]\n\n  This command spawn a test environment with a docker-db container and a\n  connected test-container. The test-container is reachable by the database\n  for output redirects of UDFs.\n\nOptions:\n  --environment-name TEXT         Name of the docker environment. This name\n                                  gets used as suffix for the container\n                                  db_container_<name> and\n                                  test_container_<name>  [required]\n\n  --database-port-forward INTEGER\n                                  Host port to which the database port gets\n                                  forwarded\n\n  --bucketfs-port-forward INTEGER\n                                  Host port to which the BucketFS port gets\n                                  forwarded\n\n  --db-mem-size TEXT              The main memory used by the database. Format\n                                  <number> <unit>, e.g. 1 GiB. The minimum\n                                  size is 1 GB, below that the database will\n                                  not start.  [default: 2 GiB]\n\n  --db-disk-size TEXT             The disk size available for the database.\n                                  Format <number> <unit>, e.g. 1 GiB. The\n                                  minimum size is 100 MiB. However, the setup\n                                  creates volume files with at least 2 GB\n                                  larger size, because the database needs at\n                                  least so much more disk.  [default: 2 GiB]\n\n  --nameserver TEXT               Add a nameserver to the list of DNS\n                                  nameservers which the docker-db should use\n                                  for resolving domain names. You can repeat\n                                  this option to add further nameservers.\n\n  --deactivate-database-setup / --no-deactivate-database-setup\n                                  Deactivates the setup of the spawned\n                                  database, this means no data get populated\n                                  and no JDBC drivers get uploaded. This can\n                                  be used either to save time or as a\n                                  workaround for MacOSX where the\n                                  test_container seems not to be able to\n                                  access the tests directory  [default: False]\n\n  --docker-runtime TEXT           The docker runtime used to start all\n                                  containers\n\n  --docker-db-image-version TEXT  Docker DB Image Version against which the\n                                  tests should run.  [default: 7.1.5]\n\n  --docker-db-image-name TEXT     Docker DB Image Name against which the tests\n                                  should run.  [default: exasol/docker-db]\n\n  --output-directory DIRECTORY    Output directory where the system stores all\n                                  output and log files.  [default:\n                                  .build_output]\n\n  --temporary-base-directory DIRECTORY\n                                  Directory where the system creates temporary\n                                  directories.  [default: /tmp]\n```\n\nYou can look at them on the commandline with:\n\n```\n./start-test-env spawn-test-environment --help \n```\n\n### The integration-test-docker-environment command line tool\nBesides, the already mentioned command `spawn-test-environment`, the integration-test-docker-environemnt\ncommand line tool provides a couple of other helpful tools.\n\nRun `main.py --help`, to get a list of the available commands:\n```console\nUsage: main.py [OPTIONS] COMMAND [ARGS]...\n\nOptions:\n  --help  Show this message and exit.\n\nCommands:\n  build-test-container    This command builds all stages of the test...\n  health                  Check the health of the execution environment.\n  push-test-container     This command pushs all stages of the test...\n  spawn-test-environment  This command spawn a test environment with a...\n```\n\nTo get more details on a specific command run `main.py <command> --help`,\ne.g. `main.py health --help`:\n\n```console\nUsage: main.py health [OPTIONS]\n\n  Check the health of the execution environment.\n\n  If no issues have been found, using the library or executing the test should\n  work just fine. For all found issues there will be a proposed fix/solution.\n\n  If the environment was found to be healthy the exit code will be 0.\n\nOptions:\n  --help  Show this message and exit.\n```\n\n### Default Credentials\n\nThe default credentials for the database are\n\n  * User: `sys`\n  * Password: `exasol`\n  \nand for the Bucket-FS:\n\n  * User: `w`\n  * Password: `write`\n  \nor\n\n  * User: `r`\n  * Password: `read`\n\n### Accessing the Environment Information\n\nThe python setup script creates configuration files on the host and in the test container.\n\nOn the host the container information get stored in the build output directory usually under `.build_output/cache/<ENVIRONMENT_NAME>/*`. In the test container the config file is stored at the root directory `/`.\n\nThe following config files are available:\n\n- environment_info.sh: This file is meant to be source by the bash and then provides the information as environment variables. Here an example for the content:\n\n  ```\n  export ENVIRONMENT_NAME=test\n  export ENVIRONMENT_TYPE=EnvironmentType.docker_db\n\n  # Database IP in environment docker network\n  export ENVIRONMENT_DATABASE_HOST=172.21.0.2\n  export ENVIRONMENT_DATABASE_DB_PORT=8888\n  export ENVIRONMENT_DATABASE_BUCKETFS_PORT=6583\n  export ENVIRONMENT_DATABASE_CONTAINER_NAME=db_container_test\n  export ENVIRONMENT_DATABASE_CONTAINER_NETWORK_ALIASES="exasol_test_database db_container_test"\n  # Database IP in the environment docker network\n  export ENVIRONMENT_DATABASE_CONTAINER_IP_ADDRESS=172.21.0.2\n  export ENVIRONMENT_DATABASE_CONTAINER_VOLUMNE_NAME=db_container_test_volume\n  # Database IP on the docker default bridge which under Linux available from the host\n  export ENVIRONMENT_DATABASE_CONTAINER_DEFAULT_BRIDGE_IP_ADDRESS=172.17.0.3\n\n  export ENVIRONMENT_TEST_CONTAINER_NAME=test_container_test\n  export ENVIRONMENT_TEST_CONTAINER_NETWORK_ALIASES="test_container test_container_test"\n  # Test Container IP in the environment docker network\n  export ENVIRONMENT_TEST_CONTAINER_IP_ADDRESS=172.21.0.3\n  ```\n- environment_info.json: Contains the EnvironmentInfo objects pickled with JsonPickle\n  \n### Currently supported Exasol Versions\n\n* **7.0**: up to 7.0.15 **except 7.0.5**\n* **7.1**: up to 7.1.5\n\n\nIf you need further versions, please open an issue.\n\n### Tested Docker Runtimes\n\n- Docker Default Runtime\n- [NVIDIA Container Runtime](https://github.com/NVIDIA/nvidia-container-runtime) for GPU accelerated UDFs\n\n## Mac OS X Support\n\n### What do I need to do to start the Test Environment with Mac OS X\n\nThe Exasol Docker-DB needs per default a bit more than 2 GB of RAM, however the Docker VM on Mac OS X provides often not enough RAM to accommodate this. You should increase the RAM of the Docker VM to at least 4.25 GB or reduce the DB Mem Size for the Exasol Docker-DB to less than 2 GB with `--db-mem-size 1 GiB`.\n\n### What happens under the hood\n\nMac OS X with Docker Desktop for Mac uses a lightweight virtual machine with linux in which the docker daemon runs and the containers get started. This makes [networking](https://docs.docker.com/docker-for-mac/networking/) and [shared directories](https://docs.docker.com/docker-for-mac/osxfs/) more complicated then on Linux.\n\nWe start the python setup script for the test environment in its own Docker container, lets call it `docker runner`, because the library [Luigi](https://luigi.readthedocs.io/en/stable/) can have problems with Mac OS X and to avoid the installation of further dependencies. To support Mac OS X, the `start-test-env` script starts the `docker runner` container and mounts the docker socket at `/var/run/docker.sock` and the directory of the test environment from the Mac OS X host to the container. Then, it starts `start-test-env-without-docker` which then starts the python script. It is important, that the repository gets cloned to the Mac OS X host and not to a docker container, because the python scripts tries to start further docker container which use host mounts to share the tests directory of the test environment with the docker container.\n',
     'author': 'Torsten Kilias',
     'author_email': 'torsten.kilias@exasol.com',
     'maintainer': None,


Test patch:
diff --git a/.github/workflows/test_db_versions_minimal.yml b/.github/workflows/test_db_versions_minimal.yml
index f7c365a59..b6f10899d 100644
--- a/.github/workflows/test_db_versions_minimal.yml
+++ b/.github/workflows/test_db_versions_minimal.yml
@@ -49,6 +49,8 @@ jobs:
         poetry-version: 1.1.6
 
     - name: Run minimal tests
-      run: ./scripts/test/run_test.sh exasol_integration_test_docker_environment/test/test_test_environment.py
+      run: |
+          ./scripts/test/run_test.sh exasol_integration_test_docker_environment/test/test_test_environment.py
+          ./scripts/test/run_test.sh exasol_integration_test_docker_environment/test/test_doctor.py
       env:
         EXASOL_VERSION: "${{ matrix.exasol_version }}"
diff --git a/.github/workflows/test_docker_starter.yml b/.github/workflows/test_docker_starter.yml
index e98cd7c77..58cf63487 100644
--- a/.github/workflows/test_docker_starter.yml
+++ b/.github/workflows/test_docker_starter.yml
@@ -13,4 +13,4 @@ jobs:
     - uses: actions/checkout@v2
 
     - name: Test ./start-test-env
-      run: ./start-test-env --help
+      run: ./start-test-env health
diff --git a/.github/workflows/test_shell_scripts.yml b/.github/workflows/test_shell_scripts.yml
new file mode 100644
index 000000000..1586e6b83
--- /dev/null
+++ b/.github/workflows/test_shell_scripts.yml
@@ -0,0 +1,21 @@
+name: Test Shell Scripts
+
+on: [push, pull_request]
+
+jobs:
+  build:
+    name: Test Shell Scripts
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Install Test Dependencies
+        run: |
+          sudo apt-get install -y shunit2
+
+      - name: Run shunit2 based Shell Tests
+        run: shunit2 scripts/health_test.sh
+
+      - name: Run Starter Script Tests
+        run: starter_scripts/test/test_scripts.sh
+
diff --git a/exasol_integration_test_docker_environment/cli/commands/health.py b/exasol_integration_test_docker_environment/cli/commands/health.py
new file mode 100644
index 000000000..6fdd6a1fb
--- /dev/null
+++ b/exasol_integration_test_docker_environment/cli/commands/health.py
@@ -0,0 +1,51 @@
+import sys
+from inspect import cleandoc
+
+from exasol_integration_test_docker_environment.cli.cli import cli
+from exasol_integration_test_docker_environment.doctor import (
+    health_checkup,
+    recommend_mitigation,
+)
+
+
+@cli.command()
+def health():
+    """
+    Check the health of the execution environment.
+
+    If no issues have been found, using the library or executing the test should work just fine.
+    For all found issues there will be a proposed fix/solution.
+
+    If the environment was found to be healthy the exit code will be 0.
+    """
+    success, failure = 0, -1
+
+    problems = set(health_checkup())
+    if not problems:
+        sys.exit(success)
+
+    suggestion_template = cleandoc(
+        """
+        * {problem}
+          Fix: {suggestion}
+        """
+    )
+    message = cleandoc(
+        """
+        {count} problem(s) have been identified.
+        
+        {problems}
+        """
+    ).format(
+        count=len(problems),
+        problems="\n".join(
+            (
+                suggestion_template.format(
+                    problem=icd.value, suggestion=recommend_mitigation(icd)
+                )
+                for icd in problems
+            )
+        ),
+    )
+    print(message)
+    sys.exit(failure)
diff --git a/exasol_integration_test_docker_environment/doctor.py b/exasol_integration_test_docker_environment/doctor.py
new file mode 100644
index 000000000..d94160e96
--- /dev/null
+++ b/exasol_integration_test_docker_environment/doctor.py
@@ -0,0 +1,66 @@
+"""
+The doctor module provides functionality to check the health of the `exasol_integration_test_docker_environment`
+package and also provide help to find potential fixes.
+"""
+from enum import Enum
+from typing import Iterator
+
+import docker
+from docker.errors import DockerException
+
+
+class ErrorCodes(Enum):
+    """The equivalent of ICD-10 codes this doctor is using"""
+
+    Unknown = "Unknown issue"
+    UnixSocketNotAvailable = "Could not find unix socket to connect to"
+
+
+def recommend_mitigation(error_code) -> str:
+    """Get treatment advice based on the error_code"""
+    return {
+        ErrorCodes.Unknown: "You are sick but this symptoms are unknown, please contact the maintainer.",
+        ErrorCodes.UnixSocketNotAvailable: "Make sure your DOCKER_HOST environment variable is configured correctly.",
+    }[error_code]
+
+
+def diagnose_docker_daemon_not_available() -> Iterator[ErrorCodes]:
+    """Diagnose reasons why docker deamon is not available"""
+
+    def _is_unix_socket_issue(message: str) -> bool:
+        return "FileNotFoundError(2, 'No such file or directory')" in message
+
+    errors = set()
+    try:
+        _docker = docker.from_env()
+    except DockerException as ex:
+        msg = f"{ex}"
+        if _is_unix_socket_issue(msg):
+            errors.add(ErrorCodes.UnixSocketNotAvailable)
+        if len(errors) == 0:
+            errors.add(ErrorCodes.Unknown)
+    return errors
+
+
+def is_docker_daemon_available() -> bool:
+    """
+    Checks weather or not the docker daemon is available.
+    """
+    try:
+        _docker = docker.from_env()
+    except DockerException:
+        return False
+    return True
+
+
+def health_checkup() -> Iterator[ErrorCodes]:
+    """
+    Runs all known examinations
+
+    return an iterator of error codes specifying which problems have been identified.
+    """
+    examinations = [(is_docker_daemon_available, diagnose_docker_daemon_not_available)]
+    for is_fine, diagnosis in examinations:
+        if not is_fine():
+            for error_code in diagnosis():
+                yield error_code
diff --git a/exasol_integration_test_docker_environment/main.py b/exasol_integration_test_docker_environment/main.py
index 0382cd667..0e71c2916 100755
--- a/exasol_integration_test_docker_environment/main.py
+++ b/exasol_integration_test_docker_environment/main.py
@@ -2,7 +2,12 @@
 #
 from exasol_integration_test_docker_environment.cli.cli import cli
 # noinspection PyUnresolvedReferences
-from exasol_integration_test_docker_environment.cli.commands import spawn_test_environment, push_test_container, build_test_container
+from exasol_integration_test_docker_environment.cli.commands import (
+    health,
+    spawn_test_environment,
+    push_test_container,
+    build_test_container
+)
 
 if __name__ == '__main__':
     cli()
diff --git a/exasol_integration_test_docker_environment/test/test_doctor.py b/exasol_integration_test_docker_environment/test/test_doctor.py
new file mode 100644
index 000000000..64b316602
--- /dev/null
+++ b/exasol_integration_test_docker_environment/test/test_doctor.py
@@ -0,0 +1,67 @@
+import os
+import unittest
+from contextlib import contextmanager
+from typing import ContextManager, Mapping
+
+from exasol_integration_test_docker_environment.doctor import (
+    ErrorCodes, diagnose_docker_daemon_not_available,
+    is_docker_daemon_available)
+
+
+@contextmanager
+def temporary_env(env_vars) -> ContextManager[Mapping[str, str]]:
+    """
+    Creates a temporary environment, containing the current environment variables.
+
+    :param env_vars: to be updated within the temporary environment.
+
+    :return: the temporary environment variables in use
+    """
+    old_env = dict(os.environ)
+    os.environ.update(env_vars)
+    yield os.environ
+    os.environ.clear()
+    os.environ.update(old_env)
+
+
+class IsDockerDaemonAvailableTest(unittest.TestCase):
+    """
+    Attention: this tests require docker.
+    """
+
+    def test_docker_connection_attempt_on_non_existing_unix_socket_returns_false(self):
+        """
+        Regression:  https://github.com/exasol/integration-test-docker-environment/issues/17
+
+        Cause: If docker tries to use a unix socket to connect to the docker deamon but the associated
+               file of the unix socket is not existent, creating a docker client using
+               `docker.from_env()` will fail with an exception.
+        """
+        env = {"DOCKER_HOST": "unix:///var/non/existent/path"}
+        with temporary_env(env):
+            self.assertFalse(is_docker_daemon_available())
+
+    def test_successful_connection_to_the_daemon(self):
+        self.assertTrue(is_docker_daemon_available())
+
+
+class DiagnoseDockerDaemonNotAvailable(unittest.TestCase):
+    """
+    Attention: this tests require docker.
+    """
+
+    def test_non_existing_unix_socket(self):
+        expected = {ErrorCodes.UnixSocketNotAvailable}
+        env = {"DOCKER_HOST": "unix:///var/non/existent/path"}
+        with temporary_env(env):
+            self.assertEqual(expected, diagnose_docker_daemon_not_available())
+
+    def test_unknown_error(self):
+        expected = {ErrorCodes.Unknown}
+        env = {"DOCKER_HOST": "https://foobar"}
+        with temporary_env(env):
+            self.assertEqual(expected, diagnose_docker_daemon_not_available())
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/scripts/health_test.sh b/scripts/health_test.sh
new file mode 100644
index 000000000..b9b17af67
--- /dev/null
+++ b/scripts/health_test.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# file: scripts/health_test.sh
+# Attention:
+#  * This test uses [shunit2](https://github.com/kward/shunit2)
+#  * It assumes it is executed from the project root like this
+#    shunit2 scripts/health_test.sh
+#
+. ./scripts/health.sh
+
+test_is_version_compatible_invalid_major_version() {
+  local major="1"
+  local minor="1"
+  local min_major="2"
+  local min_minor="1"
+  assertFalse "required: >= ${min_major}.${min_minor}, actual: ${major}.${minor}"\
+    "is_version_compatible ${min_major} ${min_minor} ${major} ${minor}"
+}
+
+test_is_version_compatible_invalid_minor_version() {
+  local major="1"
+  local minor="0"
+  local min_major="1"
+  local min_minor="1"
+  assertFalse "required: >= ${min_major}.${min_minor}, actual: ${major}.${minor}"\
+    "is_version_compatible ${min_major} ${min_minor} ${major} ${minor}"
+}
+
+test_is_version_compatible_valid_version() {
+  local major="2"
+  local minor="10"
+  local min_major="1"
+  local min_minor="2"
+  assertTrue "required: >= ${min_major}.${min_minor}, actual: ${major}.${minor}"\
+    "is_version_compatible ${min_major} ${min_minor} ${major} ${minor}"
+}
+
+test_is_command_available_returns_false_if_command_is_not_available() {
+  assertFalse "is_command_available 'UnknownCommandXYZ'"
+}
+
+test_is_command_available_returns_true_if_command_is_available() {
+  assertTrue "is_command_available 'ls'"
+}
diff --git a/start-test-env b/start-test-env
index 2652c806e..2dedb29d9 100755
--- a/start-test-env
+++ b/start-test-env
@@ -18,6 +18,7 @@ fi
 
 SCRIPT_DIR="$(dirname "$($rl -f "${BASH_SOURCE[0]}")")"
 
-RUNNER_IMAGE_NAME="$("$SCRIPT_DIR/starter_scripts/construct_docker_runner_image_name.sh")"
+bash "$SCRIPT_DIR/scripts/health.sh" "run"
 
+RUNNER_IMAGE_NAME="$("$SCRIPT_DIR/starter_scripts/construct_docker_runner_image_name.sh")"
 bash "$SCRIPT_DIR/starter_scripts/exaitde_within_docker_container_with_container_build.sh" "$RUNNER_IMAGE_NAME" "${@}"
diff --git a/starter_scripts/test/test_scripts.sh b/starter_scripts/test/test_scripts.sh
index d0a7dff8a..56c77a5ec 100755
--- a/starter_scripts/test/test_scripts.sh
+++ b/starter_scripts/test/test_scripts.sh
@@ -19,12 +19,12 @@ function assert() {
   fi
 }
 
-flavorDirA="$SCRIPT_DIR/test/abc=def"
-exportDirA="$SCRIPT_DIR/test/exportdir=xyz"
+cacheDirectory="$SCRIPT_DIR/test/abc=def"
+saveDirectory="$SCRIPT_DIR/test/exportdir=xyz"
 
-mkdir "$flavorDirA" || true
-trap 'rm -rf "$flavorDirA" "$exportDirA"' EXIT
+mkdir "$cacheDirectory" || true
+trap 'rm -rf "$cacheDirectory" "$saveDirectory"' EXIT
 
-testStr=$(bash "$SCRIPT_DIR/mount_point_parsing.sh" --flavor-path="$flavorDirA" --export-path "$exportDirA" dummy)
+testStr=$(bash "$SCRIPT_DIR/mount_point_parsing.sh" --cache-directory="$cacheDirectory" --save-directory "$saveDirectory" dummy)
 
-assert "$testStr" "$flavorDirA" "$exportDirA"
+assert "$testStr" "$cacheDirectory" "$saveDirectory"