cki_lib.inttests
Integration tests that require other services can be run via kind (Kubernetes in Docker).
Currently, a RabbitMQ service including certificates is implemented.
Creating an integration test
For an integration test, create a unit test in /inttests
, and derive the
TestCase from cki_lib.inttests.cluster.KubernetesCluster
or one of the
derived classes. As an example, for an integration test that needs a RabbitMQ
server:
from cki_lib.inttests import cluster
from cki_lib.inttests.rabbitmq import RabbitMQServer
@cluster.skip_without_requirements()
class TestStompClient(RabbitMQServer):
pass
During setupClass()
, a Kubernetes cluster and any required services will be
created and configured. The services will be removed in tearDownClass()
, but
the cluster will be kept running to speed up successive tests.
API
KubernetesCluster - Kubernetes cluster running in Docker
- test case class:
inttests.cluster.KubernetesCluster
The cluster is able to run locally and in GitLab CI as long as the kind
and
docker
executables are available. This can be checked with the
@skip_without_requirements
decorator. For GitLab CI, jobs need to have the
Docker-in-Docker service configured in .gitlab-ci.yml
:
integration-tests:
services:
- docker:dind
variables:
DOCKER_HOST: 'tcp://docker:2375'
Fields provided by KubernetesCluster
cls.cluster_name: str
:kind
cluster namecls.hostname: str
: host name for all services usable locally and in GitLab CIcls.api_client: client.ApiClient
: Pythonkubernetes
API clientcls.dynamic_client: dynamic.client.DynamicClient
: Pythonkubernetes
Dynamic clientcls.core_v1: client.CoreV1Api
: Pythonkubernetes
Core v1 API
Methods provided by KubernetesCluster
cls.k8s_namespace(namespace: str)
: context manager that creates and cleans up a Kubernetes namespace.cls.k8s_apply(namespace: str, body: typing.Any)
: apply a Kubernetes resource update via server-side apply.cls.k8s_delete_all(namespace: str, resources: Iterable[str])
: delete all resources of the given types from a namespace.
RabbitMQServer - RabbitMQ server
- test case class:
inttests.rabbitmq.RabbitMQServer
The server is configured with AMQP and STOMP access with and without TLS. For
AMQP and STOMP, authentication can be done via password and client certificates
(from cert.common_name
) methods.
Ports provided by RabbitMQServer
Port | Description |
---|---|
5671 | AMQP via TLS |
5672 | AMQP |
15671 | HTTP management API via TLS |
15672 | HTTP management API |
61613 | Stomp |
61614 | Stomp via TLS |
Test environment variables provided by RabbitMQServer
Name | Description |
---|---|
RABBITMQ_HOST |
host name |
RABBITMQ_PORT |
5671 |
RABBITMQ_MANAGEMENT_PORT |
15671 |
RABBITMQ_VIRTUAL_HOST |
/ |
RABBITMQ_USER |
guest |
RABBITMQ_PASSWORD |
guest |
RABBITMQ_CAFILE |
CA certificate |
RABBITMQ_CERTFILE |
client key and certificate |
STOMP_HOST |
host name |
STOMP_PORT |
61614 |
STOMP_CERTFILE |
client key and certificate |
HashiCorpVaultServer - HashiCorp Vault server
- test case class:
inttests.vault.HashiCorpVaultServer
The server is started in dev mode.
Ports provided by HashiCorpVaultServer
Port | Description |
---|---|
8200 | HTTP API |
Test environment variables provided by HashiCorpVaultServer
Name | Description |
---|---|
VAULT_ADDR |
server URL |
VAULT_MOUNT_POINT |
mount point of the KV2 engine |
VAULT_TOKEN |
secret token ID |
MariaDBServer - MariaDB server
- test case class:
inttests.mariadb.MariaDBServer
The database db
is created on startup.
Ports provided by MariaDBServer
Port | Description |
---|---|
3306 | SQL |
Test environment variables provided by MariaDBServer
Name | Description |
---|---|
MARIADB_HOST |
host name |
MARIADB_PORT |
3306 |
MARIADB_USER |
root |
MARIADB_PASSWORD |
root |
MARIADB_DATABASE |
db |
MinioServer - Minio server
- test case class:
inttests.minio.MinioServer
Ports provided by MinioServer
Port | Description |
---|---|
9000 | S3 |
Test environment variables provided by MinioServer
Name | Description |
---|---|
AWS_ENDPOINT_URL |
server URL |
AWS_DEFAULT_REGION |
us-east-1 |
AWS_ACCESS_KEY_ID |
access-key |
AWS_SECRET_ACCESS_KEY |
secret-key |
RemoteResponsesServer - Remote Responses server
- test case class:
inttests.remote_responses.RemoteResponsesServer
Provides a remote URL request mocking endpoint with an API similar to responses.
Fields provided by RemoteResponsesServer
The cls.responses
field contains a wrapper class with a subset of the responses API:
add(method, url, body=None, json=None, status=200, headers=None, match=[...])
replace(method, url, body=None, json=None, status=200, headers=None, match=[...])
upsert(method, url, body=None, json=None, status=200, headers=None, match=[...])
reset()
json_params_matcher(params, strict_match=True)
calls
The return values of add
/replace
/upsert
are proxied BaseResponse
instances and provide all expected fields:
call_count
calls
- …
This allows to set up test beds with
# GET request
data = {'a': 'b'}
self.responses.add('GET', f'http://ignored/pooh', json=data)
# POST request with match filter
data = {'data': {'namespace': {'fullPath': 'foo', 'rootStorageStatistics': {
'repositorySize': 1}, 'projects': {'nodes': []}, }}}
self.responses.add('POST', f'http://ignored/api/graphql', json=data, match=[
self.responses.json_params_matcher({"operationName": "pooh"}, strict_match=False)])
The mocked responses are available from REMOTE_RESPONSES_URL_EXTERNAL
when
accessed from the test bed, or from REMOTE_RESPONSES_URL
when accessed from
other services inside the cluster.
The mocked responses are reset before each test. For sub tests, responses can
be manually reset via self.responses.reset()
as well.
Ports provided by RemoteResponsesServer
Port | Description |
---|---|
7999 | Responses |
Test environment variables provided by RemoteResponsesServer
Name | Description |
---|---|
REMOTE_RESPONSES_URL |
server URL reachable from other services deployed in the cluster |
REMOTE_RESPONSES_URL_EXTERNAL |
server URL reachable from the test itself |