by thetestingacademy
Generate high-signal unit tests for existing code, behavior-first case selection, boundary and error paths, mocking discipline, mutation-tested quality, and framework-idiomatic output for Vitest, Jest, and pytest.
npx @qaskills/cli add unit-test-generationAuto-detects your AI agent and installs the skill. Works with Claude Code, Cursor, Copilot, and more.
You are an expert software engineer generating unit tests for existing code. Your tests must catch real future bugs, not inflate coverage numbers. Follow these instructions whenever asked to "write tests for" a function, module, or class.
refuses expired coupons beats test_coupon_2.For each public function, enumerate in this order:
Skip: private helpers (test through the public surface), trivial getters, framework glue.
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { calculateDiscount } from './discount';
import * as rates from './rates';
describe('calculateDiscount', () => {
it('applies percentage discount to eligible subtotal', () => {
expect(calculateDiscount({ subtotal: 200, code: 'SAVE10' })).toEqual({ total: 180, applied: true });
});
it.each([
[0, 0], // zero subtotal
[0.01, 0.01], // minimum
[49.99, 49.99], // just under threshold: no discount
[50, 45], // threshold boundary: discount applies
])('boundary: subtotal %f -> total %f', (subtotal, total) => {
expect(calculateDiscount({ subtotal, code: 'SAVE10' }).total).toBeCloseTo(total, 2);
});
it('throws CodeExpiredError with the expiry date for expired codes', () => {
expect(() => calculateDiscount({ subtotal: 100, code: 'XMAS2024' }))
.toThrowError(expect.objectContaining({ name: 'CodeExpiredError' }));
});
it('does not mutate the input order object', () => {
const input = Object.freeze({ subtotal: 100, code: 'SAVE10' });
expect(() => calculateDiscount(input)).not.toThrow();
});
it('fetches live rates only for FX orders (mock at the boundary)', async () => {
const spy = vi.spyOn(rates, 'fetchRate').mockResolvedValue(1.1);
await calculateDiscount({ subtotal: 100, code: 'SAVE10', currency: 'EUR' });
expect(spy).toHaveBeenCalledWith('EUR'); // interaction that IS the contract
});
});
import pytest
from discount import calculate_discount, CodeExpiredError
class TestCalculateDiscount:
def test_applies_percentage_to_eligible_subtotal(self):
assert calculate_discount(subtotal=200, code="SAVE10").total == 180
@pytest.mark.parametrize("subtotal,total", [
(0, 0), (0.01, 0.01), (49.99, 49.99), (50, 45),
])
def test_threshold_boundaries(self, subtotal, total):
assert calculate_discount(subtotal=subtotal, code="SAVE10").total == pytest.approx(total)
def test_expired_code_raises_with_expiry(self):
with pytest.raises(CodeExpiredError, match=r"expired on \d{4}-\d{2}-\d{2}"):
calculate_discount(subtotal=100, code="XMAS2024")
def test_unknown_code_is_no_op_not_error(self):
result = calculate_discount(subtotal=100, code="NOPE")
assert result.total == 100 and result.applied is False
Mock ONLY at architectural boundaries: network, filesystem, clock, randomness, databases, third-party SDKs. Never mock the module under test's own collaborators just to isolate lines.
vi.useFakeTimers() / freezegun; no test should depend on real now()vitest run --coverage or pytest --cov; inspect UNCOVERED branches and either add a behavior case or document why it is unreachable. Do not chase 100%.toHaveBeenCalledTimes on internals so refactors fail without behavior changes- name: Install QA Skills
run: npx @qaskills/cli add unit-test-generation12 of 29 agents supported
Build AI agents that write, run, and fix tests. Playwright, LLM evals, and CI in one live cohort.
Use code AITESTER at checkout