[1] 단위 테스트 (Unit Test) - 좋은 단위 테스트란!?

김법우·2022년 7월 19일
0

Nest.js

목록 보기
6/10
post-thumbnail

단위 테스트 (Unit Test) - 정의

들어가며 …

단위 테스트 코드를 왜 작성해야 할까?

백엔드팀(아직은 1인 이지만 ..)에서 개발자로 일하며 많은 API 들을 개발했다. 이것은 현재 진행형이며, 작은 모듈 몇 개로 시작한 Nest.js 서버 애플리케이션은 기능이 추가됨에 따라 수십 개의 모듈로 구성되게 되었다.

모듈이 늘어남에 따라 모듈이 포함하는 비즈니스 로직의 수가 늘어나고 비즈니스 로직간 의존성도 복잡해진다. 특히 플러그인 모듈로 구성한 특정 모듈들은 다수의 모듈들이 의존하게 되므로, 기능의 추가나 변경에 의해 플러그인 모듈의 코드를 수정할려 할 때면 알지 못할 불안감이 엄습한다.

나름 클린 아키텍쳐를 만들고자 노력을 하지만, 배포하기전 기능의 정상 동작을 테스트하는 것은 별개의 문제이다. 잘 정의된 인터페이스를 따르는 모듈들, 그리고 노출할 부분과 노출하지 않을 부분에 대한 명확한 구분은 기능의 변경이나 수정이 가해지는 상황에서 코드의 수정 자체를 적게 하도록 유도한다.

하지만 코드의 수정이 적든 많든간에 일단 수정이 발생하면 기존의 코드는 잘 작동할지, 예기치 못한 버그를 발생시키지는 않을지 테스트를 해야지만 배포를 할 수 있다. 눈으로 보이는, 내 머리속에 있는 생각만으로 이상적인 상황을 바라기에는 결함시 감내해야 할 리스크가 너무 크기 때문이다.

원래는 API 문서에 일일이 변경 날짜와 변경 내용, 그리고 이전의 테스트 케이스를 포함해 이번 수정으로 인해 추가된 테스트 케이스를 모두 테스트하는 방식을 사용했다. 메소드 내부에서 일어나는 분기점이나 외부 모듈의 로직을 호출하는 부분, 데이터베이스를 접근하는 부분을 중점적으로 가능한 입력값에 대해 테스트케이스를 생성하고 API 를 직접 호출해 테스트했다.

지금까지는 이 방법이 꽤 유효했다고 생각한다. 나름 열심히 테스트케이스를 고려했고, 웬만한 오류들은 테스트케이스를 수행하는 단계에서 잡혔기 때문이다.

내가 위기 의식을 느낀점은 이 방법이 유효하지 않기 때문이아니라, 이 방법을 지속하기가 어려웠기 때문이다. 수정할때마다 영향받는 부분들을 일일이 찾아가며 테스트하는 것은 지루할 뿐만아니라 시간이 오래 걸린다. 테스트용 데이터베이스를 연결하고 데이터를 확인하는 작업, 테스트를 끝내고 잘 치우는 작업도 만만치 않다.

이런 상황이다보니, 코드 수정을 하고 나면 자동으로 연관된 모듈들에 대해 로직을 점검하고 이상이 생긴 부분을 알려주는 것을 바라게 된 것 같다. ( 많은 개발자들이 단위, 통합 테스트 코드 작성 및 테스트 자동화에 대해 목메는 이유를 어렴풋이 알게 된 것 같다 … )

단위 테스트와 테스트 자동화를 도입하게 된 서론이 길었는데!! 이번 시리즈에서 말하고 싶은 주제는 크게 2가지이다. 하나는 좋은 테스트케이스란 무엇인가 이고 다른 하나는 Nest.js 를 사용한 단위 테스트 코드 작성 및 테스트 자동화에 대한 이야기이다.


좋은 단위 테스트란?

FIRST (feat. Clean Code)

좋은 단위 테스트는 깨끗한 단위 테스트이다!

FIRST 는 Clean Code (로버트 마틴 저)를 읽고 배운 깨끗한 테스트를 작성하는 규칙인데, 갑자기 왜 깨끗하다는 단어가 나왔는지 의아 할 수 있다.

여기서 깨끗하다는 의미는 가독성이 좋다는 의미이다. 누구나 테스트 코드를 읽었을 때 이 테스트가 무엇을 중점적으로 테스트하는지를 이해할 수 있어야 한다는 의미이다.

단위 테스트는 소프트웨어의 테스트 가능한 개별적인 소스 코드가 의도된 대로 작동하는지를 검증하는 절차이다. 결국 내가 특정 모듈을 개발하기 전, 개발 하면서, 개발하고 나서 의도된 바를 구현하는지를 테스트하는 절차인데, 가독성이 좋지 않다면 가장 중요한 의도된 바를 이해하기가 어려워진다.

테스트 코드를 뜯어보고, 다시 짜고 실행하는 시간이 너무 오래걸린다면, 차라리 이전처럼 노션에 테스트 케이스를 일일이 적고 돌려보는 것이 더 나을지도 모른다.

그런만큼 테스트 코드에서 가장 중요한 것은 기능이 구현해야 할 의도된 바를 잘 나타내는데 있다.


FIRST 는 각각 무엇인가?

FIRST 는 단위 테스트를 작성하는 5가지 규칙의 앞글자를 따서 만든 단어이다.

  • Fast

    테스트 결과는 빠르게 도출되어야 한다.

    빠르게 도출된 테스트 결과는 테스트를 자주 돌릴 수 있도록 하는 기본적인 요소이다. 느리게 도출되는 테스트 결과는 단위 테스트의 비용을 증가시켜 자주 테스트를 할 수 없게 한다.

  • Independent

    테스트는 서로 의존해서는 안된다.

    특정 소스 코드의 테스트를 수행하기 위해 이 소스 코드가 실행 될 수 있는 환경을 실제로 구성해서는 안된다. 여기에서 말하는 환경에는 데이터베이스 연결, 외부 모듈 호출 등등이 있을 수 있겠다. 테스트가 독립적이어야 하는 가장 큰 이유는 테스트의 결과가 독립적이어야 하기 때문이다.

    다시 짚어보면, 단위 테스트를 하는 이유는 기능이 의도한 바를 충족하는지 이다. “데이터 베이스에서 데이터를 조회 해오고, 가공하는 함수를 외부 모듈에서 호출하고 결과적으로 원하는 형태의 데이터를 출력하는가” 가 우리가 검증하고자 하는 부분이지, 데이터베이스가 잘 연결되었는지, 외부 모듈의 종속성이 잘 주입되었는지는 단위 테스트에서 중요한 부분이 아니다.

  • Repeatable

    테스트는 어떠한 환경에서도 반복 가능해야 한다.

    클린 코드 책에서는 재치있는 상황으로 풀어내는 부분이지만, 나는 이게 가장 중요한 규칙이라고 생각한다. 내가 단위 테스트의 중요성을 직접적으로 깨달은 부분도 매번마다 일일이 입력한 데이터로 테스트를 계획하고 수행하는것이 너무 번거로웠던 부분이기 때문이다.

    설령 네트워크가 연결되어 있지 않더라도, 데이터 베이스가연결되어 있지 않더라도 내가 작성한 로직이 정상적으로 동작하는지 테스트 할 수 있어야 한다.

  • Self-validating

    테스트는 참/거짓 값으로 결과를 내야한다.

    당연히 테스트의 결과는 합 불합아니냐고 생각 할 수 있는데, 이 규칙이 강제하고자 하는 부분은 단위 테스트를 수행하는 코드가 종료될 때 무조건 테스트 결과를 내야 한다는 점이다.

    테스트를 끝내고나서 나온 결과가 문자열 값이고, 이 문자열을 다른 문자열과 비교하여 다시 합/불합을 판단한다던지, 기타 다른 파일에서 데이터를 읽어와 추가적으로 검증한다던지 하는 작업은 있어서는 안된다.

    이런 부분들이 쌓이게되면 테스트 코드는 위의 규칙들을 어기게된다. 반복 가능하지 않게 되며 독립적이지 않게 된다.

  • Timely

    테스트는 적시에 작성해야 한다.

    단위 테스트는 테스트하려는 실제 코드를 작성하기 직전에 구현해야 한다. 실제 코드를 다 작성하고 나서 테스트 코드를 작성하려 하면 테스트 코드를 작성하는 일 자체의 난이도가 올라간다.

    이 부분은 지금 구현된 코드들에 대해 테스트 코드를 작성하며 뼈저리게 느끼는 부분인데, 분명히 테스트 하기 쉬운 코드는 잘 작동하는 실제 코드와 간격이 있다.

    내가 이전에 작성한 코드들이 테스트 코드를 고려하지 않고 작성했기에, 비록 잘 돌아가고 잘 작성된 코드라 할지라도 테스트 코드를 작성하려 하면 고민거리인 부분들이 분명히 있다.

    이런 부분들이 쌓이게되면 테스트 코드를 통해 검증하고자 하는 부분을 타협하게 되고, 올바르지 않은 단위 테스트 결과를 신뢰하게 될 수도 있다.

    테스트 하기 좋은 코드가 실제로 좋은 코드라는 말이 있듯이, 테스트 하기 좋은 코드를 작성하기 위해서는 당연히 테스트 코드를 먼저 작성해서 기능이 구현하고자 하는 바를 명확히 이해해야 한다.


마무리

단위 테스트는 실제 코드만큼 양이 방대해 질 수 있다. 비즈니스 로직당 하나의 단위 테스트 파일이 나올 수도 있는데, 이것을 일일이 실행시키고 결과를 확인하는 것은 비효율적인 일이다.

그러다보니 작성한 테스트 코드를 그룹으로 관리하거나 결과를 일괄적으로 도출할 도구들이 필요한데, Nest.js 에서는 단위 테스트 도구로 jest 라이브러리를 사용한다.

다음 글에서는 jest 라이브러리를 사용해 어떻게 API 의 단위 테스트를 작성하는지에 대해 다뤄 보려고 한다!

profile
개발을 사랑하는 개발자. 끝없이 꼬리를 물며 답하고 찾는 과정에서 공부하는 개발자 입니다. 잘못된 내용 혹은 더해주시고 싶은 이야기가 있다면 부디 가르침을 주세요!

0개의 댓글