자바/단위테스트

실용주의 단위테스트(JUNIT)

끄적끄적 2022. 6. 15. 22:25

좋은 테스트의 FIRST 속성

Fast : 테스트가 오래 걸리면 자주 돌리기 어렵다. 느린 로직이 있으면 의존성을 줄여야 한다. 예를 들어, DB처리하는 로직이 포함되어 있으면, 해당 부분을 별도로 떼어내서 따로 테스트를 짜도록 구조개선한다.
Isolated : 어떤 순서나 시간에 관계없이 실행할 수 있도록. 하나의 테스트가 여러 이유로 실패할 수 있다면, 독립적으로 분리해 내야 한다. 
Repeatable : 실행할 때마다 결과가 같아야 한다. 시간값이나 외부 값에 따라 결과가 다르다면 Mock객체 활용 등으로 동일한 결과가 나오도록 구현한다.
Self-validating : 출력값을 확인하기보다는 성공/실패가 명확히 나오도록 한다. 
Timely : 테스트코드를 미루는 것은 양치를 미루는 것과 같다. 큰 결함이 없는 레거시코드에 당장 변경이 필요없으면, 노력을 보상받지 못할 것이다.  그 노력을 말썽이 많고 역동적인 부분에 사용하라.

 

무엇을 테스트할 것인가? Right-BICEP

Right : 코드 전체에 대해 정상적으로 동작하는지 알 수 있는가? 없다면, 코드를 계속 짜기보다는 테스트를 보완하라(TDD개념)
Boundary conditions : 경계조건을 고려하라. 특수문자, 잘못된 데이터, 비거나 빠진 값, 공백포함, 중복데이터, 수치적 오버플로, 순서가 맞지 않는 데이터 등을 테스트하라.
Inverse relationship : 역관계를 검사해보기를 활용하라. 자료구조나 DB에 넣는 로직 수행후 찾기로 검증하거나, 복식부기 회계에서 차변의 합계와 대변의 합계 동일한지 비교하는 등의 방법이 있다.
Cross-check : 다른 수단을 활용하여 교차 검사하라. 성능이 좋거나 사용법이 좋은 1등 해법의 결과와 조금 떨어지는 다른 방법의 결과가 동일한지 검증하는 방법이 있다. 클래스의 서로 다른 조각 데이터들을 합산하였을때 전체 사이즈와 맞는지 검증할 수도 있다.
Error conditions : 오류 조건에서 예외처리가 잘 되는지 확인한다. 
Performance characteristics : 성능 조건은 기준에 부합하는지? 특정 코드를 반복해서 특정 시간안에 수행되는지 검증한다.

경계 조건(Boundary conditions) CORRECT
Conformance(준수) : 값이 기대한 양식을 준수하는가. 예를 들어 이메일 주소이면 name@domain.com 등의 양식을 벗어나거나, 헤더가 없는 데이터 등이 있을 수 있다.

Ordering(순서) : 순서대로 잘 나오는지

Range(범위) : 데이터의 범위를 고려. ex) 사람 나이면 0~200, 원 내부 각도 0~360, 두 점사이의 거리 등
    자주 하는 테스트 케이스 :  시작과 마지막 인덱스 같으면 안되는 경우, 시작이 마지막보다 크면 안되는 경우, 인덱스가 음수면 안되는 경우, 인덱스가 허용된 값보다 크면 안되는 경우, 개수가 실제항목 개수와 맞아야 하는 경우
             
Reference(참조) : 메서드를 테스트할 때 1) 범위를 너머서는 것을 참조하지 않는지, 2) 외부 의존성은 무엇인지 3) 특정 상태에 있는 객체를 의존하고 있는지 4) 반드시 존재해야 하는 다른 조건이 있는지 등 참조하는 정보를 고려해야 한다.
    예를 들어, 자동차 모듈의 경우 주행중에 기어변속을 호출하면, 사전 조건(멈춰야 기어변속 가능)에 따른 동작(변경불가)하는지를 테스트해야 한다.

Existence(존재) : 값이 null, 0, 또는 비어있는 경우, 또는 기대하는 파일이 없는 등 존재하지 않는 경우에 대한 테스트가 필요하다.

Cardinality(집합내의 개수) : 집합의 개수가 얼마가 될지 모르지만, 보통 테스트에서는 0일때, 1일때, n일때 형태로 테스트한다. 이때, n의 값이 변경되더라도 테스트코드 변경없이 상수값만 변경하면 되도록 구현하라.

Time(시간) : 테스트시 시간을 고려할 때 1) 시간의 순서 2) 측정된 시간 3) 동시성 문제에 대해 고려할 필요가 있다.
       메서드의 호출 순서나 타임아웃에 대해 테스트해야 하며, 현재 시간으로 동작이 나뉘면 주의해서 테스트하라.

 

단위테스트 구현과 설계의 상관관계
단위테스트를 설정하는데 코드가 몇 줄 혹은 수십 줄 필요하다면 설계에 문제가 있다는 냄새이다. SRP를 위반하면 클래스는 커지면서 의존성이 커지며, 테스트를 설정하는데 많은 노력이 요구된다. 클래스를 분활해야 한다.
private메서드(구현 세부사항)를 테스트하려는 충동은 클래스가 필요 이상으로 커졌다는 힌트이다. 내부 동작을 새 클래스로 옮기고 public으로 만드는게 좋다.
단위테스트가 어려워 보인다면 그것도 좋은 힌트이다. 설계를 개선하여 단위테스트를 쉽게 만들어야 한다.
시스템 설계 및 코드 품질이 낮아질수록 단위테스트의 유지 보수 비용은 증가한다.

 

반응형