Skip to content

feat(test-integrity): detect weakened Python tests - #99

Merged
caiopizzol merged 3 commits into
mainfrom
feat/test-integrity-pytest
Sep 28, 2026
Merged

caiopizzol merged 3 commits into
mainfrom
feat/test-integrity-pytest

Conversation

@caiopizzol

Copy link
Copy Markdown
Owner

Problem

Test integrity only knew JavaScript tests. On a Python change that weakens tests four ways, it caught only the deleted test file. A new @pytest.mark.skip, an added return before the assertions, and removed assertions all passed.

Change

Detector only (detect.ts). The Python gate is a separate follow-up: the justfile, uv run pytest, and pytest options in pyproject.toml.

  • Test files. test_*.py, *_test.py, and conftest.py are test files, as are files under tests/ as before. Deleting one blocks.
  • Skips block. Each language now has its own rules; JavaScript's are unchanged. The Python ones:
    • pytest and unittest skip and expected-failure markers, as decorators (@pytest.mark.skip, @unittest.skip, @skip), as marks (pytestmark =, pytest.param(marks=…)), or as calls (pytest.skip(), pytest.xfail(), pytest.importorskip(), self.skipTest(), SkipTest);
    • __test__ = False and collect_ignore, which stop pytest collecting tests.
  • Conditional skips report instead of blocking. A skipif, skipIf, skipUnless, or xfail whose condition compares sys.platform, os.name, platform.system(), or an environment variable with a string, and whose reason is plain text. The rules match the JavaScript ones: truthiness conditions such as not IMAGE still block, and so does an or that is always true. skipUnless is read inverted, because it skips when its condition is false.
  • Early exits block. An added bare return, or return None, in a Python test file.
  • Assertions. Removed assert statements, self.assert…(), mock .assert_…() calls, and pytest.raises() or pytest.warns() are counted.

Verification

  • bun run check passes; 93 package tests.
  • Each new rule has a control: removing it fails a named test. There are 16 controls.
  • Replayed over the last 200 commits of a public pytest repository, each commit against its parent: 5 blocked, 0 errors. Each block would need the label:
    • a refactor that moved tests into a new directory, which the detector sees as deletions;
    • two skipif calls on truthiness conditions;
    • a fixture that skips when PostgreSQL is absent;
    • a helper that added return None.
  • The JavaScript replay over two TypeScript repositories gives identical results before and after.

🤖 Generated with Claude Code

caiopizzol and others added 2 commits September 28, 2026 13:55
Treat pytest's test files and conftest.py as tests, and block unconditional
pytest and unittest skips, expected failures, and added bare returns in them.
A skip conditioned on the platform or an environment variable, with a plain
reason, is reported instead. Count assert statements, unittest and mock
assertions, and pytest.raises or warns when assertions are removed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ection switches

return None gives up like a bare return. skipUnless skips when its condition
is false, so an impossible condition is read as always skipping. __test__ =
False and collect_ignore stop pytest collecting tests, like a skip.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@caiopizzol
caiopizzol enabled auto-merge (squash) September 28, 2026 16:59

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/test-integrity/src/detect.ts Outdated
Comment thread packages/test-integrity/src/detect.ts Outdated
Comment thread packages/test-integrity/src/detect.ts Outdated
…t_ignore in conftest only

A skipif may name condition= and reason= in either order. return; gives up
like return. pytest reads collect_ignore only from a conftest, so elsewhere
it is an ordinary name.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@caiopizzol
caiopizzol merged commit bf90fb6 into main Sep 28, 2026
2 checks passed
@caiopizzol
caiopizzol deleted the feat/test-integrity-pytest branch September 28, 2026 17:14
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