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.

Okjsp 13주년 발표자료: 생존 프로그래밍 Test

9,789 views

Published on

okjsp 13주년 행사에서 발표한 자료입니다.

Published in: Technology
  • D0WNL0AD FULL ▶ ▶ ▶ ▶ http://1lite.top/tJE0P ◀ ◀ ◀ ◀
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • D0WNL0AD FULL ▶ ▶ ▶ ▶ http://1lite.top/tJE0P ◀ ◀ ◀ ◀
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • You might get some help from ⇒ www.HelpWriting.net ⇐ Success and best regards!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • D0WNL0AD FULL ▶ ▶ ▶ ▶ http://1lite.top/tJE0P ◀ ◀ ◀ ◀
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... Download Full EPUB Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... Download EPUB Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... Download doc Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Okjsp 13주년 발표자료: 생존 프로그래밍 Test

  1. 1. 생존 프로그래밍:TEST OKJSP 13주년 컨퍼런스, 2013-12-07 최범균(madvirus@madvirus.net)
  2. 2. 목표 ● 목표임 ○ 테스트 코드를 만들지 않는 프로그래머들에게, 어쩐 지 테스트 코드가 개발 시간을 줄여줄 것 만 같은 “느 낌”을 주는 것 ● 목표 아님 ○ JUnit 설명하기 ○ 기타 프레임워크 설명하기 ○ TDD 설명하기
  3. 3. 내용 ● 사람이 하는 TEST ● 테스트 시간을 단축하려면 ● 기계가 하는 테스트 ○ 스프링 통합 테스트 ○ 한 클래스 / Mock ● 주의 사항 ○ 테스트 환경 맞추기 ● 정리
  4. 4. 구현 과정? Java 웹브라우저 테스트 XML SQL HTML JS WAS 기능과 관련된 모든 코드 작성 WAS 실행 버그 또는 에러 원인분석 및 코드수정
  5. 5. 디버깅 과정? 왜 DB에 데이터가 null이지? 의 태그 나 ? t> npu 잘못됐 <i 이 ame n HTML JS 커맨 값이 드 객체 에 안들 어가 나? Java Ajax 호 값을 출할 때 안주 나? 재시 작 안했 나? XML 이 설정 가? 른 올바 SQL WAS 이 럼 컬 서 에 나? 리 쿼 빠졌
  6. 6. 개발 시간의 증가 원인 폼에 수동 입력 (주로 ‘1’, ‘a’ 등 입력) URL을 붙여넣기 하기도 함 웹브라우저 테스트 Java WAS JS HTML SQL XML 한 번에 집중해서 만들어야 할 게 많음! 시간이 오래 걸리고, 흐름 깨지기 쉬움 WAS 실행 JRebel 없어 재시작해야 함 심한 경우, 재배포 버그 또는 에러 원인분석 및 코드수정 확인해 봐야 할 게 많음! 한 곳만 잘못되지 않음! 오래 걸림, 흐름 깨지기 쉬움
  7. 7. 개발/디버깅/테스트 시간을 줄이려면 범위 좁히기 (즉, 나누기)
  8. 8. 한 놈씩 골라서! 관련된 것만 묶어서! 서버 기능은 정 상동작하나? HTML JS 스프링 설정 문제없나? Java Controller SVC 컨트롤러가 응답을 정 상으로 만드나? DAO SQL +DB DAO 잘 되나? 다 잘 되나? XML WAS
  9. 9. 테스트 종류 통합 테스트 HTML JS Java Controller 단위테스트 SVC DAO SQL +DB 단위테스트 end-to-end (통합) 테스트 Acceptance 테스트 XML WAS
  10. 10. JUnit ● 테스트 프레임워크 ○ 코드로 테스트 시나리오 작성 ○ 코드로 결과 검증 ● 쉬운 반복 실행 ○ 지정한 범위의 테스트를 빠르게 실행 가능 ○ IDE는 모두 JUnit 실행 기능 기본 제공 ● 주로 다루는 범위 ○ 한 개 클래스 (단위 테스트) ○ 서버 기능 (통합 테스트) ○ 종종, end-to-end 테스트 (통합 테스트)
  11. 11. 자바 웹 서버 개발 속도에 도움 되는 것 ● 단위 테스트 ○ 한 모듈(보통 클래스 한 개)의 기능을 테스트 ○ 예, ■ 컨트롤러가 JSON을 제대로 만드나? ■ 엑셀 생성 모듈이 엑셀 파일을 제대로 만드나? ■ DAO가 데이터를 잘 읽어오나? ■ 스프링 설정이 올바른가? ● 서버측 통합 테스트 ○ 모듈을 통합해서 수행하는 기능 테스트 ○ 예, ■ 컨트롤러-서비스-DAO-DB 연동된 상태의 기능 테 스트
  12. 12. 테스트 작성 사례 ● 기능 ○ DB에서 대량의 데이터를 읽어와 서버의 로컬에 엑셀 파일을 생성한 후, 그 파일을 웹 브라우저에 내려주는 기능
  13. 13. 검색해서 iBATIS의 데이터를 순차적 으로 받아 엑셀로 만드는 코드 찾음 시작 ● 일단 막 구현 나 초짜 복사/붙여넣기 해서 코드 작성 토드에서 쿼리 돌아감 다른 것 참조해서 스프링 설정 톰캣 실행/브라우저 실행/링크 클릭 결과는…..
  14. 14. 잔뜩 코딩한 뒤 실행한 결과는
  15. 15. 테스트 방법 복사&붙여넣기 버튼 클릭넣기 반복 뭔가 코드 수정 (서버 재시작..) 여러 코드 탐색 에러 발생
  16. 16. 범위 좁히기: 에러 나는 영역 에러 유발자!
  17. 17. 에러 잡기 위한 테스트 코드 작성 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( locations = { "classpath:spring-*.xml" }) public class BaseBigExcelDownDAOIntTest { @Autowired private BaseBigExcelDownDAO excelDownDao; private String tempFilePath = "...."; @Test public void shouldCreateExcelFile() { String queryId = "..."; excelDownDao.createSheetFile( querId, createCommand(), createSheetMap(), tempFilePath); assertTempFileCreated(); } @Before public void setUp() { deleteIfTempFileExists(); } private void assertTempFileCreated() { File file = new File(tempFilePath); assertThat(file.exists(), equalTo(true)); } private CustomerServiceRequestCommand createCommand() { CustomerServiceRequestCommand command = new CustomerServiceRequestCommand(); command.setMenuId("C000732"); command.setCust_flag("0"); command.setReceive_num_flag("2"); ... return command; } …. …. } 수동 입력과 눈 확인 대체
  18. 18. 테스트 과정 원인 확인 테스트 및 결과 확인 에러 확인
  19. 19. 테스트 과정 집중 속도감 수동 입력/서버/브라우저 필요 없음
  20. 20. 범위 좁히기: 파일 전송 파일 전송 기능 구현 전
  21. 21. 컨트롤러 테스트 실제 DB 연동/엑셀 파일 생성 필요 없음 컨트롤러는 다른 객체가 생성한 파일을 response로 전송해주면 됨 데이터를 어디서 읽어오는지는 중요하지 않음!
  22. 22. 진짜 대신 가짜 쓰기 public class CustomerServiceRequestControllerTest { private CustomerServiceRequestController controller = new CustomerServiceRequestController(); @Mock private BaseBigExcelDownDAO mockBaseBigExcelDownDAO; private MockHttpServletResponse mockResponse = new MockHttpServletResponse(); private CustomerServiceRequestCommand command = new Customer…(); private byte[] realBytes = new byte[125]; @Before public void setUp() { controller.setBaseBigExcelDownDAO(mockBaseBigExcelDownDAO); for (byte i = 0; i < realBytes.length; i++) realBytes[i] = i; doAnswer(new Answer<Void>() { public Void answer(InvocationOnMock invocation) throws Throwable { String genFilePath = (String) invocation.getArguments()[3]; FileCopyUtils.copy(realBytes, new File(genFilePath)); return null; } }).when(mockBaseBigExcelDownDAO).createSheetFile(anyString(), any(), any(LinkedHashMap.class), anyString()); } 가짜 쓰도록 설정 가짜에서 컨트롤러가 사용할 파일 생성
  23. 23. 진짜 대신 가짜 쓰기 public class CustomerServiceRequestControllerTest { private CustomerServiceRequestController controller = new CustomerServiceRequestController(); @Mock private BaseBigExcelDownDAO mockBaseBigExcelDownDAO; private MockHttpServletResponse mockResponse = new MockHttpServletResponse(); private CustomerServiceRequestCommand command = new Customer…(); private byte[] realBytes = new byte[125]; @Before public void setUp() { controller.setBaseBigExcelDownDAO(mockBaseBigExcelDownDAO); … } 가짜 사용 @Test public void should_create_filepath_in_random_and_send_filedata_to_client() { controller.customerServiceRequestExcel(mockResponse, command); assertSendDataBytes(); } private void assertSendDataBytes() { byte[] sendedFileBytes = mockResponse.getContentAsByteArray(); assertEquals(realBytes.length, sendedFileBytes.length); for (int i = 0; i < realBytes.length; i++) assertEquals(realBytes[i], sendedFileBytes[i]); } 컨트롤러가 전송한 파일 데이터 확인
  24. 24. 진짜 대신 가짜 쓰기 public class CustomerServiceRequestControllerTest { private CustomerServiceRequestController controller = new CustomerServiceRequestController(); @Mock private BaseBigExcelDownDAO mockBaseBigExcelDownDAO; private MockHttpServletResponse mockResponse = new MockHttpServletResponse(); private CustomerServiceRequestCommand command = new Customer…(); private byte[] realBytes = new byte[125]; 스프링 초기화 없음 @Before public void setUp() { controller.setBaseBigExcelDownDAO(mockBaseBigExcelDownDAO); … } @Test public void should_create_filepath_in_random_and_send_filedata_to_client() { controller.customerServiceRequestExcel(mockResponse, command); assertSendDataBytes(); } DB 연동 없음 WAS/브라우저 없음 private void assertSendDataBytes() { byte[] sendedFileBytes = mockResponse.getContentAsByteArray(); assertEquals(realBytes.length, sendedFileBytes.length); for (int i = 0; i < realBytes.length; i++) assertEquals(realBytes[i], sendedFileBytes[i]); } 속도감
  25. 25. 가짜를 이용한 병행 개발 개발자1: 가짜를 이용해서 개발 가능 기능 검증은 단위 테스트 코드로 개발자2: 기능 구현 기능 검증은 통합 테스트 코드로
  26. 26. 마지막: 톰캣 띄우고 기능 테스트 상당한 부분의 코드를 테스트 코드로 확인한 뒤에, 거의 마지막에 기능 테스트 수행 이 시점에서 오류는 대부분 UI 관련된 것 서버쪽은 이미 테스트가 거의 끝남
  27. 27. 사실은, 사용자 기능도 코드로 테스트 ● 테스트 코드가 웹 브라우저를 실행해서 입력/ 검증 수행 ● 관련 프레임워크 ○ ○ ○ ○ ○ ○ Cucumber FitNess Selenium Watir Geb …
  28. 28. 테스트 작성 시 주의 사항 ● 동일 조건에서 테스트가 동작하도록 ○ 즉, 테스트 코드를 반복해서 실행해도 문제 없도록 ● 예, ○ 파일 생성 테스트면, 기능 실행 전에 기존에 생성된 파일 삭제 처리 ○ DB 조회 테스트면, 동일한 데이터 집합을 갖도록 처 리
  29. 29. 정리 ● 테스트 코드와 개발 시간 단축 ○ 사람 대신 기계가 테스트를 수행해서, 실행 시간 단축 효과 ○ 개발 범위를 좁혀주어, 구현 시간 단축 효과 ○ 병행 개발 가능, 대기 시간 단축 효과 ● 코딩+테스트+디버깅 시간 ○ 범위 나눠 테스트 <<< 모든 코드 구현 후 테스트 ■ 모든 코드 구현: 코딩+테스트+디버깅+큰뻘짓 ■ 범위 나눠 구현: 코딩+테스트+디버깅+작은뻘짓 ● 회귀(regression) 테스트로도 사용 ● 좋은 설계도 원하면: TDD 시도 필요
  30. 30. 참고 ● 테스트 관련 ○ JUnit ■ 테스트 프레임워크 ○ 스프링 MVC 테스트 ■ 스프링 컨트롤러에 대한 테스트 진행 ○ DBUnit ■ DB 데이터 초기화/확인 기능 제공 ■ spring-test-dbunit (편리성 추가) ○ Mockito 등 ■ 가짜 객체 생성 및 호출 여부 검증 기능 제공
  31. 31. 참고: Spring MVC 응답 테스트 예시 public class PaymentSyncSourceListControllerTest { private MockMvc mockMvc; private PaymentSyncSourceListController controller = new PaymentSyncSourceListController(); @Before public void setUp() { mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); } @Test public void jsonList() throws Exception { mockMvc.perform(get("/sync/syncsources.json").param("offset", "0").param("size", "10")) .andExpect(status().isOk()) .andExpect(content().contentType(createJsonMediaType())) .andExpect(jsonPath("$", hasSize(2))) .andExpect(jsonPath("$[0].id", is(2))) .andExpect(jsonPath("$[0].totalAmount", is(50000))) ... .andExpect(jsonPath("$[0].orderLines", hasSize(1))) .andExpect(jsonPath("$[0].orderLines[0].id", is(2))) ... .andExpect(jsonPath("$[1].deliveryCharge", is(2500))); }
  32. 32. 맺음말 일단 한 번 테스트 코드 만들기!
  33. 33. Q&A, 의견 트위터: @madvirus 이메일: madvirus@madvirus.net

×