TDD, OOP, 클린코드

단위 테스트 / TDD / 리팩토링

keepbang 2021. 5. 27. 23:33

테스트는 5개의 범위로 나눌 수 있다.

단위 테스트를 제외한 나머지는 아래와 같이 정의되어진다.

  • 통합 테스트 : 여러 작업 단위가 연계된 워크플로우를 테스트 하기 위한 수단(객체 간, 서비스 간, 시스템 간)
  • 기능 테스트 : 공개된 API의 가장 바깥쪽에 해당하는 코드 검사( Controller 호출, Security, http )
  • 부하 테스트 : 주어진 단위 시간 동안 어플리케이션이 얼마나 많은 요청을 처리할 수 있는지 검사
  • 인수 테스트 : 고객 또는 대리인이 정의되어진 모든 목적에 부합되는지 확인해보고자 하는 검사

 

단위 테스트

단위 테스트는 유형에 따라 논리 단위 테스트, 통합 단위 테스트 등으로 나눌 수 있습니다.

논리 단위 테스트 : 한 메서드에 집중한 테스트로 mock이나 stub을 이용해 테스트 메서드의 경계를 제어할 수 있습니다.
통합 단위 테스트 : 실제 운영 환경(혹은 그 일부)에서 컴포넌트 간 연동에 치중한 테스트, 예를 들어 데이터베이스를 사용하는 코드라면 데이터베이스를 효과적으로 호출하는가를 테스트할 수 있습니다.

위에서 살펴보았던 다른 테스트는 해당 코드를 작성한 개발자가 진행하기도 QA또는 고객이 직접 테스트하는 경우도 있다. 하지만 단위 테스트의 경우 해당 코드를 작성한 개발자가 진행하는것이 일반적이라고 한다....

 

단위 테스트 왜 필요할까?

위에 다른 테스트와는 별개로 단위 테스트를 개발자가 직접 진행해야하는 이유는 무엇일까?

단위 테스트는 메서드 단위의 테스트로 어플리케이션이 기대한 대로 잘 동작함을 증명하고, 버그를 조기에 잡아내는 것을 기본 목적으로 한다.

 

단위 테스트의 장점

  • 테스트 케이스가 꼼꼼하게 작성되어 있다면, 개발과정 중 미리 문제를 파악 할 수 있다.
  • 코드 변경시, 변경한 부분으로 인한 영향도를 쉽게 파악이 가능하다.
  • 코드 리팩토링을 안심하고 할 수 있다.
  • 통합 테스트시 오류가 발생할 확률이 적다.

 

단위 테스트를 진행하는 방법

IDEA : IntelliJ
OS : MacOS
Junit Version : 5.x
Project : Maven

Main method 테스트

Calculator 클래스는 사용자가 실제로 사용하는 소스코드로 프로덕션 코드(Production code)라고 한다.

main method는 테스트 코드(Test Code)로 프로덕션 코드가 정상적으로 동작하는지를 확인하는 코드이다.

 

main method 테스트 문제점

  • Production code와 Test Code가 클래스 하나에 존재한다. 클래스 크기가 커짐. 복잡도 증가함.
  • Test Code가 실 서비스에 같이 배포됨.
  • main method 하나에서 여러 개의 기능을 테스트 함. 복잡도 증가.
  • method 이름을 통해 어떤 부분을 테스트하는지에 대한 의도를 드러내기 힘듦.
  • 테스트 결과를 사람이 수동으로 확인

Junit 테스트

intelliJ 기준 : cmd + shift + t 를 클래스나 메소드에서 입력하면 테스트 메소드를 만들 수 있다.

 

  • 애노테이션(Annotation)을 활용해 테스트 코드 구현 
    • @Test : Test를 진행하는 메소드
    • @BeforeEach : @Test를 진행 하기 전에 실행되는 메소드 (4.x버전에서는 @Before)
    • @AfterEach : @Test를 전부 진행하고 실행되는 메소드 (4.x버전에서는 @After)
    • Assertions 클래스의 static assert method를 활용해 테스트 결과 검증
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {

    Calculator cal;

    @BeforeEach
    public void setUp()  {
        cal = new Calculator();
    }

    @Test
    public void 덧셈()  {
        assertEquals(7, cal.add(3, 4));
    }

    @Test
    public void 뺄셈()  {
        assertEquals(1, cal.subtract(5,  4));
    }

    @Test
    public void 곱셉()  {
        assertEquals(6, cal.multiply(2, 3));
    }

    @Test
    public void 나눗셈()  {
        assertEquals(2, cal.divide(8, 4));
    }

    @AfterEach
    public void tearDown() {
        cal = null;
    }

}

test 결과

 


 

TDD란?

  • TDD = TFD(Test First Development) + 리팩토링
  • TDD란 프로그래밍 의사결정과 피드백 사이의 간극을 의식하고 이를 제어하는 기술이다. - 켄트벡, Test Driven Development by Example 중
  • TDD의 아이러니 중 하나는 테스트 기술이 아니라는 점이다. TDD는 분석 기술이며, 설계 기술이기도 하다. - 켄트벡, Test Driven Development by Example 중

TDD 사이클

  • 실패하는 테스트를 구현한다.
  • 테스트가 성공하도록 프로덕션 코드를 구현한다.
  • 프로덕션 코드와 테스트 코드를 리팩토링한다.

TDD 의 원칙

  • 실패하는 단위 테스트를 작성할 때까지 프로덕션 코드를 작성하지 않는다.
  • 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
  • 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.

 

 

 

참조

https://sabarada.tistory.com/68