1. 테스트 코드란?

  • 테스트(Test)란 프로그램의 품질을 검증하는 것으로, 의도대로 프로그램이 잘 동작하는 지 확인 하는 과정.

  • 사람이 직접 일일이 요청을 보내고 응답을 받아 확인하는 방법이 아닌, 테스트 도구를 이용해서 반복적인 검증 절차자동화할 수 있음.

  • 테스트 코드 작성 방식.

    • 예상 데이터 작성.
    • 실제 데이터 획득.
    • 두 데이터를 비교, 검증.
  • 작성한 코드가 테스트를 통과하면 지속적인 리팩토링으로 코드를 개선하고, 통과하지 못했다면 잘못된 부분을 찾아서 디버깅(debugging)을 해야함.

    • 디버깅이란?
      • 프로그램에서 발생하는 오류(bug)를 찾아 수정하는 과정을 뜻함.
      • 소프트웨어가 예상대로 작동하지 않을 때 그 원인을 분석하고 해결하는 단계.
  • 테스트 코드는 작성시 다양한 경우의 수를 따져서 작성함.

    • 이를 테스트 케이스(Test case)라고 함.
    • 즉, 성공할 경우뿐만 아니라 실패할 경우도 따져야 함.

1-1. 테스트 주도 개발. (TDD)

  • 테스트 주도 개발(TDD, Test Driven Development)란?
    • 먼저 테스트 코드를 작성한 후 이를 통과하는 코드부터 시작해서 점진적으로 코드를 리팩토링 및 확장해 나가는 개발 방식.

2. 테스트 코드 작성.

  • JUnit5
    • Java에서 단위 테스트(Unit Test)를 작성하고 실행할 수 있도록 해주는 테스트 프레임워크(Framework).
  • @Test
    • 어노테이션이 붙은 메서드가 테스트를 위한 코드라고 선언.
  • @SpringBootTest
    • 어노테이션이 붙은 클래스스프링 부트와 연동해서 통합 테스트를 수행하겠다고 선언.
    • 테스트 코드에서 스프링 부트가 관리하는 다양한 객체주입받을 수 있음.

2-1. 모든 데이터.

@SpringBootTest
class ArticleServiceTest {
    @Autowired
    ArticleService articleService;
    @Test
    void index() {
        Article a = new Article(1L, "안녕하세요", "반가워요");
        Article b = new Article(2L, "안녕", "반가워");
        Article c = new Article(3L, "안녕하세요 반가워요", "네 반가워요");
        List<Article> expected = new ArrayList<Article>(Arrays.asList(a, b, c));

        List<Article> articles = articleService.index();
        
        assertEquals(expected.toString(), articles.toString());
    }
}
  • @Autowired ArticleService articleService;
    • 객체 선언 (외부 객체를 주입해야 하므로 @Autowired 붙임.)
  • assertEquals(expected.toString(), articles.toString());
    • assertEquals를 이용해서 예상 데이터와 실제 데이터를 비교하고 두 값이 일치하면 통과.
      • 예상 데이터를 문자열로 변환, 실제 데이터를 문자열로 변환.
    • JUnit5에서 제공하는 메서드.
  • Arrays.asList() 메서드.
    • 입력된 배열 or 2개 이상의 동일한 타입 데이터를 정적 리스트로 만들어서 반환.
      • 정적 리스트는 크기가 고정되어 있어서 add(), remove()메서드 사용 불가.
    • 정적 리스트에 add(), remove()메서드를 사용하려면 정적 리스트일반 리스트로 새로 만들어야 됨.
    • new ArrayList<Article>(Arrays.asList(a, b, c))
      • Arrays.asList() 메서드로 합친 정적 리스트새 ArrayList로 만들었음.

예상 데이터와 실제 데이터가 같은 경우, (테스트 합격)

예상 데이터와 실제 데이터가 다를 경우, (테스트 불합격)


2-2. 단일 데이터 (실패).

    @Test
    void show_실패_존재하지_않는_id입력() {
        Long id = -1L;
        Article expected = null;

        Article article = articleService.show(id);

        assertEquals(expected, article);
    }
  • 존재하지 않는 id = -1L;
    • DB에서 조회되는 내용이 없어서 null이 반환될 것이므로 expected = null.
  • nulltoString() 메서드를 호출할 수 없으므로 값 그대로를 비교.

2-3. 데이터 생성.

    @Test
    void create_성공_title과_content만_있는_dto입력() {
        String title = "연말 잘 보내세요";
        String content = "올 한 해도 수고하셨습니다";
        ArticleForm dto = new ArticleForm(null, title, content);
        Article expected = new Article(4L, title, content);

        Article article = articleService.create(dto);

        assertEquals(expected.toString(), article.toString());
    }
  • ArticleForm dto = new ArticleForm(null, title, content);
    • id는 DB에서자동으로 생성해주니깐 써줄 필요없음.

2-4. 테스트 코드 여러개를 한 번에 실행.

  • 유일하게 index()(= 전체 데이터 조회) 만 통과하지 못했음.
    • 사진을 통해 이유를 살펴보면 데이터 생성 테스트 코드로인해 id=4값의 데이터가 있는 것을 확인.
    • 트랜잭션(@Transactional)어노테이션을 추가해서 테스트가 끝나면 롤백하도록 해줌으로써 해결.
      • 즉, 테스트가 끝난 후 변경된 데이터를 초기상태로 롤백.
  • 생성(create), 수정(update), 삭제(delete)와 같이 데이터에 변화가 생기는 테스트들은 트랜잭션(@Transactional)으로 묶어서 테스트가 종료된 후 초기상태로 돌아가도록 롤백 처리 해줘야함.
profile
Every cloud has a silver lining.

0개의 댓글