From 2138689d2065902e41649903ade73d2769070d0e Mon Sep 17 00:00:00 2001 From: Robert Marki Date: Wed, 28 Nov 2018 08:12:06 +0100 Subject: [PATCH] Improve the documentation of integration tests --- tests/integration/helpers.py | 42 +++++++++++++++++++++++++++++++- tests/integration/test_client.py | 20 ++++++++++++--- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index fa8267f..1a993c6 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -1,3 +1,4 @@ +"""Helper classes for integration tests""" import time from urllib.request import urlopen from http import HTTPStatus @@ -7,21 +8,43 @@ class DockerContainer: + """Docker container encapsulation + + If the container with the given *name* doesn't exists yet it'll be created. + """ def __init__(self, image_name, name, container_port, host_port): + """ + :param str image_name: A docker image name with or without a tag + :param name: Container name + :param container_port: TCP port exposed by the container + :param host_port: TCP port on the host where the exposed container \ + port gets published + """ + #: docker image name with or without a tag self.image_name = image_name + #: container name self.name = name + #: TCP port exposed by the container self.contaner_port = container_port + #: TCP port on the host where the exposed container port gets published self.host_port = host_port + #: container instance self._container = None + #: docker client self.client = docker.from_env() + self._ensure_exists() def _ensure_exists(self): + """Create the container if it doesn't already exists""" + # try to find the container by name and image filter = { "name": self.name, "ancestor": self.image_name } results = self.client.containers.list(all=True, filters=filter) + + # if it doesn't exists then create it if not results: self._container = self.client.containers.run( name=self.name, @@ -29,32 +52,47 @@ def _ensure_exists(self): ports={f"{self.contaner_port}/tcp": self.host_port}, detach=True ) + # if it exists assign it to the instance attribute else: self._container = results[0] def _wait_for_state(self, state): + """Wait until the state of the container becomes the given *state* + value + """ while self._container.status != state: time.sleep(1) self._container.reload() def _ensure_running(self): + """Get the container into the ``running`` state if it's in a different + one""" + # make sure the container exists self._ensure_exists() + # if the container is not running if self._container.status != "running": + # if the container is stopped then start it if self._container.status == "exited": self._container.start() + # if the container is paused then resume it if self._container.status == "paused": self._container.unpause() self._wait_for_state("running") def _get_url(self): + """Return the url of the container's service""" return f"http://localhost:{self.host_port}" - def ensure_reacheable(self): + def ensure_reachable(self): + """Start the container and make sure it's exposed service is reachable + """ + # make sure the container is running self._ensure_running() url = self._get_url() + # query the service's URL until it can be reached status = None with suppress(Exception): status = urlopen(url).status @@ -66,9 +104,11 @@ def ensure_reacheable(self): return url def stop(self): + """Stop the container""" self._container.stop() self._wait_for_state("exited") def pause(self): + """Pause the container""" self._container.pause() self._wait_for_state("paused") diff --git a/tests/integration/test_client.py b/tests/integration/test_client.py index 3b4520f..e4857fb 100644 --- a/tests/integration/test_client.py +++ b/tests/integration/test_client.py @@ -1,4 +1,3 @@ -import logging import asyncio from asynctest import TestCase, TestSuite @@ -9,24 +8,37 @@ class BaseTestCase(TestCase): + #: name of the docker image containing the CometD demo services IMAGE_NAME = "robertmrk/cometd-demos:alpine" + #: a name for the container CONTAINER_NAME = "aiocometd-integration-test" + #: TCP port exposed by the container CONTAINER_PORT = 8080 + #: TCP port where the container's port will be published HOST_PORT = 9999 + #: URL of the CometD service COMETD_URL = f"http://localhost:{HOST_PORT}/cometd" + #: CometD connection type CONNECTION_TYPE = None + #: container instance container = None + #: name of the chat room CHAT_ROOM = "demo" + #: channel where the room's messages get published CHAT_ROOM_CHANNEL = "/chat/" + CHAT_ROOM + #: channel where the room's memeber get published MEMBERS_CHANGED_CHANNEL = "/members/" + CHAT_ROOM + #: channel for adding user's to the room MEMBERS_CHANNEL = "/service/members" + #: name of the first user USER_NAME1 = "user1" + #: name of the second user USER_NAME2 = "user2" def setUp(self): - self.container.ensure_reacheable() + self.container.ensure_reachable() @classmethod def setUpClass(cls): @@ -214,7 +226,7 @@ async def test_revover_on_server_restart(self): await asyncio.sleep(3) # start the service - self.container.ensure_reacheable() + self.container.ensure_reachable() # give a few seconds for the client to recover the connection await asyncio.sleep(3) @@ -247,7 +259,7 @@ async def test_recover_on_temporary_network_outage(self): await asyncio.sleep(3) # start the service - self.container.ensure_reacheable() + self.container.ensure_reachable() # give a few seconds for the client to recover the connection await asyncio.sleep(3)