Continuous Integration 지속적인테스트 조영호카페PJT팀 2008.09.16 youngho.cho@nhncorp.com
목차 1. 지속적인테스트 2. 테스트분류 3. xunit
1. 지속적인테스트
선형시스템의신뢰도 컴포넌트 A ( 신뢰도 90%) 컴포넌트 B ( 신뢰도 90%) 컴포넌트 C ( 신뢰도 90%) 신뢰도 = 0.9 x 0.9 x 0.9 = 0.73 4 / 문서의제목
신뢰할수있는시스템 100% 짜리 ( 또는그정도에가까운 ) 서비스수준계약서를 체결한소프트웨어어플리케이션을만들고자한다면, 반드시개별객체수준에서신뢰도를보장해야만할겁니다. 단위테스트 (Unit Test) 5 / 문서의제목
신뢰할수있는시스템 단위테스트를통한객체수준의신뢰도보장객체가이용되는상황을효과적으로재현하는테스트케이스구축테스트를자주실행시스템내변경사항발생시언제라도테스트실행 지속적인테스트 6 / 문서의제목
자동화된개발자테스트돌리기 소스코드컴파일하기 테스트돌리기 통합하기 검사수행하기 데이터베이스통합하기 소프트웨어배포하기 피드백주기 소프트웨어품질을향상시키고위험을줄이기 P ㅖㅔ { [ ] \ \? / Integrate? / shift 7 / 문서의제목
2. 테스트분류 8 / 문서의제목
테스트의분류 단위테스트 소프트웨어시스템내의작은요소의행동검증 일반적으로하나의클래스를테스트 컴포넌트테스트 소프트웨어시스템의일부를테스트 상호작용하는컴포넌트들간의행동검증 외부의존성요구완전히설치된시스템, DB, 파일시스템, 네트워크종점 단위테스트보다오래걸림 시스템테스트 전체소프트웨어시스템을실행 완전히설치된시스템요구 설치하는시간이길고실행시간도김 테스트를위한설치작업이빌드의일부로포함 기능테스트 어플리케이션의기능성을클라이언트관점에서테스트 인수테스트 9 / 문서의제목
테스트의분류 사용자 사용자 서버 연동시스템 사용자 10 / 문서의제목 데이터베이스
단위테스트 네트워크케이블을빼고데이터베이스를종료시키고나서도돌아 가는테스트가진짜단위테스트입니다 사용자 class class 사용자 사용자 class 서버 연동시스템 사용자 데이터베이스 11 / 문서의제목
컴포넌트테스트 컴포넌트수준의테스트는 API 를통해코드를수행하지만, 외부 클라이언트에노출될때도있고, 그렇지않을수도있습니다. 사용자 사용자 서버 연동시스템 사용자 12 / 문서의제목 데이터베이스
시스템테스트 시스템테스트는웹페이지, 웹서비스종점, GUI 가처음부터끝까지 설계된대로작동하는지를검증합니다. 사용자 사용자 서버 연동시스템 사용자 13 / 문서의제목 데이터베이스
기능테스트 어플리케이션의기능을클라이언트관점에서테스트하는것이며, 이는테스트 자체가클라이언트를흉내낸다는뜻입니다. 사용자 사용자 서버 연동시스템 사용자 14 / 문서의제목 데이터베이스
테스트의분류 단위테스트컴포넌트테스트시스템테스트기능테스트 소프트웨어시스템내의작은요소의행동검증 일반적으로하나의클래스를테스트 테스트에필요한설치작업에따라테스트분화 소프트웨어시스템의일부를테스트 상호작용하는컴포넌트들간의행동검증테스트 외부실행에의존성요구소요되는시간과직접적인연관완전히설치된시스템, DB, 파일시스템, 네트워크종점 단위테스트보다오래걸림 테스트범주화는지속적인통합문맥하에서매우중요 시간이덜걸리는테스트부터실행 전체소프트웨어시스템을실행 완전히설치된시스템요구 설치하는시간이길고실행시간도김 테스트를 Feedback 위한설치작업이빌드의일부로포함 어플리케이션의기능성을클라이언트관점에서테스트 인수테스트 15 / 문서의제목
개발자테스트를여러범주로나누기 Annotation Test Suite 구성 디렉토리분류 project/ src/ main/ java/ test/ java/ unit/ component/ system/ pom.xml 16 / 문서의제목
개발자테스트를여러범주로나누기 Maven2 Profile 사용 <profiles> <profile> <id>junit</id> <properties> <deploy.phase>local</deploy.phase> <settings.runenv>test</settings.runenv> <maven.test.skip>false</maven.test.skip> <log4j.runenv>log4j.xml</log4j.runenv> </properties> <build> <plugins> <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-surefire-plugin</artifactid> <version>2.4.2</version> <configuration> <excludes> <exclude>**/*integrationtest.java</exclude> </excludes> </configuration> </plugin> </plugins> </build> </profile> 17 / 문서의제목
3. xunit 18 / 문서의제목
JUnit Unit 자바프로그래밍언어를위한단위테스팅프레임워크 By Kent Beck and Erich Gamma Kent Beck의 SUnit 프레임워크로부터유래 http://www.junit.org/ xunit Family PHPUnit (PHP) NUnit (C#) PyUnit (Python) funit (Fortran) Test::Class, Test::Unit (Perl) CPPUnit (C++) JSUnit (JavaScript) 유사프레임워크 TestNG 19 / 문서의제목
JUnit 3.x Unit 이름짓기규약 TestAccount.java Account.java testcreateaccount() testcreateaccdef() testcreateacctdup() createaccount() 20 / 문서의제목
JUnit 3.x Unit 단정메소드 asserttrue(boolean condition) assertfalse(boolean condition) assertequals(object expected, Object actual) Uses equals() comparison Overloaded for all primitive types assertsame(object expected, Object actual) assertnotsame(object expected, Object actual) Uses == comparison assertequals(float expected, float actual, float tolerance) TestCase assertnull(object o) assertnotnull(object o) fail(string message) MyTestCase 21 / 문서의제목
JUnit 3.x Unit 샘플 package org.eternity.common.money; import junit.framework.testcase; public class FirstTestCase extends TestCase { public FirstTestCase(String method) { super(method); public void testadd() { assertequals(2, 1+1); TestCase MyTestCase 22 / 문서의제목
JUnit 3.x Unit Test Fixture public class DatabaseTestCase extends TestCase { private Connection dbconn; protected void setup() { dbconn = new Connection("oracle", 1521, "fred", "foobar"); dbconn.connect(); protected void teardown() { dbconn.disconnect(); dbconn = null; public void testaccountaccess() { // dbconn 사용 //... setup() testaccountaccess() teardown setup() public void testemployeeaccess() { // dbconn 사용 //... testemployeeaccess() teardown() 23 / 문서의제목
JUnit 3.x Unit Test Suite junit.framework * <<interface>> Test TestSuite TestCase MyTestCase 24 / 문서의제목
JUnit 3.x Unit Test Suite package org.eternity.common.money; import junit.framework.test; import junit.framework.testcase; import junit.framework.testsuite; public class SecondTestCase extends TestCase { public SecondTestCase(String method) { super(method); public void testsubtract() { asserttrue(10-5 > 0); public void testmultiply() { assertequals(50, 10*5); public void testdivide() { assertequals(2, 10/5); public static Test suite() { TestSuite suite = new TestSuite(); suite.addtest(new SecondTestCase("testMultiply")); suite.addtest(new SecondTestCase("testDivide")); return suite; 25 / 문서의제목
JUnit 3.x Unit Exception public void testforexception() { try { sortmylist(null); fail("should have thrown an exception!"); catch(nullpointerexception ex) { asserttrue(true); 26 / 문서의제목
JUnit3 에서 JUnit 4 로 Unit JUnit4 는 Java 5 이상을요구 junit.framework.testcase 를상속하지않는독립클래스로작성 org.junit.* 과 org.junit.assert.* 를 import org.junit.assert.* 에대해 static import TestCase 로부터상속받지않기때문 명명규칙을따르는메소드대신 Annotation 사용 @Test 는 testxxx() 메소드대체 @Before 는 setup() 메소드대체 @After 는 teardown() 메소드대체 + @ 27 / 문서의제목
JUnit4 Unit Test Fixture public class DatabaseTestCase { private Connection dbconn; @Before protected void connectdb() { dbconn = new Connection("oracle", 1521, "fred", "foobar"); dbconn.connect(); @After protected void closedb() { dbconn.disconnect(); dbconn = null; connectdb() checkaccountaccess() closedb @Test public void checkaccountaccess() { // dbconn 사용 //... @Test public void checkemployeeaccess() { // dbconn 사용 //... connectdb() checkemployeeaccess() closedb() 28 / 문서의제목
JUnit4 Unit Test Suite package org.eternity.common.money; import junit.framework.test; import junit.framework.testcase; import junit.framework.testsuite; public class SecondTestCase extends TestCase { public SecondTestCase(String method) { super(method); public void testsubtract() { asserttrue(10-5 > 0); public void testmultiply() { assertequals(50, 10*5); public void testdivide() { assertequals(2, 10/5); public static Test suite() { TestSuite suite = new TestSuite(); suite.addtest(new SecondTestCase("testMultiply")); suite.addtest(new SecondTestCase("testDivide")); return suite; 29 / 문서의제목
JUnit4 Unit Test Suite package org.eternity.common.money; import org.junit.runner.runwith; import org.junit.runners.suite; import org.junit.runners.suite.suiteclasses; @RunWith(Suite.class) @SuiteClasses({FirstTestCase.class,SecondTestCase.class) public class SimpleTestSuite{ @RunWith, @SuiteClasses 30 / 문서의제목
JUnit4 Unit Exception @Test(expected=NullPointerException.class) public void checknullparameterlist() { sortmylist(null); 31 / 문서의제목
Mock Object Unit 디버깅하기위해사용되는실세계객체의대용물 Mock Object가유용한경우 진짜객체가비결정적인동작을할경우 결과예측이어려운경우 진짜객체를준비설정하기어려운경우진짜객체자직접유발시키기어려운동작을하는경우 네트워크에러 진짜객체가너무느린경우진짜객체가 UI를가지거나, UI 자체인경우진짜객체에게그것이어떻게사용되는지물어봐야하는경우진짜객체가아직존재하지않는경우 32 / 문서의제목
Mock Object Unit Mock Object 구조 객체에인터페이스사용 TestTarget Interface 인터페이스를구현한모의객체 MockObject RealObject 인터페이스를구현한제품코드 33 / 문서의제목
Mock Object Unit Behavior Verification 테스트대상객체가다른객체와의협력테스트테스트대상객체가협력객체의메소드를정상적으로호출하는지여부검증 Mock Object는 Behavioral Verification 기법 State Verification 기존의 JUnit 기반의단위테스트 대상객체의상태변화체크 Object MockObject 정상적으로호출하는지테스트 Mocks Aren t Stubs By Martin Fowler http://martinfowler.com/articles/mocksarentstubs.html 34 / 문서의제목
Mock Object Unit Mock Object 를실행시간에자동생성 jmock http://www.jmock.org/ EasyMock http://www.easymock.org/ TestCase TestTarget Interface MockObject RealObject 35 / 문서의제목 Mock Object 자동생성
Mock Object Unit 게시물스크랩 Test 대상객체 네트워크를통해게시글전송 CafeScrapTest CafeScrap Scrapable MockObject ArticleScrappable 네트워크가비정상적일경우? Dependency Problem 36 / 문서의제목
Mock Object Unit jmock @RunWith(JMock.class) public class CafeScrapTest { private Mockery context = new JUnit4Mockery(); private CafeScrap cafescrap; private Scrapable scrapable; @Before public void preparecafesrap() { cafescrap = new CafeScrap(); scrapable = context.mock(scrapable.class); cafescrap.setscrappable(scrapable); Scrapable 인터페이스를구현한 Mock Object 생성 @Test public void scraptoblog() { final Article article = new Article(); context.checking(new Expectations() {{ one(scrapable).scrap(article, Service.BLOG); will(throwexception(new BlogServerNotAvailableException())); ); Expectation 설정 Behavior Verification assertfalse(cafescrap.sendtoblog(article)); 37 / 문서의제목
Mock Object Unit EasyMock public class CafeScrapTest { private CafeScrap cafescrap; private Scrapable scrapable; @Before public void preparecafesrap() { cafescrap = new CafeScrap(); scrapable = EasyMock.createMock(Scrapable.class); cafescrap.setscrappable(scrapable); @Test public void scraptoblog() { Article article = new Article(); EasyMock.expect(scrapable.scrap(article, Service.BLOG)).andThrow(new BlogServerNotAvailableException()); EasyMock.replay(scrapable); Scrapable 인터페이스를구현한 Mock Object 생성후테스트객체에연결 Expectation 설정 Behavior Verification 행동재생 assertfalse(cafescrap.sendtoblog(article)); EasyMock.verify(scrapable); 행동검증 38 / 문서의제목
Spring Database Test Support Component AbstractTransactionalSpringContextTests org.springframework.test.abstracttransactionalspringcontexttests 테스트종료후데이터베이스트랜잭션롤백 getconfiglocations() 스프링빈컨텍스트위치목록반환 onsetupbeforetransaction() 트랜잭션이시작되기전호출 onsetupintransaction() 트랜잭션이시작된후호출 onteardownintransaction() 트랜잭션이롤백되기전에호출 onteardownaftertransaction() 트랜잭션이롤백된후호출 39 / 문서의제목
Spring Database Test Support Component CafeBaseTransactionalSpringContextTests public abstract class CafeBaseTransactionalSpringContextTests extends AbstractTransactionalSpringContextTests { private String[] getcommonconfiglocations() { return new String[] { ConfigLocations.TEST ; protected abstract String[] getmoduleconfiglocations(); @Override protected String[] getconfiglocations() { String[] commonconfigs = getcommonconfiglocations(); String[] moduleconfigs = getmoduleconfiglocations(); String[] configs = new String[commonConfigs.length + moduleconfigs.length]; for (int i = 0; i < commonconfigs.length; i++) { configs[i] = commonconfigs[i]; for (int i = 0; i < moduleconfigs.length; i++) { int j = commonconfigs.length + i; configs[j] = moduleconfigs[i]; return configs; 40 / 문서의제목
Spring Database Test Support Component CafeBaseTransactionalSpringContextTests @Override protected void onsetupbeforetransaction() throws Exception { ContextHolder.setAttribute( CafeConstants.CONTEXTHOLDER_MULTIPLEDBKEY, new MultipleDBKeyInfo(getMultipleDBKey(), true)); SqlMapPlugIn plugin = new SqlMapPlugIn(); plugin.init(null); /** * CLUBBBS 나 CAFEINFO db 를사용하는경우에는무조건이메소드를 override 해야한다. * @return */ protected Integer getmultipledbkey() { return null; 41 / 문서의제목
Spring Database Test Support Component Custom Test Case public class TemplateMovieDAOImplTest extends CafeBaseTransactionalSpringContextTests { private TemplateMovieDAO templatemoviedao; private Integer TEST_CLUBID = 10141287; @Override protected String[] getmoduleconfiglocations() { return new String[]{ConfigLocations.DAO_BOARD, ConfigLocations.TEST_CLUBBBS ; /META-INF/applicationContext-common-dao-board.xml /META-INF/applicationContext-common-test-clubbbs.xml protected Integer getmultipledbkey() { return TEST_CLUBID; public void settemplatemoviedao(templatemoviedao templatemoviedao) { this.templatemoviedao = templatemoviedao; public void testselect() { // DAO 를사용한테스트코드 //... 42 / 문서의제목
Spring Database Test Support Component Transaction Manager 설정 applicationcontext-common-test-clubbbs.xml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="transactionmanager" class="com.naver.cafe.common.transaction.cafetransactionmanager"> <property name="dbkey"> <bean id="com.naver.cafe.common.dao.dbkeygenerator.db_key_clubbbs" class="org.springframework.beans.factory.config.fieldretrievingfactorybean" /> </property> </bean> </beans> clubbbs conf/datasource/datasource-clubbbs.xml 43 / 문서의제목
DbUnit Component 데이터베이스 Component Testing 툴 테스트간에데이터베이스를알려진상태로유지하기위해사용테스트데이터를자동으로데이터베이스에입력테스트종료후테스트이전으로자동복귀 http://www.dbunit.org/ DbUnit Best Practices 개발자한명당하나의데이터베이스인스턴스사용테스트를정상적으로설정한경우클린업절차불필요하나의거대한데이터셋대신여러개의작은데이터셋사용전체테스트클래스나테스트스위트에대해현행화된데이터를사용할것 44 / 문서의제목
DbUnit Component 테스트라이프사이클 초기화 테스트데이터 데이터베이스 테스트코드 테스트코드 테스트코드 45 / 문서의제목
DbUnit Component 테스트라이프사이클 테스트데이터 데이터베이스 테스트코드 테스트코드 테스트코드 46 / 문서의제목
DbUnit Component 테스트라이프사이클 데이터변경 실행 테스트데이터 데이터베이스 테스트코드 테스트코드 테스트코드 47 / 문서의제목
DbUnit Component 테스트라이프사이클 데이터베이스 복구 테스트데이터 테스트코드 데이터베이스 테스트코드 테스트코드 48 / 문서의제목
DbUnit Component 테스트라이프사이클 초기화 테스트데이터 데이터베이스 테스트코드 테스트코드 테스트코드 49 / 문서의제목
DbUnit Component 테스트라이프사이클 테스트데이터 데이터베이스 테스트코드 테스트코드 테스트코드 50 / 문서의제목
DbUnit Component 테스트라이프사이클 데이터변경 테스트데이터 데이터베이스 테스트코드 테스트코드 테스트코드 51 / 문서의제목
DbUnit Component Cafe 프로젝트용 DbUnit 커스터마이징 bridge 프로젝트의 com.naver.cafe.unit 패키지다중 DB 지원카페 DB별테스트데이터초기화기능지원전체테이블이아닌결과 XML에명시된데이터만검증가능, 초기데이터 PK를사용하여테스트데이터제거 AbstractDependencyInjection SpringContextTests CafeTestCase MyTestCase 52 / 문서의제목
DbUnit Component 테스트데이터 <?xml version="1.0" encoding="utf-8"?> <dataset> <CLT_ARTICLE clubid="14446632" articleid="158" menuid="2" subject=" 제목 " content=" 테스트용게시물 " writerid="baejjae93" writernickname="baejjae93" writedt="2008-02-14" refarticleid="14446632" replylistorder=" readcount="0" commentcount="0" refarticlecount="0" lastcommentdate="[null]" type="[null]" openyn="y" replyyn="y" scrapyn="y" attachimageyn="[null]" attachfileyn="[null]" attachpollyn="[null]" attachmovie="0" scrapcount="0" scrapedyn="[null]" accesslevel="0" personacon="0" font="" leveragecode="39" searchopen="1" rclick="0" hastag="0" blockyn="0" modifydt="[null]" spamscore="0" gdid="99999999_99999999999999999999999" headid="[null] blockstatus="[null]" ccl="0" autosourcing="0" templatecode="[null]"/> <CFT_LEVERAGE_ARTICLE clubid="14446632" articleid="158" leveragecode="39" leveragepk="[null]" categoryname="[null]" srcurl="[null]" srcurlhtml="[null]" commentcount="[null]" status="l" modifydate="[null]" adddate="2008-02-14" userip="172.0.0.1"/> <CFT_LEVERAGE_THEME clubid="14446632" articleid="158" leveragecode="39" theme=" 내책 "/> </dataset> 53 / 문서의제목
DbUnit Component 결과데이터 <?xml version="1.0" encoding="utf-8"?> <dataset> <CFT_LEVERAGE_ARTICLE TEST_CASE_INDEX="1" clubid="14446632" articleid="158" leveragecode="39" leveragepk="120" categoryname="categoryresult" srcurl="http://dev.book.naver.com/bookdb/book_detail.php?bid=2925556" srcurlhtml="[null]" commentcount="[null]" status="o" userip="172.0.0.1"/> <CFT_LEVERAGE_ARTICLE TEST_CASE_INDEX="2" clubid="14446632" articleid="158" leveragecode="39 leveragepk="[null]" categoryname="" srcurlhtml="[null]" commentcount="[null]" status="l" userip="172.0.0.1"/> <CFT_LEVERAGE_ARTICLE TEST_CASE_INDEX="3" clubid="14446632" articleid="158" leveragecode="39 leveragepk="" categoryname="" srcurlhtml="[null]" commentcount="0" status="r" userip="172.0.0.1"/> <CFT_LEVERAGE_THEME clubid="14446632" articleid="158" leveragecode="39" theme=" 내책 "/> </dataset> 54 / 문서의제목
DbUnit Component Custom Test Case public class ApplyOperationIntegrationTest extends CafeTestCase { @Override protected String[] getcafeconfiglocations() { return new String [] { "/META-INF/applicationContext-bridge-bo.xml",... "/META-INF/applicationContext-bridge-leverage.xml" ; @Override protected Integer getclubid() { return 14446632; @Override protected void aftersetup() throws Exception { loaddataset(dbkeygenerator.db_key_club, "ApplyOperationIntegrationTest-club-setup.xml"); loaddataset(dbkeygenerator.db_key_clubbbs, "ApplyOperationIntegrationTest-clubbbs-setup.xml"); 어플리케이션컨텍스트로드 데이터베이스선택을위해오버라이딩 테스트데이터로드 55 / 문서의제목
DbUnit Component Custom Test Case public void testapplysuccessonnormalqueue() throws Exception { HttpClientInvokerStub httpclientinvokerstub = new HttpClientInvokerStub("1", FailureCause.NO_FAILURE.name(), "120", "http://dev.book.naver.com/bookdb/book_detail.php?bid=2925556", "categoryresult"); ((LeverageRequestSenderImpl)getBean("leverageRequestSenderTarget")).setHttpClientInvoker(httpClientInvokerStub); LeverageRequest leveragerequest = LeverageRequestBuilder.apply(getClubId(), Leveraged.before(getArticleId(), LeverageEnum.BOOK.getCode())); asserttrue(cafetoverticalproducerbo.senddirectly(leveragerequest)); verify(dbkeygenerator.db_key_clubbbs, "ApplyOperationIntegrationTest-clubbbs-result.xml", 1); 결과테스트데이터를사용하여 데이터베이스상태검증 56 / 문서의제목
HTTPUnit System 웹어플리케이션 System Testing Tool 웹어플리케이션용테스트스크립트구현 JUnit 기반프레임웍 http://httpunit.sourceforge.net/ 57 / 문서의제목
HTTPUnit System HTTPUnit Test Case public class CaclHttpTestCase { @Test public void calc() throws Exception { WebConversation conversation = new WebConversation(); WebRequest request = new GetMethodWebRequest( "http://127.0.0.1:8080/calc.action?added=10&addend=20"); WebResponse response = conversation.getresponse(request); assertequals(30, Integer.parseInt(response.getElementWithID("result").getText())); 58 / 문서의제목
HTTPUnit System HTTPUnit Test Case @Test public void calcusingform() throws Exception { WebConversation conversation = new WebConversation(); WebRequest request = new GetMethodWebRequest( "http://127.0.0.1:8080/calcview.action"); WebResponse response = conversation.getresponse(request); WebForm form = response.getformwithname("calc"); form.setparameter("addend", "100"); form.setparameter("added", "20"); response = form.submit(); assertequals(120, Integer.parseInt(response.getElementWithID("result").getText())); 59 / 문서의제목
JWebUnit System 웹어플리케이션 System Testing Tool 웹어플리케이션용테스트스크립트구현 HTTPUnit 기반 JUnit 기반프레임웍특징웹애플리케이션검색에쓰이는고급 API 제공링크를통한네비게이션폼엔트리와제출테이블내용 assertion 집합포함 http://httpunit.sourceforge.net/ 60 / 문서의제목
JWebUnit System JWebUnit Test Case public class CaclHttpTestCase { private WebTester webtester; @Before public void inittestcontext() { webtester = new WebTester(); webtester.gettestcontext().setbaseurl("http://127.0.0.1:8080/"); @Test public void calc() throws Exception { webtester.beginat("/calc.action?added=10&addend=20"); webtester.assertelementpresent("result"); webtester.asserttextinelement("result", "30"); 61 / 문서의제목
JWebUnit System JWebUnit Test Case @Test public void calcusingform() throws Exception { webtester.beginat("/calcview.action"); webtester.setworkingform("calc"); webtester.settextfield("addend", "100"); webtester.settextfield("added", "20"); webtester.submit(); webtester.assertelementpresent("result"); webtester.asserttextinelement("result", "120"); 62 / 문서의제목
Selenium Functional 웹어플리케이션을위한 Acceptance Testing 툴 테스트를 HTML 테이블로작성 http://selenium.openqa.org/ Selenium IDE FireFox 플러그인 Test Case Record & Replay 기능제공 Selenium-RC(Remote Control) 프로그래밍언어를사용하여 Acceptance Test 작성및실행가능 Server 브라우저를자동으로실행하고웹요청을처리하는 Proxy Client 프로그램작성을위한클라이언트라이브러리 63 / 문서의제목
Selenium Functional Selenium IDE 64 / 문서의제목
Selenium Functional Selenium IDE 65 / 문서의제목
Selenium Functional Selenium-RC 66 / 문서의제목
Selenium Functional Selenium-RC 와 JUnit 통합 Selenium IDE 의 Test Case Export 기능을사용하여생성 public class CalcAcceptTestCase extends SeleneseTestCase { public void setup() throws Exception { setup("http://localhost:8080/", "*iexplore"); public void testcalc() throws Exception { selenium.open("/calc.action?added=10&addend=20"); asserttrue(selenium.istextpresent("30")); assertequals("30", selenium.gettext("result")); public void testcalcview() throws Exception { selenium.open("/calcview.action"); selenium.type("added", "100"); selenium.type("addend", "20"); selenium.click("//input[@value=' 계산 ']"); assertequals("120", selenium.gettext("result")); 67 / 문서의제목
Thank you.
Question.