SlideShare a Scribd company logo
Cygnus Unit Test
전략개발팀 박성재
Agenda
• Test?
• TDD
• Database Test
• Service Tier Test
• Web Tier Test
• Test Coverage
인수 테스트
스트레스 / 부하 테스트
기능 테스트
통합 테스트
테스트 종류
유닛 테스트
테스트 종류
• 유닛 테스트 - 작성이 쉽다 , 로직의 버그와 디자인
문제 ( 단일 책임 원칙 , 하드 코딩 ) 를 찾는다
• 통합 테스트 – 객체 간 , 서비스 간 , 서브 시스템
간 상호 작용 테스트
• 기능 테스트 – 공개된 api 의 가장 바깥 부분 테스
트 , 유스케이스 단위 테스트
• 스트레스 테스트 – jMeter 등의 전용 도구 이용
• 인수 테스트 – 개발자가 아닌 고객 혹은 QA 에서 진
행
Mockito
Tapestry Test
Test 관련 Tools
Spring Test
유닛 테스트
“ 유닛 테스트 (unit test) 는 소스 코드가
의도된 대로 정확히 작동하는지 검증하
는 절차다 . 즉 , 모든 클래스와 메소드
에 대한 테스트 케이스를 작성하는 절차
를 말한다 .”
wikipedia.org
Why Unit Test
• 디버깅은 많은 시간을 소비하고 싶지 않
아
• 새로운 기능 추가나 리팩토링 후 기존
기능들이 잘 동작하는지 확신하고 싶어
• 테스트 코드를 읽고 class 의 동작을 명
확하게 이해할 수 있지
• 유닛 테스트를 통해 프로젝트 헬스와 코
드 퀄리티를 측정할 수 있거든
Cygnus unit test
Why not Unit Test
• 난 절대 실수 하지 않아
• 기능이 너무 단순해
• 테스트 코드까지 만들 시간이 없어
• 테스트 하는 방법을 몰라 ㅠㅠ
유닛 테스트 특징
• Isolated
– 타이어 테스트 할 때 자동차까지 만들지 말자
• Repeatable
– 모든 개발자에서 테스트 가능
– 환경에 영향 받지 않게
• Fast
– 시간은 돈이다 .
– 쉽고 빠르게 테스트 코드를 만들 수 있어야 한다
• Self-Documenting
– 테스트 코드는 단순해서 이해하기 쉬워야 한다
– 테스트 코드를 설명하는 문서가 필요 없어야 한다
First Unit Test
Public class Calculator {
public double add(double number1, double number2) {
return number1 + number2;
}
}
import static org.junit.Assert.*;
import org.junit.Test;
public class CalculatorTest {  1.public class
@Test  2.unit test
public void test() {
Calculator calc = new Calculator();
double result = calc.add(10, 20);  3. 대상메소드콜
assertEquals(30, result, 0);  4. 결과 확인
}
}
First Unit Test 실행
Test Driven
Development(TDD)
“ 좋은 코드는 테스트하기 쉽다 . 그 반대
도 마찬가지다 .”
Cygnus unit test
Cygnus unit test
Cygnus unit test
Cygnus unit test
Cygnus Tier Flow
CreateServer
ServerServic
e
ServerDao
saveServer(server)
saveServer(server)
doSomething(server)
session.save(server)
ViewServer
ServerServic
e
ServerDao
getServerById(id)
getServerById(id)
session.get(Server.class, id
http://.../viewserver/{id}
Server
Web Tier :
Service Tier :
Dao Tier :
Persistent Tier :
Database Test 어려움
• Isolated
– DB 는 외부에 있다
• Repeatable
– Test 할 때마다 DB 가 변경된다
• Fast
– DB 접속은 상대적으로 느리다
– DB 접속 코드는 복잡하고 어렵다
• 초기 데이터 입력
• 평가 코드 작성
Database Test 전략
• Embedded DB(H2, HSQL) 사용
– Fast
– 개발자 별로 독립적 실행 가능
• DbUnit 사용
– 테스트 코드 작성 용이
– 쉬운 초기 데이터 셋팅
– 쉬운 평가 방법 제공
Database Test 대상
• 클래스와 테이블간 맵핑 오류
– DB 예약어 사용 예 )user, index, unique,
max
– 제품 DB 변경 시 활용
• 테이블 릴레이션
– one-to-many 등에서 이상한 forign 키 관계
가 없는지 ?
– Cascade 가 잘 동작하는지 ?
• 조회 쿼리
– 단일 객체 반환을 원하는데 복수 객체가 리턴
되지 않는지 ?
Database Test Code
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/META-INF/spring/test-applicationContext.xml")
@Transactional
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class
,
TransactionDbUnitTestExecutionListener.class,
DbUnitTestExecutionListener.class })
public class ServerDaoTest {
@Test
@DatabaseSetup("testServer.xml") 1. 초기 데이터
@ExpectedDatabase(value="empty.xml", 2. 기대 데이터 검증
assertionMode=DatabaseAssertionMode.NON_STRICT)
public void testDeleteServer() {
Server server = serverDao.getById(1);
serverDao.delete(server); 3. 테스트 대상
serverDao.flush(); 4. ORM 캐시 비우기
assertThat(serverDao.findAll().size(), is(0)); 5. delete 검증
}
Service 계층 Test 어려움
• Isolated
– 다른 서비스 / 계층 (DAO) 이 연관되어 있다
– 다른 시스템 (Agent, Mail Server, REST)
과 연관되어 있다
• Repeatable
– Test 할 때마다 모든 환경을 구축하기 어렵
다
• Fast
– 테스트 코드 작성시 많은 노력이 필요하다
Service 계층 Test 전략
• Stub 객체 작성
– Stub 이란 실제 대상과 유사하게 동작하는
객체 (Agent 시뮬레이터 )
– 동작 방식을 stub 객체에 코딩한다
– Stub 제작의 어려움이 남아 있다
• Mock 객체 이용
– Mock 이란 실제 객체와 유사한 동작을 하지
만 시키는
Service 계층 Test 전략
• Mock 객체 이용
– Mock 이란 실제 객체를 흉내내는 객체
– 동작 방식은 외부에서 알려준다 .
– Mock Framework 활용한 손쉬운 작성
• Mockito, EasyMock, Jmock
Service 계층 Test 코드
@Service
public class ServerServiceImpl implements ServerService {
@Autowired
ServerDao serverDao;
@Transactional
public Server discoveryServer(String ipAddress) {
Server server = serverDao.findServerByIpAddress(ipAddress);
if(server != null) {
throw new ServerDuplicatedException("Duplicated ipAddres=" + ipAddress);
}
Server newServer = new Server();
newServer.setIpAddress(ipAddress);
serverDao.save(newServer);
return newServer;
}
Service 계층 Test 코드
@RunWith(MockitoJUnitRunner.class)  1. mockito 러너 사용
public class ServerServiceTest {
@InjectMocks  2. mock 주입
ServerService serverService = new ServerServiceImpl();
@Mock  3. mock 객체 생성
ServerDao serverDao;
@Test
public void testDiscoveryServer() {
String ipAddress = "127.0.0.1";
//stub 4. mock 동작 정의
when(serverDao.findServerByIpAddress(ipAddress)).thenReturn(null);
//run
Server server=serverService.discoveryServer(ipAddress);  5. 대상 메소드 실행
//assert
assertThat(server.getIpAddress(), equalTo(ipAddress));  6. 메소드 리턴 결과 판
정
verify(serverDao).findServerByIpAddress(ipAddress);  7. mock 호출 여부 확인
verify(serverDao).save(server);  8. mock 호출 여부 확인
}
Service 계층 Test 코드
@Test(expected=ServerDuplicatedException.class)  1. 예외 기대 및 판정
public void testDiscoveryServerDuplicated() {
String ipAddress = "127.0.0.1";
Server existServer = new Server();
when(serverDao.findServerByIpAddress(ipAddress)).thenReturn(existServer);  2.
mock 동작
Server server = serverService.discoveryServer(ipAddress);  3. 테스트 메
소드 실행
}
Web 계층 test 어려움
• 컴파일 타임에 문법 오류를 잡을 수 없다
– template 파일 , javascript 등
• 페이지 / 컴포넌트간 링크가 잘 동작하는 테
스트기 어렵다
• 국제화나 validate 등의 리소스 버그를 테
스트 하기 어렵다
• Isolate
– 서비스 계층이 구현되지 않은 경우 테스트가
어렵다
• Fast
– 웹 어플리케이션 기동 후 육안 검사에 의존
Web 계층 테스트 전략
• 서비스 계층을 mock 객체로 활용
• Tapestry Test framework 활용
– PageTester.renderPage()
– PageTester.clickLink()
• Selenium 테스트 도입
Web 계층 테스트 코드
public class ViewServerTest {
PageTester tester;
@Before  1. test setUp
public void setUp() {
String appPackage = "com.nkia.cygnus.management.server";
String appName = "development";
tester = new PageTester(appPackage, appName, "src/main/webapp",
TestAppModule.class);
}
@Test
public void testExistServer() {
ServerService serverService = tester.getService(ServerService.class);  2.
MockServerServic
when(serverService.getServerById(1)).thenReturn(newServer());  3. Mock 동
작 정의
Document doc = tester.renderPage("server/ViewServer/1");  4. 대상 페이지 렌더링
assertThat(doc.toString(),
containsString("View Server - testserver123456"));  4. 정상 여부
판정
Web 계층 테스트 코드
// link test
@Test
public void testDeleteNotExistServer() {
ServerService serverService = tester.getService(ServerService.class);  1. Mock
객체
when(serverService.findServersAll()).thenReturn(newServerList());  2. Mock 동
작 정의
when(serverService.getServerById(1)).thenReturn(null);
Document doc = tester.renderPage("server/ServerPage");  3. page rendering
Element delete = doc.getElementById("delete");  4. link 객체 얻기
assertThat(delete, notNullValue());  5. link 존재 검증
Document linkDoc = tester.clickLink(delete);  5. link 클릭
assertThat(linkDoc.toString(),
containsString("Server not found. id = 1"));  5. link 동작
검증
}
Test 커버리지 보고서
• 소스의 단위 테스트 커버리지 측정
• Cobertura 활용
• 테스트 커버리지 기준을 만들고 일정 수준
이 되어야 만 릴리즈 할 수 있는 정책 가능
– http://cms.nkia.net:8088/projects/cygnus/cygnu
• 클래스 복잡도 측정 - McCabe's
cyclomatic complexity) 
– http://blog.wisedog.net/110

More Related Content

PPTX
Maven의 이해
PPTX
메이븐파헤치기(김우용)
PPTX
Maven
PPTX
Maven
PDF
메이븐 기본 이해
PPTX
Jenkins를 활용한 javascript 개발
PDF
자바 웹프로젝트 개발환경 셋팅
PPTX
Vert.x 세미나 이지원_배포용
Maven의 이해
메이븐파헤치기(김우용)
Maven
Maven
메이븐 기본 이해
Jenkins를 활용한 javascript 개발
자바 웹프로젝트 개발환경 셋팅
Vert.x 세미나 이지원_배포용

What's hot (20)

PDF
지속적인 통합
PPTX
Springmvc
PDF
[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project
PDF
okspring3x
PDF
Spring boot 5장 cli
PDF
[오픈소스컨설팅]Spring 3.1 Core
PPTX
Backend Master | 3.1.4 Build - Java build tool - Maven/Gradle Build Lifecycle
PDF
Spring boot 공작소(1-4장)
PPTX
20170310 tech day-1st-maven을 이용한 프로그램 빌드-박준홍
PPTX
오픈소스 프레임워크 기반 웹 서비스 설계 (Example)
PPTX
bamboo 로 PHP 프로젝트 지속적인 배포
PDF
Tomcat monitoring using_javamelody
PDF
오늘 당장 시작하는 HTML5
PDF
iOS9 소개
PPTX
Spring Boot + React + Gradle in VSCode
PDF
소프트웨어 개선 그룹(Sig) 개발 원칙
PDF
자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)
PDF
Universal Rendering
PDF
우아한테크세미나-우아한멀티모듈
PPTX
Spring boot-summary(part2-part3)
지속적인 통합
Springmvc
[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project
okspring3x
Spring boot 5장 cli
[오픈소스컨설팅]Spring 3.1 Core
Backend Master | 3.1.4 Build - Java build tool - Maven/Gradle Build Lifecycle
Spring boot 공작소(1-4장)
20170310 tech day-1st-maven을 이용한 프로그램 빌드-박준홍
오픈소스 프레임워크 기반 웹 서비스 설계 (Example)
bamboo 로 PHP 프로젝트 지속적인 배포
Tomcat monitoring using_javamelody
오늘 당장 시작하는 HTML5
iOS9 소개
Spring Boot + React + Gradle in VSCode
소프트웨어 개선 그룹(Sig) 개발 원칙
자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)
Universal Rendering
우아한테크세미나-우아한멀티모듈
Spring boot-summary(part2-part3)
Ad

Similar to Cygnus unit test (20)

PPTX
TDD - Test Driven Development
PDF
[고급과정] 코드 테스트와 커버리지 교육(실습위주)
PDF
아꿈사.C++ api 디자인.20140315 a
PDF
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
PPTX
PDF
TDD.JUnit.조금더.알기
PDF
Effective unit testing ch3. 테스트더블
PDF
Effective Unit Testing
PPTX
X unittestpattern 1장_아꿈사
PDF
PDF
개발이 테스트를 만났을 때(Shift left testing)
PDF
테스트수행사례 W통합보안솔루션
PDF
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
PDF
시작하자 단위테스트
PDF
테스트개선지원 사례 - 웹어플리케이션대상
PDF
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
PDF
사용자 스토리 대상 테스트 설계 사례(테스트기본교육 3장 3절)
PPTX
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
PDF
(편집-테스트카페 발표자료) 1인 QA 수행사례로 발표한 자료 (W프로젝트 사례)
PDF
엔지니어의 학습, 그리고 테스트 코드
TDD - Test Driven Development
[고급과정] 코드 테스트와 커버리지 교육(실습위주)
아꿈사.C++ api 디자인.20140315 a
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
TDD.JUnit.조금더.알기
Effective unit testing ch3. 테스트더블
Effective Unit Testing
X unittestpattern 1장_아꿈사
개발이 테스트를 만났을 때(Shift left testing)
테스트수행사례 W통합보안솔루션
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
시작하자 단위테스트
테스트개선지원 사례 - 웹어플리케이션대상
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
사용자 스토리 대상 테스트 설계 사례(테스트기본교육 3장 3절)
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
(편집-테스트카페 발표자료) 1인 QA 수행사례로 발표한 자료 (W프로젝트 사례)
엔지니어의 학습, 그리고 테스트 코드
Ad

Cygnus unit test

  • 2. Agenda • Test? • TDD • Database Test • Service Tier Test • Web Tier Test • Test Coverage
  • 3. 인수 테스트 스트레스 / 부하 테스트 기능 테스트 통합 테스트 테스트 종류 유닛 테스트
  • 4. 테스트 종류 • 유닛 테스트 - 작성이 쉽다 , 로직의 버그와 디자인 문제 ( 단일 책임 원칙 , 하드 코딩 ) 를 찾는다 • 통합 테스트 – 객체 간 , 서비스 간 , 서브 시스템 간 상호 작용 테스트 • 기능 테스트 – 공개된 api 의 가장 바깥 부분 테스 트 , 유스케이스 단위 테스트 • 스트레스 테스트 – jMeter 등의 전용 도구 이용 • 인수 테스트 – 개발자가 아닌 고객 혹은 QA 에서 진 행
  • 6. 유닛 테스트 “ 유닛 테스트 (unit test) 는 소스 코드가 의도된 대로 정확히 작동하는지 검증하 는 절차다 . 즉 , 모든 클래스와 메소드 에 대한 테스트 케이스를 작성하는 절차 를 말한다 .” wikipedia.org
  • 7. Why Unit Test • 디버깅은 많은 시간을 소비하고 싶지 않 아 • 새로운 기능 추가나 리팩토링 후 기존 기능들이 잘 동작하는지 확신하고 싶어 • 테스트 코드를 읽고 class 의 동작을 명 확하게 이해할 수 있지 • 유닛 테스트를 통해 프로젝트 헬스와 코 드 퀄리티를 측정할 수 있거든
  • 9. Why not Unit Test • 난 절대 실수 하지 않아 • 기능이 너무 단순해 • 테스트 코드까지 만들 시간이 없어 • 테스트 하는 방법을 몰라 ㅠㅠ
  • 10. 유닛 테스트 특징 • Isolated – 타이어 테스트 할 때 자동차까지 만들지 말자 • Repeatable – 모든 개발자에서 테스트 가능 – 환경에 영향 받지 않게 • Fast – 시간은 돈이다 . – 쉽고 빠르게 테스트 코드를 만들 수 있어야 한다 • Self-Documenting – 테스트 코드는 단순해서 이해하기 쉬워야 한다 – 테스트 코드를 설명하는 문서가 필요 없어야 한다
  • 11. First Unit Test Public class Calculator { public double add(double number1, double number2) { return number1 + number2; } } import static org.junit.Assert.*; import org.junit.Test; public class CalculatorTest {  1.public class @Test  2.unit test public void test() { Calculator calc = new Calculator(); double result = calc.add(10, 20);  3. 대상메소드콜 assertEquals(30, result, 0);  4. 결과 확인 } }
  • 12. First Unit Test 실행
  • 13. Test Driven Development(TDD) “ 좋은 코드는 테스트하기 쉽다 . 그 반대 도 마찬가지다 .”
  • 19. Database Test 어려움 • Isolated – DB 는 외부에 있다 • Repeatable – Test 할 때마다 DB 가 변경된다 • Fast – DB 접속은 상대적으로 느리다 – DB 접속 코드는 복잡하고 어렵다 • 초기 데이터 입력 • 평가 코드 작성
  • 20. Database Test 전략 • Embedded DB(H2, HSQL) 사용 – Fast – 개발자 별로 독립적 실행 가능 • DbUnit 사용 – 테스트 코드 작성 용이 – 쉬운 초기 데이터 셋팅 – 쉬운 평가 방법 제공
  • 21. Database Test 대상 • 클래스와 테이블간 맵핑 오류 – DB 예약어 사용 예 )user, index, unique, max – 제품 DB 변경 시 활용 • 테이블 릴레이션 – one-to-many 등에서 이상한 forign 키 관계 가 없는지 ? – Cascade 가 잘 동작하는지 ? • 조회 쿼리 – 단일 객체 반환을 원하는데 복수 객체가 리턴 되지 않는지 ?
  • 22. Database Test Code @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/META-INF/spring/test-applicationContext.xml") @Transactional @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class , TransactionDbUnitTestExecutionListener.class, DbUnitTestExecutionListener.class }) public class ServerDaoTest { @Test @DatabaseSetup("testServer.xml") 1. 초기 데이터 @ExpectedDatabase(value="empty.xml", 2. 기대 데이터 검증 assertionMode=DatabaseAssertionMode.NON_STRICT) public void testDeleteServer() { Server server = serverDao.getById(1); serverDao.delete(server); 3. 테스트 대상 serverDao.flush(); 4. ORM 캐시 비우기 assertThat(serverDao.findAll().size(), is(0)); 5. delete 검증 }
  • 23. Service 계층 Test 어려움 • Isolated – 다른 서비스 / 계층 (DAO) 이 연관되어 있다 – 다른 시스템 (Agent, Mail Server, REST) 과 연관되어 있다 • Repeatable – Test 할 때마다 모든 환경을 구축하기 어렵 다 • Fast – 테스트 코드 작성시 많은 노력이 필요하다
  • 24. Service 계층 Test 전략 • Stub 객체 작성 – Stub 이란 실제 대상과 유사하게 동작하는 객체 (Agent 시뮬레이터 ) – 동작 방식을 stub 객체에 코딩한다 – Stub 제작의 어려움이 남아 있다 • Mock 객체 이용 – Mock 이란 실제 객체와 유사한 동작을 하지 만 시키는
  • 25. Service 계층 Test 전략 • Mock 객체 이용 – Mock 이란 실제 객체를 흉내내는 객체 – 동작 방식은 외부에서 알려준다 . – Mock Framework 활용한 손쉬운 작성 • Mockito, EasyMock, Jmock
  • 26. Service 계층 Test 코드 @Service public class ServerServiceImpl implements ServerService { @Autowired ServerDao serverDao; @Transactional public Server discoveryServer(String ipAddress) { Server server = serverDao.findServerByIpAddress(ipAddress); if(server != null) { throw new ServerDuplicatedException("Duplicated ipAddres=" + ipAddress); } Server newServer = new Server(); newServer.setIpAddress(ipAddress); serverDao.save(newServer); return newServer; }
  • 27. Service 계층 Test 코드 @RunWith(MockitoJUnitRunner.class)  1. mockito 러너 사용 public class ServerServiceTest { @InjectMocks  2. mock 주입 ServerService serverService = new ServerServiceImpl(); @Mock  3. mock 객체 생성 ServerDao serverDao; @Test public void testDiscoveryServer() { String ipAddress = "127.0.0.1"; //stub 4. mock 동작 정의 when(serverDao.findServerByIpAddress(ipAddress)).thenReturn(null); //run Server server=serverService.discoveryServer(ipAddress);  5. 대상 메소드 실행 //assert assertThat(server.getIpAddress(), equalTo(ipAddress));  6. 메소드 리턴 결과 판 정 verify(serverDao).findServerByIpAddress(ipAddress);  7. mock 호출 여부 확인 verify(serverDao).save(server);  8. mock 호출 여부 확인 }
  • 28. Service 계층 Test 코드 @Test(expected=ServerDuplicatedException.class)  1. 예외 기대 및 판정 public void testDiscoveryServerDuplicated() { String ipAddress = "127.0.0.1"; Server existServer = new Server(); when(serverDao.findServerByIpAddress(ipAddress)).thenReturn(existServer);  2. mock 동작 Server server = serverService.discoveryServer(ipAddress);  3. 테스트 메 소드 실행 }
  • 29. Web 계층 test 어려움 • 컴파일 타임에 문법 오류를 잡을 수 없다 – template 파일 , javascript 등 • 페이지 / 컴포넌트간 링크가 잘 동작하는 테 스트기 어렵다 • 국제화나 validate 등의 리소스 버그를 테 스트 하기 어렵다 • Isolate – 서비스 계층이 구현되지 않은 경우 테스트가 어렵다 • Fast – 웹 어플리케이션 기동 후 육안 검사에 의존
  • 30. Web 계층 테스트 전략 • 서비스 계층을 mock 객체로 활용 • Tapestry Test framework 활용 – PageTester.renderPage() – PageTester.clickLink() • Selenium 테스트 도입
  • 31. Web 계층 테스트 코드 public class ViewServerTest { PageTester tester; @Before  1. test setUp public void setUp() { String appPackage = "com.nkia.cygnus.management.server"; String appName = "development"; tester = new PageTester(appPackage, appName, "src/main/webapp", TestAppModule.class); } @Test public void testExistServer() { ServerService serverService = tester.getService(ServerService.class);  2. MockServerServic when(serverService.getServerById(1)).thenReturn(newServer());  3. Mock 동 작 정의 Document doc = tester.renderPage("server/ViewServer/1");  4. 대상 페이지 렌더링 assertThat(doc.toString(), containsString("View Server - testserver123456"));  4. 정상 여부 판정
  • 32. Web 계층 테스트 코드 // link test @Test public void testDeleteNotExistServer() { ServerService serverService = tester.getService(ServerService.class);  1. Mock 객체 when(serverService.findServersAll()).thenReturn(newServerList());  2. Mock 동 작 정의 when(serverService.getServerById(1)).thenReturn(null); Document doc = tester.renderPage("server/ServerPage");  3. page rendering Element delete = doc.getElementById("delete");  4. link 객체 얻기 assertThat(delete, notNullValue());  5. link 존재 검증 Document linkDoc = tester.clickLink(delete);  5. link 클릭 assertThat(linkDoc.toString(), containsString("Server not found. id = 1"));  5. link 동작 검증 }
  • 33. Test 커버리지 보고서 • 소스의 단위 테스트 커버리지 측정 • Cobertura 활용 • 테스트 커버리지 기준을 만들고 일정 수준 이 되어야 만 릴리즈 할 수 있는 정책 가능 – http://cms.nkia.net:8088/projects/cygnus/cygnu • 클래스 복잡도 측정 - McCabe's cyclomatic complexity)  – http://blog.wisedog.net/110