개발기록장

[etc] Unit Test란? 본문

TIL/etc

[etc] Unit Test란?

yangahh 2021. 3. 8. 05:50

 

1. Test 종류와 각 test의 특징

개발을 하다 보면 코드가 잘 동작을 하고 있는지, 버그는 없는지 등을 확인하는 테스트가 필수이다.

테스트를 범위에 따라 분류하면 아래 그림과 같이

E2E(UI) Testing(기능 테스트), Integrating Testing(통합 테스트), Unit Testing(단위 테스트)으로 나눌 수 있다. 

각 테스트 비중은 E2E - 10%, Integrating - 20%, Unit - 70%로 구현하는 것을 권장한다.

 

Google Test Automation Conference에서 제안된 테스트 피라미드

 

- E2E Test (=UI Test, Browser Test, 기능 테스트)

  • End-to-End의 약자로, 어떤 어플리케이션이 제대로 동작하는지 완전한 기능을 테스트하는 것을 의미한다.

  • 예를 들어, 웹 서비스를 E2E 테스트를 한다고 하면 웹 브라우저를 이용하여 개발한 특정 페이지에 들어가서 클릭을 한다던가 기능을 하나하나 눌러가면서 테스트 하는 것이 E2E 테스트이다.

  • Integrating, Unit test에 비해 까다롭고 비용이 많이들며 실행 시간도 많이 든다.

  • 이러한 이유로 E2E 테스트를 매우 세밀하게 나눠서 하는 것은 좋지 않으며, 전체 테스트 비중에서 10% 정도로 잡는 것을 권장한다.

  • 회원가입과 같이 브라우저에서 앱의 특정 흐름을 수동으로 테스트하는 경우에는 E2E 테스트가 유용하다.

- Integration Test

  • 이름에서 의미하는 바와 같이 각각의 시스템들이 서로 어떻게 상호작용하고, 작동하는지 테스트 하는 것을 의미한다.

  • 보통 두 개 이상의 클래스 또는 서브 시스템의 결합을 테스트한다.

  • 예를 들면 Django로 서버를 띄우고 model 클래스와 결합하여 데이터베이스 시스템과 연동한 테스트가 있다. 테스터는 Postman 또는 httpie 등을 활용해서 작성한 코드가 제대로 동작하는지 확인한다.

  • 내가 지금까지 테스트 했던 방법이 바로 Integration Test이다.

  • Integration Test는 Unit Test를 작성하는 것보다 공수가 많이들고, 데이터베이스 서버를 돌려서 테스트 해야하기 때문에 메모리도 유닛테스트보다 더 많이 사용하게 되므로 비용도 비싸다.

  • 때문에 전체 테스트에서 20% 정도로만 하는 것을 권장한다.

- Unit Test

  • Unit 테스트는 전체 코드 중 작은 부분을 테스트한다. 즉, 작성한 코드의 가장 작은 단위인 함수를 테스트 하는 메소드이다.

  • 기본적으로 테스트를 위한 입력 값을 주어서 그에 대한 함수의 출력 값이 정확 한지 아닌지를 판단하는 테스트 코드로 작성한다.

  • 테스트에 네티워크나 데이터베이스 같은 외부 리소스가 포함된다면 그건 Unit 테스트가 아닌 Integration 테스트이다.

  • 따라서 Unit 테스트는 앞의 두 테스트보다 빠르고 비용이 적게 든다.

 

2. Unit Test의 장점

1) 다른 테스트보다 비용이 저렴하고 실행 속도가 빠르다.

 E2E 테스트는 프론트와 백엔드 서버를 연동하여 사람이 직접 테스트를 해야하고, Integration 테스트도 외부 리소스가 필요하다. 하지만 유닛 테스트는 작성한 코드를 가지고 자동으로 실행하기 때문에 비용이 저렴하고, 실행 속도가 매우 빠르다. 

 

2) 빈번히 일어나는 버그를 막는데 효과적이다.

보통 코드의 일부분에 문제가 있을 경우, 그 부분을 수정하면 연쇄적으로 다른 부분의 코드도 수정해야 할 일이 많다. 그때 문제가 또 다른 문제를 일으키는 경우도 빈번하다. 이때 버그가 있는지 없는지 체크하는 Unit 테스트를 만들어 두면 이러한 문제를 쉽게 해결할 수 있다.

 

3) 중장기적으로 유지 보수가 쉽다.

새로운 기능을 구현할때 유닛 테스트를 잘 작성해놓으면 중장기적으로 유지 보수가 쉬워진다.

즉, 이전에 통과했던 테스트 집합을 가지고 버그를 찾기 위해서 이전에 테스트 되었던 유닛테스트를 반복하는것을 regression 테스트라고 하는데, unit 테스트만 반복하면 되기 때문에 regression 테스트도 반복적으로 수행 할 수 있다.

 

 

3. Unit Test의 일반 원칙

  • 테스트 유닛은 각 기능의 가장 작은 단위에 집중해야 한다.

  • 각 테스트 유닛은 반드시 독립적이어야 한다.

    각 테스트는 혼자서도 실행 가능해야하고, 테스트 슈트로도 실행 가능해야 한다. 이 때, 호출되는 순서와 무관하게 잘 동작해야 한다. 이는 새로운 데이터셋으로 각각의 테스트를 로딩해야 하고, 그 실행 결과는 꼭 삭제해야 한다는 것을 의미한다. 보통 setUp() 과 tearDown() 메소드로 이런 작업을 한다.

  • 테스트가 빠르게 돌 수 있도록 만들기 위해 노력해야 한다.

    테스트 하나가 실행하는데 몇 밀리세컨드 이상의 시간이 걸린다면, 개발 속도가 느려지거나 테스트가 충분히 자주 수행되지 못하기 때문이다.

    테스트에 필요한 데이터 구조가 너무 복잡하고, 테스트를 하려면 매번 이 복잡한 데이터를 불러와야 해서 테스트를 빠르게 만들 수 없는 경우도 있다. 이럴 때는 무거운 테스트는 따로 분리하여 별도의 테스트 슈트를 만들어 두고 스케쥴 작업을 걸어 테스트를 수행하도록 한다.

  • 그날의 코딩을 시작하기 전에 항상 풀 테스트 슈트를 돌리는 습관을 들이는 것이 좋다. 

  • 모두가 공유하는 저장소에다가 코드를 집어넣기 전에 자동으로 모든 테스트를 수행하도록 하는 훅을 구현하는 하는 것이 좋다.

  • 디버깅할 때 가장 먼저 시작할 일은 버그를 찝어내는 새로운 테스트를 작성하는 것이다.

  • 테스트 함수에는 길고 서술적인 이름을 사용한다.

    테스트에서의 스타일 안내서는 짧은 이름을 보다 선호하는 다른 일반적인 코드와는 조금 다르다. 테스트 함수는 절대 직접 호출되지 않기 때문입니다. 예를 들어 test_square_of_number_2(), test_square_negative_number() 같은 이름으로 작성한다.

  • 테스트 코드의 또다른 사용 방법은 새로운 개발자들을 위한 안내서로 쓰는 방법이다.

    이미 만들어져 있는 코드에서 작업해야할 경우, 관련 테스트 코드를 돌려보고 읽어보는 것은 매우 도움이 된다.

    이렇게 테스트 코드를 돌려보면 어느 지점이 문제인지, 수정하기 어려운 곳은 어디일지, 막다른 골목은 어디일지를 발견하게 된다.

    몇 가지 기능을 추가해야 한다면 가장 먼저 해야할 일은, 그 새로운 기능이 아직 돌아가지 않음을 확인할 수 있는 테스트를 붙여넣는 것이다.

'TIL > etc' 카테고리의 다른 글

[etc] Agile, Scrum, Sprint 간단 정리  (0) 2021.04.26