💡 Key Takeaways
- The 3 AM Wake-Up Call That Changed How I Think About Testing
- Why Testing Feels Like Pulling Teeth (And Why That's Actually Your Fault)
- The 15-Minute Rule: Making Testing Feel Like Progress, Not Punishment
- The Goldilocks Zone: Testing Just Enough (And Not a Line More)
테스트에 대한 나의 생각을 변화시킨 새벽 3시의 깨우는 전화
화요일 새벽 3시 17분, 내 핸드폰이 울리면서 나를 깨웠다. 우리의 결제 처리 시스템이 다운되었고, 40,000명의 고객이 구매를 완료할 수 없었다. 노트북으로 서둘러 뛰어가며, 배경에서 커피가 끓고 있는 동안 나는 문제의 원인을 발견했다: 어제 저녁 6시에 병합한 겉보기에는 무해한 두 줄의 변경. 어떤 테스트도 이를 잡아내지 못했다. 어떤 CI 파이프라인도 경고하지 않았다. 그것은 우리 수익 흐름을 겨냥한 어뢰처럼 생산으로 무사히 넘어갔다.
💡 주요 내용
- 테스트에 대한 나의 생각을 변화시킨 새벽 3시의 깨우는 전화
- 테스트가 왜 고통스럽게 느껴지는가 (그리고 그것이 실제로 당신의 잘못인 이유)
- 15분 규칙: 테스트를 처벌이 아닌 진행으로 느끼게 하라
- 골디락스 존: 적절한 양의 테스트 (그리고 그 이상은 금물)
그 사건은 우리에게 180,000달러의 판매 손실과 50,000달러의 비상 엔지니어링 시간을 초래했다. 하지만 더 중요한 것은, 나에게 몇 년 전 배워야 했던 것을 가르쳐주었다: 테스트를 작성하는 것은 본질적으로 지루해서가 아니라, 우리가 잘못하고 있기 때문에 지루하다.
나는 마르쿠스 천이며, 11년 동안 선임 소프트웨어 엔지니어로 일해왔고, 마지막 6년은 연간 23억 달러의 거래를 처리하는 핀테크 회사에서 기술 책임자로 일하고 있다. 나는 제 경력 동안 약 47,000줄의 테스트 코드를 작성했으며—맞다, 실제로 git 통계를 사용해 계산했다—나는 테스트를 싫어하는 팀과 이를 수용하는 팀의 차이는 태도가 아니라 접근 방식에 따른 것이라는 것을 배웠다.
일반적으로 통용되는 지혜에 따르면 테스트는 치실질하는 것과 같다고 한다: 모두가 해야 한다는 것을 알고 있지만 그것은 보상을 지연시키는 일처럼 느껴진다. 나는 당신에게 그것이 잘못된 비유라고 말하려고 왔다. 제대로 수행된 테스트는 미래의 나와 대화하는 것과 같으며, 이 대화는 당신을 새벽 3시의 공황 발작과 6자리 숫자의 실수로부터 구해줄 수 있다.
테스트가 왜 고통스럽게 느껴지는가 (그리고 그것이 실제로 당신의 잘못인 이유)
대부분의 개발자가 테스트를 고통스럽게 느끼는 이유에 대해. 내가 3개의 엔지니어링 팀을 대상으로 실시한 설문조사에서 87명의 개발자 중 73%가 "반복적인 보일러플레이트"를 주요 불만으로 언급했으며, 61%가 "테스트할 내용을 명확히 알 수 없음"을 근소한 차이로 두 번째로 언급했다. 실제로 테스트 작성을 즐기는 사람은 12%밖에 없으며, 그 12%는 공통점이 있었다: 테스트가 문서화가 아니라 문제 해결처럼 느껴지도록 하는 시스템을 개발했다.
"테스트는 본질적으로 지루해서가 아니라 우리가 잘못하고 있기 때문에 지루하다. 테스트를 싫어하는 팀과 이를 수용하는 팀의 차이는 태도가 아니라 접근 방식에 따른 것이다."
근본적인 문제는 우리가 테스트를 후순위로 다룬다는 것이다—코드를 배포하기 위해 지불하는 세금처럼 말이다. 우리는 구현을 작성하고, 작동하게 만든 다음, 그것이 실행되는 것을 보는 도파민 히트를 느끼고, 테스트 작성을 생각하며 신음한다. 그 시점에 우리의 뇌는 이미 다음 기능, 다음 문제, 다음 도파민 히트에 대해 생각하고 있다.
이러한 역행적 접근 방식은 여러 가지 문제를 야기한다. 첫째, 이미 작동하는 코드에 대한 테스트를 작성하는 것이므로 중복처럼 느껴진다. 당신의 뇌는 코드가 작동한다는 것을 알고 있다—당신은 그것이 작동하는 것을 보았으니까—그래서 테스트 작성을 바쁜 일로 느낀다. 둘째, 이미 모든 디자인 결정을 내렸기 때문에 테스트는 잠재적으로 테스트할 수 없는 아키텍처에 의해 제약을 받는다. 셋째, 신선한 문제를 해결할 때 오는 창의적인 에너지를 잃게 된다.
나는 이렇게 3년 동안 테스트를 작성했으며, 내 테스트 커버리지는 약 40%에 머물렀다. 게을러서가 아니라, 그 과정이 진짜 고통스러웠기 때문이다. 모든 테스트는 내가 이미 읽었던 소설을 내가 거의 말하지도 않는 언어로 번역하는 것처럼 느껴졌다. 돌파구는 특히 엉망인 인증 흐름에 대해 테스트를 먼저 작성하기 시작했을 때 찾아왔고, 나는 놀라운 사실을 발견했다: 그것은 실제로 구현을 작성하는 것보다 더 즐거웠다.
그 이유는? 먼저 테스트를 작성하면 여전히 문제 해결 모드에 있기 때문이다. API를 설계하고, 엣지 케이스를 생각하고, 아키텍처 결정을 내리고 있다. 당신의 뇌는 기계적인 문서 작업이 아닌 창의적인 작업에 참여하고 있다. 테스트는 명세서이자 디자인 문서이자 안전망으로 변신한다. 갑자기 테스트는 지루하지 않다—오히려 흥미로운 부분이다.
15분 규칙: 테스트를 처벌이 아닌 진행으로 느끼게 하라
내가 테스트와의 관계를 변화시킨 기술이 하나 있다: 나는 15분 이상 테스트를 작성한 후 무엇인가가 통과하는 것을 보지 않는다. 이것은 임의적으로 들릴 수 있지만, 그 뒤에는 심리가 있다. 우리의 뇌는 즉각적인 피드백 루프를 위해 구성되어 있다. 45분 동안 포괄적인 테스트 스위트를 작성하기 전에 아무것도 실행하지 않으면, 당신은 신경 생화학과 싸우고 있는 것이다.
| 테스트 접근 방식 | 시간 투자 | 개발자 경험 | 생산 사고 |
|---|---|---|---|
| 테스트 없음 | 0 시간 소요 | 초기 빠르지만 나중에 스트레스가 큼 | 빈도가 높고 비용이 비쌈 |
| 수동 테스트만 | 기능당 2-3시간 | 반복적이고 지루함 | 중간 빈도 |
| 보일러플레이트가 많은 테스트 | 기능당 4-5시간 | 좌절스럽고 느림 | 빈도 낮으나 테스트가 취약함 |
| 전략적 테스트 | 기능당 2-3시간 | 참여감 및 자신감 상승 | 매우 낮은 빈도 |
| 테스트 주도 개발 | 기능당 3-4시간 | 만족스러운 디자인 과정 | 최소한의 사고 |
그 대신 나는 테스트를 마이크로 사이클로 나눈다. 하나의 테스트를 작성한다. 그것이 통과하게 한다. 또 다른 테스트를 작성한다. 그것이 통과하게 한다. 각 사이클은 5-15분 소요되며, 각 사이클은 작은 성취감을 제공한다. 일반적인 6시간 코딩 세션 동안, 이는 하나의 큰 지연된 보상 대신 24-72개의 작은 승리가 된다.
구체적인 예를 들어보겠다. 지난달 나는 수요, 시간, 사용자 이력에 기반한 동적 가격을 계산하는 기능을 개발하고 있었다. 전체 가격 엔진을 작성한 후 테스트하는 대신, 나는 하나의 테스트로 시작했다: "수요가 낮고 비 peak 시간대일 때, 가격은 기본 요금이어야 한다." 그 테스트를 작성하고 통과하게 하는 데 8분이 걸렸다. 다음: "수요가 높을 때 가격은 20% 증가해야 한다." 또 12분. "수요가 높고 peak 시간대인 경우 가격은 35% 증가해야 한다." 또 10분.
90분 후, 나는 11개의 테스트와 작동하는 가격 엔진을 갖게 되었다. 더 중요한 것은, 나는 지루함을 느끼지 않았다는 것이다. 각 테스트는 해결해야 할 작은 퍼즐이었고, 구현은 테스트에서 자연스럽게 나왔다. 이것을 내 이전 접근 방식과 비교해보면: 가격 엔진 작성 (60분), 브라우저에서 수동 테스트 (20분), 그리고 마지못해 테스트 작성 (45분의 순수한 지루함). 같은 총 시간, 완전히 다른 경험이다.
핵심은 당신의 피드백 루프를 밀착시키는 것이다. 30분 이상 걸리는 테스트를 작성하고 있다면, 당신은 잘못하고 있는 것이다. 외부 의존성을 모킹하라. 인메모리 데이터베이스를 사용하라. 테스트 실행을 병렬화하라. 그 사이클을 15분 이내로 유지하기 위해 무엇이든 하라. 나는 팀들이 공격적인 병렬화와 스마트한 모킹을 통해 테스트 스위트 실행 시간을 40분에서 6분으로 줄이는 것을 보았고, 개발자 행복에 미친 영향은 측정 가능했다—우리의 내부 설문조사는 "나는 테스트 작성을 즐긴다"는 응답이 34% 증가했다는 것을 보여주었다.
골디락스 존: 적절한 양의 테스트 (그리고 그 이상은 금물)
내 경력 초기에 내가 저지른 큰 실수 중 하나는 100% 테스트 커버리지를 성스러운 잔처럼 쫓아다닌 것이었다. 나는 getters와 setters, 사소한 유틸리티 함수, 너무 간단해서 결코 깨질 수 없는 코드에 대해 테스트를 작성하는 데 몇 시간을 보내곤 했다. 내 테스트 스위트는 15,000줄로 부풀어 올랐고, 실제 코드베이스는 고작 8,000줄이었다. 비율 자체가 터무니없었고, 더 나빠서 이를 리팩토링하는 것은 악몽과 같았다.
"테스트를 작성하는 것은 미래의 당신과 대화하는 것과 같다—이 대화는 당신을 새벽 3시의 공황 발작과 6자리 숫자의 실수로부터 구해줄 수 있다."
내가 배운 것은 다음과 같다: 테스트 커버리지는 골디락스 존이 있으며, 그것은 100%가 아니다. 대부분의 애플리케이션에 대해 이는 대략 70-85% 사이에 있다. 70% 이하라면, 너무 많은 중요한 경로를 테스트하지 않는 것이다. 85% 이상이라면, 당신은 코드베이스를 취약하고 변경하기 어렵게 만드는 구현 세부 사항들에 대한 테스트를 하고 있는 것이다.
나는 이제 "위험 가중 테스트" 접근 방식을 따른다. 모든 코드가 똑같이 만들어지지 않기 때문에,