테스트: 당신의 안전망
테스트는 다른 코드가 당신이 기대하는 대로 동작하는지 점검하는 코드다. 한번 작성되면 몇 초 만에 돌아가며 무언가 퇴행했는지 즉시 알려준다.
100% 커버리지가 필요하지는 않다. 깨졌을 때 가장 아플 것들부터 테스트하라: 로그인, 결제, 재생성할 수 없는 데이터, 핵심 비즈니스 로직. AI는 테스트 작성에 탁월하다 — 기대 동작이 구체적이기 때문에 종종 기능 작성보다 더 낫다.
다음은 잘 작동하는 프롬프트다:
src/pricing.js의 calculateDiscount 함수에 대한 테스트를 작성하라.
다음을 다뤄라: 정상 케이스, 0/빈 케이스, 최대 할인
경계, 그리고 잘못된 입력 하나. 이 저장소의 기존 테스트 설정을
사용하라 (다른 *.test.js 파일들이 어떻게 구성됐는지 확인하라).
끝내기 전에 테스트를 실행해서 통과하는 것을 내게 보여라.
그 마지막 줄이 중요하다. AI에게 테스트를 작성만 하지 말고 항상 실행하라고 요청하라. 한 번도 실행되지 않은 테스트는 추측이다. 어떤 케이스를 다룰지 구체적으로 말하는 것도 가치가 있는데, 내버려두면 AI는 정상 경로의 변주 세 개를 써놓고 철저하다고 부르는 경향이 있기 때문이다. 실제로 버그를 잡는 케이스는 지루한 것들이다: 빈 입력, 경계값, 던져야 마땅한 것.
AI가 만들어내야 할 간단한 예시:
import { calculateDiscount } from "./pricing.js";
import { describe, it, expect } from "vitest";
describe("calculateDiscount", () => {
it("applies a normal percentage discount", () => {
expect(calculateDiscount(100, 0.2)).toBe(80);
});
it("returns the full price when discount is zero", () => {
expect(calculateDiscount(100, 0)).toBe(100);
});
it("never discounts below zero", () => {
expect(calculateDiscount(100, 1.5)).toBe(0);
});
it("rejects a negative price", () => {
expect(() => calculateDiscount(-10, 0.2)).toThrow();
});
});
나중에 기능을 바꿀 때는 테스트를 먼저 돌려라. 빨간불이 들어오면, 사용자보다 먼저 당신이 그 깨짐을 찾은 것이다. AI가 버그를 고칠 때는, 옛 동작에서 실패하는 테스트를 추가하라고 요청하라 — 그래야 버그가 조용히 다시 돌아올 수 없다. 이 습관에는 이름이 있다: 회귀 테스트(regression test). 당신이 마주친 모든 버그는 코드베이스가 대가를 치르고 얻은 교훈이다; 회귀 테스트는 그 교훈을 지키는 방법이다.
한 가지 경고: 테스트도 틀릴 수 있다. AI가 버그가 있는 동작이 올바르다고 단언하는 테스트를 쓰면, 그 테스트는 영원히 통과하면서 당신 앱은 깨진 채로 남는다. 그러니 초록 체크 표시만이 아니라 단언(assertion)을 읽어라. 통과하는 테스트는 "코드가 테스트가 말하는 대로 동작한다"만 의미한다 — 그 테스트가 옳은 것을 말하는지는 여전히 당신이 확인해야 한다.