테스팅(Testing) - JUnit, Hamcrest

박채은·2023년 1월 4일
0

Spring

목록 보기
22/35

테스트

테스트 케이스

  • 테스트를 하기 위해 작성하는 테스트 코드
  • 테스트를 위한 입력 데이터, 실행 조건, 기대 결과를 표현한 명세

테스트의 종류

  • 기능 테스트
    • 사용자가 애플리케이션의 전반적인 기능을 테스트
    • Frontend + BackEnd + DB + (외부 서비스) 까지 모두 연동되어 있다.
  • 통합 테스트
    • 개발팀에서 클라이언트 측 툴 없이 테스트를 진행하는 것
    • BackEnd + DB
    • 애플리케이션의 여러 계층이 연관되어 있다.
  • 슬라이스 테스트
    • 각 계층별로 쪼개어 진행하는 테스트
    • API 계층, 서비스 계층, 데이터 액세스 계층별로
  • 단위 테스트
    • 메서드 단위로 테스트
    • 보통 비즈니스 로직에서 사용하는 클래스에 적용한다.
    • 단위는 최대한 작을수록 좋다.
      • 작은 단위일수록 빠르고 간단하게 테스트를 진행할 수 있기 때문에

단위 테스트

FIRST 원칙

단위 테스트를 위한 FIRST 원칙

  • Fast
    • 작성한 테스트 케이스는 빨라야 한다.
  • Independent
    • 각각의 테스트 케이스는 독립적이여야 한다.
    • 테스트의 순서와 상관없이, 모두 정상적인 실행이 보장되어야 한다.
  • Repeatable
    • 테스트 케이스는 어떤 환경에서도 반복적으로 실행 가능해야 한다.
    • 따라서 외부 서비스/리소스의 연동을 끊어 어느 상황에서든 실행 가능하도록 해야한다.
  • Self-validating
    • 단위 테스트는 성공인지 실패인지 결과를 자체적으로 보여줘야 한다.
  • Timely
    • 단위 테스트는 기능을 구현하기 전에 작성되어야 한다.

Given-When-Then 표현

BBD 테스트 방식에서 사용하는 용어로, 테스트 케이스를 작성하는데 유용한 표현이다.

  • Given
    • 테스트에 필요한 전제 조건을 작성
      ex) 입력 값, 테스트 데이터
  • When
    • 테스트 할 동작을 실행
      ex) 메서드 호출
  • Then
    • 테스트의 결과를 검증
    • 예상 결과(expected)와 수행 결과(actual)이 같은지 Assertion한다.

Assertion

  • 테스트 검증
  • 예상하는 결과가 참이길 바라는 것

JUnit

  • 오픈소스 테스트 프레임워크 (사실상 거의 표준 테스트 프레임워크)
  • Spring Boot의 디폴트 테스트 프레임워크는 JUnit이다.

애너테이션

  • @Test
  • @BeforeEach/@BeforeAll: 테스트 케이스를 실행하기 전, 객체의 전처리 과정을 해야할 때 사용
    • @BeforeEach: 매 테스트 케이스마다 실행됨
    • @BeforeAll: 테스트 케이스가 실행되기 전에 딱 한번만 실행됨(초기화에 사용)
  • @AfterEach, @AfterAll : 후처리 과정을 해야할 때 사용

Assertions

아래의 메서드들은 JUnit에서 지원하는 Assertions의 메서드이다.

assertEquals(expected, actual);

  • 기대값과 실제값이 같으면 passed

assertNotNull(actual);

  • actual이 null이 아니면 passed

assertThrows(expectedType, executable);

  • expectedType: 발생이 기대되는 예외 클래스
  • executable: 메서드 호출
  • 호출한 메서드에서 expectedType의 예외가 발생하면 passed
    • expectedType의 상위 타입이여도 가능하다.
      • Exception은 최상위 예외 클래스이므로 어떤 예외 클래스가 발생하더라도 passed이다.
    • expectedType과 상속 관계가 아니거나, expectedType을 상속하는 하위 타입은 failed이다.

✔️ executable = 함수형 인터페이스
내부에 execute() 메서드 하나만 정의되어 있다.


Assumption 메서드

  • Assumption : ~라고 가정하다.
  • 테스트의 if문이라고 생각할 수 있다.
  • assumeTrue()
    • 테스트가 실패하면, 에러 발생
    • 테스트가 성공하면, 아래의 코드를 실행한다.(if 문)
  • assumeFalse() : 테스트가 성공하면, 에러 발생

Assertion vs Assumption

  • Assertion: 값을 넣었을 때, 기대한 결과가 나오는지 테스트해보는 경우에 사용

  • Assumption: 개발자가 실제 값을 정확히 모를 때 사용

ex) 현재 OS가 무엇인지 모를 때,

assumeTrue(System.getProperty("os.name").startsWith("Windows"));

이렇게 작성한 후에, 맞다면 아래의 로직을 계속 수행하고 아니면 수행을 멈춘다.


Hamcrest

Hamcrest란?

  • JUnit 기반의 단위 테스트에서 사용할 수 있는 Assertion Framework
  • JUnit Assertion 메서드를 Hamcrest Assertion 메서드로 변경해서 사용한다.

Hamcrest를 사용하는 이유?

  • 테스트 실패 메세지를 이해하기 쉽다.
  • Assertion을 위한 다양한 매쳐(Matcher)가 존재한다.
    -> Assertion을 자연스러운 문장으로 만들어주어 가독성이 향상된다.

매쳐(Matcher)

http://hamcrest.org/JavaHamcrest/javadoc/2.2/

assertThat(actual, is(equalTo(expected)));
assertThat(actual, is(notNullValue()));
assertThat(actual, is(nullValue())); 
  • is()
  • equalsTo()
  • notNullValue()
  • nullValue()

❗️ 주의
인텔리제이에 자동 import를 켜놨음에도 Assertion 메서드에 대한 import 문이 자동으로 import 되지 않았다. 또한, import를 하려고 해도 나에게 추천해주는 import문 중에 없어서 직접 import 문을 찾아 작성해야 했다.
-> 인텔리제이의 문제인지 잘 모르겠지만 해결 방법은 없을까?


[참고]

https://effortguy.tistory.com/123

0개의 댓글