SlideShare a Scribd company logo
테스트 가능한
소프트웨어 설계와
TDD작성 패턴
Testable software design & TDD patterns




                         한국 스프링 사용자 모임 (KSUG )

                                          채수원
발표자 개
발 자 소개
LG CNS 경영기술교육원 기술교육팀 전임강사

강의 과목
디자인 패턴 & 리팩터링
분석설계 실무
Agile
A il 적용실무

블로그
여름으로 가는 문 blog.doortts.com



Comments
  내용이나 후기에 대해서는 Outsider님의 후기
  (http://blog.outsider.ne.kr/494) 를 참조 하시면
  (htt //bl      t id      k /494)
  좀 더 도움이 될 겁니다.
흠
흠…

     Comments
       2010년 7월 10일 화창한 토요일 오후 이대 ECC
Why are we here?
보다 더 나은 소프트웨어와
 다         웨어와
보다 더 나은 삶을 만들기 위해
객체 지향 기본 원칙
OCP
SRP
ISP
Demeter s
Demeter’s Law (=hollywood law)
              ( hollywood
IOC
        Comments
        언어도 열심히 배우고 원칙도 학습했으니까 개발을 더 잘할 수 있겠죠?
다음 두 코드 중 더 나은 디자인은?
 Case.1   class Rental {
              Movie movie;
              Rental(Service service) {
                  this.movie = service.getMovie();
              }
          }

 Case.2
 C    2   class R t l {
                Rental
              Movie movie;
              Rental(Movie movie) {
                  this.movie = movie;
              }
          }
(based on my five years of educational experience)

Strongly recommended approach #1
St    l          d d        h




               테스트 주도 개발
               Test-Driven D
               T t Di      Development
                               l     t
TDD 관점에서 바라봤을 때 드러나는



     안 좋은 디자인의 징후
      - 단위 테스트 케이스 작성이 어렵다
      - 단위 테스트 케이스가 자주 깨진다
                       깨진다.
      - 단위 테스트 케이스 실행을 위한 준비해야 할 것이 많다.
      - 다른 사람의 테스트 케이스를 읽기가 어렵다.
강형 마이크로 디자인
기초 점검 코스
“프로그램을 작성하기 전에 테스트 먼저 하라!”
 프로그램을                하라!
Test the program before you write it.




“잘 동작하는 깔끔한 코드”
 잘
Clean code that works




“질문
 질             응답            정
                             정제         반복
                                        반복”
Ask     Respond     Refine    Repeat
p
public class Calculator {
  public int sum(int a, int b) {
    return 0;
  }

    public static void main(String[] args) {
        Calculator calc = new Calculator();
        System.out.println( calc.sum(10, 20) == 30 );
        System.out.println( calc.sum(1, 2) == 3 );
        System.out.println( calc.sum(-10, 20) == 10 );
        S            i l ( l        ( 10            )
        System.out.println( calc.sum(0, 0) == 0 );
    }
}                 모두 true면 작성완료!

-----실행 결과-----
     실행 결과
false
false
false       Comments
true       굳이 프레임워크를 쓰지 않아도 무방합니다. 업무로직 작성 전에 완성상태를
              검증해 줄 수 있는 코드가 존재하기만 하면 충분합니다.
기본 코스
생성자 메소드 테스트
(
(constructor method test)
                        )

 public class E l
   bli l      EmployeeDaoTest {
                      D T t

 @Test
 public EmployeeDaoTest {
     EmployeeDao d = new E l
     E l     D dao         EmployeeDao();
                                    D ()
     assertTrue(dao.isConnected());
 }
동치 비교
( q
(equivalence test)
                 )

@Test
public void testEquals_case2() {
    Music musicA = new M i ("BAD" "Mi h l")
       i     i         Music("BAD", "Michael");
    Music musicB = new Music("BAD", "Michael");
    assertEquals ( musicA musicB);
                   musicA,
}
동치 비교
( q
(equivalence test)
                 )
해결책.1
해결책 1   내부 상태(보통은 필드값)를 직접 꺼내와서 각각
        비교한다.
해결책.2   toString을 중첩구현해(override)놓고, toString 값
        으로 비교한다.

해결책.3   equals 메소드를 중첩구현한다.

해결책.3   Unitils의 assertReflectionEquals를 이용한다.
배열비교
(
(array test)
     y     )
해결책.1
해결책 1   JUnit 4의 assertArrayEquals를 이용한다
                                    이용한다.


해결책.2   Unitils의 assertReflectionEquals나
        assertLenientEquals를 이용한다

해결책.3   List로 변환해서 비교한다.
배열비교
(
(array test)
     y     )

@Test
public void testArrayEqual_NotSorted() {
    String[] arrayA = new String[] {"A", "B", "C"};
                                   { A    B    C };
    String[] arrayB = new String[] {"B", "A", "C"};
    Arrays.sort
    Arrays sort (arrayA);
    Arrays.sort (arrayB);
    assertArrayEquals (arrayA, arrayB);
}
몇 가지 오해
boolean isRight(){
    return TDD == UnitTest
}
(Do) All or Noting
단위 테스트 케이스 작성
Skeleton vs Incremental
      package main;
      public class Account {

          public Account(int i) {
          }
          public i
            bli int getBalance() {
                          l    ()
              return 0;
          }
          public void withdraw(){
          }
          public void deposit(){
          }
      }
One method one assert ?
  @Test
  public void testGetBalance() throws Exception {
    bli    id          l    () h            i
      assertEquals (10000, account.getBalance());
      account = new Account(1000);

      assertEquals (1000, account.getBalance());
      account = new Account(0);

      assertEquals (0, account.getBalance());
  }
Anti-pattern
Anti pattern
      private Account account;

      @Before
      public void setUp(){
          account = new Account(10000);
      }

      @Test
      public void testWithdraw() throws Exception {
          account.withdraw(1000);
                          (    )
          assertEquals(9000, account.getBalance());
      }
Anti-pattern
    public     class AccountTest {

            @Before
            public void setUp(){
            }

            @Test
            p
            public void testDeposit() throws Exception {
                              p    ()            p
                Account account = new Account(10000);
                account.deposit(1000);
                assertEquals(11000, account.getBalance());
            }

            @Test
            public void testWithdraw() throws Exception {
                Account account = new Account(10000);
                account.withdraw(1000);
                assertEquals(9000, account.getBalance());
                          l (                   l     ())
        }
    }
단위 테스트 접근 방식
상태기반 테스트
                 입력



       methodA


           doSomething



            ?


     예상결과
          = 실제결과
상태기반 테스트

 @Test
 public void t tFil R
             testFileRemove() {
                           ()
     FileUtile fileUtil = new FileUtil();
     fileUtil.cleanContents( targetFile );
     assertEquals( 0 fileUtil size( targetFile ) );
                   0, fileUtil.size(
 }
행위기반 테스트
  Case.1
  Case 1      입력A


           methodA               methodB


            doSomething          rampOn




  Case.2      입력B


           methodA
                                 methodB

                          call
           doSomething
           d S   thi                 rampOn
                                         O
행위기반 테스트

@Test
public void testGetOrderPrice () throws Exception {
    PriceCalculator calculator = new PriceCalculator();
    Item item = new Item("LightSavor","Kitchen knife",100000);
    ICoupon coupon = new Coupon();
    assertEquals(93000, calculator.getOrderPrice(item, coupon));
    int methodCallCount = ((Coupon)coupon).getIsAppliableCallCount();
    assertEquals (1, methodCallCount);
}
행위기반 테스트
public class Coupon implements ICoupon {

    private int isAppliableCallCount;
    @Override
    public boolean isAppliable(Item item) {
        isAppliableCallCount++; // 호출되면 증가
                                     출
         ……..
    }

    p
    public int getIsAppliableCallCount(){
               g     pp               (){
        return this.isAppliableCallCount;
    }
}
행위기반 테스트

@Test
p
public void testGetOrderPrice () throws Exception {
                                            p
    PriceCalculator calculator = new PriceCalculator();
    Item item = new Item("LightSavor","Kitchen knife",100000);
                    Item( LightSavor   Kitchen knife 100000);
    ICoupon mockCoupon = mock(ICoupon.class);
        … // mocking 작업
    assertEquals(93000, calculator.getOrderPrice(item, mockCoupon));
    verify (
       if (mockCoupon, ti
              kC       times(1)).isAppliable(box);
                            (1)) i A li bl (b );
}
TDD with Spring
  스프링 프레임워크의 Unit Test 지원
    링 레임워 의


     - 의존관계 주입을 통한 객체 생성
     - 웹 컨테이너 없는 웹 애플리케이션 테스트
     - 단위 테스트 지원 유틸리티


                   => Injection과 Mock
XmlBeanFacotry로 컨텍스트 가져오는 버전
             y   텍
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi http://www.w3.org/2001/XMLSchema instance
        xmlns:xsi="http://www w3 org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http //www.springframework.org/schema/beans/spring beans.xsd >
        http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="music" class="main.MP3">
    <constructor-arg value="Belong to me.mp3"/>
                   g             g        p
  </bean>
  <bean id="musicPlayer" class="main.MusicPlayer">
    <property name="music" ref="music"/>
  </bean>
</beans>


XmlBeanFactory beanFactory
  = new XmlBeanFactory(
      new ClassPathResource("/context-musicplayer xml")
          ClassPathResource( /context musicplayer.xml )
     );
Unitils를 사용

 @RunWith(UnitilsJUnit4TestClassRunner class)
 @RunWith(UnitilsJUnit4TestClassRunner.class)
 public class UnitilsMusicPlayerTest {

     @SpringApplicationContext( /context-musicplayer.xml )
     @SpringApplicationContext("/context-musicplayer xml")
     private ApplicationContext context;
 …
 …
 }
annotation및 autowire를 사용해서

@RunWith(SpringJUnit4ClassRunner class)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/context-musicplayer.xml"})
public class AutowiredMusicPlayerTest {

    @Autowired
    MusicPlayer player;
…
…
}
Injection기능만 사용할 경우
Google Guice(쥬스)로 처리해 보면

static Injector injector = Guice.createInjector(new MusicModule());

@Test
public void testGetFileName() throws Exception {
    MusicPlayer player = injector.getInstance(MusicPlayer.class);
    assertEquals("Belong To Me.mp3", player.getFileName());
}
TDD with Spring – servlet test




           이름     박성철
           사번     5874

           아이디    fupfin

           직위     회장
TDD with Spring – servlet test
public class EmployeeSearchServletTest {
@Test
public void testSearchByEmpid() throws Exception {
  bli    id      S   h     id() h            i
    MockHttpServletRequest request = new MockHttpServletRequest(); // ➊
    MockHttpServletResponse response = new MockHttpServletResponse(); // ➋
    request.addParameter("empid", "5874") // ➌
             ddP        ("   id" "5874");

    EmployeeSearchServlet searchServlet
        = new EmployeeSearchServlet(); // ➍
    searchServlet.service(request, response); // ➎

    Employee employee = (Employee)request getAttribute("employee"); // ➏
                        (Employee)request.getAttribute( employee );

    assertEquals ("박성철", employee.getName() ); // ➐
    assertEquals ("5874", employee getEmpid() );
                 ( 5874   employee.getEmpid()
    assertEquals ("fupfin", employee.getId() );
    assertEquals ("회장", employee.getPosition() );
    assertEquals( /SearchResult.jsp ,
    assertEquals("/SearchResult.jsp", response.getForwardedUrl()); // ➑
    }
}
발표를 마치며
Q&A
    감사합니다

doortts@gmail.com
이미지 참조
Longing for Summer
http://www.flickr.com/photos/68165632@N00/1553091251/

Coupling sketches cropped
http://www.flickr.com/photos/49432745@N03/4533798684/

Tagged, finally...
http://www.flickr.com/photos/kornrawiee/3189034267/

Vincent Boiteau
 i         i
http://www.flickr.com/photos/2dogs_productions

More Related Content

PPTX
Rest assured
Varun Deshpande
 
PDF
Introduction to Unit Testing with PHPUnit
Michelangelo van Dam
 
PPTX
The Django Web Application Framework 2
fishwarter
 
PDF
Django admin site 커스텀하여 적극적으로 활용하기
영우 박
 
PDF
JUnit & Mockito, first steps
Renato Primavera
 
PPTX
API Testing Using REST Assured with TestNG
Siddharth Sharma
 
PPT
Spring Core
Pushan Bhattacharya
 
PDF
Build Automation using Maven
Ankit Gubrani
 
Rest assured
Varun Deshpande
 
Introduction to Unit Testing with PHPUnit
Michelangelo van Dam
 
The Django Web Application Framework 2
fishwarter
 
Django admin site 커스텀하여 적극적으로 활용하기
영우 박
 
JUnit & Mockito, first steps
Renato Primavera
 
API Testing Using REST Assured with TestNG
Siddharth Sharma
 
Spring Core
Pushan Bhattacharya
 
Build Automation using Maven
Ankit Gubrani
 

What's hot (20)

PPTX
Introduce yourself to java 17
ankitbhandari32
 
PDF
Clean coding-practices
John Ferguson Smart Limited
 
PDF
Spring framework aop
Taemon Piya-Lumyong
 
PPTX
Automation - web testing with selenium
Tzirla Rozental
 
PPTX
jQuery Fundamentals
Gil Fink
 
KEY
Spring AOP
Jeroen Rosenberg
 
PDF
Angular Directives
iFour Technolab Pvt. Ltd.
 
PDF
2015-StarWest presentation on REST-assured
Eing Ong
 
PDF
Spring Boot
Jaran Flaath
 
PDF
Java Serialization Deep Dive
Martijn Dashorst
 
PPTX
Cryptography for Java Developers: Nakov jProfessionals (Jan 2019)
Svetlin Nakov
 
PPTX
Api testing
Keshav Kashyap
 
PPTX
Rest assured
Yaniv Rodenski
 
PDF
Mocking in Java with Mockito
Richard Paul
 
ODP
Testing RESTful Webservices using the REST-assured framework
Micha Kops
 
PDF
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
SangIn Choung
 
PDF
Gherkin - crash course
Michele Costa
 
PDF
Angular Pipes Workshop
Nir Kaufman
 
PDF
Unit Testing in Angular
Knoldus Inc.
 
Introduce yourself to java 17
ankitbhandari32
 
Clean coding-practices
John Ferguson Smart Limited
 
Spring framework aop
Taemon Piya-Lumyong
 
Automation - web testing with selenium
Tzirla Rozental
 
jQuery Fundamentals
Gil Fink
 
Spring AOP
Jeroen Rosenberg
 
Angular Directives
iFour Technolab Pvt. Ltd.
 
2015-StarWest presentation on REST-assured
Eing Ong
 
Spring Boot
Jaran Flaath
 
Java Serialization Deep Dive
Martijn Dashorst
 
Cryptography for Java Developers: Nakov jProfessionals (Jan 2019)
Svetlin Nakov
 
Api testing
Keshav Kashyap
 
Rest assured
Yaniv Rodenski
 
Mocking in Java with Mockito
Richard Paul
 
Testing RESTful Webservices using the REST-assured framework
Micha Kops
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
SangIn Choung
 
Gherkin - crash course
Michele Costa
 
Angular Pipes Workshop
Nir Kaufman
 
Unit Testing in Angular
Knoldus Inc.
 
Ad

Viewers also liked (6)

PPTX
테스트 자동화와 TDD(테스트 주도 개발방법론)
KH Park (박경훈)
 
PPTX
IoT 개발자를 위한 Embedded C에서 TDD를 해보자
Taeyeop Kim
 
PDF
Amazon ECS를 통한 도커 기반 콘테이너 서비스 구축하기 - AWS Summit Seoul 2017
Amazon Web Services Korea
 
PDF
콘테이너 운영을 위한 Amazon EC2 Container Service(ECS) 집중 분석
Amazon Web Services Korea
 
PDF
AWS DevDay 실습 가이드 - 콘테이너
Amazon Web Services Korea
 
PDF
Tdd 왜 배우기 어려운가
Jaehoon Oh
 
테스트 자동화와 TDD(테스트 주도 개발방법론)
KH Park (박경훈)
 
IoT 개발자를 위한 Embedded C에서 TDD를 해보자
Taeyeop Kim
 
Amazon ECS를 통한 도커 기반 콘테이너 서비스 구축하기 - AWS Summit Seoul 2017
Amazon Web Services Korea
 
콘테이너 운영을 위한 Amazon EC2 Container Service(ECS) 집중 분석
Amazon Web Services Korea
 
AWS DevDay 실습 가이드 - 콘테이너
Amazon Web Services Korea
 
Tdd 왜 배우기 어려운가
Jaehoon Oh
 
Ad

Similar to 테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD) (20)

PDF
TDD&Refactoring Day 03: TDD
Suwon Chae
 
PDF
TDD&Refactoring Day 02: TDD
Suwon Chae
 
PPTX
TDD - Test Driven Development
ChangHyeon Bae
 
PDF
시작하자 단위테스트
YongEun Choi
 
PDF
TDD.JUnit.조금더.알기
Wonchang Song
 
DOCX
Android unit testing
Hyeoungkyu Chang
 
PDF
Effective Unit Testing
Yeon Soo Kim
 
PDF
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
용근 권
 
PDF
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
beom kyun choi
 
PDF
아꿈사.C++ api 디자인.20140315 a
Choonghyun Yang
 
PPTX
10장 결과 검증
dagri82
 
PDF
자바 웹 개발 시작하기 (8주차 : 명세서, 단위테스트, 통합)
DK Lee
 
PDF
Tdd with JUnit 1
Junyoung Lee
 
PDF
테스터가 말하는 테스트코드 작성 팁과 사례
SangIn Choung
 
PDF
Devon 2011-b-5 효과적인 레거시 코드 다루기
Daum DNA
 
PDF
KGC2010 - 낡은 코드에 단위테스트 넣기
Ryan Park
 
PDF
Tdd
savemyface
 
PDF
자바 테스트 자동화
Sungchul Park
 
PDF
개발이 테스트를 만났을 때(Shift left testing)
SangIn Choung
 
PPTX
TEST?
beom kyun choi
 
TDD&Refactoring Day 03: TDD
Suwon Chae
 
TDD&Refactoring Day 02: TDD
Suwon Chae
 
TDD - Test Driven Development
ChangHyeon Bae
 
시작하자 단위테스트
YongEun Choi
 
TDD.JUnit.조금더.알기
Wonchang Song
 
Android unit testing
Hyeoungkyu Chang
 
Effective Unit Testing
Yeon Soo Kim
 
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
용근 권
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
beom kyun choi
 
아꿈사.C++ api 디자인.20140315 a
Choonghyun Yang
 
10장 결과 검증
dagri82
 
자바 웹 개발 시작하기 (8주차 : 명세서, 단위테스트, 통합)
DK Lee
 
Tdd with JUnit 1
Junyoung Lee
 
테스터가 말하는 테스트코드 작성 팁과 사례
SangIn Choung
 
Devon 2011-b-5 효과적인 레거시 코드 다루기
Daum DNA
 
KGC2010 - 낡은 코드에 단위테스트 넣기
Ryan Park
 
자바 테스트 자동화
Sungchul Park
 
개발이 테스트를 만났을 때(Shift left testing)
SangIn Choung
 

More from Suwon Chae (6)

PDF
실패한 프로젝트들의 개발문화_개발방법론
Suwon Chae
 
PDF
Refactoring
Suwon Chae
 
PDF
TDD&Refactoring Day 01: Refactoring
Suwon Chae
 
PDF
Ryan Dahl의 Node.js 소개 동영상 해설 by doortts
Suwon Chae
 
PDF
Mongo db로 배우는 nosql
Suwon Chae
 
PDF
잘하면고효율, 못하면가문의원수가되는 짝프로그래밍 (Effective Pair Programming with Lessons Learned)
Suwon Chae
 
실패한 프로젝트들의 개발문화_개발방법론
Suwon Chae
 
Refactoring
Suwon Chae
 
TDD&Refactoring Day 01: Refactoring
Suwon Chae
 
Ryan Dahl의 Node.js 소개 동영상 해설 by doortts
Suwon Chae
 
Mongo db로 배우는 nosql
Suwon Chae
 
잘하면고효율, 못하면가문의원수가되는 짝프로그래밍 (Effective Pair Programming with Lessons Learned)
Suwon Chae
 

테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)

  • 1. 테스트 가능한 소프트웨어 설계와 TDD작성 패턴 Testable software design & TDD patterns 한국 스프링 사용자 모임 (KSUG ) 채수원
  • 2. 발표자 개 발 자 소개 LG CNS 경영기술교육원 기술교육팀 전임강사 강의 과목 디자인 패턴 & 리팩터링 분석설계 실무 Agile A il 적용실무 블로그 여름으로 가는 문 blog.doortts.com Comments 내용이나 후기에 대해서는 Outsider님의 후기 (http://blog.outsider.ne.kr/494) 를 참조 하시면 (htt //bl t id k /494) 좀 더 도움이 될 겁니다.
  • 3. 흠 흠… Comments 2010년 7월 10일 화창한 토요일 오후 이대 ECC
  • 4. Why are we here?
  • 5. 보다 더 나은 소프트웨어와 다 웨어와 보다 더 나은 삶을 만들기 위해
  • 7. OCP SRP ISP Demeter s Demeter’s Law (=hollywood law) ( hollywood IOC Comments 언어도 열심히 배우고 원칙도 학습했으니까 개발을 더 잘할 수 있겠죠?
  • 8. 다음 두 코드 중 더 나은 디자인은? Case.1 class Rental { Movie movie; Rental(Service service) { this.movie = service.getMovie(); } } Case.2 C 2 class R t l { Rental Movie movie; Rental(Movie movie) { this.movie = movie; } }
  • 9. (based on my five years of educational experience) Strongly recommended approach #1 St l d d h 테스트 주도 개발 Test-Driven D T t Di Development l t
  • 10. TDD 관점에서 바라봤을 때 드러나는 안 좋은 디자인의 징후 - 단위 테스트 케이스 작성이 어렵다 - 단위 테스트 케이스가 자주 깨진다 깨진다. - 단위 테스트 케이스 실행을 위한 준비해야 할 것이 많다. - 다른 사람의 테스트 케이스를 읽기가 어렵다.
  • 13. “프로그램을 작성하기 전에 테스트 먼저 하라!” 프로그램을 하라! Test the program before you write it. “잘 동작하는 깔끔한 코드” 잘 Clean code that works “질문 질 응답 정 정제 반복 반복” Ask Respond Refine Repeat
  • 14. p public class Calculator { public int sum(int a, int b) { return 0; } public static void main(String[] args) { Calculator calc = new Calculator(); System.out.println( calc.sum(10, 20) == 30 ); System.out.println( calc.sum(1, 2) == 3 ); System.out.println( calc.sum(-10, 20) == 10 ); S i l ( l ( 10 ) System.out.println( calc.sum(0, 0) == 0 ); } } 모두 true면 작성완료! -----실행 결과----- 실행 결과 false false false Comments true 굳이 프레임워크를 쓰지 않아도 무방합니다. 업무로직 작성 전에 완성상태를 검증해 줄 수 있는 코드가 존재하기만 하면 충분합니다.
  • 16. 생성자 메소드 테스트 ( (constructor method test) ) public class E l bli l EmployeeDaoTest { D T t @Test public EmployeeDaoTest { EmployeeDao d = new E l E l D dao EmployeeDao(); D () assertTrue(dao.isConnected()); }
  • 17. 동치 비교 ( q (equivalence test) ) @Test public void testEquals_case2() { Music musicA = new M i ("BAD" "Mi h l") i i Music("BAD", "Michael"); Music musicB = new Music("BAD", "Michael"); assertEquals ( musicA musicB); musicA, }
  • 18. 동치 비교 ( q (equivalence test) ) 해결책.1 해결책 1 내부 상태(보통은 필드값)를 직접 꺼내와서 각각 비교한다. 해결책.2 toString을 중첩구현해(override)놓고, toString 값 으로 비교한다. 해결책.3 equals 메소드를 중첩구현한다. 해결책.3 Unitils의 assertReflectionEquals를 이용한다.
  • 19. 배열비교 ( (array test) y ) 해결책.1 해결책 1 JUnit 4의 assertArrayEquals를 이용한다 이용한다. 해결책.2 Unitils의 assertReflectionEquals나 assertLenientEquals를 이용한다 해결책.3 List로 변환해서 비교한다.
  • 20. 배열비교 ( (array test) y ) @Test public void testArrayEqual_NotSorted() { String[] arrayA = new String[] {"A", "B", "C"}; { A B C }; String[] arrayB = new String[] {"B", "A", "C"}; Arrays.sort Arrays sort (arrayA); Arrays.sort (arrayB); assertArrayEquals (arrayA, arrayB); }
  • 22. boolean isRight(){ return TDD == UnitTest }
  • 23. (Do) All or Noting
  • 25. Skeleton vs Incremental package main; public class Account { public Account(int i) { } public i bli int getBalance() { l () return 0; } public void withdraw(){ } public void deposit(){ } }
  • 26. One method one assert ? @Test public void testGetBalance() throws Exception { bli id l () h i assertEquals (10000, account.getBalance()); account = new Account(1000); assertEquals (1000, account.getBalance()); account = new Account(0); assertEquals (0, account.getBalance()); }
  • 27. Anti-pattern Anti pattern private Account account; @Before public void setUp(){ account = new Account(10000); } @Test public void testWithdraw() throws Exception { account.withdraw(1000); ( ) assertEquals(9000, account.getBalance()); }
  • 28. Anti-pattern public class AccountTest { @Before public void setUp(){ } @Test p public void testDeposit() throws Exception { p () p Account account = new Account(10000); account.deposit(1000); assertEquals(11000, account.getBalance()); } @Test public void testWithdraw() throws Exception { Account account = new Account(10000); account.withdraw(1000); assertEquals(9000, account.getBalance()); l ( l ()) } }
  • 30. 상태기반 테스트 입력 methodA doSomething ? 예상결과 = 실제결과
  • 31. 상태기반 테스트 @Test public void t tFil R testFileRemove() { () FileUtile fileUtil = new FileUtil(); fileUtil.cleanContents( targetFile ); assertEquals( 0 fileUtil size( targetFile ) ); 0, fileUtil.size( }
  • 32. 행위기반 테스트 Case.1 Case 1 입력A methodA methodB doSomething rampOn Case.2 입력B methodA methodB call doSomething d S thi rampOn O
  • 33. 행위기반 테스트 @Test public void testGetOrderPrice () throws Exception { PriceCalculator calculator = new PriceCalculator(); Item item = new Item("LightSavor","Kitchen knife",100000); ICoupon coupon = new Coupon(); assertEquals(93000, calculator.getOrderPrice(item, coupon)); int methodCallCount = ((Coupon)coupon).getIsAppliableCallCount(); assertEquals (1, methodCallCount); }
  • 34. 행위기반 테스트 public class Coupon implements ICoupon { private int isAppliableCallCount; @Override public boolean isAppliable(Item item) { isAppliableCallCount++; // 호출되면 증가 출 …….. } p public int getIsAppliableCallCount(){ g pp (){ return this.isAppliableCallCount; } }
  • 35. 행위기반 테스트 @Test p public void testGetOrderPrice () throws Exception { p PriceCalculator calculator = new PriceCalculator(); Item item = new Item("LightSavor","Kitchen knife",100000); Item( LightSavor Kitchen knife 100000); ICoupon mockCoupon = mock(ICoupon.class); … // mocking 작업 assertEquals(93000, calculator.getOrderPrice(item, mockCoupon)); verify ( if (mockCoupon, ti kC times(1)).isAppliable(box); (1)) i A li bl (b ); }
  • 36. TDD with Spring 스프링 프레임워크의 Unit Test 지원 링 레임워 의 - 의존관계 주입을 통한 객체 생성 - 웹 컨테이너 없는 웹 애플리케이션 테스트 - 단위 테스트 지원 유틸리티 => Injection과 Mock
  • 37. XmlBeanFacotry로 컨텍스트 가져오는 버전 y 텍 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi http://www.w3.org/2001/XMLSchema instance xmlns:xsi="http://www w3 org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http //www.springframework.org/schema/beans/spring beans.xsd > http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="music" class="main.MP3"> <constructor-arg value="Belong to me.mp3"/> g g p </bean> <bean id="musicPlayer" class="main.MusicPlayer"> <property name="music" ref="music"/> </bean> </beans> XmlBeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource("/context-musicplayer xml") ClassPathResource( /context musicplayer.xml ) );
  • 38. Unitils를 사용 @RunWith(UnitilsJUnit4TestClassRunner class) @RunWith(UnitilsJUnit4TestClassRunner.class) public class UnitilsMusicPlayerTest { @SpringApplicationContext( /context-musicplayer.xml ) @SpringApplicationContext("/context-musicplayer xml") private ApplicationContext context; … … }
  • 39. annotation및 autowire를 사용해서 @RunWith(SpringJUnit4ClassRunner class) @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"/context-musicplayer.xml"}) public class AutowiredMusicPlayerTest { @Autowired MusicPlayer player; … … }
  • 40. Injection기능만 사용할 경우 Google Guice(쥬스)로 처리해 보면 static Injector injector = Guice.createInjector(new MusicModule()); @Test public void testGetFileName() throws Exception { MusicPlayer player = injector.getInstance(MusicPlayer.class); assertEquals("Belong To Me.mp3", player.getFileName()); }
  • 41. TDD with Spring – servlet test 이름 박성철 사번 5874 아이디 fupfin 직위 회장
  • 42. TDD with Spring – servlet test public class EmployeeSearchServletTest { @Test public void testSearchByEmpid() throws Exception { bli id S h id() h i MockHttpServletRequest request = new MockHttpServletRequest(); // ➊ MockHttpServletResponse response = new MockHttpServletResponse(); // ➋ request.addParameter("empid", "5874") // ➌ ddP (" id" "5874"); EmployeeSearchServlet searchServlet = new EmployeeSearchServlet(); // ➍ searchServlet.service(request, response); // ➎ Employee employee = (Employee)request getAttribute("employee"); // ➏ (Employee)request.getAttribute( employee ); assertEquals ("박성철", employee.getName() ); // ➐ assertEquals ("5874", employee getEmpid() ); ( 5874 employee.getEmpid() assertEquals ("fupfin", employee.getId() ); assertEquals ("회장", employee.getPosition() ); assertEquals( /SearchResult.jsp , assertEquals("/SearchResult.jsp", response.getForwardedUrl()); // ➑ } }
  • 44. Q&A 감사합니다 [email protected]
  • 45. 이미지 참조 Longing for Summer http://www.flickr.com/photos/68165632@N00/1553091251/ Coupling sketches cropped http://www.flickr.com/photos/49432745@N03/4533798684/ Tagged, finally... http://www.flickr.com/photos/kornrawiee/3189034267/ Vincent Boiteau i i http://www.flickr.com/photos/2dogs_productions