うまく使うと、AI は testing の enumeration 部分、つまり edge case を brainstorm し boilerplate を速く書くことに非常に向いています。ただし、assertion が意味を持つかは必ず verify する必要があります。AI は何も証明しない test でも平気で書くからです。
// Function under test, with its contract:
// applyDiscount(price, percent) -> price reduced by percent.
// Contract: percent must be 0..100; throws RangeError otherwise. price >= 0.
function applyDiscount(price, percent) {
if (percent < 0 || percent > 100) throw new RangeError('percent out of range');
return price - (price * percent) / 100;
}
// AI-suggested test cases (Jest) — happy path だけでなく edge と error path に注目:
test('applies a normal discount', () => {
expect(applyDiscount(100, 20)).toBe(80); // happy path
});
test('0% leaves price unchanged', () => {
expect(applyDiscount(100, 0)).toBe(100); // boundary: lower edge
});
test('100% makes it free', () => {
expect(applyDiscount(100, 100)).toBe(0); // boundary: upper edge
});
test('rejects percent above 100', () => {
expect(() => applyDiscount(100, 150)).toThrow(RangeError); // error path
});
AI は 0 と 100 の boundary case、そして忘れがちな error path を提案しました。あなたの仕事は toBe(80) が function の現在の return ではなく、正しい expected value であることを確認することです。
test の難しい部分は test(...) block を typing することではなく、見落としがちな case を考えることです。AI はその breadth に本当に向いています。ただし、あなたが伝えない限り、code が 何をすべきか は分かりません。放置すると implementation を mirror する test を書きがちです。これは pass しますが、function が間違っていても pass します。AI を edge-case generator として扱い、assertion の責任を自分で持つことで、広い coverage と本当の correctness を両立できます。speed は AI から、judgment はあなたからです。