Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

자바 테스트 자동화

2,224 views

Published on

자바 개발자가 테스트 코드를 작성하는 데 도움이 되는 junit, hamcrest, mockito, 스프링 MVC 테스크 사용법을 종합해 보았습니다.

Published in: Software
  • 좋은 내용공유 감사합니다. 86페이지에서 조금 아쉬운 부분이 발견되어 신고(?) 기록 남기고 갑니다.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

자바 테스트 자동화

  1. 1. 박성철 data service 개발 그룹
  2. 2. UI
  3. 3. V SW
  4. 4. -> Feedback
  5. 5. -> Feedback
  6. 6. 기능 테스트 / UI 테스트 (Record & Playback) 통합 테스트 단위 테스트 with CI & Build Tool
  7. 7. 개발자 테스트 / 프로그래머 테스트 소스 코드의 가장 작은 단위를 테스트 테스트 코드에 의해 수시로 수행 개발 속도와 품질을 동시에 향상
  8. 8. JUnit
  9. 9. JUnit 프로그래머 중심의 자바용 테스트 프레임워크. 단위 테스트 를 위한 xUnit 아키텍처의 한 종류 xUnit : http://en.wikipedia.org/wiki/XUnit JUnit : http://junit.org JUnit 설계 목표 유용한 테스트를 작성하는데 도움이 되어야 함 시간이 지나도 가치 있는 테스트를 작성하는데 도움이 되어야 함 코드를 재사용함으로써 테스트 작성 비용을 낮추는데 도움이 되 어야 함
  10. 10. JUnit JUnit is an open source framework which is used for writing & running tests. Provides Assertions for testing expected results. Provides Test runners for running tests. JUnit tests allow you to write code faster which increasing quality JUnit is elegantly simple. It is less complex & takes less time. JUnit tests can be run automatically and they check their own results and provide immediate feedback. JUnit tests can be organized into test suites containing test cases and even other test suites. Junit shows test progress in a bar that is green if test is going fine and it turns red when a test fails.
  11. 11. JUnit 4 @Test @Before, @After @BeforeClass, @AfterClass @Ignore(“any message”) @RunWith @Parameters, @Parameter @SuiteClasses
  12. 12. 단위 테스트를 정의한 메서드 조건 @Test로 표시 반환 없음(void) 공개 메서드 @Test(expected=SomeException.class) @Test(timeout=nnn)
  13. 13. JUnit fail assertTrue assertFalse assertEquals assertArrayEquals assertNull assertNotNull assertSame assertNotSame assertThat import static org.junit.Assert.*;
  14. 14. JUnit assumeNoException(Throwable t) assumeNotNull(Object… o) assumeTrue(boolean b) assumeThat(T actual, Matcher<T> matcher) import static org.junit.Assume.*;
  15. 15. 
 (test fixture) 테스트의 기반이 되는 일관된 실행 환경 테스트 수행 전에 테스트 설비를 설치(setup) 작업 과 테스트 수행 후에 초기 상태로 설비를 해체 (tearDown)하는 작업 필요 @Before, @After @BeforeClass, @AfterClass (정적 메서드)
  16. 16. 
 (hamcrest) 복잡한 단언문을 서술적으로 가독성 높게 작성 가능 실패 시 문제 파악에 도움이 되는 정보 제공 http://hamcrest.org/ JUnit 4 , assertThat(T actual, Matcher<T> matcher) 핵심 매처: org.hamcrest.CoreMatchers
 전체 매처: org.hamcrest.Matchers assertTrue(result.contains(“x”) || result.contains(“y”) || result.contains(“z”));
 
 assertThat(result, is(hasItem(anyOf(equalTo(“x”, equalTo(“y”), equalTo(“z”)))));
  17. 17. import static org.hamcrest.CoreMatchers.*; 논리 allOf(), anyOf(): not(): 비교 결과 부정 또는 다름 컬렉션(Collection) hasItem(), hasItems(): 문자열 contansString(), containsStringIgnoringCase(): startWith(), startsWithIgnoringCase(): endsWith(), endsWithIgnoringCase():
  18. 18. 기본 equalTo(): 두 객체가 동일한지 판단 is(Matcher matcher): 단언문의 서술성을 높임, 기능 없음 is(Object o): equalTo()와 동일 anything(): 항상 참 객체 any(), instanceOf(): 특정 유형의 클래스면 참 isA(): is(instanceOf(…)) notNullValue(), nullValue(): 널 확인 sameInstance(): 동일 객체 인스턴스 확인
  19. 19. AssertJ import static org.assertj.core.api.Assertions.*; API (fluent) API assertThat(fellowshipOfTheRing) .filteredOn(character -> character.getName().contains("o") ) .containsOnly(aragorn, frodo, legolas, boromir); assertThat(frodo.getName()).isEqualTo("Frodo"); assertThat(frodo).isNotEqualTo(sauron).isIn(fellowshipOfTheRing); assertThat(fellowshipOfTheRing).extracting(“name") .contains("Boromir", "Gandalf", "Frodo", "Legolas") .doesNotContain("Sauron", "Elrond");
  20. 20. (Test Double)
  21. 21. No man is an island entire of itself; every man is a piece of the continent, a part of the main; object object
  22. 22. SUT
 (small & light) 
 (huge& heavy)
  23. 23. SUT
 (small & light) 
 (huge& heavy)
  24. 24. 제라드 메스자로스(Gerad Meszaros)가 xUnit Test Patterns 책을 통해 소개한 용어 영화에서 위험한 장면에서 배우 대신 등장하는 스 턴트 대역(Stunt Double)을 차용 특정 객체를 사용해서 테스트를 진행하기 어려울 경우, 그 객체 대신 사용하는 테스트용 객체 훨씬 협조적이고 원하는 대로 테스트를 작성할 수 있게 해주는 대역 객체
  25. 25. 테스트 대상을 의존 객체와 관계를 끊고 격리시킬 때 느린 테스트를 더 빠르게 만들어 자주 실행하고 싶을 때 예측 불가능한 요소를 통제하여 테스트하고 싶을 때 특수한 상황을 시뮬레이션하고 싶을 때 감춰진 정보를 얻어내는 용도로 활용하고 싶을 때 통합 환경 부재로 실제와 같은 대용품 객체를 만들고 싶을 때 필요한 객체를 점진적으로 설계하는 방식(Need-Driven Development)으로 테스트 및 구현을 확장해 나가고 싶을 때
  26. 26. 
 (Dummy Object) 단순한 빈 껍데기 객체가 필요할 때 사용 테스트 대상 객체의 생성자나 메서드의 인자로 전 달하는 용도 아무런 기능도 구현되지 않으며 호출됐을 때 정상 동작은 보장되지 않음 일부에선 호출을 가정해서 만들었다고 보기 힘들기 때문에 만일 호출시엔 예외를 발생시켜야 한다고 말함 (http://toby.epril.com/?p=706)
  27. 27. (Test Stub) 필요한 만큼 최소한의 기능만 구현 주로 정해진 값을 반환하도록 하드 코딩 public class LoggerStub implements Logger { public void log(LogLevel level, String message) { throw new UnsupportedOperationException(); } public LogLevel getLogLevel() { return LogLevel.WARN; } }
  28. 28. (Test Spy) 사용 여부, 호출 내용, 처리 결과 등을 기록 했다가 나 중에 확인 가능 public class LogTargetSpy implements LogTarget { public void write(Level level, String message) { log.add(level + “:” + message); } boolean received(Level level, String message) { return log.contains(level + “:” + message); } }
  29. 29. (Fake Object) 원 객체보다는 단순하지만 여러 테스트에서 공용으로 사용할 수 준으로 구현된 객체 테스트 토막을 테스트 시나리오 별로 따로 만드는 번거로움을 해 결 실제 객체의 대용품(ex 실 DB 대신 메모리에 저장하는 DAO)
  30. 30. (Mock Object) 특정 조건에 정해진 행위를 취함 상태보다는 행위 기반으로 테스트를 작성 모의 객체 제작용 프레임워크를 주로 활용해서 제작 모의객체는 스텁이 아니다(Mocks Aren't Stubs)
 http://testing.jabberstory.net/
  31. 31. Mockito
  32. 32. import static org.mockito.Mockito.*; 
 AbcService serviceMock = mock(AbcService.class) Mockito target class mocked target mock() Test 생성 반환
  33. 33. thenReturn(T value) thenThrow(Throwable t)
 thenThrow(Class<? extends Throwable> t) then(Answer answer)
 thenAnswer(Answer answer) thenCallRealMethod() when() thenReturn() when(someMock.getSomething()).thenReturn(TEST_NUMBER_OF_LEAFS);
  34. 34. doThrow(Throwable toBeThrown) doThrow(Class<? extends Throwable> toBeThrown) doAnswer(Answer answer) doCallRealMethod() doNothing() Mockito doXxx() doThrow(SomeException.class).when(someMock).getSomething();
  35. 35. doThrow(new RuntimeException()).when(mockedList).clear(); mockedList.clear(); //throws RuntimeException when(mock.someMethod(anyString())).thenAnswer( (InvocationOnMock invocation) -> { Object[] args = invocation.getArguments(); return "called with arguments: " + args; } }); System.out.println(mock.someMethod("foo")); ArrayList clear
  36. 36. 
 (Argument Matcher) when(mockedList.get(anyInt())).thenReturn(“element”); System.out.println(mockedList.get(999)) // print “element” verify(mockedList).get(anyInt()); when(mockedList.contains(argThat(isValid())).thenReturn(“element”); Mockito Hamcrest (argThat() )
  37. 37. 1/3 any() Matches anything, including nulls any(Class<T> clazz) Matches any object, including nulls anyBoolean() Any boolean or non-null Boolean anyByte() Any byte or non-null Byte. anyChar() Any char or non-null Character. anyCollection() Any non-null Collection. anyCollectionOf(Class<T> clazz) Generic friendly alias to anyCollection(). anyDouble() Any double or non-null Double. anyFloat() Any float or non-null Float. anyInt() Any int or non-null Integer. anyList() Any non-null List. anyListOf(Class<T> clazz) Generic friendly alias to anyList(). anyLong() Any long or non-null Long. anyMap() Any non-null Map. anyMapOf(Class<K> keyClazz, Class<V> valueClazz) Generic friendly alias to anyMap(). anyObject() Matches anything, including null. anySet() Any non-null Set. anySetOf(Class<T> clazz) Generic friendly alias to anySet(). anyShort() Any short or non-null anyString() Any non-null String anyVararg() Any vararg, meaning any number and values of arguments.
  38. 38. 2/3 Hamcrest argThat(org.hamcrest.Matcher<T> matcher) booleanThat(org.hamcrest.Matcher<Boolean> matcher) byteThat(org.hamcrest.Matcher<Byte> matcher) charThat(org.hamcrest.Matcher<Char> matcher) doubleThat(org.hamcrest.Matcher<Double> matcher) floatThat(org.hamcrest.Matcher<Float> matcher) intThat(org.hamcrest.Matcher<Integer> matcher) longThat(org.hamcrest.Matcher<Long> matcher) shortThat(org.hamcrest.Matcher<Short> matcher) contains(String substring) String argument that contains the given substring. matchers. endsWith(String suffix) String argument that ends with the given suffix. matches(String regex) String argument that matches the given regular expression. refEq(T value, String... excludeFields) Object argument that is reflection- equal to the given value with support for excluding selected fields from a class. startsWith(String prefix) String argument that starts with the given prefix.
  39. 39. 3/3 eq(boolean value) boolean argument that is equal to the given value. eq(byte value) byte argument that is equal to the given value. eq(char value) char argument that is equal to the given value. eq(double value) double argument that is equal to the given value. eq(float value) float argument that is equal to the given value. eq(int value) int argument that is equal to the given value. eq(long value) long argument that is equal to the given value. eq(short value) short argument that is equal to the given value. eq(T value) Object argument that is equal to the given value. isA(Class<T> clazz) Object argument that implements the given class. isNotNull() Not null argument. isNotNull(Class<T> clazz) Not null argument, not necessary of the given class. isNull() null argument. isNull(Class<T> clazz) null argument. notNull() Not null argument. notNull(Class<T> clazz) Not null argument, not necessary of the given class. same(T value) Object argument that is the same as the given value.
  40. 40. import static org.mockito.AdditionalMatchers.*; and(first, second), or(first, second), not(first) aryEq(), cmpEq(Comparable<T> value) eq(value, delta), geq(value), gt(value), leq(value), lt(value) find(String regex)
  41. 41. verify(T mock) verify(T mock, VerificationMode mode) times(int num) num회 호출 never() 호출되지 않음 atLeastOnce() 최소한 한 번 이상 호출 atLeast(int min) min회 이상 호출 atMost(int max) max회 이하 호출 only() 마지막 호출 timeout(int millis) 지정한 시간 안에 처리 종료 verify(mockedList).add(“once"); verify(mockedList, atLeastOnce()).add("three times"); verify(mockedList, atLeast(2)).add("five times"); verify(mockedList, atMost(5)).add("three times");
  42. 42. public static InOrder inOrder(Object... mocks) //given List singleMock = mock(List.class); // when singleMock.add("was added first"); singleMock.add("was added second"); // than InOrder inOrder = inOrder(singleMock); inOrder.verify(singleMock).add("was added first"); inOrder.verify(singleMock).add("was added second");
  43. 43. @Test public void shouldStubMethodAndCallRealNotStubbedMethod(){ //given Flower realFlower = new Flower(); realFlower.setNumberOfLeafs(ORIGINAL_NUMBER_OF_LEAFS); Flower flowerSpy = spy(realFlower); willDoNothing().given(flowerSpy).setNumberOfLeafs(anyInt()); //when flowerSpy.setNumberOfLeafs(NEW_NUMBER_OF_LEAFS); /than verify(flowerSpy).setNumberOfLeafs(NEW_NUMBER_OF_LEAFS); assertEquals(flowerSpy.getNumberOfLeafs(), ORIGINAL_NUMBER_OF_LEAFS); } ,
  44. 44. JUnit
  45. 45. JUnit 4 @Test @Before, @After @BeforeClass, @AfterClass @Ignore(“any message”) @RunWith @Parameters @SuiteClasses
  46. 46. 작성된 JUnit 테스트를 실행 org.junit.runner.Runner 구현 @RunWith JUnit에서 기본으로 여러가지 실 행기 제공 기본은 org.junit.runners.JUnit4 클래스 Runner ParentRunner Suite BlockJUnit4- ClassRunner JUnit4 Theories Categories Enclosed Parameterized
  47. 47. 한 클래스에 여러 테스트 클래스가 포함되어 있을 때 사용 org.junit.runner.Enclosed 
 @RunWith(Enclosed.class) @RunWith(Enclosed.class) public class SomeTest { public class SomeInnerTest { @Test public void test() {…} } public class AnotherInnerTest { @Test public void test() {…} } }
  48. 48. 
 (Test Suite) 여러 테스트를 한 묶음으로 모아서 실행하려고 할 때 사용 org.junit.runner.Suite 실행기로 실행 @RunWith(Suite.class) @Suite.SuiteClasses로 한 묶음으로 묶을 테스트 클래스 또는 테스트 모음 클래스 지정 import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ TestFeatureLogin.class, TestFeatureLogout.class, TestFeatureNavigate.class, TestFeatureUpdate.class }) public class FeatureTestSuite { }
  49. 49. 한 테스트 모음을 여러 분류로 구분해서 독립적으로 실행 @Category로 테스트 클래스나 테스트 메서드를 특정 분류로 지정 (ex @Category(UnitTest.class)) @IncludeCategory와 @ExcludeCategory로 테스트에 포함시킬 테스트 지정 org.junit.runner.Categories 
 @RunWith(Categories.class) @RunWith(Categories.class) @IncludeCategory(CommunityVersion.class) @ExcludeCategory(EnterpriseVersion.class) @SuiteClasses( { A.class, B.class }) public class FeatureTestSuite { }
  50. 50. 테스터가 입력값과 기대값을 표 형태로 제공하고 테스트를 수행 경계 값 등 여러 값의 조합으로 다양한 시나리오를 제공 가능 Junit에서는 매개변수화 테스트와 이론으로 지원 user id location time benefit park 명동 9:00 12 kim 강남 12:00 4 lee 홍대 10:00 9 choi 부산 22:00 0
  51. 51. 
 (Parameterized Test) 테스트 클래스를 생성할 때 여러가지 초기 상태를 지정하고 반복 수행 org.junit.runners.Parameterized 실행기 사용 @Parameters 어노테이션으로 인자 목록 정의 name 속성으로 테스트 이름 부여 가능 {index} : 인자 순번 {#}: 0부터 시작, 인자 값 import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @RunWith(Parameterized.class) public class FibonacciTest { @Parameterized.Parameters(name="{index}: fib({0})={1}") public static Collection<Object[]> args() { return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 } }); } …… }
  52. 52. private int input; private int expected; public FibonacciTest(int input, int expected) { this.input = input; this.expected = expected; } @Parameterized.Parameter(0) public int input; @Parameterized.Parameter(1) public int expected;
  53. 53. 
 (Theories) 무한대의 데이터에 대한 다양한 조합으로 테스트 수행 org.junit.runners.Theories 실행기 사용 : @DataPoint, @DataPoints @FromDataPoints assumeXxx 수행할 테스트에는 @Test 대신 @Theory 표시 @RunWith(Theories.class) public class AdultValidationTest { @DataPoints(“uid”) public static long[] UIDS = new long[] { 10, 33, 452, 4321 }; @DataPoints(“cid”) public static long[] CIDS = new long[] { 1, 53, 100, 984, 1343 }; @Theory public void validate(@FromDataPoints("uid")long userId, @FromDataPoints("cid")long contentId){ User user = UserService.findById(userId); assumeTrue(user.isAdult()); Content content = ContentService.findById(contentId); assertTrue(content.isValid(user)); } }
  54. 54.
  55. 55. JUnit public class MemberJUnitWithSpringTest { AnnotationConfigApplicationContext appctx; MemberService memberService; @Before public void setUp() { appctx = new AnnotationConfigApplicationContext(Config.class); memberService = appctx.getBean(MemberService.class); } @Test public void test() throws Exception { assertEquals(memberService.getMember(1).getName(), " "); assertEquals(memberService.getMember(2).getName(), " "); assertEquals(memberService.getMember(3).getName(), " "); } @After public void teardown() { appctx.close(); } }
  56. 56. 애플리케이션 컨텍스트 관리와 캐시 테스트 설비 의존관계 주입 트랜잭셕 관리 통합 테스트에 유용한 스프링의 클래스 라이브러리 제공
  57. 57. @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) public class MemberJUnitWithManualSpringTest { @Autowired public MemberService memberService; @Test public void test() throws Exception { assertEquals(memberService.getMember(1).getName(), " "); assertEquals(memberService.getMember(2).getName(), " "); assertEquals(memberService.getMember(3).getName(), " "); } } SpringJUnit4ClassRunner
  58. 58. @DirtiesContext public void test() throws Exception { …… } @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) public class ContextDirtyingTests { @DirtiesContext public class ContextDirtyingTests { 초기화가 오래 걸리는 애플리케이션 컨텍스트 재사용 @DirtiesContext: ,
  59. 59. @Transactional을 테스트 클래스에 지정할 경우 매 테스트마다 자동으로 원복 (rollback) 처리가 됨 @TransactionConfiguration으로 빈 설정과 별도로 테스트 클래스 수준의 트 랜잭션 설정 추가 가능 @TransactionConfiguration(transactionManager = “txMgr", defaultRollback = false) @Transactional public class CustomConfiguredTransactionalTests { @Rollback로 클래스 수준의 기본 트랜잭션 설정을 메서드 단위에서 변경 가능 @Rollback(false) public void testProcessWithoutRollback() { …… } (commit)
  60. 60. 트랜잭션 전후에 로직 실행 가능 @BeforeTransaction public void beforeTransaction() { …… } @AfterTransaction public void afterTransaction() { …… } public class PartiallyTransactionalTests { @Transactional public void testProcessWithTransaction(){ …… } public void testProcessWithoutTransaction(){ …… }
  61. 61. @WebAppConfiguration을 지정한 테스트 클래스의 애플리케이션 컨텍스트는 WebApplicationContext가 됨 기본으로 “file:src/main/webapp"을 웹 루트 경로로 사용 웹 루트 경로를 @WebAppConfiguration의 인자로 지정 가능 MockHttpServletRequest나 MockHttpSession을 주입 받고 리퀘스트와 세 션 스코프 빈을 테스트 할 수 있음 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @WebAppConfiguration public void ScopedBeanTests() { @Autowired WebApplicationContext wac; @Autowired MockHttpServletRequest request; …… } WebApplicationContext HttpServletRequest
  62. 62. MVC
  63. 63. MVC DB + WACMVC UI
  64. 64. Client HttpServletRequest HttpServletResponse WAS Test Mock Request Mock Response MockMVC Spring MVC Spring MVC MVC
  65. 65. MVC 스프링 MVC 테스트 프레임워크 유창한(fluent) API로 서술적으로 테스트 조건과 단정문을 작성 서블릿 컨테이너 없이 스프링 MVC의 모든 동작과 뷰(View) 처 리 결과까지 테스트 MockMvcBuilders를 사용해서 생성 mockMvc = standaloneSetup(new AccountController()) .defaultRequest(get("/") .contextPath("/app").servletPath("/main") .accept(MediaType.APPLICATION_JSON).build(); mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); Web Application Context
  66. 66. MVC @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=AppConfig.class) @WebAppConfiguration public class ControllerTest { @Autowired WebApplicationContext wac; MockMvc mockMvc; @Before public void init() { mockMvc = MockMvcBuilders.webAppContextSetup(wac) .alwaysDo(MyResultLogger.log()) .alwaysExpect(status().isOk()) .build(); } … }
  67. 67. MVC mockMvc.perform( get("/test/") .header(“x-requested-with", "XMLHttpRequest") .accept(MediaType.APPLICATION_JSON)) .andExpect(handler().handlerType(MyController.class)) .andExpect(handler().methodName("test")) .andExpect(status().isOk()); } 202 ResultActions perform(RequestBuilder requestBuilder) get “/test/“ URL ajax JSON
  68. 68. 
 (MockMvcRequestBuilders) import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; … mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON)); mockMvc.perform(fileUpload(“/doc").file(“a1", "ABC".getBytes("UTF-8"))); mockMvc.perform(get("/hotels").param("foo", "bar")); delete(), fileUpload(), get(), post(), put() 다섯 가지 HTTP 메소드별 빌더 생성 정적 메서드 제공 공통적으로 url 템플릿 기능 제공 fileUpload()는 MockMultipartHttpServletRequestBuilder 반환, 나머지는 MockHttpServletRequestBuilder 반환
  69. 69. 
 (MockMvcRequestBuilders) accept(MediaType... mediaTypes) buildRequest(javax.servlet.ServletContext servletContext) characterEncoding(java.lang.String encoding) content(byte[] content) content(java.lang.String content) contentType(MediaType mediaType) contextPath(java.lang.String contextPath) cookie(javax.servlet.http.Cookie... cookies) createServletRequest(javax.servlet.ServletContext servletContext) flashAttr(java.lang.String name, java.lang.Object value) flashAttrs(java.util.Map<java.lang.String,java.lang.Object> flashAttributes) header(java.lang.String name, java.lang.Object... values) headers(HttpHeaders httpHeaders) isMergeEnabled() locale(java.util.Locale locale) merge(java.lang.Object parent) param(java.lang.String name, java.lang.String... values) pathInfo(java.lang.String pathInfo) principal(java.security.Principal principal) requestAttr(java.lang.String name, java.lang.Object value) secure(boolean secure) servletPath(java.lang.String servletPath) session(MockHttpSession session) sessionAttr(java.lang.String name, java.lang.Object value) sessionAttrs(java.util.Map<java.lang.String,java.lang.Object> sessionAttributes) with(RequestPostProcessor postProcessor)
  70. 70. ContentResultMatchers content() CookieResultMatchers cookie() FlashAttributeResultMatchers flash() ResultMatcher forwardedUrl(java.lang.String expectedUrl) HandlerResultMatchers handler() HeaderResultMatchers header() <T> ResultMatcher jsonPath(java.lang.String expression, org.hamcrest.Matcher<T> matcher) JsonPathResultMatchers jsonPath(java.lang.String expression, java.lang.Object... args) ModelResultMatchers model() ResultMatcher redirectedUrl(java.lang.String expectedUrl) RequestResultMatchers request() StatusResultMatchers status() ViewResultMatchers view() XpathResultMatchers xpath(java.lang.String expression, java.util.Map<java.lang.String,java.lang.String> namespaces, java.lang.Object... args) XpathResultMatchers xpath(java.lang.String expression, java.lang.Object... args)
  71. 71. • Request attribute test ( Attribute ) • .andExpect(request().attribute(.., ..)) • Session attribute test ( ) • .andExpect(request().sessionAttribute(.., ..)) • Async test ( Servlet 3.0, Spring 3.2 ) • .andExpect(request(). asyncStarted(.., ..)) • ? • .andExpect(request(). asyncNotStarted(.., ..)) • ? • .andExpect(request(). asyncResult(.., ..)) • ?
  72. 72. • Handler type test ( Handler ) • .andExpect(handler().handlerType(..)) • Handler method name test ( Handler ) • .andExpect(handler().methodName(..)) • Handler method type test ( Handler ) • .andExpect(handler().method(..))
  73. 73. • Model attrbute test ( Model ) • .andExpect(model().attribute(..)) • .andExpect(model().attributeExists(..)) • .andExpect(model().attributeErrorCount(..)) • .andExpect(model().attributeHasErrors(..)) • .andExpect(model().attributeHasNoErrors(..)) • .andExpect(model().attributeHasFieldErrors(..)) • .andExpect(model().errorCount(..)) • .andExpect(model().hasErrors(..)) • .andExpect(model().hasNoErrors(..))
  74. 74. • Status test ( ) • .andExpect(status().is(..)) • ( 200: … ) • org.springframework.http HttpStatus • Error message test ( ) • .andExpect(status().reason(..)) • . • Header test ( ) • .andExpect(header().string(..)) • .andExpect(header().longValue(..))
  75. 75. • ContentType test( contentType ) • .andExpect(content().contentType(..)) • .andExpect(content().contentTypeCompatibleWith(..)) • Encoding test ( content ) • .andExpect(content().encoding(..)) • Content test ( content ) • .andExpect(content().string(..)) : content • .andExpect(content().bytes(..)) : content byte • .andExpect(content().xml(..)) : content xml dom • .andExpect(content().node(..)) : content xml dom node • .andExpect(content().source(..)) : content xml dom source
  76. 76. • View name test ( View name ) • .andExpect(view().name(..)) • Forwarded url test( URL ) • .andExpect(forwardedUrl(..)) • Redirected url test ( URL ) • .andExpect(redirectedUrl(..)) • Flash attribute test ( Spring 3.1 Flash attribute ) • .andExpect(flash().attribute(..)) : attribute • .andExpect(flash(). attributeExists(..)) : attribute • .andExpect(flash(). attributeCount(..)) : attribute
  77. 77. • ? (Right-BICEP, ) - Right - ? - Boundary - correct ? - Inverse - ? - Cross-check - ? - Error condition - ? - Performance - ? • (A-trip) - Automatic (IDE, CI) - Thorough (Coverage ) - Repeatable - Independent (Fixture setting) - Professional ( )
  78. 78. Inside-out vs Outside-in
  79. 79. vs . . 
 . Outside-in .
  80. 80. : -> -> : = (spec.) (Testability) : Simple Design “사전에 테스트를 고려하여 개발한게 아니다보니 억지로 테스트를 만들게 된다. 그 리고 언젠가 부터 테스트는 mocking으로 도배되거나 @Ignore가 추가되고 있다.”
  81. 81. TDD / /
  82. 82. ( )
  83. 83. ATDD Step 1: Step 2: Step 3: Step 4:
  84. 84. ATDD Concordion: http://www.concordion.org/ Cucumber: http://cukes.info/ Fitnesse: http://fitnesse.org/ Selenium: http://docs.seleniumhq.org/ and JUnit… ;^)
  85. 85. 100%

×