Modern QA2026Best Practices — tiles
Log inJoin
57 / 75 · 08 Infrastructure as Code Testing · Testcontainers for Infrastructure Testing← prev⊞ allnext →☰ Read as one page

10.7Best Practices

  1. Use scope="module" -- Starting containers is slow (2-10 seconds each). Share containers across tests in a module, not per-test.

  2. Use fixtures for cleanup -- Each test should get a clean state (truncated tables, flushed caches) via fixtures, not by starting new containers.

  3. Pin image versions -- Use postgres:16-alpine, not postgres:latest. Tests must be reproducible.

  4. Set wait strategies -- Some containers need custom health checks:

from testcontainers.core.waiting_utils import wait_for_logs

with KafkaContainer("confluentinc/cp-kafka:7.6.0") as kafka:
    wait_for_logs(kafka, "started (kafka.server.KafkaServer)", timeout=60)
  1. Handle port randomization -- Testcontainers assigns random host ports. Always use container.get_exposed_port() rather than hardcoding ports.

  2. Run in CI with Docker-in-Docker or Docker socket -- CI environments need Docker access. Most CI providers support this natively.

# GitHub Actions: Docker is available by default
jobs:
  integration-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install testcontainers pytest
      - run: pytest tests/integration/ -v

Testcontainers has become the standard for integration testing because it eliminates the "works locally, fails in CI" problem. Real services in Docker are more reliable than mocks and more portable than shared test environments.