"테스트는 숨 참지 않고 코드를 바꾸기 위해 존재해."
종교적 답 (건너뛰어)
"왜 테스트해?" 에 대한 종교적 답은 보통 이래: "테스트는 정확성을 증명해," "TDD 만이 유일한 길이야," "Coverage 100% 가 곧 품질이야." 다 틀려. 실제로 프로덕션 코드 ship 하는 일하는 엔지니어들은 알아. 테스트는 정확성을 증명 하지 않아 — 샘플링 해. TDD 는 여러 워크플로우 중 하나일 뿐이야. Coverage 는 후행 지표라서, 쓰레기 코드를 100% 커버해도 그래도 쓰레기야.
일하는 엔지니어의 답
진짜 이유는 이거야: 코드를 바꿀 때 숨 안 참아도 되게 하려고. 6개월 후에 auth handler 를 refactor 해야 할 거고, Next.js major 두 칸 올려야 할 거고, 갑자기 abandoned 된 라이브러리를 교체해야 할 거야. 그때 너랑 "내가 방금 까먹은 뭔가를 깬 거 아닐까?" 사이를 막아주는 게 test suite 야.
나머지는 — coverage 퍼센트, 코드 리뷰 체크 마크, 심지어 버그를 그 순간 잡는 것 자체 — 다 부수 효과야. 본질 가치는 신뢰지. 통과하는 suite 가 너에게 '바꿀 권리' 를 사줘.
모든 테스트의 모양 — AAA
Arrange. Act. Assert.
Arrange 는 세계를 준비해 — 입력, fixture, mock 다 세팅. Act 는 대상 코드를 실행 — 함수 호출, 버튼 클릭. Assert 는 결과 확인 — 뭐가 돌아왔는지, 뭐가 바뀌었는지, 뭐가 불렸는지.
너무 작아서 세 단계가 한 줄에 뭉치는 테스트도 있어. 근데 구조는 그대로야. 테스트가 정신없게 느껴지면 보통 AAA 가 망가진 거야 — act 안에서 너무 많이 arrange 한다거나, assertion 이 본문 곳곳에 흩어졌다거나. 떼어내면 테스트가 알아서 읽혀.
테스트가 아닌 것
테스트는 정확성의 증명 이 아냐 — 모든 입력을 열거할 수 없어. 테스트는 스펙 도 아냐 — 스펙은 바뀌고, 테스트는 커밋이야. 테스트는 문서 도 아냐 — 대체로. 좋은 테스트 이름은 문서처럼 읽히긴 하지만. 테스트는 코드 리뷰 도 아냐. 초록 suite 가 좋은 설계를 의미하지도 않아.
테스트가 뭐냐면: 작은 낙하를 잡는 안전망, 큰 낙하를 알리는 경보. 그게 다야. 그거면 충분해.