사용자 입출력 함수로 구성된 함수는 어떻게 테스트 할 수 있을까?
회사 개발자 교육 때 진행하는 페어프로그래밍에서, 최대한 강의를 통해 배운 단위 테스트를 해보려고 했지만
void 형식의 함수의 프린트 결과값을 통해 함수의 테스트결과를 알려고 할 때,
그리고 입력 또한 함수 인자가 아닌 콘솔을 통한 입력을 받는 경우에 어떻게 테스트를 할 수 있을까에 대해 의문이 있었고
스택오버플로우의 힘을 통해 극복했다. 그 내용을 기록하고자 한다.
먼저 내가 테스트하려는 함수가 아래와 같다고 하자.
1. 사용자 입력을 받는다. 계산기 함수이므로 입력의 방식은 " {숫자} {연산자} {숫자} " 이어야만 한다.
2. 만약 위 형식 외에 다른 입력이 주어지는 경우엔 "올바른 계산식을 입력해주세요" 라는 메시지가 콘솔을 통해 프린트 된다.
3. 위 함수의 리턴값은 void 이며, 입력 또한 Scanner 를 이용한 사용자 입력 외엔 없다.
이 경우에는 일반적인
Assertions.assertThat(calculator("1+2+3")).isEqualTo(6);
과 같은 Assertj를 활용한 테스트코드를 쓸 수 없을 것이다. 함수의 리턴값과 입력인자가 없기 때문이다.
그럴땐 아래와 같이 하면 된다.
public class CalculatorTest {
private static Calculator calculator;
private static final String errMsg = "계산식을 입력해주세요.\n올바른 계산식을 입력해주세요.\n";
@BeforeAll
static void initAll() {
calculator = new Calculator();
}
@Test
void 연산자_에러테스트() {
String input = "1 + 2 k 3";
OutputStream out = new ByteArrayOutputStream();
System.setOut(new PrintStream(out));
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);
calculator.start();
Assertions.assertThat(errMsg).isEqualTo(out.toString());
}
}
먼저 모든 테스트코드에 공통으로 활용할 객체나 메시지 값을 전역으로 선언한다.
"@BeforeAll" 어노테이션은 모든 테스트가 실행되기 전에 "1회" 실행되는 함수이다.
OutputStream out = new ByteArrayOutputStream();
System.setOut(new PrintStream(out));
을 통해, 콘솔에 출력되는 아웃풋을 바이트 아웃풋 스트림 out에 지정해 저장한다.
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);
을 통해 input 문자열을 시스템의 사용자입력으로 입력시킨다.
두 입출력을 지정한 뒤 계산기를 시작하면 콘솔에 입력할 필요없이 지정한 문자열이 Scanner 객체에 입력되게 된다.
그 후 Assertions.assertThat(errMsg).isEqualTo(out.toString()); 를 통해
에러 메시지와 아웃풋 텍스트의 문자열이 일치하는지를 통해 테스트 결과를 검증할 수 있다.
이것이 가능한 이유
java.lang.System.setOut() method reassigns the "standard" output stream.
System.setOut() 메서드는 사용자 표준 출력 스트림을 재지정할 수 있게 해준다.
콘솔 출력을 생성한 나의 아웃풋 스트림 객체에 지정함으로써 출력값을 해당객체에 저장할 수 있게 된다.
사용자 입력 또한 같다.
www.tutorialspoint.com/java/lang/system_setout.htm
stackoverflow.com/questions/1119385/junit-test-for-system-out-println
'프로그래밍 > JAVA' 카테고리의 다른 글
[Java] Optional 에 대해 알아보자 - 1 (0) | 2021.03.29 |
---|---|
[Java] 내가 만든 클래스 객체 배열 정렬하기 (comparable, comparator, comparing) (0) | 2021.02.14 |
[Java] JVM, JRE, JDK 한줄 정리 (0) | 2020.10.30 |
[Java] == 와 equals() 의 차이 (0) | 2020.10.24 |
[Java] abstract class 추상클래스란? (0) | 2020.10.22 |