पाठ 14 / 25
Detecting Test Tampering
Removed assertions, skips and trivial tests.
Look at what changed in tests
The most common way to "fix" a failing test without fixing the code is to change the test: delete assertions, add skip or xfail markers, loosen expected values, or replace checks with assertions that are always true. A tampering detector scans the patch for these patterns. Simplest policy for autonomous fixes: test files are read-only; tests are added or changed only in a separate, human-reviewed step.
Block the cheats and the leaks
Mechanical checks stop test tampering, edits to protected files and leaked secrets.
Scanning patches for test tampering, run
I ran this with Python 3 (standard library) and, where it uses git, real git in a throwaway temporary repository. Candidate patches are written by hand to stand in for model output. An honest one-line code fix is clean. A cheating patch is flagged three times: an assertion removed, a skip decorator added, and a trivial assertTrue(True) added. Pattern checks catch common cases; making tests read-only closes the loophole entirely.
import re
def review_test_changes(diff):
findings = []
for line in diff.splitlines():
if line.startswith("-") and re.search(r"\bassert", line) and not line.startswith("---"):
findings.append("assertion removed: " + line[1:].strip())
if line.startswith("+") and re.search(r"@(unittest\.)?skip|pytest\.mark\.(skip|xfail)", line):
findings.append("test skipped: " + line[1:].strip())
if line.startswith("+") and re.search(r"assert\w*\(.*\b(True|1)\)\s*$", line):
findings.append("trivial assertion added: " + line[1:].strip())
return findings
honest = """--- a/pricing.py
+++ b/pricing.py
- if code == "FLAT50" and total > 50:
+ if code == "FLAT50" and total >= 50:"""
cheating = """--- a/test_pricing.py
+++ b/test_pricing.py
- self.assertEqual(discount(50, "FLAT50"), 0)
+ @unittest.skip("flaky")
+ self.assertTrue(True)"""
for name, diff in [("honest patch", honest), ("cheating patch", cheating)]:
f = review_test_changes(diff)
print(name, "->", "clean" if not f else f)
Output:
honest patch -> clean
cheating patch -> ['assertion removed: self.assertEqual(discount(50, "FLAT50"), 0)', 'test skipped: @unittest.skip("flaky")', 'trivial assertion added: self.assertTrue(True)']Make tests read-only for bots
Enforce at the file level (protected paths) instead of relying only on pattern detection.
त्वरित जाँच: Which change should a tampering check flag?
- Renaming a local variable in source
- Changing > to >= in source code
- Adding a docstring to a function
- Adding @unittest.skip to the failing test
Answer
Adding @unittest.skip to the failing test — Skipping a test hides the failure.