Backend
테스트코드를 왜 짜는가?와 테스트코드 짜는 법(Java)(1)
사과만쥬
2024. 6. 21. 16:08
테스트코드 시리즈는 킹갓백엔드 친구와의 메신저 내용과 개인과외 내용을 재구성하였습니다.
테스트코드를 왜 짜는가?
1. 테스트 코드를 짜기 시작하면, 당장 어떤 부분을 "검증"할지 먼저 생각해본다.
- 이 부분은, 최소한 어떤 입력이 들어왔을 때 어떤 결과를 내보낼 것인가, 그리고 내가 어떤 값만 유효하게 두고 어떤 값을 배제할 것인가 하는 부분이 중요하다.
- 그렇게 생각이 들어오면 "어? 이게 들어오면 어쩌지? 저게 들어오면 어쩌지?"에서 본인이 상상의 나래를 펼칠 수 있는 모든 케이스를 본인 스스로가 방어함으로 인해서 500이 뜰 확률을 급격하게 낮춰주는 효과가 있다.
2. 테스트 코드가 점점 쌓이기 시작하면, 본인이 실수하는 코드로 인해서 다른 부분을 건드리고 있는지 확인할 수 있다.
- 다른 사람들도 같이 쓰고 있는 객체 함수가 있는데, 본인이 고쳤던 부분으로 인해서 다른 사람이 쓰고 있는 부분에 영향이 갈 수 있다.
- 그런데, 테스트코드가 점점 쌓이기 시작하면, 본인이 어떤 모험을 하더라도 테스트 코드 전체 실행으로 인해서 모두 검증할 수 있고, 그 모든 검증으로 인해서 전체적으로 관리가 쉬워진다.
- 만약에 이 케이스에 있어서, 테스트 코드가 없다고 생각했다면, 일단 마음이 불안한 사람은 개발자이다.
- 내가 어떤 코드를 고쳤는데, 이 고친 부분으로 인해서 다른 사람 기능에 문제가 생기면 어떻게 하지? 이런 생각을 아예 배제해 줄 수 있다.
3. 개발자 본인의 결과물에 대해서, 본인이 자신 있는 상태가 될 수 있다.
- 테스트 코드 상 검증이 완료되었고, 본인이 테스트 코드를 짜면서 본인의 코드를 다시 돌아보게 되고, 만약에 내가 고려하지 못한 테스트 케이스에서 500 에러가 뜬다고 하더라도 그것을 고쳐놓고 본인이 실수한 부분을 다시 커버하는 테스트를 생성하면 좋다.
(참고로 이 친구는 500 에러가 안 뜨게 만드는 것이 백엔드의 기본 소양이라고 생각하는 친구입니다.) - 테스트 코드만 200~300개 쌓이면 내가 어떤 실수를 해도 테스트 코드가 검증해 줄 것이라는 확신이 있어서 더 좋다. 자신감의 원천이 될 수 있다.
테스트코드를 짜는 법(Java)
자바로 테스트코드를 짜는 데는 여러 가지 도구가 있다.
1. JUnit5
- 자바, 특히 gradle 기반의 자바 프로젝트에서 기본적으로 제공하는 테스트 도구
- 프로젝트 생성 시 IntelliJ로 생성하면 main/test가 나뉘지 않는다. 그러나 gradle로 생성 시 main/test로 나뉨.
- IntelliJ에서 Generate 이용하면 편하게 생성 가능 (Ctrl + Shift + T)
1) 기존의 불편함
package org.example;
public class Main {
public static void main(String[] args) {
System.out.println(abc(1));
}
public static String abc(int a) {
return a + " hello";
}
}
매번 테스트 시
System.out.println(abc(1));
안에 새로운 값을 넣어줘야 함. 그러나 테스트 코드를 이용하면 이러한 불편함은 없앨 수 있음.
package org.example;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class MainTest {
@Test
void main() {
System.out.println("hello");
}
@Test
void abcTest() {
System.out.println(Main.abc(1));
}
}
위와 같이 테스트코드를 작성한다면,
이런 식으로 나오는 것을 볼 수 있음.
그러나 이런 식으로 테스트하는 것으로는 테스트의 성공/실패 여부를 가늠하기 힘들다. 그래서 assertJ를 이용하기로 함.
2) assertj 이용하기
testImplementation 'org.assertj:assertj-core:3.6.1'
build.gradle의 dependencies 항목에 위 항목을 추가한다. (시간이 지남에 따라 버전을 달라질 수 있습니다.)
틀리는 케이스를 보여주기 위해 Main.java 코드를 아래와 같이 수정하였다.
package org.example;
public class Main {
public static void main(String[] args) {
System.out.println(abc(1));
}
public static String abc(int a) {
if (a<0) {
return a + "negative";
}
return a + " hello";
}
}
테스트 코드를 아래와 같이 작성한다.
이 코드의 경우 -1이기 때문에 -1negative가 출력이 되어야 한다.
package org.example;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class MainTest {
@Test
void main() {
System.out.println("hello");
}
@Test
void abcTest() {
System.out.println(Main.abc(-1));
Assertions.assertThat(Main.abc(-1)).isEqualTo("-1 hello");
}
}
그럼 아래와 같이 오류가 난 것을 볼 수 있다.
여기서 하나의 팁이 있다면 Alt+Enter를 치면
위와 같은 창이 나오는데 Add Static import를 선택하면
@Test
void abcTest() {
System.out.println(Main.abc(-1));
assertThat(Main.abc(-1)).isEqualTo("-1 hello");
}
코드가 위와 같이 간단해진다.
이것이 JUnit5의 기본적인 모양새이다.
참고
Assertions 이용 시 위의 org.junit.jupiter.api를 클릭하자.