Skip to content

Open source, Python and pytest, runs locally

Catch test weakeningbefore it merges.

TestSeal compares the before and after syntax of Python tests and flags removed assertions, new skips, wider tolerances, and other changes that make a green suite less meaningful.

Deterministic and offline. No LLM, API key, telemetry, or project-code execution.

Example TestSeal pull request report
TSPull request report
SCAN COMPLETE
tests/test_totals.py2 lines changed
8def test_discount_total():
9 total = calculate_total(cart)
10 assert total == Decimal("19.99")
10+ assert total
11 assert receipt.currency == "USD"
$testseal scan --diff examples/diffs/assertion-weakened.diff
1 high findingadvisory modeJSON and SARIF available
AST-awarebefore / after analysis
Offlineno network boundary
Portabletext / JSON / SARIF
ConsistentCLI / hook / Action

The gap in ordinary CI

A green build can outlive the guarantee it was meant to enforce.

Both sides of a weakened assertion can be valid Python. Linters stay quiet, tests stay green, and the semantic downgrade gets buried inside the diff.

Ordinary CI
Did the current suite pass?
TestSeal
Did the suite become easier to pass?

TestSeal reports the observed transformation. It does not infer intent, authorship, or whether AI wrote the change.

Eight deterministic checks

Focused on test integrity.

Every rule describes a concrete before-and-after transformation. Context-heavy signals remain lower severity and advisory.

RuleSignalWhat changedSeverity
TS001Assertion removedA previously enforced condition disappears from a test.High
TS002Test disabledA skip, skipif, xfail, or unittest marker is introduced.High
TS003Assertion weakenedA precise comparison becomes a truthy or non-null check.High
TS004Tolerance widenedNumeric tolerance grows or decimal precision drops.High
TS005Exception swallowedA broad handler can fall through without validation.High
TS006Snapshot regeneratedSnapshot update behavior or an artifact enters the diff.Low
TS007Subject mockedA new patch target overlaps with the behavior under test.Medium
TS008Guard co-editedSource and its configured guarding test change together.Low
Supported patterns and limits

One engine, three review surfaces

Run it where the change happens.

The Python analyzer owns every finding. Local scans and CI annotations stay consistent because there is no second detection engine.

CLI

Review a branch locally

Run the same analyzer before opening a pull request.

terminal
testseal scan --base origin/main --head HEAD
pre-commit

Inspect staged changes

Keep the default advisory posture or set a threshold.

.pre-commit-config.yaml
repos:
  - repo: https://github.com/satwiksps/testseal
    rev: v0.1.0
    hooks:
      - id: testseal
GitHub Actions

Annotate the pull request

Install bundled source and annotate the exact changed lines.

.github/workflows/testseal.yml
name: Test integrity
on: [pull_request]
permissions:
  contents: read
jobs:
  testseal:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          fetch-depth: 0
      - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
        with:
          python-version: "3.12"
      - uses: satwiksps/testseal@v0.1.0
        with:
          fail-on: high

Small, explicit trust boundary

Inspect the diff. Do not execute it.

TestSeal reads Git changes and Python syntax. It never imports the target repository or runs code from the pull request.

Read the architecture
  1. 01

    Read the change

    Git refs, staged changes, the working tree, or a unified diff.

  2. 02

    Hydrate both states

    Recover complete before and after Python source where available.

  3. 03

    Compare syntax

    Evaluate narrow AST-level transformations with documented limits.

  4. 04

    Publish evidence

    Return file, line, rule, severity, evidence, and remediation.

No importsNo test runsNo model callsNo telemetry

Install the release

Add a second signal to your next Python review.

Install v0.1.0, evaluate findings in advisory mode, and opt into blocking after measuring your baseline.

terminal
python -m pip install testseal
testseal scan --base origin/main --head HEAD

Apache-2.0, Python 3.11+, advisory by default

View on PyPI