Skip to content

Test Polarity Deficit Signal (TPD)

Signal ID: TPD
Full name: Test Polarity Deficit
Type: Scoring signal (contributes to drift score)
Default weight: 0.04
Scope: file_local


What TPD detects

TPD detects test suites that contain only happy-path assertions — tests that verify correct behavior but never test boundary conditions, error cases, or invalid inputs. A test suite that only checks "does it work?" without checking "does it fail correctly?" provides incomplete safety.

Before — happy path only

# tests/test_calculator.py
def test_add():
    assert add(2, 3) == 5

def test_subtract():
    assert subtract(10, 4) == 6

def test_multiply():
    assert multiply(3, 7) == 21

Three tests, all positive. No tests for divide-by-zero, overflow, or invalid inputs.

After — balanced polarity

def test_add():
    assert add(2, 3) == 5

def test_subtract():
    assert subtract(10, 4) == 6

def test_divide_by_zero():
    with pytest.raises(ZeroDivisionError):
        divide(10, 0)

def test_add_invalid_type():
    with pytest.raises(TypeError):
        add("a", 3)

def test_multiply_overflow():
    assert multiply(MAX_INT, 2) == expected_overflow_result

Why test polarity matters

  • False confidence — 100% passing tests with only happy paths gives a false sense of security.
  • AI generates happy-path tests by default — LLMs produce tests that verify the example output, not edge cases.
  • Bugs live in edge cases — the most dangerous bugs are in error paths, boundary conditions, and unexpected inputs.
  • Regression risk — without negative tests, error-handling changes can silently break without any test failure.

How the score is calculated

TPD analyzes each test file for the presence of negative test indicators:

  1. Check for pytest.raises — standard pytest error expectation.
  2. Check for assertRaises — unittest-style error expectations.
  3. Check for boundary/edge-case assertions — comparisons against zero, None, empty containers, limits.
  4. Calculate polarity ratio — tests with negative assertions vs. total tests.

Modules where < 20% of tests have negative polarity are flagged.

Severity thresholds:

Score range Severity
≥ 0.7 HIGH
≥ 0.5 MEDIUM
≥ 0.3 LOW
< 0.3 INFO

How to fix TPD findings

  1. Add error-case tests — for each function, ask "what should happen with invalid input?"
  2. Use pytest.raises — explicit error expectations are more readable than try/except in tests.
  3. Test boundary conditions — empty lists, None, zero, maximum values.
  4. Follow the testing pyramid for polarity — aim for ≥ 30% negative/boundary tests.

Configuration

# drift.yaml
weights:
  test_polarity_deficit: 0.04   # default weight (0.0 to 1.0)

Detection details

  1. Identify test files via naming conventions (test_*.py, *_test.py).
  2. Parse test functions from AST.
  3. Scan for negative indicatorspytest.raises, assertRaises, with self.assertRaises, exception-related assertions.
  4. Calculate polarity ratio per test file.
  5. Flag test files below the negative polarity threshold.

TPD is deterministic and AST-only.


  • EDS (Explainability Deficit) — checks for test existence. TPD checks for test quality.
  • BAT (Bypass Accumulation) — detects @pytest.mark.skip markers. TPD detects missing negative tests.