Skip to Content
Suffering builds character
아카이브12.테스팅개요1.테스트 프레임워크 만들기

1.테스트 프레임워크 만들기

다음의 프로그램을 작성했다고 가정할 경우,

Calculator.java
public class Calculator { public double add(double number1, double number2) { return number1 + number2; } }

작성한 계산기가 컴파일에도 문제가 없지만, 런타임에도 문제가 없는지 확인이 필요함
이 코드만으로는 해당 기능(덧셈)이 제대로 동작하는지에 대해 증명할 수 없는 상태

→ 즉, 자동화된 테스트가 필요함!

Calculator를 테스트하는 코드 작성

따라서 Calculator를 테스트하는 코드를 작성해보면 다음과 같음

CalculatorTest.java
public class CalculatorTest { public static void main(String[] args) { // Calculator 객체 생성 Calculator calculator = new Calculator(); // 덧셈 메서드를 호출하여 테스트 double result = calculator.add(3, 5); if (result != 8) { System.out.println("잘못된 결과: " + result); } else { System.out.println("테스트 성공: " + result); } } }

CalculatorTest 코드 개선

테스트에 용이하게 하기 위해 개선한 코드는 다음과 같음

CalculatorTest.java
public class CalculatorTest { private int errors = 0; // 확장성을 고려하여 덧셈 메서드만 모듈화 public void testAdd() { Calculator calculator = new Calculator(); double result = calculator.add(3, 5); if (result != 8) { // 예외를 던지도록 지정 throw new IllegalStateException("잘못된 결과: " + result); } } public static void main(String[] args) { // Calculator 객체 생성 Calculator calculator = new Calculator(); try { test.testAdd(); // 덧셈 메서드 호출 } catch (Throwable e) { test.erros++; e.printStackTrace(); } // 테스트 메서드에서 발생한 에러의 개수 확인하기 if (test.errors > 0) { throw new IllegalStateException(test.errors + "개의 에러가 있습니다."); } } }

단위 테스트 프레임워크의 동작 이해하기

보편적인 단위 테스트는 지켜야할 몇 가지 규칙이 있음

1. 단위 테스트는 다른 단위 테스트와 독립적으로 실행되어야 함

테스트하고자하는 대상을 다른 테스트와 분리하여 외부 변인을 통제하기 위해 다른 테스트와 독립적으로 실행되어야 함

CalculatorTest.java
// 덧셈 기능만 별도의 메서드로 분리 public void testAdd() { Calculator calculator = new Calculator(); double result = calculator.add(3, 5); if (result != 8) { // 예외를 던지도록 지정 throw new IllegalStateException("잘못된 결과: " + result); } } // 뺄셈 기능 메서드 // public void testSub() { ... } // main(String[] args) ..

2. 프레임워크는 각 단위 테스트의 오류를 파악하여 개발자에게 알려주어야 함

프레임워크는 개발자가 테스트의 오류를 빠르게 파악할 수 있도록 통지가 필요

CalculatorTest.java
// void testAdd() { ... } public static void main(String[] args) { Calculator calculator = new Calculator(); try { test.testAdd(); // 덧셈 메서드 호출 } catch (Throwable e) { test.erros++; e.printStackTrace(); } // 테스트 메서드에서 발생한 에러의 개수를 파악하여 개발자에게 알려주기 if (test.errors > 0) { throw new IllegalStateException(test.errors + "개의 에러가 있습니다."); } }

3. 개발자가 어떤 테스트를 실행할지 쉽게 정의하고 작성할 수 있어야 함

실행하고 싶은 테스트를 편리하게 지정할 수 있으면 더 좋음

CalculatorTest.java
// void testAdd() { ... } public static void main(String[] args) { Calculator calculator = new Calculator(); // 실행할 테스트를 try 블럭 내에 작성하여 테스트를 실행함 try { test.testAdd(); // 덧셈 테스트 메서드 호출 } catch (Throwable e) { test.erros++; e.printStackTrace(); } // 테스트 메서드에서 발생한 에러의 개수를 파악하여 개발자에게 알려주기 if (test.errors > 0) { throw new IllegalStateException(test.errors + "개의 에러가 있습니다."); } }

3. 간이 테스트 프레임워크의 단점

그럼에도 불구하고 간이로 구현해본 테스트 프레임워크는 몇 가지 단점이 있음

1. try 블럭에 추가되는 테스트 메서드

만약 뺄셈, 곱셈 등 다른 기능들이 추가되면 try 블럭 내 코드가 늘어나고 유지보수가 어려워짐
→ 덧셈 기능만 테스트하고 싶을 경우, 다른 클래스들에 주석 처리 필요

CalculatorTest.java
// void testAdd() { ... } public static void main(String[] args) { Calculator calculator = new Calculator(); // 실행할 테스트를 try 블럭 내에 작성하여 테스트를 실행함 try { test.testAdd(); // 덧셈 테스트 메서드 호출 } catch (Throwable e) { test.erros++; e.printStackTrace(); } // 테스트 메서드에서 발생한 에러의 개수를 파악하여 개발자에게 알려주기 if (test.errors > 0) { throw new IllegalStateException(test.errors + "개의 에러가 있습니다."); } }

2. 테스트 대상이 되는 메서드만 찾으려면?

프로그램을 구현하다보면 현실적으로 테스트 필요성이 떨어지는 메서드가 있을 수 있음

프로그램에게 테스트 대상이 되는 메서드만 찾게 하려면 어떻게 해야할까?

런타임에 코드를 조작할 수 있는 Java의 reflection API을 활용하여 test~로 시작하는 메서드만 테스트 대상의 메서드만 되도록 처리

CalculatorTest.java
void calculatorUtil() { ... } // test~로 시작하는 메서드만 테스트 대상의 메서드가 되도록 등록 void testAdd() { ... } void testSub() { ... } void testMul() { ... }

3. 보일러 플레이트 코드 준비

단위 테스트를 수행하기 위해서는 지금까지 확인한 테스트를 위한 템플릿 코드를 준비해야 함

Last updated on