네 단계로 이어진 흐름에서 결과가 틀렸고 두 번째 단계를 의심해 떼어 내 돌려 봤다. 정상으로 나와서 그 단계는 아니라고 보고 다른 곳을 며칠 동안 봤는데 결국 그 단계가 원인이었다.
Table of contents
Open Table of contents
원인 — 떼어 내며 바뀐 조건
떼어 낼 때 입력을 내가 만들었다는 것이 문제였다. 실제로 앞 단계가 넘겨 주는 값에는 items 필드가 하나 더 있었고 그것이 []일 때 다음 단계가 틀리게 동작했다.
내가 만든 입력에는 items 자체가 아예 없었다. 떼어 내면서 조건도 함께 바꿔 버린 것이고 그 상태의 통과는 실제 조건에 대해 아무것도 말해 주지 않는다.
조치 — 실제 출력을 넣는 재현
앞 단계의 실제 출력을 stage1.json으로 받아 다음 단계에 그대로 넣으니 재현됐다. 그 뒤로는 실제 흐름에서 나온 각 단계의 출력을 fixtures/ 아래 저장해 두고 재현에 썼다.
각 단계의 출력을 남겨 두니 다음부터는 손으로 입력을 만들 이유가 없어졌다. 손으로 만드는 순간 실제와 어긋날 여지가 생기기 때문이다.
판단 기준 — 바꾼 것을 적고 되돌리기
떼어 낼 때 무엇을 바꿨는지도 목록으로 적었다. 입력을 손으로 만들었고 데이터베이스를 sqlite 시험용으로 바꿨으며 외부 호출을 mock으로 바꿨고 동시 실행이 없어졌다.
넷 다 결과에 영향을 줄 수 있었다. 두 가지 방법이 있었는데 넷을 한 번에 실제 것으로 되돌리는 것과 하나씩 되돌리는 것이다. 뒤쪽을 골랐다. 이유는 한 번에 되돌리면 재현돼도 넷 중 무엇 때문인지가 안 갈려서다. 대신 되돌릴 때마다 한 번씩 더 돌리는 시간을 감수했다. stage1.json 입력만 실제 것으로 바꾼 첫 단계에서 재현됐고 나머지는 되돌릴 필요가 없었다. 전부 되돌리기 전에 하나씩 하니 무엇 때문인지가 갈렸다.
교훈 — 통과의 해석
여기서 말을 정확히 적어 두기로 했다. 떼어 놓고 통과했다는 것은 그 조건에서 정상이라는 뜻이지 그 부분이 아니라는 증거가 아니다.
정상이라는 결론과 이 입력에서 정상이라는 결론은 다르고 앞의 것을 쓰면 조사 대상에서 그 단계가 빠진다. 말을 정확히 하니 판단도 달라졌다.
재현된 뒤에는 최소 조건을 찾았다. items가 []이기만 하면 재현되고 나머지는 상관없었으며 최소 조건을 찾으니 고치는 것도 그 자리 empty() 분기 한 줄이었다. 그 조건으로 items: [] 시험도 남겼다.
주의 — 반대 방향의 함정
떼어 놓고 실패하는 경우도 있었다. 떼어 내면 실패하는데 전체 흐름에서는 정상인 건이었다.
떼어 낼 때 필요한 config 설정이 빠져 있었기 때문인데 전체 흐름에서는 앞 단계가 그 설정을 초기화하고 있었다. 떼어 놓고 실패한 것도 그 부분이 문제라는 증거가 아니며 통과든 실패든 조건이 달라졌다는 사실이 먼저다. 떼어 낸 상태에서 무엇이 필요한지 적어 두니 다음부터 빨랐다.
정리
- 떼어 놓고 통과해도 그 부분이 아니라는 증거는 아니다
- 떼어 내면서 입력과 자료와
mock외부 호출과 동시성이 바뀐다 - 실제 흐름에서 나온 것을
fixtures/에 저장해 두고 쓴다 - 떼어 내면서 무엇을 바꿨는지 적는다
- 하나씩 실제 것으로 되돌리며 어디서 재현되는지 본다
- 정상이다와 이 입력에서 정상이다는 다르다
- 재현되면 최소 조건을 찾고 그것으로
fixtures/시험을 남긴다 - 떼어 놓고 실패한 것도 그 부분이 문제라는 증거가 아니다