Files
Manuel de la Peña 36d384d2da docs(guides): add two testcontainers intro guides (go and python) (#24450)
## 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
2026-03-23 13:58:19 +00:00

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.