SlideShare a Scribd company logo
생존 프로그래밍:TEST
OKJSP 13주년 컨퍼런스, 2013-12-07

최범균(madvirus@madvirus.net)
목표
● 목표임
○ 테스트 코드를 만들지 않는 프로그래머들에게, 어쩐
지 테스트 코드가 개발 시간을 줄여줄 것 만 같은 “느
낌”을 주는 것

● 목표 아님
○ JUnit 설명하기
○ 기타 프레임워크 설명하기
○ TDD 설명하기
내용
● 사람이 하는 TEST
● 테스트 시간을 단축하려면
● 기계가 하는 테스트
○ 스프링 통합 테스트
○ 한 클래스 / Mock

● 주의 사항
○ 테스트 환경 맞추기

● 정리
구현 과정?
Java

웹브라우저
테스트

XML
SQL
HTML
JS
WAS

기능과 관련된
모든 코드 작성

WAS
실행

버그 또는
에러
원인분석 및
코드수정
디버깅 과정?
왜 DB에 데이터가 null이지?
의
태그 나 ?
t>
npu 잘못됐
<i
이
ame
n
HTML

JS

커맨
값이 드 객체
에
안들
어가
나?
Java

Ajax
호
값을 출할 때
안주
나?

재시
작
안했
나?
XML

이
설정 가?
른
올바

SQL

WAS

이

럼
컬
서
에 나?
리
쿼 빠졌
개발 시간의 증가 원인
폼에 수동 입력 (주로 ‘1’, ‘a’ 등 입력)
URL을 붙여넣기 하기도 함

웹브라우저
테스트
Java
WAS
JS
HTML
SQL
XML

한 번에 집중해서
만들어야 할 게 많음!
시간이 오래 걸리고,
흐름 깨지기 쉬움

WAS
실행

JRebel 없어
재시작해야 함
심한 경우, 재배포

버그 또는
에러

원인분석 및
코드수정
확인해 봐야 할 게 많음!
한 곳만 잘못되지 않음!
오래 걸림, 흐름 깨지기 쉬움
개발/디버깅/테스트 시간을 줄이려면

범위 좁히기
(즉, 나누기)
한 놈씩 골라서! 관련된 것만 묶어서!
서버 기능은 정
상동작하나?

HTML

JS

스프링 설정
문제없나?

Java
Controller

SVC

컨트롤러가 응답을 정
상으로 만드나?

DAO

SQL
+DB

DAO 잘 되나?

다 잘 되나?

XML

WAS
테스트 종류
통합 테스트

HTML

JS

Java
Controller

단위테스트

SVC

DAO

SQL
+DB

단위테스트

end-to-end (통합) 테스트
Acceptance 테스트

XML

WAS
JUnit
● 테스트 프레임워크
○ 코드로 테스트 시나리오 작성
○ 코드로 결과 검증

● 쉬운 반복 실행
○ 지정한 범위의 테스트를 빠르게 실행 가능
○ IDE는 모두 JUnit 실행 기능 기본 제공

● 주로 다루는 범위
○ 한 개 클래스 (단위 테스트)
○ 서버 기능 (통합 테스트)
○ 종종, end-to-end 테스트 (통합 테스트)
자바 웹 서버 개발 속도에 도움 되는 것
● 단위 테스트
○ 한 모듈(보통 클래스 한 개)의 기능을 테스트
○ 예,
■ 컨트롤러가 JSON을 제대로 만드나?
■ 엑셀 생성 모듈이 엑셀 파일을 제대로 만드나?
■ DAO가 데이터를 잘 읽어오나?
■ 스프링 설정이 올바른가?

● 서버측 통합 테스트
○ 모듈을 통합해서 수행하는 기능 테스트
○ 예,
■ 컨트롤러-서비스-DAO-DB 연동된 상태의 기능 테
스트
테스트 작성 사례
● 기능
○ DB에서 대량의 데이터를 읽어와 서버의 로컬에 엑셀
파일을 생성한 후, 그 파일을 웹 브라우저에 내려주는
기능
검색해서 iBATIS의 데이터를 순차적
으로 받아 엑셀로 만드는 코드 찾음

시작
● 일단 막 구현
나 초짜

복사/붙여넣기 해서 코드 작성
토드에서 쿼리 돌아감
다른 것 참조해서 스프링 설정
톰캣 실행/브라우저 실행/링크 클릭
결과는…..
잔뜩 코딩한 뒤 실행한 결과는
테스트 방법
복사&붙여넣기
버튼 클릭넣기

반복

뭔가 코드 수정
(서버 재시작..)
여러 코드 탐색

에러 발생
범위 좁히기: 에러 나는 영역
에러 유발자!
에러 잡기 위한 테스트 코드 작성
@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;

}

….
….
}

수동 입력과
눈 확인 대체
테스트 과정

원인 확인

테스트 및
결과 확인

에러 확인
테스트 과정

집중

속도감
수동 입력/서버/브라우저
필요 없음
범위 좁히기: 파일 전송
파일 전송 기능 구현 전
컨트롤러 테스트
실제 DB 연동/엑셀 파일 생성 필요 없음

컨트롤러는 다른 객체가 생성한
파일을 response로 전송해주면 됨
데이터를 어디서 읽어오는지는
중요하지 않음!
진짜 대신 가짜 쓰기
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());
}

가짜 쓰도록
설정
가짜에서
컨트롤러가
사용할
파일 생성
진짜 대신 가짜 쓰기
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]);
}

컨트롤러가 전송한
파일 데이터 확인
진짜 대신 가짜 쓰기
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]);
}

속도감
가짜를 이용한 병행 개발
개발자1: 가짜를 이용해서 개발 가능
기능 검증은 단위 테스트 코드로

개발자2: 기능 구현
기능 검증은 통합 테스트 코드로
마지막: 톰캣 띄우고 기능 테스트
상당한 부분의 코드를 테스트 코드로 확인한 뒤에,
거의 마지막에 기능 테스트 수행

이 시점에서 오류는 대부분 UI 관련된 것
서버쪽은 이미 테스트가 거의 끝남
사실은, 사용자 기능도 코드로 테스트
● 테스트 코드가 웹 브라우저를 실행해서 입력/
검증 수행
● 관련 프레임워크
○
○
○
○
○
○

Cucumber
FitNess
Selenium
Watir
Geb
…
테스트 작성 시 주의 사항
● 동일 조건에서 테스트가 동작하도록
○ 즉, 테스트 코드를 반복해서 실행해도 문제 없도록

● 예,
○ 파일 생성 테스트면, 기능 실행 전에 기존에 생성된
파일 삭제 처리
○ DB 조회 테스트면, 동일한 데이터 집합을 갖도록 처
리
정리
● 테스트 코드와 개발 시간 단축
○ 사람 대신 기계가 테스트를 수행해서, 실행 시간 단축
효과
○ 개발 범위를 좁혀주어, 구현 시간 단축 효과
○ 병행 개발 가능, 대기 시간 단축 효과

● 코딩+테스트+디버깅 시간
○ 범위 나눠 테스트 <<< 모든 코드 구현 후 테스트
■ 모든 코드 구현: 코딩+테스트+디버깅+큰뻘짓
■ 범위 나눠 구현: 코딩+테스트+디버깅+작은뻘짓

● 회귀(regression) 테스트로도 사용
● 좋은 설계도 원하면: TDD 시도 필요
참고
● 테스트 관련
○ JUnit
■ 테스트 프레임워크
○ 스프링 MVC 테스트
■ 스프링 컨트롤러에 대한 테스트 진행
○ DBUnit
■ DB 데이터 초기화/확인 기능 제공
■ spring-test-dbunit (편리성 추가)
○ Mockito 등
■ 가짜 객체 생성 및 호출 여부 검증 기능 제공
참고: 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)));
}
맺음말

일단 한 번 테스트 코드 만들기!
Q&A, 의견
트위터: @madvirus
이메일: madvirus@madvirus.net

More Related Content

What's hot

Spring test mvc 발표자료
Spring test mvc 발표자료Spring test mvc 발표자료
Spring test mvc 발표자료수홍 이
 
Spring one참석기 ksug
Spring one참석기 ksugSpring one참석기 ksug
Spring one참석기 ksug
Sanghyuk Jung
 
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)Suwon Chae
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작
Taegon Kim
 
DDD로 복잡함 다루기
DDD로 복잡함 다루기DDD로 복잡함 다루기
DDD로 복잡함 다루기
beom kyun choi
 
Ddd start 부록 지앤선&ksug
Ddd start 부록 지앤선&ksugDdd start 부록 지앤선&ksug
Ddd start 부록 지앤선&ksug
beom kyun choi
 
C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기Heo Seungwook
 
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
Kim Hunmin
 
시작하자 단위테스트
시작하자 단위테스트시작하자 단위테스트
시작하자 단위테스트
YongEun Choi
 
React 튜토리얼 2차시
React 튜토리얼 2차시React 튜토리얼 2차시
React 튜토리얼 2차시
태현 김
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Javajigi Jaesung
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수
NAVER D2
 
KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기
Ryan Park
 
React 튜토리얼 1차시
React 튜토리얼 1차시React 튜토리얼 1차시
React 튜토리얼 1차시
태현 김
 
ECMAScript 6의 새로운 것들!
ECMAScript 6의 새로운 것들!ECMAScript 6의 새로운 것들!
ECMAScript 6의 새로운 것들!
WooYoung Cho
 
영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA
경원 이
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
경원 이
 
스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴
Sanghyuk Jung
 
구글테스트
구글테스트구글테스트
구글테스트
진화 손
 

What's hot (19)

Spring test mvc 발표자료
Spring test mvc 발표자료Spring test mvc 발표자료
Spring test mvc 발표자료
 
Spring one참석기 ksug
Spring one참석기 ksugSpring one참석기 ksug
Spring one참석기 ksug
 
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작
 
DDD로 복잡함 다루기
DDD로 복잡함 다루기DDD로 복잡함 다루기
DDD로 복잡함 다루기
 
Ddd start 부록 지앤선&ksug
Ddd start 부록 지앤선&ksugDdd start 부록 지앤선&ksug
Ddd start 부록 지앤선&ksug
 
C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기
 
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
 
시작하자 단위테스트
시작하자 단위테스트시작하자 단위테스트
시작하자 단위테스트
 
React 튜토리얼 2차시
React 튜토리얼 2차시React 튜토리얼 2차시
React 튜토리얼 2차시
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수
 
KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기
 
React 튜토리얼 1차시
React 튜토리얼 1차시React 튜토리얼 1차시
React 튜토리얼 1차시
 
ECMAScript 6의 새로운 것들!
ECMAScript 6의 새로운 것들!ECMAScript 6의 새로운 것들!
ECMAScript 6의 새로운 것들!
 
영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
 
스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴
 
구글테스트
구글테스트구글테스트
구글테스트
 

Viewers also liked

TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기
Wonchang Song
 
소프트웨어 개발자 로드맵
소프트웨어 개발자 로드맵소프트웨어 개발자 로드맵
소프트웨어 개발자 로드맵중선 곽
 
TEST?
TEST?TEST?
Spring-Boot (springcamp2014)
Spring-Boot (springcamp2014)Spring-Boot (springcamp2014)
Spring-Boot (springcamp2014)
sung yong jung
 
자동화된 Test Case의 효과
자동화된 Test Case의 효과자동화된 Test Case의 효과
자동화된 Test Case의 효과
도형 임
 
목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해
Yong Hoon Kim
 
Tdd live spring camp 2013
Tdd live spring camp 2013Tdd live spring camp 2013
Tdd live spring camp 2013
beom kyun choi
 
간단 Ip 필터 구현 이야기
간단 Ip 필터 구현 이야기간단 Ip 필터 구현 이야기
간단 Ip 필터 구현 이야기
beom kyun choi
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
beom kyun choi
 
TDD 발담그기 @ 공감세미나
TDD 발담그기 @ 공감세미나TDD 발담그기 @ 공감세미나
TDD 발담그기 @ 공감세미나
beom kyun choi
 
자바8 스트림 API 소개
자바8 스트림 API 소개자바8 스트림 API 소개
자바8 스트림 API 소개
beom kyun choi
 
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Jemin Huh
 
스프링 부트와 로깅
스프링 부트와 로깅스프링 부트와 로깅
스프링 부트와 로깅
Keesun Baik
 
Spring Boot 소개
Spring Boot 소개Spring Boot 소개
Spring Boot 소개
beom kyun choi
 
java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰
Sungchul Park
 
세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발
Jay JH Park
 
세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화
Jay JH Park
 
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
Jay JH Park
 
세션2. 이더리움 합의 알고리즘과 마이닝
세션2. 이더리움 합의 알고리즘과 마이닝세션2. 이더리움 합의 알고리즘과 마이닝
세션2. 이더리움 합의 알고리즘과 마이닝
Jay JH Park
 

Viewers also liked (20)

TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기
 
소프트웨어 개발자 로드맵
소프트웨어 개발자 로드맵소프트웨어 개발자 로드맵
소프트웨어 개발자 로드맵
 
TEST?
TEST?TEST?
TEST?
 
Spring-Boot (springcamp2014)
Spring-Boot (springcamp2014)Spring-Boot (springcamp2014)
Spring-Boot (springcamp2014)
 
자동화된 Test Case의 효과
자동화된 Test Case의 효과자동화된 Test Case의 효과
자동화된 Test Case의 효과
 
목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해
 
Tdd live spring camp 2013
Tdd live spring camp 2013Tdd live spring camp 2013
Tdd live spring camp 2013
 
간단 Ip 필터 구현 이야기
간단 Ip 필터 구현 이야기간단 Ip 필터 구현 이야기
간단 Ip 필터 구현 이야기
 
Maven의 이해
Maven의 이해Maven의 이해
Maven의 이해
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
 
TDD 발담그기 @ 공감세미나
TDD 발담그기 @ 공감세미나TDD 발담그기 @ 공감세미나
TDD 발담그기 @ 공감세미나
 
자바8 스트림 API 소개
자바8 스트림 API 소개자바8 스트림 API 소개
자바8 스트림 API 소개
 
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
Spring boot 를 적용한 전사모니터링 시스템 backend 개발 사례
 
스프링 부트와 로깅
스프링 부트와 로깅스프링 부트와 로깅
스프링 부트와 로깅
 
Spring Boot 소개
Spring Boot 소개Spring Boot 소개
Spring Boot 소개
 
java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰
 
세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발
 
세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화
 
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
 
세션2. 이더리움 합의 알고리즘과 마이닝
세션2. 이더리움 합의 알고리즘과 마이닝세션2. 이더리움 합의 알고리즘과 마이닝
세션2. 이더리움 합의 알고리즘과 마이닝
 

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

Android Native Module 안정적으로 개발하기
Android Native Module 안정적으로 개발하기Android Native Module 안정적으로 개발하기
Android Native Module 안정적으로 개발하기
hanbeom Park
 
Servlet design pattern
Servlet design patternServlet design pattern
Servlet design pattern
Sukjin Yun
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
현철 조
 
데이터베이스패턴
데이터베이스패턴데이터베이스패턴
데이터베이스패턴Suan Lee
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.Ryan Park
 
Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발지수 윤
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
ChangHyeon Bae
 
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
SangIn Choung
 
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modificationSecrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Hyuncheol Jeon
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
Ryan Park
 
Design pattern 옵저버
Design pattern 옵저버Design pattern 옵저버
Design pattern 옵저버Sukjin Yun
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10
흥배 최
 
Enterprise Java web Deployment Strategy
Enterprise Java web Deployment StrategyEnterprise Java web Deployment Strategy
Enterprise Java web Deployment Strategy
Sukjin Yun
 
practical perf testing - d2startup
practical perf testing - d2startuppractical perf testing - d2startup
practical perf testing - d2startup
JunHo Yoon
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
기동 이
 
V8 add on with middleware modules
V8 add on with middleware modulesV8 add on with middleware modules
V8 add on with middleware modules
Jay Kim
 
Spring Boot 2
Spring Boot 2Spring Boot 2
Spring Boot 2
경륜 이
 

Similar to Okjsp 13주년 발표자료: 생존 프로그래밍 Test (20)

Cygnus unit test
Cygnus unit testCygnus unit test
Cygnus unit test
 
Android Native Module 안정적으로 개발하기
Android Native Module 안정적으로 개발하기Android Native Module 안정적으로 개발하기
Android Native Module 안정적으로 개발하기
 
Servlet design pattern
Servlet design patternServlet design pattern
Servlet design pattern
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
데이터베이스패턴
데이터베이스패턴데이터베이스패턴
데이터베이스패턴
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.
 
Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
 
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
 
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modificationSecrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
 
Design pattern 옵저버
Design pattern 옵저버Design pattern 옵저버
Design pattern 옵저버
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10
 
Enterprise Java web Deployment Strategy
Enterprise Java web Deployment StrategyEnterprise Java web Deployment Strategy
Enterprise Java web Deployment Strategy
 
practical perf testing - d2startup
practical perf testing - d2startuppractical perf testing - d2startup
practical perf testing - d2startup
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 
V8 add on with middleware modules
V8 add on with middleware modulesV8 add on with middleware modules
V8 add on with middleware modules
 
Spring Boot 2
Spring Boot 2Spring Boot 2
Spring Boot 2
 

More from beom kyun choi

옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
beom kyun choi
 
keras 빨리 훑어보기(intro)
keras 빨리 훑어보기(intro)keras 빨리 훑어보기(intro)
keras 빨리 훑어보기(intro)
beom kyun choi
 
DDD 준비 서문래
DDD 준비 서문래DDD 준비 서문래
DDD 준비 서문래
beom kyun choi
 
Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀
beom kyun choi
 
MVP 패턴 소개
MVP 패턴 소개MVP 패턴 소개
MVP 패턴 소개
beom kyun choi
 
파이썬 언어 기초
파이썬 언어 기초파이썬 언어 기초
파이썬 언어 기초
beom kyun choi
 
도메인구현 KSUG 20151128
도메인구현 KSUG 20151128도메인구현 KSUG 20151128
도메인구현 KSUG 20151128
beom kyun choi
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰
beom kyun choi
 
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료beom kyun choi
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
beom kyun choi
 
리뷰의 기술 소개
리뷰의 기술 소개리뷰의 기술 소개
리뷰의 기술 소개
beom kyun choi
 
스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해
beom kyun choi
 
Zookeeper 소개
Zookeeper 소개Zookeeper 소개
Zookeeper 소개
beom kyun choi
 
하둡2 YARN 짧게 보기
하둡2 YARN 짧게 보기하둡2 YARN 짧게 보기
하둡2 YARN 짧게 보기
beom kyun choi
 
차원축소 훑어보기 (PCA, SVD, NMF)
차원축소 훑어보기 (PCA, SVD, NMF)차원축소 훑어보기 (PCA, SVD, NMF)
차원축소 훑어보기 (PCA, SVD, NMF)
beom kyun choi
 
객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회
beom kyun choi
 
Storm 훑어보기
Storm 훑어보기Storm 훑어보기
Storm 훑어보기
beom kyun choi
 
Hive 입문 발표 자료
Hive 입문 발표 자료Hive 입문 발표 자료
Hive 입문 발표 자료
beom kyun choi
 
HBase 훑어보기
HBase 훑어보기HBase 훑어보기
HBase 훑어보기
beom kyun choi
 
Flume 훑어보기
Flume 훑어보기Flume 훑어보기
Flume 훑어보기
beom kyun choi
 

More from beom kyun choi (20)

옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
 
keras 빨리 훑어보기(intro)
keras 빨리 훑어보기(intro)keras 빨리 훑어보기(intro)
keras 빨리 훑어보기(intro)
 
DDD 준비 서문래
DDD 준비 서문래DDD 준비 서문래
DDD 준비 서문래
 
Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀
 
MVP 패턴 소개
MVP 패턴 소개MVP 패턴 소개
MVP 패턴 소개
 
파이썬 언어 기초
파이썬 언어 기초파이썬 언어 기초
파이썬 언어 기초
 
도메인구현 KSUG 20151128
도메인구현 KSUG 20151128도메인구현 KSUG 20151128
도메인구현 KSUG 20151128
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰
 
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
리뷰의 기술 소개
리뷰의 기술 소개리뷰의 기술 소개
리뷰의 기술 소개
 
스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해
 
Zookeeper 소개
Zookeeper 소개Zookeeper 소개
Zookeeper 소개
 
하둡2 YARN 짧게 보기
하둡2 YARN 짧게 보기하둡2 YARN 짧게 보기
하둡2 YARN 짧게 보기
 
차원축소 훑어보기 (PCA, SVD, NMF)
차원축소 훑어보기 (PCA, SVD, NMF)차원축소 훑어보기 (PCA, SVD, NMF)
차원축소 훑어보기 (PCA, SVD, NMF)
 
객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회
 
Storm 훑어보기
Storm 훑어보기Storm 훑어보기
Storm 훑어보기
 
Hive 입문 발표 자료
Hive 입문 발표 자료Hive 입문 발표 자료
Hive 입문 발표 자료
 
HBase 훑어보기
HBase 훑어보기HBase 훑어보기
HBase 훑어보기
 
Flume 훑어보기
Flume 훑어보기Flume 훑어보기
Flume 훑어보기
 

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

  • 1. 생존 프로그래밍:TEST OKJSP 13주년 컨퍼런스, 2013-12-07 최범균(madvirus@madvirus.net)
  • 2. 목표 ● 목표임 ○ 테스트 코드를 만들지 않는 프로그래머들에게, 어쩐 지 테스트 코드가 개발 시간을 줄여줄 것 만 같은 “느 낌”을 주는 것 ● 목표 아님 ○ JUnit 설명하기 ○ 기타 프레임워크 설명하기 ○ TDD 설명하기
  • 3. 내용 ● 사람이 하는 TEST ● 테스트 시간을 단축하려면 ● 기계가 하는 테스트 ○ 스프링 통합 테스트 ○ 한 클래스 / Mock ● 주의 사항 ○ 테스트 환경 맞추기 ● 정리
  • 4. 구현 과정? Java 웹브라우저 테스트 XML SQL HTML JS WAS 기능과 관련된 모든 코드 작성 WAS 실행 버그 또는 에러 원인분석 및 코드수정
  • 5. 디버깅 과정? 왜 DB에 데이터가 null이지? 의 태그 나 ? t> npu 잘못됐 <i 이 ame n HTML JS 커맨 값이 드 객체 에 안들 어가 나? Java Ajax 호 값을 출할 때 안주 나? 재시 작 안했 나? XML 이 설정 가? 른 올바 SQL WAS 이 럼 컬 서 에 나? 리 쿼 빠졌
  • 6. 개발 시간의 증가 원인 폼에 수동 입력 (주로 ‘1’, ‘a’ 등 입력) URL을 붙여넣기 하기도 함 웹브라우저 테스트 Java WAS JS HTML SQL XML 한 번에 집중해서 만들어야 할 게 많음! 시간이 오래 걸리고, 흐름 깨지기 쉬움 WAS 실행 JRebel 없어 재시작해야 함 심한 경우, 재배포 버그 또는 에러 원인분석 및 코드수정 확인해 봐야 할 게 많음! 한 곳만 잘못되지 않음! 오래 걸림, 흐름 깨지기 쉬움
  • 8. 한 놈씩 골라서! 관련된 것만 묶어서! 서버 기능은 정 상동작하나? HTML JS 스프링 설정 문제없나? Java Controller SVC 컨트롤러가 응답을 정 상으로 만드나? DAO SQL +DB DAO 잘 되나? 다 잘 되나? XML WAS
  • 10. JUnit ● 테스트 프레임워크 ○ 코드로 테스트 시나리오 작성 ○ 코드로 결과 검증 ● 쉬운 반복 실행 ○ 지정한 범위의 테스트를 빠르게 실행 가능 ○ IDE는 모두 JUnit 실행 기능 기본 제공 ● 주로 다루는 범위 ○ 한 개 클래스 (단위 테스트) ○ 서버 기능 (통합 테스트) ○ 종종, end-to-end 테스트 (통합 테스트)
  • 11. 자바 웹 서버 개발 속도에 도움 되는 것 ● 단위 테스트 ○ 한 모듈(보통 클래스 한 개)의 기능을 테스트 ○ 예, ■ 컨트롤러가 JSON을 제대로 만드나? ■ 엑셀 생성 모듈이 엑셀 파일을 제대로 만드나? ■ DAO가 데이터를 잘 읽어오나? ■ 스프링 설정이 올바른가? ● 서버측 통합 테스트 ○ 모듈을 통합해서 수행하는 기능 테스트 ○ 예, ■ 컨트롤러-서비스-DAO-DB 연동된 상태의 기능 테 스트
  • 12. 테스트 작성 사례 ● 기능 ○ DB에서 대량의 데이터를 읽어와 서버의 로컬에 엑셀 파일을 생성한 후, 그 파일을 웹 브라우저에 내려주는 기능
  • 13. 검색해서 iBATIS의 데이터를 순차적 으로 받아 엑셀로 만드는 코드 찾음 시작 ● 일단 막 구현 나 초짜 복사/붙여넣기 해서 코드 작성 토드에서 쿼리 돌아감 다른 것 참조해서 스프링 설정 톰캣 실행/브라우저 실행/링크 클릭 결과는…..
  • 14. 잔뜩 코딩한 뒤 실행한 결과는
  • 15. 테스트 방법 복사&붙여넣기 버튼 클릭넣기 반복 뭔가 코드 수정 (서버 재시작..) 여러 코드 탐색 에러 발생
  • 16. 범위 좁히기: 에러 나는 영역 에러 유발자!
  • 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. 테스트 과정 원인 확인 테스트 및 결과 확인 에러 확인
  • 20. 범위 좁히기: 파일 전송 파일 전송 기능 구현 전
  • 21. 컨트롤러 테스트 실제 DB 연동/엑셀 파일 생성 필요 없음 컨트롤러는 다른 객체가 생성한 파일을 response로 전송해주면 됨 데이터를 어디서 읽어오는지는 중요하지 않음!
  • 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. 진짜 대신 가짜 쓰기 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. 진짜 대신 가짜 쓰기 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. 가짜를 이용한 병행 개발 개발자1: 가짜를 이용해서 개발 가능 기능 검증은 단위 테스트 코드로 개발자2: 기능 구현 기능 검증은 통합 테스트 코드로
  • 26. 마지막: 톰캣 띄우고 기능 테스트 상당한 부분의 코드를 테스트 코드로 확인한 뒤에, 거의 마지막에 기능 테스트 수행 이 시점에서 오류는 대부분 UI 관련된 것 서버쪽은 이미 테스트가 거의 끝남
  • 27. 사실은, 사용자 기능도 코드로 테스트 ● 테스트 코드가 웹 브라우저를 실행해서 입력/ 검증 수행 ● 관련 프레임워크 ○ ○ ○ ○ ○ ○ Cucumber FitNess Selenium Watir Geb …
  • 28. 테스트 작성 시 주의 사항 ● 동일 조건에서 테스트가 동작하도록 ○ 즉, 테스트 코드를 반복해서 실행해도 문제 없도록 ● 예, ○ 파일 생성 테스트면, 기능 실행 전에 기존에 생성된 파일 삭제 처리 ○ DB 조회 테스트면, 동일한 데이터 집합을 갖도록 처 리
  • 29. 정리 ● 테스트 코드와 개발 시간 단축 ○ 사람 대신 기계가 테스트를 수행해서, 실행 시간 단축 효과 ○ 개발 범위를 좁혀주어, 구현 시간 단축 효과 ○ 병행 개발 가능, 대기 시간 단축 효과 ● 코딩+테스트+디버깅 시간 ○ 범위 나눠 테스트 <<< 모든 코드 구현 후 테스트 ■ 모든 코드 구현: 코딩+테스트+디버깅+큰뻘짓 ■ 범위 나눠 구현: 코딩+테스트+디버깅+작은뻘짓 ● 회귀(regression) 테스트로도 사용 ● 좋은 설계도 원하면: TDD 시도 필요
  • 30. 참고 ● 테스트 관련 ○ JUnit ■ 테스트 프레임워크 ○ 스프링 MVC 테스트 ■ 스프링 컨트롤러에 대한 테스트 진행 ○ DBUnit ■ DB 데이터 초기화/확인 기능 제공 ■ spring-test-dbunit (편리성 추가) ○ Mockito 등 ■ 가짜 객체 생성 및 호출 여부 검증 기능 제공
  • 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. 맺음말 일단 한 번 테스트 코드 만들기!