Skip to content

Fix integration test warnings and restore container log streaming - #98

Open
oysand wants to merge 2 commits into
equinor:mainfrom
oysand:fix-integration-test-warnings
Open

Fix integration test warnings and restore container log streaming#98
oysand wants to merge 2 commits into
equinor:mainfrom
oysand:fix-integration-test-warnings

Conversation

@oysand

@oysand oysand commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

The integration test suite emits 54 warnings on main (c2dca4b). Investigating them turned up a real defect: container log streaming has never worked.

PytestUnhandledThreadExceptionWarning (39 warnings)

StreamLoggingDockerContainer started its log streaming thread in __init__, i.e. before .start() had been called, so _container was still None. The thread then began with:

while not self.get_wrapped_container():

That guard assumes the accessor returns None when the container is not yet started, which was true of an older testcontainers API. In 4.x it raises ContainerStartException instead. Every streaming thread therefore died on its first statement, for every container in every test. The logger.info(...) call below it was unreachable, which is why -s never showed any container output despite the class existing to provide exactly that.

The thread is now started from an overridden start(), after super().start(), where the container is guaranteed to exist — so the polling loop is unnecessary and is removed. It is also marked as a daemon, and stop() signals it and joins it so pytest cannot observe a dying thread after a test ends.

The stream body is wrapped in try/except: logs(stream=True, follow=True) is a blocking generator that fails when the fixture removes the container during teardown. Without this, fixing the bug above simply converts the warnings into a new batch of the same warnings.

DeprecationWarning from testcontainers.postgres (15 warnings)

That module is now a re-export shim that warns on import; the implementation lives in testcontainers.community.postgres and exposes an identical PostgresContainer.

Verification

uv run --frozen pytest -s -n auto robotics_integration_tests, on macOS/arm64:

before after
result 4 passed, 54 warnings 4 passed, 0 warnings
streamed container log lines 0 3829

Zero warnings alone would not have been sufficient evidence — a silent run would equally mean the thread never ran. The streamed output is the actual acceptance criterion.

Also verified:

  • the class in isolation against a throwaway alpine container: logs stream, the thread joins cleanly on exit, no exception;
  • no log streaming stopped messages in the full run, so teardown is genuinely clean rather than having its errors swallowed;
  • the first commit standalone (1 passed, carrying only the thread warnings that the second commit removes), per the checklist item that every commit runs individually.

Notes for reviewers

  • No test logic is touched. wait_for_sara_logs uses container.get_logs() directly and is unaffected.
  • All seven create_* factories return an unstarted container that callers enter via with/enter_context, so start() is always invoked; it returns self to keep the chained builder calls working.
  • Runs are now considerably more verbose under -s. That is the intended behaviour of this class, and CI only surfaces the output on failure.

Checklist

  • Self-review performed
  • Every commit runs individually
  • No leftover logging or TODOs
  • Tested locally
  • A test was written — not applicable: this fixes the test harness itself, and the assertion is the suite reaching zero warnings while emitting container logs

oysand added 2 commits August 21, 2026 14:46
testcontainers.postgres is a re-export shim that emits a
DeprecationWarning on import. The implementation now lives in
testcontainers.community.postgres, which exposes an identical
PostgresContainer.
The log streaming thread was started in __init__, before the container
existed. Its first statement called get_wrapped_container(), which
raises ContainerStartException while _container is None rather than
returning None as an earlier testcontainers API did. The thread
therefore died immediately every time, so container logs were never
streamed and each container produced a PytestUnhandledThreadExceptionWarning.

Start the thread from start() instead, once the container is guaranteed
to exist, which also removes the need to poll for it. Mark it as a
daemon, stop and join it in stop(), and tolerate the stream failing when
the container is removed during teardown.
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.

1 participant