ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 단위테스트가 도대체 뭐야 ❓
    Project 2021. 10. 27. 15:57

    단위테스트

    하나의 API 기능을 개발하고 수정했을 때, 모든 테스트케이스를 개발자가 직접 수행해서 성공/실패 여부를 판별하는 것은 인적 리소스 낭비일 뿐 아니라 제대로 테스트를 수행하기 힘들다

    단위 테스트는 하나의 모듈을 기준으로 독립적으로 수행 되는 최소 단위의 테스트

    모듈을 애플리케이션 내의 하나의 기능 / 메서드 / API로 이해하면 특정 메서드에 대한 테스트의 집합이 하나의 단위 테스트가 될 수 있다

    스프링/다른 컨테이너로부터 격리된 환경에서 테스트가 가능해야 한다는 목적을 가지고 있다 ❗

    프로젝트 빌드 시 테스트를 통과하지 못하면 배포되지 못하게 하는 용도로 많이 활용된다

    https://miro.medium.com/max/996/1*lqWygfNJqWQ4VCyjecQ6Eg.png

     

    단위 테스트 규칙

    단위 테스트에서 강조하는 것으로 클린코드에서 언급한 FIRST 규칙이 있다

    Fast

    테스트는 자주 실행되어야 하기 때문에 빨라야 한다. 테스트 실행을 주저할 만큼 느린 테스트는 잘못된 테스트다.

    Independent

    각각의 테스트는 독립적으로 실행되어서 실패 지점을 명확하게 파악할 수 있어야 한다. 테스트를 연속적으로 호출해서 하나의 테스트가 다른 테스트의 결과에 영향을 미치는 것은 잘못된 테스트다.

    Repeatable

    실행 환경에 따라 결과가 달라지는 것이 아닌, 어느 환경에서도 반복해서 실행할 수 있어야 한다. 테스트를 실행했을 때 방해가 되는 자원(DB, 파일, 전역 변수 등)을 남기면 안된다. 반복 가능한 테스트는 외부 서비스나 리소스에 종속되지 않는다.

    Self-Validating

    테스트는 성공/실패를 Boolean 값으로 결과를 내서 자체적으로 검증할 수 있어야 한다. 테스트의 결과값이 명확하지 않다면 올바른 시행인지를 판단하기 위한 추가 검토가 필요하며, 이는 주관적일 수 있다.

    Timely

    테스트는 테스트하려는 실제 코드를 구현하기 전 작성해야 한다. TDD에서는 실패하는 테스트 코드를 먼저 작성하고, 이것을 통과할 수 있는 실제 코드를 작성하는 것을 목적으로 한다.

     

    TDD의 철학과 테스트 비용 측면에서는 Timely 성질을 많이 강조한다.

     

    단위 테스트의 범위

    단위 테스트를 도입한다! 라고 할 시 사용하면 안 되는 어노테이션은 @SpringBootTest 이다.

    이 어노테이션을 사용하면 스프링 컨테이너를 구동해서(사용자가 등록한 빈을 모두 컴포넌트 스캔해서 빈으로 등록하고) 테스트 환경을 구축한다.

    단위 테스트를 위해 Spring Container를 구동하는 것은 빠르고 반복적인 테스트를 수행하자는 목적에 어긋난다.

    이를 위해 DI 방식 중 IoC 컨테이너가 구동되어야만 빈을 등록할 수 있는 필드 주입(@Autowired)를 사용하는 것을 지양한다.

     

    이외에도 @WebMvcTest, @DataJpaTest를 활용한 데이터베이스, API 기능 테스트가 활용될 수 있지만 단위 테스트의 범위에는 속하지 않는다.

    단위 테스트는 메서드의 비즈니스 로직이 의도한대로 동작하는지 검증하는 빠르고 간편한 테스트 수행을 위해, 어떠한 dependency도 설정되지 않는 것이 목표이다.

     

    단위 테스트의 사용

    Mocking

    "데이터베이스와 연결을 해제하는데 Repository 메서드는 어떻게 실행되지?"

    Mock 객체는 퍼시스턴스 데이터로의 액세스 없이 DAO를 Mocking(실제 모듈이 아닌 흉내내는 가짜 객체)하거나 Stubbing해서 서비스 레이어를 테스트할 수 있도록 도와준다.

    이를 위해 Java 오픈 소스 테스트 프레임워크인 Mockito를 사용한다.

    SsafyRepository ssafyRepo = Mockito.mock(SsafyRepository.class);

    이 예시에서는 ssafyRepo 인스턴스를 Mock 객체로 생성했다

    Mock 객체의 메서드는 디폴트로 null, 0, false의 값을 반환하기 때문에, Stub이 추가로 필요하다.

     

    Stub

    Mockito.when(ssafyRepo.findByName("윤이진")).thenReturn(new SsafyMember("윤이진"));

    모킹된 객체는 실제 퍼시스턴스 데이터에 접근할 수 없기 때문에 메서드의 의도적인 수행이 불가능하다. 

    예시에서는 위와 같이 작성했는데, findByName("윤이진") 메서드를 실행하면 new SsafyMember("윤이진") 객체를 반환하도록 임의로 설정해줄 수 있다는 뜻이다. 이 때 인자의 값을 정확하게 제시해야 한다.

    메서드 스텁을 이용하면 모킹된 객체의 메서드가 어떤 값을 반환할 지 지정해줄 수 있다.

     

    BDD

    : Behavior-Driven Development. 행위 주도 개발

    Test 구조를 Given-When-Then 구조로 나누어 시나리오를 기반으로 테스트하는 패턴을 권장한다.

     

    BDDMockito는 Mockito를 상속한 클래스로, 기존 Mockito의 Stubbing 코드가 Given-When-Then 가독성을 해치는 것을 고려해 나온 클래스이며, 다음 글에서 설명할 given() 메서드를 포함한다.

    BDDMockito provides BDD aliases for various Mockito methods, so we can write our Arrange step using given (instead of when), likewise, we could write our Assert step using then (instead of verify) - Quick Guide to BDDMockito(Baeldung)

     

    Given-When-Then 패턴

    • Given
      • 테스트를 시작하기 전 전제 조건 및 초기 상태/발생 가능한 모든 사전 테스트 설정
      • 인스턴스 생성 및 입력값, 변수를 정의
      • Mock 객체를 정의, Stubbing 구문 포함
    • When
      • 수행할 비즈니스 로직 테스트
    • Then
      • 테스트를 검증하는 부분
      • 주로 assert~ 메서드를 이용해서 테스트의 성공/실패를 판별

     

    Test 메서드 작성법

    @DisplayName("테스트의 목적")    // ex. 존재하지 않는 사용자로 로그인한다
    @Test     // 해당 메서드가 단위 테스트 메서드임을 명시
    void Test_Name() {
            // given
    
            // when
    
            // then
    }

    IntelliJ의 라이브 템플릿으로 저장해서 위의 패턴을 빠르게 작성할 수 있다.

     

    참고(하면 좋을) 링크

    👇 Mockito 라이브러리의 한글 번역 문서

    Mockito features in Korean · mockito/mockito Wiki

     

    GitHub - mockito/mockito: Most popular Mocking framework for unit tests written in Java

    Most popular Mocking framework for unit tests written in Java - GitHub - mockito/mockito: Most popular Mocking framework for unit tests written in Java

    github.com

    👇 실제 단위 테스트를 어떻게 수행하는지 알기 위해 참고한 예시

    2021-pick-git/CommentServiceTest_delete.java at develop · woowacourse-teams/2021-pick-git

     

    GitHub - woowacourse-teams/2021-pick-git: 💻 Github Repo 기반 개발 장려 SNS

    💻 Github Repo 기반 개발 장려 SNS. Contribute to woowacourse-teams/2021-pick-git development by creating an account on GitHub.

    github.com

     

Designed by Tistory.