Skip to content

Conversation

@tylernisonoff
Copy link
Contributor

Problem

The PostgresContainer currently uses the deprecated @wait_container_is_ready() decorator, which is slated for removal. The container was previously migrated away from log-based waiting due to
locale-dependent issues (#703, #695), but still relies on the deprecated decorator pattern.

Solution

This PR introduces a new ExecWaitStrategy wait strategy and migrates PostgresContainer to use it.

Changes

  1. New ExecWaitStrategy in core/testcontainers/core/wait_strategies.py

    • Executes commands inside containers and waits for expected exit codes
    • Follows the modern structured wait strategy pattern
    • Reusable for any DockerContainer with CLI-based health checks
    • Composable with other wait strategies via CompositeWaitStrategy
    • Includes runtime check to ensure container supports exec()
  2. Updated modules/postgres/testcontainers/postgres/__init__.py

    • Migrated _connect() method from @wait_container_is_ready decorator to ExecWaitStrategy
    • Uses psql command execution to verify database readiness
    • Maintains existing behavior and password escaping logic

Design Consideration: Protocol Limitations

Issue: The WaitStrategyTarget protocol is designed to support both DockerContainer and ComposeContainer, but ExecWaitStrategy only works with DockerContainer (which has an exec()
method).

Current Solution: Runtime check with hasattr(container, "exec") that raises a clear error if used with incompatible containers.

Discussion Points:

  • Should we have separate protocol types for different container capabilities?
  • Should ExecWaitStrategy accept a more specific type (e.g., DockerContainer directly)?
  • Is the runtime check acceptable, or should this be enforced at the type level?

I've opted for the runtime check to maintain consistency with the existing WaitStrategyTarget protocol pattern, but I'm open to alternatives if the maintainers prefer a different approach.

PR Checklist

  • Your PR title follows the Conventional Commits syntax
    as we make use of this for detecting Semantic Versioning changes.
    • Additions to the community modules do not contribute to SemVer scheme:
      all community features will be tagged community-feat,
      but we do not want to release minor or major versions due to features or breaking changes outside of core.
      So please use fix(postgres): or fix(my_new_vector_db): if you want to add or modify community modules.
      This may change in the future if we have a separate package released with community modules.
  • Your PR allows maintainers to edit your branch, this will speed up resolving minor issues!
  • The new container is implemented under modules/*
    • Your module follows PEP 420 with implicit namespace packages
      (if unsure, look at other existing community modules)
    • Your package namespacing follows testcontainers.<modulename>.*
      and you DO NOT have an __init__.py above your module's level.
    • Your module has its own tests under modules/*/tests
    • Your module has a README.rst and hooks in the .. auto-class and .. title of your container
    • Implement the new feature (typically in __init__.py) and corresponding tests.
  • Your module is added in pyproject.toml
    • it is declared under tool.poetry.packages - see other community modules
    • it is declared under tool.poetry.extras with the same name as your module name,
      we still prefer adding NO EXTRA DEPENDENCIES, meaning mymodule = [] is the preferred addition
      (see the notes at the bottom)
  • Your branch is up-to-date (or your branch will be rebased with git rebase)

Replace deprecated @wait_container_is_ready decorator in PostgresContainer
with new ExecWaitStrategy for checking database readiness.

- Add ExecWaitStrategy to core wait_strategies module for command-based
  readiness checks
- Update PostgresContainer._connect() to use ExecWaitStrategy with psql
- Remove dependency on deprecated wait_container_is_ready decorator
- Strategy executes psql command to verify database is accepting connections
- Add runtime check for exec support (DockerContainer only)

The new ExecWaitStrategy is reusable for any DockerContainer that needs to
execute commands to check readiness (databases, CLI tools, etc).

Note: ExecWaitStrategy requires containers with exec support and will not
work with ComposeContainer. The runtime check provides a clear error if used
incorrectly.
@tylernisonoff tylernisonoff changed the title Add ExecWaitStrategy and migrate Postgres from deprecated decorator feat: Add ExecWaitStrategy and migrate Postgres from deprecated decorator Dec 4, 2025
@alexanderankin alexanderankin merged commit 2d9eee3 into testcontainers:main Dec 5, 2025
7 of 11 checks passed
@codecov
Copy link

codecov bot commented Dec 5, 2025

Codecov Report

❌ Patch coverage is 10.71429% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.18%. Comparing base (37f5902) to head (ac8e151).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
core/testcontainers/core/wait_strategies.py 10.71% 25 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #935      +/-   ##
==========================================
- Coverage   79.78%   78.18%   -1.60%     
==========================================
  Files          14       14              
  Lines        1182     1210      +28     
  Branches      184      187       +3     
==========================================
+ Hits          943      946       +3     
- Misses        197      222      +25     
  Partials       42       42              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants