백엔드의 길을 걷는다면 겪어야 하는 관문이 필수적으로 있다고 들었다. 아직 나도 개인적으로 처음부터 끝까지 작성해 본적은 없지만 깃헙 레포에 서버 코드를 올릴 때 테스트 코드까지 완벽하게 올린다면 주는 뱃지가 있다고 들어는 봤다. 그리고 테스트 케이스의 중요성에 대해 많이 들었기 때문에 실질적으로 직접 작성을 해보기 전 개념을 확실히 짚고 넘어가고 싶다.
테스트 케이스의 종류 중 가장 널리 쓰이고 흔한 것은 TDD(Test Driven Development)와 BDD(Behavior Driven Development)이다.
실패
성공
리팩토링
객체지향적인 코드생산:
TDD는 코드의 재사용성을 보장하게 만들기에 TDD를 통한 소프트웨어 개발 시 기능 별로 철처하게 모듈화가 이루어진다. 기능별로 모듈화가 되기 때문에 종속성과 의존성이 낮은 모듈로 조합된 소프트웨어 개발이 가능하고 필요에 따라 모듈을 추가하거나 제거해도 소프트웨어 전체 구조에 영향을 주지 않는다.
재설계 시간의 단축:
TDD는 테스트 코드를 먼저 작성하고 개발을 시작하기때문에 다양한 예외상황과 방향성, 목적들을 모두 고려해 테스트 시니리오를 작성한다. 그러기에 설계의 완성도 자체가 높고 완성 후 심각한 예외상황이 생길 확률이 매우 낮으며, 개발 중 소프트웨어의 전반적인 설계가 변경되는 일을 방지한다.
디버깅 시간의 단축:
유닛 테스팅을 실행하기에 모듈 별로 테스트를 하지 않았다면 특정 버그를 찾기 위해 모든 레벨의 코드를 봐야 했겠지만 TDD의 경우 자동화된 유닛테스팅을 하기에 특정 버그를 보다 수월하게 찾아낼 수 있다.
테스트 문서의 대체가능:
TDD를 할 경우 테스트를 자동화 시키고 보다 정확한 테스트 근거를 산출할 수 있다.
추가 구현의 용이함
추가 기능을 개발한다면 해당 기능이 기존 코드들에 어떠한 영향을 미칠지 모르기 때문에 모든 기능들을 처음부터 테스트 해야 될 것 같지만 TDD는 자동화된 유닛 테스팅을 전재하기에 테스트 기간을 단축시킬 수 있다.
가장 큰 단점은 생산성의 저하이다. 단순 애플리케이션은 경험에 의해 어떤 예외상황이 발생할지 눈에 뻔히 보이는데 타이트한 개발 기간동안 뻔한 테스트 코드를 작성해 통과시키는 것은 너무나도 비효율적이고, 코드량도 무지막지하게 늘어난다. 그리고 테스트 윈칙 때문에 쉽사리 실제 코드의 수정을 망설이는 경우도 있다.
그리고 실제 구현 코드보다 예외 케이스를 위한 테스트 코드를 작성하며 배보다 배꼽이 커질 수 있다. 그렇다면 방대해진 이 테스트 코드 관리도 쉽지 않을 것이다.
개발 중후반에 수정되는 내용에 대해 깨지는 테스트 케이스를 계속 유지하면서 가져가기도 매우 어렵고 크게 변경을 주는 리팩토링을 하는 날에는 관련 테스트를 뒤집어 엎으며 일일이 맞춰주어야 한다.
TDD는 테스트 코드 작성도 쉽지 않고 진입 장벽이 존재하기 때문에 익숙해지기도 시간이 걸리고 팀 단위로 수행되는 특성상 테스트 코드에 대한 팀원 전체의 이해와 동의가 필요하다.
BDD는 시나리오를 기반으로 테스트 케이스를 작성하며 함수 단위 테스트를 권장하지 않는다. 이 시나리오는 비개발자가 봐도 이해할 수 있을 정도의 레벨로 작성하는 것을 권장하기때문에 특수영어가 없고 이해하기 쉽게 소통 가능한 것은 BDD의 장점으로 기술팀과 비 기술팀 사이에서 협업을 더 효율적으로 진행할 수 있다.
TDD를 근간으로 파생되었기에 테스트 케이스 자체가 요구사양이 되도록 하는 개발 방식이고 "이 클래스가 어떤 행위를 해야한다"라는 개념을 문장으로 작성해 행위를 위한 테스트에 집중을 할 수 있다.
Feature: 테스트에 대상의 기능/책임을 명시.
Scenario: 테스트 목적에 대한 상황을 설명.
Given: 시나리오 진행에 필요한 값을 설정.
When: 시나리오를 진행하는데 필요한 조건 명시.
Then: 시나리오를 완료했을 때 보장해야 하는 결과 명시.
테스트 대상의 상태 변화를 테스트 하는 게 목적이다.
테스트 대상은 A 상태에서 출발하며 (Given) 어떤 상태 변화를 가했을 때 (When) 기대하는 상태로 완료되어야 한다 (Then).
Side Effect가 전혀 없는 테스트 대상이라면 테스트 대상의 환경을 A 상태에 두고 (Given) 어떤 행동을 요구했을 때 (When) 기대하는 결과를 돌려받아야 한다.(Then)
예를 들면, 유저가 폼에 아무런 데이터를 적지 않았을 때 (Given), 제출 버튼을 누르면 (When), 적절한 인증 요구 메시지가 떠야 한다 (Then).
As a(초기 설정)
I want(실행하는 행동)
So that(원하는 결과)
이 매트릭스로 작성한 유저 스토리의 예를 든다면,
As a reatil customer, I want to return a purchased MacBook within 14 days, so that the refund will be processed.
TDD와 BDD 말고도 검색해보니, DDD(Domain Driven Development), ATDD(Acceptance Test Driven Development) 같은 더 많은 개발 주도 개발 방식이 있지만 관련 개념을 처음 공부하는 것이기에 가장 그래도 많이 사용하는 두가지 방식의 이론을 정리해보았다.
추상적으로 이론을 아는 것과 실제 코드를 작성해 적용하는 것은 다른 문제이겠지만, 처음 주도 개발 방식을 정해 모든 것을 기획 한 후 테스트 케이스를 코드로 변환한다면 그 단계는 크게 어렵지 않을 것이라 전망한다. 가까운 시일 내에 작은 사이즈더라도 방식을 도입해 계획했으면 좋겠다. 좋겠다가 아니라 실행해야 겠다 ㅋㅋㅋㅋ 나의 발전을 위해...
TDD와 BDD가 있는데, 한번씩 해보고 싶다. 자료 조사를 하며 학습을 할 때 많이 배우지만 모든 것을 글로 정리하기 보단 꼭 기록에 남겨야 할 부분만 남기고 나머지는 내가 흡수하는 것 같다.
참조
https://blog.testlodge.com/what-is-bdd/
https://asfirstalways.tistory.com/296
https://manorgass.tistory.com/63
https://www.popit.kr/bdd-behaviour-driven-development%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B0%84%EB%9E%B5%ED%95%9C-%EC%A0%95%EB%A6%AC/
https://velog.io/@velopert/TDD%EC%9D%98-%EC%86%8C%EA%B0%9C
https://www.guru99.com/test-case.html