Getting started¶
Installation¶
Seaworthy can be installed using pip:
pip install seaworthy
The pytest and testtools integrations can be used if those libraries are installed, which can be done using extra requirements:
pip install seaworthy[pytest,testtools]
Defining containers for tests¶
Containers should be defined using subclasses of
ContainerDefinition
. For example:
from seaworthy.definitions import ContainerDefinition
from seaworthy.utils import output_lines
class CakeContainer(ContainerDefinition):
IMAGE = 'acme-corp/cake-service:chocolate'
WAIT_PATTERNS = (
r'cake \w+ is baked',
r'cake \w+ is served',
)
def __init__(self, name):
super().__init__(name, self.IMAGE, self.WAIT_PATTERNS)
# Utility methods can be added to the class to extend functionality
def exec_cake(self, *params):
return output_lines(self.inner().exec_run(('cake',) + params))
WAIT_PATTERNS
is a list of regex patterns. Once these patterns have been
seen in the container logs, the container is considered to have started and be
ready for use. For more advanced readiness checks, the
wait_for_start()
method should
be overridden.
This container can then be used as fixtures for tests in a number of ways, the easiest of which is with pytest:
import pytest
container = CakeContainer('test')
fixture = container.pytest_fixture('cake_container')
def test_type(cake_container):
output = cake_container.exec_cake('type')
assert output == ['chocolate']
A few things to note here:
- The
pytest_fixture()
method returns a pytest fixture that ensures that the container is created and started before the test begins and that the container is stopped and removed after the test ends. - The scope of the fixture is important. By default, pytest fixtures have
function scope, which means that for each test function the fixture is
completely reinitialized. Creating and starting up a container can be a
little slow, so you need to think carefully about what scope to use for your
fixtures. See
ContainerDefinition.clean
for a way to avoid container setup/teardown overhead.
For simple cases, ContainerDefinition
can be
used directly, without subclassing:
container = ContainerDefinition(
'test', 'acme-corp/soda-service:cola', [r'soda \w+ is fizzing'])
fixture = container.pytest_fixture('soda_container')
def test_refreshment(soda_container):
assert 'Papor-Colla Corp' in soda_container.get_logs()
Note that pytest is not required to use Seaworthy and there are several other ways to use the container as a fixture. For more information see Test framework integration and Resource definitions & helpers.