ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 올바른 단위 테스트 작성법
    Object & Test 2010. 12. 3. 20:56


    automatedtestinginstitute.com

    단위 테스트(Unit Test) 코드를 작성할 때 지켜야 할 명확한원칙이 있습니다. 주요 비즈니스 코드가 아닌 단위 테스트를 위한 코드라고 대충 작성해서는 안됩니다. 단위 테스트 코드는 테스트할 코드가 돌아가는지 확인하는 기본 목적만 달성하면 된다고 생각하지만, 이는 잘못된 생각입니다.



    문제는 이런 인식을 갖고 단위 테스트를 작성한다는 제 주변의 개발자들 조차도 단위테스트 작성의 가장 기본적인원칙도 지키지 않은 채 테스트 코드를 작성하는 경우가 있다는 것입니다

    그렇다면 단위 테스트 작성시 지켜야 할 기본적인 원칙이 무엇일까요? 바로, 하나의 테스트 메소드에서는 하나의 기능에 대해서 한 경우만 테스트해야 한다는 것입니다. 정말 간단한 원칙이지만 또한 매우 중요한 원칙이기도 합니다.


    왜 그럴까요? 하나의 테스트 메소드에서 여러 가지 경우를 테스트하게될 경우 테스트의 목적이 불분명해지게 됩니다. 뭘 테스트해야 하는지 모호해 지게 되는 것이지요. , 테스트가 실패할 경우 기능의 어느 부분에서 테스트가 실패하게되는지 바로 파악할 수 없게 됩니다. 결국은 테스트를 디버그(debug)해야하는 경우가 발생하게 됩니다. 다음의 코드가 나쁜 테스트 코드 작성의 예입니다. 하나의 테스트 코드에서 여러가지 기능을 검증하고 있습니다. 아래의 코드는 비교적 간단합니다만 여기에 검증을 위한 루프나  조건문까지 사용하게 된다면 이해하기는 더욱 어려울 겁니다.

    public void testUpdateInvestForSecede() {
    Invest invest = new Invest();
    invest.setUserId("bee3");
    invest.setTerminateDate("2008-05-09");
    invest.setSecedeId(100);

    this.investService.updateAccumulatedInvestForSecede(invest);
    List<Invest>result = this.investService.readInvestByUserId("bee3");

    assertNotNull(result);
    assertEquals(2, result.size());
    assertEquals("2007-12-25", result.get(1).getTerminateDate());

    this.investService.updateDeferredInvestForSecede(invest);
    result = this.investService.readInvestByUserId("bee2");

    assertNotNull(result);
    assertEquals(1, result.size());
    assertEquals("2008-05-09", result.get(0).getTerminateDate());

    invest.setUserId("bee3");
    invest.setTerminateDate("2008-05-09");
    invest.setSecedeId(100);

    this.investService.cancelSecede(invest);
    result = this.investService.readInvestByUserId("bee3");

    assertNotNull(result);
    assertEquals(2, result.size());
    assertEquals("2007-12-25", result.get(1).getTerminateDate());
    assertEquals(0, result.get(1).getSecedeId().intValue());
    assertEquals(null, result.get(0).getTerminateDate());
    assertEquals(0, result.get(0).getSecedeId().intValue());

    }

    또한, 테스트 코드는 문서(document)로써의역할도 하게 됩니다. 비즈니스 코드를 구동하는 방식 및 사용하는 방식을 테스트 코드를 통해 파악할 수있어야 합니다. 만약, 테스트 코드를 복잡하게 작성해서 테스트코드를 이해하기 어렵다면 테스트 코드 작성의 의미가 반감됩니다. 따라서 테스트 케이스를 최대한 간단(simple)하게 작성하여 가독성 및 이해도가 높아질 수 있도록 해야 합니다. 다음은 좋은 테스트 코드의 예입니다. 하나의 기능에 대해 두 가지 경우를 각각 독립적으로 검증합니다.

    @Test
    public void testReadAttendanceByDate() throws Exception {

    //setup
    final Long projectId = 1L;
    final Long humanResourceId = 3L;
    Date date = DateUtil.stringToDate("2009-08-01");
    //exercise
    Attendance attendance =
    this.humanResourceProvider.readAttendanceByDate(projectId, humanResourceId, date);
    //verify
    Assert.assertNotNull(attendance);
    Assert.assertEquals("08:50", attendance.getStartTime().getTime());
    }
    @Test
    public void testReadAttendanceList_shouldBeEmpty() throws Exception {
    //setup
    final Long projectId = 1L;
    Date date = DateUtil.stringToDate("2009-08-02");
    //exercise
    List<Attendance> results =
     this.humanResourceProvider.readAttendanceListByDate(projectId, date);
    //verify
    Assert.assertEquals(3, results.size());
    Assert.assertNull(results.get(0).getAttendanceDate());
    Assert.assertNull(results.get(1).getAttendanceDate());
    Assert.assertNull(results.get(2).getAttendanceDate());
    }

    geekswithblogs.net

    가장 치명적인 것은 테스트 코드가 복잡하고 난해하면 결국은 버려진다는 것입니다.비즈니스 코드는 마음에 안들거나 읽기 힘들다고 함부로 지울 지 않지만, 테스트 코드는 그렇지않습니다. 자꾸 실패하는데 봐도 잘 모른다면, Delete 키위로 손이 올라가게 되는 것이지요.

Designed by Tistory.