들어가며
the-zero 백엔드를 담당하면서 작성하게 된 테스트 코드에 대해 공유하는 시간을 가져보려 합니다.
테스트 코드를 작성하게 된 이유
테스트 코드를 작성하게 된 이유는 아래 두 가지 때문입니다.
1. the-zero 애플리케이션의 신뢰성
2. 이 코드를 보게 될 미래의 그룹원과 미래의 나를 위해서
신뢰성
- 잘 동작하는 애플리케이션을 만들었다.
- 일정에 쫓기느라 마음에 들지 않는 코드를 수정하고 싶지만 잘 동작하는 애플리케이션이 고장날까 걱정하며 리팩터링을 미룬다.
- 급하게 다음 버전 기능 추가, 수정을 위해 코드를 추가한다.
- 기존 코드와 새로운 기능을 하는 코드가 얽히고설키며 복잡해진다.
- 기존 기능과 새로운 기능이 잘 동작하는지 테스트한다.
- 기존 기능에서 오류가 발생한다. 새로운 기능 코드를 수정한다.
- 새로운 기능에서 오류가 발생한다. 기존 기능 코드를 수정한다.
- 기존 기능, 새로운 기능을 완벽히 고쳤지만 시간이 너무 많이 지났고 코드를 보니 더 엉망진창이 되어버렸다.
위와 같은 경우는 실무에서 상당히 많이 접하게 됩니다. 테스트 코드를 작성하면 애플리케이션의 신뢰성에 대한 최소한의 안전장치를 확보할 수 있습니다.
1. 사이드 이펙트 최소화
2. 기능 추가, 수정, 리팩터링에 대한 최소한의 안전장치 확보
테스트 코드는 애플리케이션 신뢰성에 대한 피드백을 빠르게 얻음으로써(성공 혹은 실패), 코드 리팩터링도 더 적극적이게 됩니다. 그리고 이러한 결과는 애플리케이션의 신뢰성을 높히게 됩니다.
코드를 보게될 미래의 그룹원과 미래의 나를 위해서
- 함수 하나하나, 기능 하나하나에 일일이 주석을 달 필요 없이 깔끔하고 이해하기 좋은 코드
- 잘 짜여진 테스트 코드
위 두 가지가 갖춰진다면 미래의 그룹원 혹은 미래의 내가 어떤 기능을 하는 코드인지 쉽게 알 수 있도록 도와줍니다.
테스트 코드를 작성하다 보면 함수가 상당히 잘게 쪼개져야 하고, 하나의 기능만 해야 한다는 사실을 알게 됩니다. 그리고 이런 코드는 다른 사람이 이해하기 쉬운 코드로 발전하게 됩니다.
완벽하지 않더라도 코드에 대해 신경 쓰고 고민하는 노력 자체가 미래의 본인 혹은 다른 사람이 코드를 이해하는데 충분히 도움을 줄 수 있습니다.
3. 테스트 코드란? 테스트 코드를 작성해야 하는 이유
테스트 코드에 대한 정의 및 관련 내용은 검색하면 좋은 내용이 많이 나옵니다.
4. 얻은 것
1. 사고의 확장
유닛 테스트를 하기 위해서는 함수는 하나의 기능을 하도록 해야 합니다. 테스트 코드를 작성하다 보면 어떻게 하면 좋을지 고민하게 만드는데 이런 고민을 할 수 있는 환경이 만들어지는 자체가 장점입니다.
2. 버그를 발견하고 사이드 이펙트 없이 빠르게 수정할 수 있습니다.
테스트 코드가 모든 애플리케이션의 버그를 커버하지는 못합니다. 하지만 테스트 코드를 작성하게 되면 애플리케이션의 테스트 커버리지가 높아지게 되고 애플리케이션의 신뢰성을 높힐 수 있습니다.
3. 애플리케이션에 대한 신뢰성이 있기 때문에 다양한 시도를 해볼 수 있습니다.(리팩터링, 더 좋은 아이디어 로직)
테스트 코드는 내가 수정을 가한 부분에 대한 피드백(성공, 실패)을 빠르게 확인할 수 있기 때문에 어떤 부분에서 코드가 잘못되었는지 빠르게 캐치할 수 있습니다.
5. 고려해야 할 것
Static vs Unit vs Integration vs E2E Testing for Frontend Apps에서는 테스트 코드를 작성할 때 고려해야 할 것들을 테스트 피라미드 그림을 통해 설명합니다.
1. 트레이드 오프(trade-off): 완벽한 것은 없다. 서서히 꼼꼼하게 페인트를 칠하면서(한쪽으로 편향되지 않은 적절한 비율의 테스트 코드) 완성도를 높여야 합니다.
비용: 위 링크 그림에서 알 수 있듯이 E2E에서 상당히 많은 비용이 든다는 것을 알 수 있습니다. 실제로 cypress 코드를 작성할 때 시간이 꽤 많이 걸렸으며 화면단의 잦은 수정으로 인해 Selector도 같이 수정해야 하는 번거로움이 존재했습니다. 하지만 완성된 애플리케이션을 테스트하는 것이므로 테스트 결과에 대한 신뢰성은 확실하다고 합니다.
시간, 속도: jest(unit, integration 테스트)보다 cypress(e2e)를 테스트하기 위한 코드 작성에 시간을 많이 쓰게 됩니다. 또한 테스트를 실행할 때 e2e 테스트는 실제 애플리케이션을 구동 후 테스트 하므로 unit 테스트 보다 속도도 느려지게 됩니다.
비용과 시간, 속도의 trade-off: 일반적으로 많은 사람들은 테스트 피라미드에 언급된 것 처럼 비용과 속도의 trade-off에 대해 많이 이야기 합니다. 하지만 이 trade-off만 있다면 테스팅 피라미드를 고려할 때 unit test로만 100% 작성해야 합니다. 물론 이렇게 하면 안되고 테스트가 소프트웨어 사용 방식과 유사할수록 더 많은 신뢰, 자신감을 얻을 수 있기 때문에 충분히 고려하여 복합적으로 작성되어야 합니다.
마치며
개인적으로 테스트 코드를 작성하게 된 이유 하나가 더 있는데요, 바로 저의 테스트 능력을 신뢰할 수 없어서입니다.
어떤 기능을 다 만들었고 테스트를 완벽하게 했다고 생각했지만 막상 많은 사람들이 사용하게 되거나 시간이 좀 지나서 미처 체크하지 못한 버그들이 발견되는 경우를 많이 경험했습니다.
저희와 같은 경험이 있으시다면 현재 진행하고 계시는 프로젝트에 테스트 코드를 도입해보시면 좋을 것 같습니다.
참고 문서