Explorar el Código

Merge pull request #2164 from rhansen/tests

chore: minor test improvements
Nicolas Duchon hace 2 años
padre
commit
6e9d46e672
Se han modificado 2 ficheros con 69 adiciones y 35 borrados
  1. 67 32
      test/conftest.py
  2. 2 3
      test/test_ssl/test_dhparam.py

+ 67 - 32
test/conftest.py

@@ -322,31 +322,28 @@ def wait_for_nginxproxy_to_be_ready():
             logging.debug("nginx-proxy ready")
             break
 
-def find_docker_compose_file(request):
-    """
-    helper for fixture functions to figure out the name of the docker-compose file to consider.
 
-    - if the test module provides a `docker_compose_file` variable, take that
-    - else, if a yaml file exists with the same name as the test module (but for the `.yml` extension), use that
-    - otherwise use `docker-compose.yml`.
+@pytest.fixture
+def docker_compose_file(request):
+    """Fixture naming the docker-compose file to consider.
+
+    If a YAML file exists with the same name as the test module (with the `.py` extension replaced
+    with `.yml` or `.yaml`), use that.  Otherwise, use `docker-compose.yml` in the same directory
+    as the test module.
+
+    Tests can override this fixture to specify a custom location.
     """
     test_module_dir = os.path.dirname(request.module.__file__)
     yml_file = os.path.join(test_module_dir, request.module.__name__ + '.yml')
     yaml_file = os.path.join(test_module_dir, request.module.__name__ + '.yaml')
     default_file = os.path.join(test_module_dir, 'docker-compose.yml')
 
-    docker_compose_file_module_variable = getattr(request.module, "docker_compose_file", None)
-    if docker_compose_file_module_variable is not None:
-        docker_compose_file = os.path.join( test_module_dir, docker_compose_file_module_variable)
-        if not os.path.isfile(docker_compose_file):
-            raise ValueError(f"docker compose file {docker_compose_file!r} could not be found. Check your test module `docker_compose_file` variable value.")
+    if os.path.isfile(yml_file):
+        docker_compose_file = yml_file
+    elif os.path.isfile(yaml_file):
+        docker_compose_file = yaml_file
     else:
-        if os.path.isfile(yml_file):
-            docker_compose_file = yml_file
-        elif os.path.isfile(yaml_file):
-            docker_compose_file = yaml_file
-        else:
-            docker_compose_file = default_file
+        docker_compose_file = default_file
 
     if not os.path.isfile(docker_compose_file):
         logging.error("Could not find any docker-compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__))
@@ -419,34 +416,72 @@ def connect_to_all_networks():
         return [connect_to_network(network) for network in networks]
 
 
+class DockerComposer(contextlib.AbstractContextManager):
+    def __init__(self):
+        self._docker_compose_file = None
+
+    def __exit__(self, *exc_info):
+        self._down()
+
+    def _down(self):
+        if self._docker_compose_file is None:
+            return
+        for network in self._networks:
+            disconnect_from_network(network)
+        docker_compose_down(self._docker_compose_file)
+        self._docker_compose_file = None
+
+    def compose(self, docker_compose_file):
+        if docker_compose_file == self._docker_compose_file:
+            return
+        self._down()
+        if docker_compose_file is None:
+            return
+        remove_all_containers()
+        docker_compose_up(docker_compose_file)
+        self._networks = connect_to_all_networks()
+        wait_for_nginxproxy_to_be_ready()
+        time.sleep(3)  # give time to containers to be ready
+        self._docker_compose_file = docker_compose_file
+
+
 ###############################################################################
 #
 # Py.test fixtures
 #
 ###############################################################################
 
+
 @pytest.fixture(scope="module")
-def docker_compose(request):
-    """
-    pytest fixture providing containers described in a docker compose file. After the tests, remove the created containers
+def docker_composer():
+    with DockerComposer() as d:
+        yield d
+
+
+@pytest.fixture
+def ca_root_certificate():
+    return CA_ROOT_CERTIFICATE
 
-    A custom docker compose file name can be defined in a variable named `docker_compose_file`.
+
+@pytest.fixture
+def monkey_patched_dns():
+    original_dns_resolver = monkey_patch_urllib_dns_resolver()
+    yield
+    restore_urllib_dns_resolver(original_dns_resolver)
+
+
+@pytest.fixture
+def docker_compose(monkey_patched_dns, docker_composer, docker_compose_file):
+    """Ensures containers described in a docker compose file are started.
+
+    A custom docker compose file name can be specified by overriding the `docker_compose_file`
+    fixture.
 
     Also, in the case where pytest is running from a docker container, this fixture makes sure
     our container will be attached to all the docker networks.
     """
-    docker_compose_file = find_docker_compose_file(request)
-    original_dns_resolver = monkey_patch_urllib_dns_resolver()
-    remove_all_containers()
-    docker_compose_up(docker_compose_file)
-    networks = connect_to_all_networks()
-    wait_for_nginxproxy_to_be_ready()
-    time.sleep(3)  # give time to containers to be ready
+    docker_composer.compose(docker_compose_file)
     yield docker_client
-    for network in networks:
-        disconnect_from_network(network)
-    docker_compose_down(docker_compose_file)
-    restore_urllib_dns_resolver(original_dns_resolver)
 
 
 @pytest.fixture()

+ 2 - 3
test/test_ssl/test_dhparam.py

@@ -1,6 +1,5 @@
 import re
 import subprocess
-import os
 
 import backoff
 import docker
@@ -219,7 +218,7 @@ def test_custom_dhparam_is_supported(docker_compose):
 
 # Only `web2` has a site-specific DH param file (which overrides all other DH config)
 # Other tests here use `web5` explicitly, or implicitly (via ENV `DEFAULT_HOST`, otherwise first HTTPS server)
-def test_custom_dhparam_is_supported_per_site(docker_compose):
+def test_custom_dhparam_is_supported_per_site(docker_compose, ca_root_certificate):
     container_name="dh-file"
     sut_container = docker_client.containers.get(container_name)
     assert sut_container.status == "running"
@@ -242,7 +241,7 @@ def test_custom_dhparam_is_supported_per_site(docker_compose):
     # - `web2` has it's own cert provisioned at `/etc/nginx/certs/web2.nginx-proxy.tld.crt`.
     can_verify_chain_of_trust(
         sut_container,
-        ca_cert = f"{os.getcwd()}/certs/ca-root.crt",
+        ca_cert = ca_root_certificate,
         fqdn    = 'web2.nginx-proxy.tld'
     )