Skip to content

Stop three tests failing on every pull request - #164

Merged
mihow merged 2 commits into
mainfrom
fix/ci-network-dependent-tests
Sep 12, 2026
Merged

mihow merged 2 commits into
mainfrom
fix/ci-network-dependent-tests

Conversation

@mihow

@mihow mihow commented Aug 12, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Three tests fail on pull requests for reasons unrelated to what those pull requests change. One fails on every run: it downloads a thumbnail from Wikimedia, which now refuses arbitrary thumbnail widths and returns an HTTP 400 pointing at its allowed-sizes policy. The other two fail intermittently: they test whichever sample image the filesystem happens to list first, and one of the sample images is an empty frame with nothing for the detector to find. This makes all three reliable, by serving the thumbnail from a local test server and by having tests pick their images deterministically. No application code changes; the fixes are entirely in the tests and their helpers.

None of this was caused by an open pull request. The last test run on main (2026-04-14) passed. The Wikimedia change happened after that, and main has not had a test run since, so its green status is out of date rather than evidence that the suite still passes.

The two intermittent failures were not network problems at all. The two API tests asked for "the first" trap image and then checked that the ML pipeline found insects in it. The helper picked that image from an unsorted directory listing, so which image a test got depended on filesystem ordering, which differs between checkouts and between runs. When the listing put the empty Vermont frame first, the pipeline correctly returned no detections and the test had nothing to assert on. Whenever it put a different image first, the same tests passed, which is why they looked flaky rather than broken.

List of Changes

# Change (what it means for the reader) How (implementation)
1 Tests that check the ML pipeline found insects always run against an image that actually contains insects, instead of whichever image the filesystem happened to return first. test_logits_in_classification_response and test_config_num_classification_predictions pass an explicit filename via a new IMAGE_WITH_DETECTIONS constant in trapdata/api/tests/utils.py.
2 Every test that pulls sample images gets the same images on every machine and every run. This includes the Antenna worker and memory-leak tests, which now also receive images in sorted order; they already allow for an image without detections, so what they check is unchanged. get_test_image_urls sorts the glob result and accepts an optional filenames argument, added last so existing callers are unaffected. The helpers pass subdir, num and filenames to each other by keyword.
3 The source image URL test no longer reaches out to the public internet, so it cannot break again when a third-party host changes what it will serve. test_url writes an image to a temporary directory and serves it through StaticFileTestServer, which the repository already uses for this purpose. The same download-and-open code path is exercised, and the image has unequal dimensions so a mixed-up image would be caught, not only a failed download.

Verification

When this pull request was opened (2026-08-12), run against this branch with the GPU disabled, matching the CPU-only CI runners:

  • Full suite: 39 passed, 1 skipped, 0 failed.
  • The three previously failing tests passed.
  • Negative control: temporarily pointing IMAGE_WITH_DETECTIONS at the empty frame reproduced the exact CI failure (AssertionError: No detections found in response), confirming the image choice is what these tests turn on.
  • Pinned tooling was clean on the changed files: black 22.3.0, isort 5.11.5, flake8 4.0.0 with bugbear and comprehensions, autoflake 1.4.

Rechecked on 2026-09-11, during review:

Notes for reviewers

🤖 Generated with Claude Code

…emote host

Three tests fail on every pull request for reasons unrelated to the changes
under review, which blocks anything from merging on a green check.

Two API tests asked for "the first" Vermont trap image and then asserted that
the pipeline returned detections. The helper took that image from an unsorted
glob, so which image it got depended on directory order, which differs between
a developer checkout and a fresh CI checkout. One of the three Vermont images
is an empty frame where nothing clears the detector's 0.80 score threshold, and
CI consistently picked it, so the pipeline correctly returned zero detections
and the assertions failed. The helper now sorts, and both tests name the image
they need.

The source image URL test fetched a thumbnail from a third-party host that now
rejects arbitrary thumbnail widths with an HTTP 400. It now serves the image
from the local test HTTP server the repository already uses elsewhere, which
exercises the same download path without depending on the public internet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HcXFHJRXMrsHPX7xz9ZifF
@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 34 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: f2546da9-c236-404e-8b9c-4e4fe51f853b

📥 Commits

Reviewing files that changed from the base of the PR and between a33746a and a1f1ad9.

📒 Files selected for processing (3)
  • trapdata/api/tests/test_api.py
  • trapdata/api/tests/test_models.py
  • trapdata/api/tests/utils.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mihow mihow left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude says: Reviewed in place of the CodeRabbit pass that was rate-limited. This looks good to merge. It is posted as a comment review because it comes from the author's account, which cannot approve its own pull request.

What's solid

  • Each fix targets the actual cause. Sorted selection removes the dependence on directory order, the two pipeline tests name an image that has detections, and test_url serves a generated image from the existing local test server (free port, context manager) while exercising the same download-and-open path.
  • The unequal image dimensions in test_url are a nice touch: they would catch a mixed-up image, not only a failed download.
  • filenames is added as the last parameter, so existing callers are unaffected. The six callers in trapdata/antenna/tests/ now also receive sorted images; I checked that each tolerates an image without detections (len(response.detections) >= 0, or an explicit empty check), so the deterministic order does not introduce a new failure mode.

Worth knowing before merge

  1. The green checks predate the object store move. They ran on 2026-08-12. The CI workflow has no model cache, and the insect-orders pipeline these tests use downloads its weights from the previous object store host, which now returns 403 for both the classifier and the detector weights; the URLs in #168 return 200. A re-run of this pull request on its own would likely fail on those downloads. The two pull requests complement each other: #168's CI currently fails only TestSourceImageSchema::test_url, which this one fixes. Suggest merging this first and then updating #168's branch, which should come back green.
  2. Description wording. "Three tests have been failing on every pull request" holds for test_url, but the two order-dependent tests fail intermittently rather than every time; both passed in #168's latest CI run. The fix is still the right one, since it removes the flakiness. It may also be worth a line pointing at #168, because the remote-weights dependency mentioned under "Notes for reviewers" has since become a real failure.

Smaller cleanups (low priority)

Three inline suggestions: an existence check for explicitly named fixtures, an assertion that can no longer fail, and passing arguments by keyword. None of them block merging.

if filenames is None:
paths = sorted(images_dir.glob("*.jpg"))[:num]
else:
paths = [images_dir / filename for filename in filenames]

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude says: Small robustness suggestion: an explicitly named file is not checked for existence here, so if the fixture is ever renamed or removed, the test would likely fail as a 404 from the test server inside the pipeline rather than as a clear missing-fixture error. For example:

paths = [images_dir / filename for filename in filenames]
missing = [path.name for path in paths if not path.exists()]
assert not missing, f"Test images not found in {images_dir}: {missing}"

It may also be worth saying in the docstring that num is ignored when filenames is given.

"""
test_images = self.get_test_images(num=1)
test_images = self.get_test_images(filenames=[IMAGE_WITH_DETECTIONS])
assert test_images, "No test images found"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude says: With an explicit filename this assertion can no longer fail, because the helper always returns one URL per filename. It could be dropped, or made meaningful again by the existence check suggested in utils.py. The same applies at line 191.

Comment thread trapdata/api/tests/test_api.py Outdated
The wrapper in test_api.py and the helper chain in utils.py passed subdir, num and filenames positionally. Passing them by keyword keeps these calls correct if another optional parameter is added to the helpers later.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012iwV2sD1vVtL5xEUN8Rgf3
@mihow

mihow commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator Author

The remaining CI failures are due to the new model URLs. Merging this, then will work on #168

@mihow
mihow merged commit 2baee25 into main Sep 12, 2026
2 of 5 checks passed
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