Spring & SpringBoot/Testing

여러 테스트 방식, 단위테스트의 FIRST 원칙, GWT(given-when-then)

Hyeonni 2022. 11. 8. 11:54

그동안 프로젝트를 하는 동안 따로 테스트 코드를 작성하지 않고 하나의 기능이 완료된 후에 postman을 통해서 api를 실행해보는 방식으로 테스트를 진행해왔다. 이렇게 할 경우, 하나의 기능이 모두 완성된 상태에서 테스트가 진행되기 때문에 만약 에러가 발생한다면 에러가 발생하는 부분을 찾는데 시간이 오래 걸릴 뿐만 아니라 정밀하게 테스트를 하는 데 있어서 한계가 있었다. 그래서 실제 서버를 배포한 후에 에러를 발견해서 고친 적도 여러 번이다.  점점 테스트 케이스를 만들고 테스트 코드를 작성하는 습관을 들여야겠다는 생각을 하게 되어 이번에 테스트 코드를 작성하는 데 있어서 필요한 내용을 간략하게 정리하고 가려고 한다.

 

여러 테스트 방식

  • 기능 테스트

기능 테스트는 주로 애플리케이션을 사용하는 사용자 입장에서 애플리케이션이 제공하는 기능이 올바르게 동작하는지를 테스트한다. 데이터베이스까지 연결하여 전체적인 테스트를 진행하는 것이다.
기능 테스트를 하는 주체는 주로 해당 애플리케이션을 개발한 개발자가 될 수 있지만 일반적으로 테스트 전문 부서인 QA부서가 된다.  즉, 제 3자가 테스트를 주로 한다고 보면 된다.

 

  • 통합 테스트

통합 테스트는 클라이언트 측 툴 없이 개발자가 짜 놓은 테스트 코드를 실행시켜 진행한다. 통합 테스트도 여러 애플리케이션 계층이 연괄되어 있고, DB까지 연결되어 있어 독립적인 테스트가 가능하다.
주로 애플리케이션을 만든 개발팀이 테스트의 주체가 된다.

 

  • 슬라이스 테스트 (부분 통합 테스트)

슬라이스 테스트는 애플리케이션을 특정 계층으로 쪼개어서 하는 테스트를 말한다. 스프링으로 서버를 개발할 때 흔히 사용하는 MVC 패턴으로 개발을 한다면 API 계층, 서비스 계층, 데이터 액세스 계층이 각각 슬라이스 테스트의 대상이 될 수 있다. 슬라이스 테스트 역시 해당 계층에서 HTTP 요청이 필요하고, 외부 서비스가 연동되는 경우도 존재한다. 데이터베이스도 여전히 연동되어 테스트가 진행된다. Mock 객체를 통해 계층별로 나누어 테스트 범위를 좁혀서 테스트를 진행할 수 있다.

 

  • 단위 테스트

단위 테스트란 특정한 단위로 구분해서 테스트를 진행하는 것을 말한다. 단위 테스트의 대상은 주로 메서드이다. 단위 테스트에서도 데이터베이스가 연동이 되어 있을 수는 있지만, 데이터베이스의 상태가 테스트 이 전과 이 후가 동일하게 유지될 수 있다면 단위 테스트에 포함될 수 있다. 하지만 단위 테스트는 최대한 독립적이고 작은 단위일수록 좋다. 작은 단위일수록 다른 연관된 기능들을 생각할 필요도 없고, 테스트 코드 짜기도 더 단순해지고 그만큼 빠르게 테스트를 수행할 수 있기 때문이다.

 

단위 테스트를 위한 F.I.R.S.T 원칙

  • Fast - 빠르게

테스트 수행에 시간이 오래 걸리지 않도록 테스트 케이스가 빠르게 수행되어야 한다.

 

  • Independent - 독립적

각각의 단위 테스트는 서로 독립적이어야 한다. 어떤 테스트 케이스를 먼저 실행시켜도 실행된느 순서와 상관없이 정상적인 실행이 보장되어야 한다. 그래야 필요한 테스트만 개발적으로 실행할 수 있기 때문이다.

 

  • Repeatable - 반복 가능

테스트 케이스는 어떤 환경에서도 반복해서 실행이 가능해야 한다. IDE 내에서 실행을 하든, Gradle과 같은 빌드 태스크를 직접 입력해서 실행하든, 서버 환경에서 실행하든 모두 같은 결과를 얻어야 한다. 
외부 서비스나 외부 리소스가 연동되는 경우 동일한 테스트 결과를 보장하지 못하기 때문에 단위 테스트 시에는 외부의 서비스나 리소스의 연동을 끊어주는 것이 좋다.

 

  • self-validating - 셀프 검증

단위 테스트는 성공 또는 실패라는 자체 검증 결과를 보여주어야 한다.

 

  • Timely - 적절한 시기

단위 테스트는 테스트 하려는 기능 구현을 하기 직전에 작성해야 한다. 테스트 주도 개발 방식(TDD)에서는 기능 구현 전에 실패하는 테스트 케이스를 먼저 작성하는 방식을 선호한다. 

 

BDD(Behavior Driven Development) 방식의 GWT(Given - When - Then)

테스트 코드를 작성할 때 좀 더 쉽게 작성할 수 있도록 돕기 위해 코드 영역을 given - when - then으로 나눈다.

  • Given
    • 테스트 하기 위한 준비 과정으로 테스트에 필요한 전제 조건들이 포함된다.
      • 테스트 대상에 전달되는 테스트 데이터인 입력값 포함
  • When
    • 테스트 할 동작을 기술한다.
    • 단위 테스트에서는 일반적으로 메서드 호출을 통해 테스트를 진행하므로 실행할 메서드를 호출한다.
  • Then
    • 테스트의 결과를 검증하는 영역이다.
    • 일반적으로 예상하는 값(expected)과 테스트 대상 메서드의 동작 수행 결과(actual) 값을 비교해서 기대한 대로 동작을 수행하는지 검증(Assertion)하는 코드들이 포함된다.