개요
1. UserDaoTest의 특징과 문제점
2. 테스트 검증의 자동화
3. JUnit테스트로 전환
본문
1. UserDaoTest의 특징과 문제점
테스트는 코드를 만들 때 필수적으로 요구되는 일이다. 테스트 없이는 코드가 원하는 대로 작동하는지 확신할 수 없으며 확신 없이 프로그램을 완성한다는 것은 말이 되지 않는 일이다. 1장에서 만들었던 코드도 나름대로 UserDaoTest를 통해서 테스트를 하고 있었다. 이 테스트의 특징을 알아보고 보다 효율적인 테스트 방법에 대해서 배워나가는 것이 이번 장의 목표이다.
테스트는 가능하면 작은 단위로 이루어져야 한다.
UserDaoTest는 Dao가 제대로 작동하고 있는 가에 초점이 맞춰져있다. Dao의 기능을 확인하기 위해서 view까지 만들고 서버 환경까지 만들어가며 연결하고 테스트하고 있지 않다. 이 자체가 효율적인 테스트가 가능하게 만든다. view, 서버 환경까지 만들어서 테스트 한다면 테스트가 실패했을 때 어디에서 문제가 생기고 있는 것인지 확신할 수가 없다. 따라서 가능하다면 작은 단위, 테스트 하고 싶은 부분만 테스트 할 수 있도록 해야한다.
테스트는 자동 수행이 가능해야 한다
테스트는 반복적으로 이루어지며 여러 가능성을 조회해볼 필요가 있는 경우가 많다. 반복 할 때마다 손으로 일일이 값을 바꾼다든지 맞는 값인지 확인하는 일을 반복해야 한다면 비효율적이다. 이를 피하기 위해서 자동수행이 가능하게끔 테스트를 만들 필요가 있다.
테스트의 개선과 개발도 점진적으로 이루어질 수 있어야 한다
개발 코드가 확장 개선이 용이하게 만들어지는 만큼 테스트도 개선 수정, 확장이 용이해야한다. 그래야 기존의 코드의 변경에 따라서 테스트의 개선도 이루어질 수 있고 테스트에서 먼저 원하는 기능을 떠올리고 값을 찾으면서 '테스트 주도 개발'이 가능해질 수 있다.
UserDaoTest는 자동 수행이 제대로 이루어지지 않고 main을 매번 실행한다는 점에서 번거로움이 있다. DB에 입력된 값과 불러온 값이 같은 값인지 확인하는 데에 사람의 판단력이 요구되는 점에서 자동화가 되어 있지 않고 각 Dao마다 생성되어서 수백개가 될지도 모르는 main메소드를 모두 실행하며 테스트를 봐야 한다는 것에서 문제점을 안고 있다.
2. 테스트 검증의 자동화
모든 테스트는 성공과 실패의 두 가지 결과를 가질 수 있다. 또 테스트의 실패는 테스트가 진행되는 동안에 에러가 발생해서 실패하는 경우와 테스트 작업 중에 에러가 발생하진 않았지만 그 결과가 기대한 것과 다르게 나오는 경우로 구분해 볼 수 있다. 여기서 전자를 테스트 에러, 후자를 테스트 실패로 구분해서 부르자.
기존의 UserDaoTest는 에러는 체크하고 있지만 실패를 체크하고 있지는 않다. 따라서 이를 수정해볼 필요가 있다.
System.out.println(user2.getName());
System.out.println(user2.getPassword());
System.out.println(user2.getId() + "조회 성공"); //수정 전 테스트 코드
//수정 후 테스트 코드
if(!user.getName().equals(user2.getName())) {
System.out.println("테스트 실패 (name)");
}
else if(!user.getPassword().equals(user2.getPassword())) {
System.out.println("테스트 실패 (password)");
}
else {
System.out.println("조회 테스트 성공");
}
수정한 코드는 조건문을 통해서 입력한 이름과 출력 받은 값이 같은지 체크 하여 원하는 결과물이 나오는지 확인하고 있다. 맞지 않는 값이 발견되면 실패문을 출력한다. 이렇게 하여 수동으로 확인하던 부분을 자동화 했다고 할 수 있다.
3. JUnit테스트로 전환
이제 main메소드로 일일이 실행하기에 생기는 문제점을 해결할 차례이다. 여기서 JUnit이라는 자바 개발자를 위한 테스팅 프레임워크가 등장한다. JUnit에게 제어 권한을 넘겨주고 JUnit에 의해서 진행하게끔 할 수 있다. 따라서 main()메소드나 오브젝트를 만들어서 실행시키는 코드 없이 실행가능 하게끔 할 수 있다.
@Test //Junit에게 테스트 메소드임을 알려줌
public static void addAndGet() throws ClassNotFoundException, SQLException {//테스트 메소드는 반드시 public으로 선언
// 애플리케이션 컨텍스트를 적용
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml", UserDao.class);
UserDao dao = context.getBean("userDao", UserDao.class);
...
JUnit을 쓰려면 가장 먼저 기본적으로 JUnit에게 테스트용 메소드라는 것을 알려주는 애너테이션 @Test를 사용해야하며 해당 메소드를 public으로 선언해야 한다는 규칙을 따라야 한다. 이것만으로 JUnit프레임워크로 메소드를 사용할 수 있다.
또한 JUnit은 여러가지 테스트에 필요한 기능들을 제공해준다. 이 중에서 검증에 쓰이는 조건문을 JUnit에서 쓰이는assertThat으로 바꿀 수 있다. asserThat()메소드는 첫 번째 파라미터의 값을 뒤에 나오는 조건으로 비교해서 일치하면 다음으로 넘어가고 아니면 테스트가 실패하도록 기능한다. 기존의 if/else를 assertThat으로 바꾸면 아래와 같다.
//수정 전
if(!user.getName().equals(user2.getName())) {
System.out.println("테스트 실패 (name)");
}
else if(!user.getPassword().equals(user2.getPassword())) {
System.out.println("테스트 실패 (password)");
}
else {
System.out.println("조회 테스트 성공");
}
//수정 후
assertThat(user2.getName(), is(user.getName()));
assertThat(user2.getPassword(), is(user.getPassword()));
수정된 JUnit테스트를 실행하려면 어디에든 아래와 같은 메소드를 추가하고 실행해주면 된다.
import org.junit.runner.JUnitCore;
...
public static void main(String[] args) {
JUnitCore.main("springbook.user.dao.UserDaoTest");
}
물론 이클립스와 같은 IDE를 통해서 작업하고 있다면 Run as JUnitTest라는 항목이 있으니 이를 활용해서 실행하면 된다.
정리
1. 테스트는 개발을 진행할 수 있게 해주고 안정성을 더해주는 아주 중요한 일이다.
2. 개발자의 테스트는 작은 단위, 자동화, 간편한 실행이 핵심이다.
3. JUnit프레임워크를 활용하여 테스트의 효율을 높일 수 있다.
소스 깃허브
https://github.com/cholongbul/Tobyspring
cholongbul/Tobyspring
토비의 스프링 연습. Contribute to cholongbul/Tobyspring development by creating an account on GitHub.
github.com
'스프링' 카테고리의 다른 글
토비의 스프링 - 2.4 스프링 테스트 적용 (0) | 2021.05.30 |
---|---|
토비의 스프링 - 2.3 개발자를 위한 테스팅 프레임워크 JUnit (0) | 2021.05.28 |
토비의 스프링 - 1.8 XML을 이용한 설정 (0) | 2021.05.23 |
토비의 스프링 - 1.7 의존관계 주입(DI) (0) | 2021.05.23 |
토비의 스프링 - 1.6 싱글톤 레지스트리와 오브젝트 스코프 (0) | 2021.05.20 |