해피 코딩!

단위 테스트 활용 방법: JUnit 참조 가이드 를 읽고 본문

TDD

단위 테스트 활용 방법: JUnit 참조 가이드 를 읽고

지속가능한 성장을 2020. 12. 2. 01:48

본 내용은

단위 테스트 활용 방법 : JUnit 참조 가이드

의 내용을 읽고 난 후 본인이 보기 쉽게 내용 요약 및 생각을 작성한 글 입니다.

보다 나은 정보를 얻기 위한다면 반드시 해당 링크를 통해 확인하시는 것을 강력히 추천합니다. 쉽고, 빠르게 이해를 할 수 있으며 java 기반의 테스트 방식이지만 Django를 통해 백엔드를 개발하는 저도 이해하고 공감할 수 있는 내용이었습니다.

소프트웨어 개발에서 단위 테스트는 구현 코드의 개별 단위의 적합성 혹은 정확성을 확인하기 위한 방법이다.

이 단위의 정의는 객체지향 언어에서 하나의 메서드가 될 수 있다.
단위 테스트에서 하나의 테스트 단위는 테스트 가능한 가장 작은 부분으로 생각하면 된다.

단위 테스트는 버그를 찾는 것이 아니다.

단위 테스트는 버그를 찾기 위한 효과적인 방법이 아니며 정의에 따르면 단위 테스트는 시스템의 각각의 단위들을 개별적으로 조사하는 것이다.

버그를 찾기 위함이라면 검증자가 일일이 테스트 하듯 전체 시스템을 실제 통합환경에서 실행하는 것이 효과적인 테스트이며 이러한 테스트를 자동화 한 것을 통합테스트라고 한다.

이것은 일반적으로 단위 테스트와는 다른 기술들을 사용한다.

하나의 테스트 케이스는 단위 기능 중 하나의 시나리오만 테스트하라. (중요!)

단위 테스트 작성 시 가장 중요하게 인식할 점은 테스트 단위가 복수의 테스트 시나리오들을 가질 수 있다는 것이다.

모든 테스트 시나리오들은 독립적인 테스트 코드로 작성해야 한다.

예를 들어 두 매개변수를 가지고 처리한 후 값을 돌려주는 함수의 테스트 케이스를 작성하고 나면, 다음과 같은 테스트 시나리오가 가능하다.

  1. 첫 번째 파라미터가 널 값인 경우 예외 객체를 반환
  2. 두 번째 파라미터가 널 값일 경우 예외 객체를 반환
  3. 두 개의 파라미터가 모두 널 값일 경우, 예외 객체 반환
  4. 파라미터가 정상 범위 안일 경우, 작업 실행 후 결과 값을 반환

이러한 세분화된 테스트 케이스는 수정하거나 리팩토링 시 효과적

단위 테스트만 수행하면 코드의 수정이 코드의 의도된 기능을 망가뜨렸는지 확인할 수 있기 때문.( 중요 중요!!! )

또한 기능을 수정한다면 최소한의 테스트 코드만 수정하면 되기 때문

사실 이 부분에서 정말 많은 시간이 소요되는 것 같다. 하나의 기능을 위해서 정~말 많은 테스트 케이스를 구현해야 하기 때문이었다. 하지만 테스트 케이스가 세분화되어 있지 않다면? 반쪽짜리 테스트케이스는 TDD가 아니다.. 이것이 TDD의 딜레마라 느낀다.

사실 BDD와 TDD에서 위의 내용은 BDD가 아닐까 생각한다. 왜냐하면 로직에 대응하는 케이스가 이미 나와있지 않나? 라는 생각이 들었기 때문이다. 테스트 케이스를 정해놓고 코드를 짠다? 이건 BDD가 아닌가 라는 생각이 든다.

불 필요한 검증 구문을 작성하지 마라.

단위 내 모든 것에 대해 검증하는 구문을 작성하지 마라.

테스트 하려고 하는 시나리오에 집중해라.

어떤것이 불 필요한지 꾸준히 고민하고 여러 블로그 글을 찾아보지만 아직까지 스스로 답을 정의하지 못하고 있다. 취업을 하거나 주변의 지인들에게 알게 된다면 내용을 업데이트 하겠다.

각 테스트는 독립적이어야 한다.

다른 테스트에 의존적인 꼬리에 꼬리를 무는 단위 테스트를 하지 마라. (중요)

이런 상호 의존적인 테스트 코드는 유지보수도 번거로우며 이러한 테스트들은 결국 실패 원인을 디버깅을 통해 찾아보아야 한다.

모든 외부 서비스와 상태들에 테스트 더블을 사용해라.

테스트 더블은 쉽게 말하면 Mocking 하라는 말 입니다.

시스템 설정 파일에 관한 단위 테스트를 작성하지 마라.

정의에 따르면 시스템 설정은 단위 테스트의 범위가 아니다.

단위 테스트 케이스의 이름은 명확하고 일관되게 테스트의 의미를 반영한다. (중요)

이것은 언제나 명심하고 실천해야 하는 중요한 점이다.

테스트 케이스의 이름은 항상 테스트의 의도가 무엇인지 반영해야 한다.

외부 시스템이나 서비스에 대한 의존성이 가장 낮은 메서드들에 대해 테스트를 먼저 작성하라. 그리고 확장하라.

step by step

프라이빗 메서드를 포함한 모든 메서드들은 가시범위에 상관 없이 적절한 단위 테스트들을 작성해야 한다.

논란거리라고 한다. 소스의 코드의 핵심적인 부분은 그것이 프라이빗 메서드들이라도 반드시 테스트 되어져야 한다.

각각의 단위 테스트 메서드는 정확히 하나의 검증 구문을 가져야 한다.

번역자는 동의하지 않는다고 하였고, 기능의 정확성을 확인하기 위하여 복수의 검증 구문이 필요하다고 하였다.

나 역시 검증은 하나의 테스트케이스 안에서 여러번 할 수 있다면 여러번 추가적인 검증을 하는것이 옳지 않나 라고 생각한다. 모든 필드에 대해서, 특정 obj가 가진 여러 relation에 대해서 말이다.

예상된 예외 사항을 테스트하는 단위 테스트 코드를 작성하라.

예상된 예외 사항을 검증하기 위한 테스트 케이스를 작성해야 하는 경우도 있다.
이 때에는 try/catch로 검증하려 하지 말고 JUnit이 제공하는 방법을 사용해라

난 Django 개발자이다. 본인은 여태가지 try-except로 잡았는데 한 번 찾아봐야 할 것 같다.

가장 적합한 검증 구문을 사용해라.

여러 검증 구문이 있고 그 안에서 이유와 의도에 맞는 가장 적합한 것을 사용해라

쓰는 라이브러리 문서 읽으라는 말이라 생각한다.

검증 구문 파라미터들은 적합한 순서대로 배치하라.

검증 구문은 두 개의 파라미터를 취한다. 첫 번째 것은 테스트 결과가 패스할 때 기다리는 정상 값. 두 번째 값은 테스트 결과 값 이렇게 하면 실패 시 에러 메세지를 통해 무엇이 잘못 되었는지 확인 할 수 있다.

Django : self.assertEqual(response.status_code, 200) 이 말 같다.

테스트를 위한 코드는 제품 코드에서 분리되어야 한다.

OK

테스트 코드 내에서 아무것도 출력하지 마라

OK 테스트 작성 과정에서 디버깅 쓰라는 말 같다. 추가적으로 print는 비용이 비싼 메서드라서 웬만하면 안쓰는게 좋다.

정적 변수를 테스트 클래스에서 사용하지 마라. 사용했다면 각 테스트 케이스 실행시 마다 재 초기화 하라.

예외 발생시 단순히 테스트를 실패하기 위한 catch 구문을 작성하지 마라.

간접적인 테스트들에 의존하지 마라.

하나의 테스트가 본래 의도된 시나리오 외에 다른 시나리오도 테스트한다고 가정하지 마라.

혼란을 가져온다. 추가적인 테스트 케이스로 작성하라.

단위 테스트를 자동으로 실행하게 빌드 스크립트를 작성해라.

단위 테스트들의 실행을 생략하지 마라.

단위 테스트의 코드가 적절하지 않다면 코드를 삭제하라.

번역자의 결론

의심할 여지 없이 단위 테스트는 소프트웨어 프로젝트 결과물의 품질을 월등히 향상 시킬 수 있다.

소프트웨어 공학자들이 단위 테스트를 작성하는 것이 작성하지 않는 것 보다 훨씬 효율적이라 생각한다. 하지만 번역자는 반대한다고 한다. 그 이유는 번역본 (클릭)에 가서 확인을 하는것이 예의라 생각한다.

후기

이번 기회를 통해 단위테스트(unit testing), 통합 테스트, 전 구간 테스트, 인수 테스트 등 여러 테스트 방법을 알게 되었고

이 중, 나에게 가장 익숙한 단위 테스트를 확실하게 정리하는 시간이었다.

자랑같아 부끄럽지만 사실 위의 내용은 다 알고 있었으며, 위의 내용처럼 테스트 코드를 작성해 왔다. 하지만 다시 읽고 작성을 해 보면서 내가 여태까지 해 왔던 작성 방법에 대한 근거를 면접에서 제시할 수 있는 글이 되어준 것 같아 이 내용을 번역해준 최한모 님에게 감사합니다.

본 내용은 사실 자바에 대해 잘 몰라도 백엔드 개발자라면 충분히 다 이해할 수 있을거라 생각한다.

그래서 더 좋은 글이라 생각한다.

Comments