테스트란
테스트란 프로그램의 품질을 검증하는 것으로 의도대로 프로그램이 잘 동작하는지 확인하는 과정을 말한다.
초기에는 사람이 직접 요청을 보내고 응답을 받아 일일이 확인했지만,
이제는 다양한 테스트 도구들을 이용해 반복적인 검증 절차를 통해 자동화 할 수 있다.
테스트 도구를 활용해 코드를 검증한다는 것은 테스트 코드를 작성해 실행한다는 말이다.
테스트 코드는 보통 3단계로 작성하는데 예상 데이터를 먼저 작성하고,
실제 데이터를 획득 후 예상 데이터와 실제 데이터 비교해 검증한다.
작성한 코드가 통과하면 지속적인 리팩터링으로 코드를 개선하는데 테스트를 통과하지 못하면 디버깅을 해야 한다.
테스트 코드는 다양한 경우를 대비해 작성하는데 이를 테스트 케이스라고 한다.
테스트 케이스는 성공할 경우 뿐만 아니라 실패할 경우도 고려해야 하며 다양한 상황을 예상해 세부적으로 작성해야 한다.
이런 것들을 기반으로 한 개발 방법론인 테스트 주도 개발이란,
테스트 코드를 만든 후 이를 통과하는 최소한의 코드부터 시작해 점진적으로 코드를 개선 및 확장해 나가는 개발방식이다.
테스트 코드 작성하기
테스트 코드 기본 틀을 먼저 만들어 볼 것인데 ArticleService를 검증하는 테스트 코드를 작성해 볼 것이다.
ArticleService 파일에서 index() 메서드에서 마우스 오른쪽 버튼을 누르고 Generate -> Test를 선택한다.
Create Test 창이 열리면 JUnit5로 테스트를 만들어 자동으로 테스트 코드를 생성해준다.
그러면 main > test > java > com.example.firstproject > service > ArticleServiceTest로 생성된 것을 볼 수 있다.
package com.example.firstproject.service;
import org.junit.jupiter.api.Test; // Test 패키지 import
class ArticleServiceTest {
@Test // 해당 메서드가 테스트 코드임을 선언
void index() {
}
}
이제 테스트 코드를 스프링 부트와 연동하기 위해 ArticleServiceTest 클래스 위에 @SpringBootTest를 붙여준다.
그 다음 articleService 객체도 선언해주고 외부 객체 주입을 위한 어노테이션도 붙여준다.
@SpringBootTest
class ArticleServiceTest {
@Autowired
ArticleService articleService;
...
...
}
그 다음으로는 index 메서드에 본격적으로 테스트를 위한 코드를 아래와 같이 작성해주고 테스트가 통과되는지 확인해준다.
@Test // 해당 메서드가 테스트 코드임을 선언
void index() {
// 1. 예상 데이터
Article a = new Article(1L, "가가가가", "1111");
Article b = new Article(2L, "나나나나", "2222");
Article c = new Article(3L, "다다다다", "3333");
List<Article> expected = new ArrayList<Article>(Arrays.asList(a,b,c));
// 2. 실제 데이터
List<Article> articles = articleService.index();
// 3. 비교 및 검증
assertEquals(expected.toString(), articles.toString());
}
위와 같이 테스트 코드가 정상적으로 통과하여 초록색 체크표시를 볼 수 있다.
테스트 통과하지 못한 경우 어떻게 나오는지 확인하기 위해 코드를 틀리게 작성하고 다시 테스트를 실행하면 아래와 같이 나온다.
이번에는 게시글을 조회하는 show 메서드를 테스트 해 볼 것인데 앞서와 마찬가지로,
테스트 코드 작성 틀은 자동완성으로 만들어주면 되는데 이번에는 성공과 실패의 경우 나눠서 메서드를 만들 것이다.
@Test
void show_success() {
}
@Test
void show_fail() {
}
성공 시의 코드는 아래와 같고 실행 결과를 보면 테스트 케이스가 통과된 것을 볼 수 있다.
@Test
void show_success() {
// 1. 예상 데이터
Long id = 1L;
Article expected = new Article(id, "가가가가", "1111");
// 2. 실제 데이터
Article article = articleService.show(id);
// 3. 비교 및 검증
assertEquals(expected.toString(), article.toString());
}
실패하는 경우에도 다양한 케이스가 존재하지만,
여기서는 존재하지 않는 id를 입력해 실패하는 경우를 작성할 것인데 코드는 아래와 같다.
@Test
void show_fail() {
// 1. 예상 데이터
Long id = -1L;
Article expected = null;
// 2. 실제 데이터
Article article = articleService.show(id);
// 3. 비교 및 검증
assertEquals(expected, article);
}
테스트를 돌려보면 존재하지 않는 id로 조회했을 때 실제 null을 반환했고,
예상 데이터에서도 null을 반환한다고 했기 때문에 테스트에 통과한 것이다.
다음으로는 게시글을 생성하는 create 메서드를 테스트 해 볼 것이다.
위와 유사한 과정으로 진행하면 되는데,
예상 데이터에서 사용자가 새 게시물을 생성한 상황을 가정해서 임의의 값을 배정해주면 된다.
@Test
void create_success() {
// 1. 예상 데이터
String title = "라라라라";
String content = "4444";
ArticleForm dto = new ArticleForm(null, title, content);
Article expected = new Article(4L, title, content);
// 2. 실제 데이터
Article article = articleService.create(dto);
// 3. 비교 및 검증
assertEquals(expected.toString(), article.toString());
}
@Test
void create_faill() {
// 1. 예상 데이터
Long id = 4L;
String title = "라라라라";
String content = "4444";
ArticleForm dto = new ArticleForm(id, title, content);
Article expected = null;
// 2. 실제 데이터
Article article = articleService.create(dto);
// 3. 비교 및 검증
assertEquals(expected, article);
}
마지막으로 각 테스트를 돌려보는 것이 아닌 여러 테스트 케이스를 한 번에 실행하는 방법에 대해 알아볼 것이다.
ArticleServiceTest 클래스의 실행 버튼을 클릭하고 실행시켜주면 테스트 케이스 5개가 동시에 돌아간다.
그런데 index() 테스트 케이스가 통과하지 못한 것을 볼 수 있는데,
예상 값에는 1,2,3번 케이스가 있지만 실제 값을 보면 4번까지 총 4개의 데이터가 존재한다.
이러한 현상을 롤백하지 않아서 생긴 것인데,
index 메서드를 실행하기 전에 create_success 메서드를 실행하면서 새 데이터인 4번 데이터가 생성되었기 때문이다.
package com.example.firstproject.service;
...
import org.springframework.transaction.annotation.Transactional;
...
@SpringBootTest
class ArticleServiceTest {
@Autowired
ArticleService articleService;
@Test
@Transactional
void create_success() {
}
@Test
@Transactional
void create_faill() {
}
}
문제를 해결하기 위해 트랜잭션으로 처리를 해 주어서 테스트가 끝나면 롤백하도록 위와 같이 코드를 수정해주면 된다.
'Backend' 카테고리의 다른 글
코딩자율학습단 스프링부트_15장 (0) | 2024.08.24 |
---|---|
코딩자율학습단 스프링부트_14장 (0) | 2024.08.23 |
코딩자율학습단 스프링부트_12장 (0) | 2024.08.19 |
코딩자율학습단 스프링부트_11장 (0) | 2024.08.17 |
코딩자율학습단 스프링부트_10장 (0) | 2024.08.16 |