Generates pytest regression tests that capture current behavior as snapshot assertions, using Python's dynamism for low-friction recording. Use before refactoring untested Python, when the behavioral spec is "whatever it does now," or when migrating Python 2→3 or between framework versions.
Install with Tessl CLI
npx tessl i github:santosomar/general-secure-coding-agent-skills --skill python-regression-test-generator100
Quality
100%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Same idea as → java-regression-test-generator — capture current behavior, lock it in — but Python's tooling makes capture easier: pickle snapshots, syrupy/pytest-snapshot, and duck typing means fewer fixture gymnastics.
| Approach | Effort | When |
|---|---|---|
Snapshot library (syrupy) | Lowest | Outputs are dicts/lists/strings — most cases |
| Pickle round-trip | Low | Complex custom objects with sane __eq__ |
| Explicit field assertions | Medium | You want readable diffs when things break |
| Golden files | Medium | Large outputs (rendered HTML, CSVs) |
Default to snapshot libraries for the bulk, explicit assertions for the handful of truly critical paths.
# First run with --snapshot-update: records current output
# Subsequent runs: compares against recorded
def test_price_two_items_us(snapshot):
order = Order(
items=[LineItem("sku-1", 2, Decimal("10.00")),
LineItem("sku-2", 1, Decimal("5.50"))],
region="US",
discount=None,
)
assert engine.price(order) == snapshotSnapshot lives in __snapshots__/test_pricing.ambr. When behavior changes, diff is shown. Accept with --snapshot-update or fix the regression.
For the few paths you really care about, write it out:
def test_price_enterprise_eu_discount():
"""
Captured 2024-01-15. The EU enterprise discount is 15% — as observed,
no spec found. If this breaks, verify with product before updating.
"""
order = Order(
items=[LineItem("sku", 1, Decimal("100.00"))],
region="EU",
tier="enterprise",
)
invoice = engine.price(order)
assert invoice.subtotal == Decimal("100.00")
assert invoice.discount == Decimal("15.00") # 15% — observed, not spec'd
assert invoice.tax == Decimal("17.00") # 20% VAT on post-discount 85
assert invoice.total == Decimal("102.00")Explicit fields → readable failure: assert Decimal('17.00') == Decimal('20.00') tells you exactly what changed.
Python lets you record real inputs cheaply:
# Wrap the real function — deploy briefly to staging, collect inputs
_captured = []
def capturing_price(self, order):
result = _original_price(self, order)
_captured.append((copy.deepcopy(order), copy.deepcopy(result)))
return result
PricingEngine.price = capturing_price
# ... run realistic traffic ...
# Dump
with open("regression_cases.pkl", "wb") as f:
pickle.dump(_captured, f)Then generate:
with open("regression_cases.pkl", "rb") as f:
CASES = pickle.load(f)
@pytest.mark.parametrize("order,expected", CASES, ids=lambda c: repr(c)[:60])
def test_price_regression(order, expected):
assert engine.price(order) == expectedReal traffic → realistic edge cases you wouldn't think of.
| Issue | Fix |
|---|---|
datetime.now() | freezegun.freeze_time("2024-01-15") decorator |
time.time() | Same — freezegun patches both |
uuid.uuid4() | mocker.patch("uuid.uuid4", side_effect=[UUID("..."), ...]) or assert format |
random | random.seed(0) at test start, or inject Random(0) |
dict order | Guaranteed insertion-ordered since 3.7 — only a problem if code uses set or pre-3.7 |
set iteration | assert sorted(result) == sorted(expected) |
| Float precision | pytest.approx(expected, rel=1e-9) |
PYTHONHASHSEED | Set to fixed value in conftest if hashing user strings |
@pytest.mark.xfail(
reason="Bug #1234: tax computed on post-discount subtotal. "
"Spec says pre-discount. Expected 9.00, currently 8.10. "
"When fixed, flip strict=True → test must pass.",
strict=False,
)
def test_discount_tax_base_KNOWN_BUG():
...
assert invoice.tax == Decimal("9.00") # the CORRECT valuexfail(strict=False) — currently fails, that's expected. When the bug is fixed, test passes → xpass is reported. Flip to strict=True and it becomes a normal passing test.
Alternative: assert the wrong value with a # TRACKING BUG comment. Less elegant (xfail is nicer) but works without xfail semantics.
Order objects might have real customer emails in them.path.relative_to(root), socket.gethostname() → "<host>") before snapshotting.price for an hour in staging: fine. Forgetting to remove it: not fine.## Capture target
<module.function(s)>
## Input set
| # | Input summary | Source | Branches hit |
| - | ------------- | ------ | ------------ |
## Capture approach
<snapshot | explicit | pickle-parametrize | golden>
## Non-determinism
| Source | Fix |
| ------ | --- |
## Generated tests
<pytest code>
## Known-wrong captures
| Test | Bug ref | xfail or tracking-comment |
| ---- | ------- | ------------------------- |
## Coverage delta
Before: <%> After: <%> (branch, via `pytest --cov --cov-branch`)47d56bb
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.