mirror of
https://github.com/docker/docs.git
synced 2026-03-27 22:38:54 +07:00
## Description Migrate the first two Testcontainers getting-started guides from [testcontainers.com/guides](https://testcontainers.com/guides/) into the Docker docs site: - **Getting started with Testcontainers for Go** — multi-page guide with 4 chapters (create project, write tests, test suites, run tests). Code updated to testcontainers-go v0.41.0 API (`postgres.Run()`, `CleanupContainer`, `BasicWaitStrategies()`). - **Getting started with Testcontainers for Python** — multi-page guide with 3 chapters (create project, write tests, run tests). Code updated to testcontainers-python 4.14.2 (fixed `get_exposed_port()` returning `int`). Each guide appears as its own entry in the `/guides/` listing with proper language and tag filters (`testing-with-docker`). Chapters render with stepper navigation in the sidebar. Also adds: - A `testing-with-docker` tag to `data/tags.yaml` - A Claude skill (`.claude/skills/testcontainers-guides-migrator/SKILL.md`) that documents the repeatable migration process for the remaining 19 guides - Links from `content/manuals/testcontainers.md` to the new guides - Vale vocabulary entries for `pgx`, `Micronaut`, `psycopg`, `pytest` All guide code was compiled and tests verified passing in containers with Docker socket mounted. ## Related issues or tickets No related issues found. ## Reviews - [ ] Technical review - [ ] Editorial review - [ ] Product review
105 lines
3.1 KiB
Markdown
105 lines
3.1 KiB
Markdown
---
|
|
title: Write tests with Testcontainers
|
|
linkTitle: Write tests
|
|
description: Write integration tests using testcontainers-python and pytest with a real PostgreSQL database.
|
|
weight: 20
|
|
---
|
|
|
|
You'll create a PostgreSQL container using Testcontainers and use it for all
|
|
the tests. Before each test, you'll delete all customer records so that tests
|
|
run with a clean database.
|
|
|
|
## Set up pytest fixtures
|
|
|
|
This guide uses [pytest fixtures](https://pytest.org/en/stable/how-to/fixtures.html)
|
|
for setup and teardown logic. A recommended approach is to use
|
|
[finalizers](https://pytest.org/en/stable/how-to/fixtures.html#adding-finalizers-directly)
|
|
to guarantee cleanup runs even if setup fails:
|
|
|
|
```python
|
|
@pytest.fixture
|
|
def setup(request):
|
|
# setup code
|
|
|
|
def cleanup():
|
|
# teardown code
|
|
|
|
request.addfinalizer(cleanup)
|
|
return some_value
|
|
```
|
|
|
|
## Create the test file
|
|
|
|
Create a `tests/__init__.py` file with empty content to enable pytest
|
|
[auto-discovery](https://pytest.org/explanation/goodpractices.html#test-discovery).
|
|
|
|
Then create `tests/test_customers.py` with the fixtures:
|
|
|
|
```python
|
|
import os
|
|
import pytest
|
|
from testcontainers.postgres import PostgresContainer
|
|
|
|
from customers import customers
|
|
|
|
postgres = PostgresContainer("postgres:16-alpine")
|
|
|
|
|
|
@pytest.fixture(scope="module", autouse=True)
|
|
def setup(request):
|
|
postgres.start()
|
|
|
|
def remove_container():
|
|
postgres.stop()
|
|
|
|
request.addfinalizer(remove_container)
|
|
os.environ["DB_CONN"] = postgres.get_connection_url()
|
|
os.environ["DB_HOST"] = postgres.get_container_host_ip()
|
|
os.environ["DB_PORT"] = str(postgres.get_exposed_port(5432))
|
|
os.environ["DB_USERNAME"] = postgres.username
|
|
os.environ["DB_PASSWORD"] = postgres.password
|
|
os.environ["DB_NAME"] = postgres.dbname
|
|
customers.create_table()
|
|
|
|
|
|
@pytest.fixture(scope="function", autouse=True)
|
|
def setup_data():
|
|
customers.delete_all_customers()
|
|
```
|
|
|
|
Here's what the fixtures do:
|
|
|
|
- The `setup` fixture has `scope="module"`, so it runs once for all tests in
|
|
the file. It starts a PostgreSQL container, sets environment variables with
|
|
the connection details, and creates the `customers` table. A cleanup
|
|
function removes the container after all tests complete.
|
|
- The `setup_data` fixture has `scope="function"`, so it runs before every
|
|
test. It deletes all records to give each test a clean database.
|
|
|
|
## Write the tests
|
|
|
|
Add the test functions to the same file:
|
|
|
|
```python
|
|
def test_get_all_customers():
|
|
customers.create_customer("Siva", "siva@gmail.com")
|
|
customers.create_customer("James", "james@gmail.com")
|
|
customers_list = customers.get_all_customers()
|
|
assert len(customers_list) == 2
|
|
|
|
|
|
def test_get_customer_by_email():
|
|
customers.create_customer("John", "john@gmail.com")
|
|
customer = customers.get_customer_by_email("john@gmail.com")
|
|
assert customer.name == "John"
|
|
assert customer.email == "john@gmail.com"
|
|
```
|
|
|
|
- `test_get_all_customers()` inserts two customer records, fetches all
|
|
customers, and asserts the count.
|
|
- `test_get_customer_by_email()` inserts a customer, fetches it by email, and
|
|
asserts the details.
|
|
|
|
Because `setup_data` deletes all records before each test, the tests can run in
|
|
any order.
|