VUE x TDD

[VUE x TDD] 0. 테스트 주도 개발, 뭐가 좋은데?




신기능 추가와 수정의 두려움

잘 돌아가는 시스템 건드리는 것 아니다?

개발자라면 누구나 더 간결하고 의도대로 잘 동작하는 코드에 대한 니즈가 있지만, 현실 세계에서 리펙토링은 부담스럽다. 개발을 업으로 하면서 가장 두려움을 느끼는 순간이 잘 돌아가고 있는 레거시 프로젝트에 어쩔 수 없이 손을 대야할 때이다. 방대한 기능과 코드량, 그리고 수많은 복붙 코드들.. 새로운 기능을 추가한다거나 수정을 하려고 할 때, 과연 이 코드가 전체 제품에 어떤 영향을 미칠지를 파악하기 위해 많은 시간을 쏟게 된다.

코드 수정에 대한 두려움은 규모가 커진 시스템에서 흔히 볼 수 있는 부작용 중 하나다. 좋든 싫든 현실 세계의 소프트웨어(웹이든 네이티브 앱이든, OS 든 모든 종류의 소프트웨어)는 예상치 못한 변경 가능성을 내포하고 있다. 이런 상황에서 부담감(혹은 두려움) 없이, 신뢰할 수 있는 방식으로 시스템 규모를 키우려면 어떻게 해야할까?

두려움 없이 변경하는 방법

누구나 예상할 수 있는 답이지만, 코드 변경의 두려움을 덜어주는 것은 자동화된 테스트이다. 예상치 못한 변화에 안전하게 대처하는 방법은 배포전 모든 요구사항을 테스트하는 것이다. 하지만 매번 사람의 손으로 테스트하는 것은 비효율적일 뿐더러 실수할 확률을 배제할 수 없다. 이럴 때 모든 요구사항에 대해서 자동화된 회귀 테스트가 존재한다면? 코드를 추가하거나 수정하는 데 부담감을 획기적으로 낮출 수 있다.

테스트를 좋아하는 개발자는 없다. 코딩하기도 바쁜 데, 테스트 코드 작성에 시간을 빼앗기다니? 이런 상황을 근본적으로 뒤집자는 것이 테스트 주도 개발(TDD)이다. 쉽게 말해서 테스트 코드를 먼저 작성한 후 그에 맞게 코딩을 하자는 것이다. TDD를 처음 접하는 개발자의 머릿속에는 여러가지 의문이 든다. ‘테스트할 코드가 없는 데? 테스트를 먼저 하라니?’

여러 의문은 뒤에 이야기하고, 우리는 무엇을 얻을 수 있는가?

  1. 작업에 대한 인수 조건이 명확해진다.
  2. 코드가 하는 일에 대해 실행 가능한 명세가 생긴다.
  3. 완전한 회귀 테스트 스위트
  4. 코드 변경에 대한 자신감 → 기술 부채를 갚을 수 있는 기반

TDD 를 창시했거나 혹은 재발견했다고 알려진 켄트벡은 테스트 주도 개발을 한 문장으로 요약했다.

실패하는 테스트 없이는 한 줄도 작성하지 말라.

TDD 기본 프로세스

TDD 기본 프로세스

켄트백이 반쯤 농담식으로 말하는 빨간 불 → 녹색 불 → 리펙터링 이 세 과정이 프로세스의 전부이다.

  1. 실패하는 유닛테스트 작성
  2. 테스트 통과하는 코드 작성
  3. 리펙토링
  4. 1로 돌아기기

테스트의 종류

테스트는 크게 다음의 세 가지 종류의 나눌 수 있다.

  • 인수 테스트: 전체 시스템이 잘 동작하는가?
  • 통합 테스트: 변경할 수 없는 외부 라이브러리와 함께 잘 동작하는가?
  • 유닛 테스트: 객체/컴포넌트가 제대로 동작하는가?

인수 테스트는 전구간 테스트 End-to-End Test 를 말한다. 고객 혹은 기획 조직에서 넘어온 요구 사항에 시스템이 부합하는 지 여부와 전체 시스템이 원하는 방식으로 작동하는 가를 테스트한다. 인수 테스트는 가능한 모든 요구사항에 대해서, 시스템 내부에서 코드로 호출하지 않고 오직 사용자 인터페이스를 통해서 테스트한다.

통합 테스트는 기능이 API 서버와 같은 외부 시스템과 연동하는 테스트이다. 작은 규모의 프로젝트에서는 인수 테스트로 충분할 수도 있다. 시스템 규모가 커지면 많은 시간이 소요되는 인수 테스트 대신 기능 단위의 통합 테스트를 작성하는 게 필요할 수도 있다.

유닛 테스트는 인수 테스트와 통합 테스트가 커버하지 못하는 컴포넌트의 상세 스펙을 정의한다.

무엇을 테스트할 것인가? TDD 큰 그림 그리기

TDD를 처음 접할 때 허허벌판에 홀로 서있는 것 처럼 막막함을 느꼈다. 대체 어디서 부터 시작해야할지? 무엇을 테스트해야하는 건지. xUnit, mocha, jest 등 여러가지 도구의 사용법은 많이들 알려주는데, 정작 어디서 부터 시작해야할지는 알려주는 글은 찾아보기 어렵다. 어디서 부터 시작해야할까?

이제 테스트 없이는 코드를 작성하지 말라 는 황금률에 따라야겠다. 황금률은 우리가 코드를 어디서 부터 작성하고, 어디서 끝낼지를 알려준다. 우선 프로젝트 요구사항 중 가장 작은 단위의 동작하는 골격부터 시작하는 것이다. 가장 작은 기능의 인수 테스트를 작성하는 것으로 TDD 개발의 첫 발을 뗄 수 있다. 그리고 인수 테스트를 통과하는 것이 우리가 코딩을 멈추는 목표점이 될 것이다.

TDD 큰 그림 그리기

개인적으로 사용할 간단한 가계부 어플리케이션을 만들어 보려고한다. 가계부 앱으로 요구 사항은 다음과 같다.

간단한 가계부 요구사항

1. 사용자는 지출 내역을 저장할 수 있다.
2. 사용자는 지출 내역을 날짜별로 조회할 수 있다.
3. 사용자는 지출 내역을 수정할 수 있다.
4. 사용자는 지출 내역을 삭제할 수 있다.

1번 요구사항을 분석해서 가장 작은 단위의 동작하는 앱, 인수 테스트를 도출해보자.

1. 사용자는 지출 내역을 저장할 수 있다.
  1-1. 금액을 입력하지 않으면 저장할 수 없다.
  1-2. 제목없이 저장할 수 없다.
  1-3. 날짜를 입력하지 않으면 오늘 날짜로 저장한다.
  1-4. 제목, 금액, 날짜를 저장한다.

이제 1-1번을 따라서 금액을 입력하지 않으면 지출 내역 저장을 실패하는 테스트를 작성하고 드디어 코딩을 시작할 수 있다. 다음 포스트부터는 Vue-cli 를 통해 실제 개발 환경을 구성하고 테스트를 통과하는 코드를 작성해 볼 예정이다.


참고 자료:


Sangyoung Lee

개발하고 배우고 글을 씁니다.