Whiteship's Note


[DBUnit] 테이블 데이터를 엑셀로 export

모하니?/Coding : 2009.10.16 12:48


테스트
    @Test
    public void exportXls() throws Exception {
        dbUnitSupport.exportXlsFrom("code", "item", "users", "role", "users_role");
        assertTrue(new File(DBUnitSupport.EXPORTED_XLS_FILE).exists());
    }

구현
    protected void exportXlsFrom(String... tableNames) throws Exception {
        IDataSet dataSet = getConnection().createDataSet(tableNames);
        XlsDataSet.write(dataSet, new FileOutputStream(new File(EXPORTED_XLS_FILE)));
    }

흠.. 간단하네요. 간단 간단..

그런데. 테스트 할 때 생기는 파일들은 수동으로 지우기도 귀찮고.. 버전관리에 들어가면 더더욱 안 될 듯하고..
JUnit을 4.7로 올리고, @Rule 이라는 걸 써봐야겠습니다.
top

Write a comment.


웹 통합 테스트 프레임워크 개발 중

모하니?/Coding : 2009.05.14 23:10


웹 통합 테스트를 지시 받고, 몇일 전 삽질부터 시작해서 오늘까지 조금 열심히 달렸습니다. 오늘은 오후 6시쯤 되니까 머리가 아파서 더 못 앉아 있겠더군요. 아침에 오자마자 만들기 시작해서 조금 하다 보면 오후 1, 2시가 금방 되고, 그러면 밥 먹고 나서 또 조금 하다 보면 4, 5시가 되고, 또 조금 하다 보면 7, 8시가 되니까 하루가 정말 짧더군요. @_@

아직도 많이 손봐야 하지만, 이제 조금 윤곽이 잡혔습니다.
@RunWith(WebTestRunner.class)
@WarConfiguration(appName="springsprout")
@DataConfiguration(dataType=DataType.XML, location="integration/sample/testData.xml")
public class IndexPageWebTest {

    @WebTest
    public void sample(){
        WebDriver driver = new HtmlUnitDriver();
        driver.navigate().to("http://localhost:8080/springsprout/index.do");
        assertTrue(driver.getTitle().equals("SpringSprout"));
    }

}

WebDriver를 이용한 초간단 웹 테스트 코드입니다. 이렇게 설정한 다음 테스트를 실행하면..
1. 현재 프로젝트를 WAR 패키징을 합니다.
2. 생성한 WAR를 테스트용 톰캣 서버에 springsprout 컨텍스트 패스로 배포합니다.(maven/tomcat6x/webapp/springsprout)
3. 배포가 잘 됐으면, 테스트 데이터를 넣어줍니다.
4. 이제 테스트를 실행합니다.
5. 테스트 데이터를 삭제합니다.
6. 앞서 배포한 WAR 파일을 undeploy 합니다.

여기서 4번에 해당하는 코드만 작성하면 됩니다. 나머지는 애노테이션만 붙여주면 되죠. 테스트 케이스 마다 서버를 켰다 껐다 하는 건 좀 무리고, WAR만 그때 그때 배포하도록 했습니다.

@RunWith(WebTestRunner.class)
@WarConfiguration(appName="springsprout")
@DataConfiguration(dataType=DataType.XML, location="integration/sample/testData.xml")
public class IndexPageWebTest {

    @WebTest
    public void test1(){
   
    }
   
    @WebTest
    public void test2(){
       
    }

}

이렇게 테스트를 하나 더 추가하면? WAR 배포 이후에 두 개의 테스트를 모두 실행한 다음에 WAR를 unploy합니다.

약간의 변화를 줄 수 있습니다. 테스트 데이터 입력이 필요 없다면, @DataConfiguration을 생략해도 됩니다. 그리고 테스트 서버 포트를 기본으로 8080을 사용하는데, 그 값을 @WarConfiguration의 port 속성에 줄 수 있습니다. 그럼 해당 포트에 배포를 시도하죠. 물론 그럴 때 해당 포트에 서버가 실행되고 있지 않다면, debug 모드의 로깅과 적절한 이름의 RuntimeException이 발생합니다.

꾸준히 가꿔야겠지만, 이제 내일 부터는 이녀석을 이용해서 본격적으로 웹 통합 CRUD 테스트를 만들고, CI를 해보려고 합니다.

얘 때문에 조금이라도 뒤적여 본 것들은 다음과 같습니다.
- JUnit 4.6
- Spring Test
- Cargo
- DBUnit
- WebDriver
- Maven Surefire Plugin
- Appfuse
- Maven Embedder

지난주 금, 월, 화, 수, 목.. 거의 일주일이네요.
개발이 참 더디고 어설프네요. ㅎㅎ 갈 길이 멀었습니다. @_@
top

  1. Favicon of http://mckdh.net BlogIcon 산골 2009.05.15 10:36 PERM. MOD/DEL REPLY

    옷..기선님 평소 웹화면 테스트 방법이 난해하여 항상 웹은 삽질 하곤하는데요..
    저 프레임워크 혹시 공개가능한건가요? 회사 꺼라 안될라나~... ^ ^;

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2009.05.15 11:42 신고 PERM MOD/DEL

    지금은 아직 공개할 만큼 다듬질 못했구요.
    쓸만해지는 즉시 공개할 생각입니다.

    아... 이미 공개되어 있는 상태나 다름없네요.
    기트허브에서 springsprout를 받아보세요.ㅋㅋ
    git://github.com/whiteship/springsprout.git

  2. Favicon of https://yangwansu.tistory.com BlogIcon 양완수 2009.05.28 12:17 신고 PERM. MOD/DEL REPLY

    사용자스토리가 없어서 인지 어지럽네요 ㅜㅜ

    Favicon of http://whiteship.me BlogIcon 기선 2009.05.28 13:52 PERM MOD/DEL

    넹 ㅎㅎ 사용자 스토리는
    http://whiteship.me/2237
    http://whiteship.me/2238
    http://whiteship.me/2239
    이 녀석들로 대체 할 수 있을지 모르겠습니다.

Write a comment.


DBUnit + Cargo + Webdriver를 이용한 웹 테스트 삽질 중

모하니?/Coding : 2009.05.08 19:15


하려던 것은 간단합니다.

1. DBUnit으로 테스트 데이터를 넣고,
2. Cargo로 톰캣6를 돌리고
3. Webdriver로 HTML, IE, Firefox에서 CRUD+S(검색) 테스트를 하는 겁니다.

이게 되면 PageObject 패턴을 도입해서 테스트를 만들어 볼까 했는데, 아직 이 늪을 못 벗어나고 있습니다.

일단, Webdriver를 이용한 단독 테스트는 성공적이었습니다. 물론 아직 PageObject 패턴을 도입하진 않았었죠. 이 녀석이 해주는 일은 화면에 있는 정보를 쉽게 참조할 수 있게 도와주는 API를 제공해 주는 것입니다. 따라서 화면 테스트를 보다 쉽게 작성할 수 있곘죠. 그밖에 동일한 URI를 파이어폭스, 인터넷익스플로러, HTML, 사파리 드라이버를 이용하여 참조할 수 있어서 다기종 브라우저를 지원하는 자동화 테스트를 작성할 때 매우 유용할 것으로 보입니다.

Cargo는 서버를 조작할 수 있는 API를 제공하며, 여러 종류의 서버를 설정하고, WAR 파일을 배포하는 작업등을 할 수 있습니다. 자세히는 모릅니다. 매우 다양한 서버를 지원하며, 웹 테스트를 자동화 할 때 필수 도구로 보입니다. 또한 다양한 모드로 서버를 실행할 수가 있습니다.

DBUnit은 많이들 아실 것으로 생각하고 생략하겠습니다.

저는 먼저 Webdriver부터 실습해봤습니다. 홈페이지로 시작하기 같은 문서를 찾아서 살펴봤습니다. 그리고 바로 테스트를 작성해 봤습니다.

        WebDriver driver = new HtmlUnitDriver();
        driver.get("http://localhost:8080/springsprout/index.do");
        WebElement element = driver.findElement(By.linkText("Login"));
        assertNotNull(element);
        assertEquals("/login.do", element.getAttribute("href"));

음.. 잘 동작하네! API를 익혀야겠군...@_@ 이제 PageObject 패턴을 어떻게 도입해야 하나~

고민할 새도 없이 다음은 Cargo를 시작했습니다.

        Deployable war = new WAR("target/springsprout.war");
        LocalConfiguration configuration = new Tomcat6xStandaloneLocalConfiguration("target/springsprout");
        configuration.addDeployable(war);
        container = new Tomcat6xInstalledLocalContainer(configuration);
        container.setHome("c:/apps/apache-tomcat-6.0.18");
        container.start();
...
        container.stop();

이런식으로 서버를 동작 시킬 수 있었습니다. 저 ... 안에 위에 작성한 웹 드라이버를 넣어보니 잘 동작했습니다. 문제는 이렇게 서버를 매번 올리고 내리는 작업을 테스트케이스마다 하면 굉장히 테스트가 오래 걸리고 비효율적이라는 겁니다. 따라서 이 작업은 반드시 Cargo 메이븐 플러긴을 이용해서 모든 테스트를 실행하기 전에 테스트 서버를 올렸다가 내리도록 해야겠습니다. 아직 해보진 않았습니다 @_@

일단 또 다시 고민할 새 없이 바로 DBUnit 까지 적용해 봤습니다.

    private void insertXMLData() throws IOException, DataSetException, DatabaseUnitException, SQLException {
        InputStream sourceStream = new ClassPathResource("testData.xml", getClass()).getInputStream();
        IDataSet dataset = new FlatXmlDataSet(sourceStream);
        DatabaseOperation operation = DatabaseOperation.CLEAN_INSERT;
        operation.execute(new DatabaseConnection(DataSourceUtils.getConnection(dataSource)), dataset);
    }

이런 메서드를 이용해서 testData.xml에 만들어 둔 테스트 데이터를 DB에 넣고 Cargo로 서버를 돌리고 Webdriver로 화면에 출력된 데이터를 검증하면 되리라 생각했습니다.

    @Test
    public void listMember() throws Exception {
        insertXMLData();
        assertEquals(2, memberRepository.getMemberList().size());

        Deployable war = new WAR("target/springsprout.war");
        LocalConfiguration configuration = new Tomcat6xStandaloneLocalConfiguration("target/springsprout");
        configuration.addDeployable(war);
        container = new Tomcat6xInstalledLocalContainer(configuration);
        container.setHome("c:/apps/apache-tomcat-6.0.18");
        container.start();

        WebDriver driver = new HtmlUnitDriver();
        driver.get("http://localhost:8080/springsprout/member/list.do");

        // logging
        System.out.println(driver.getTitle());
       assertEquals(2, memberRepository.getMemberList().size());
        System.out.println(driver.getPageSource());

        WebElement element = driver.findElement(By.linkText("keesun@whiteship.me"));
        assertNotNull(element);
        element.getAttribute("href");
        container.stop();
    }

이런 식으로 말이죠. 하지만 결과는 참담했습니다. 분명히 빨간색 줄은 테스트가 assertion이 됩니다. Cargo로 서버도 잘 동작합니다. 하지만 WebDriver로 접근해 봤을 때 DB에 넣었던 데이터가 화면에 나와야 하는데 나오지 않습니다. sysout으로 HTML을 찍어 봤지만, 정말로 데이터가 없었습니다.

1. WAR로 배포한 애플리케이션과 테스트 코드가 다른 DB를 사용한다.

이런... 그렇치..mvn package로 묶었을 때 그 안에 들어가는 건 src에 있는 설정 파일이지 test가 아니니깐, 지금 test할 때 사용하는 DB랑은 다른 걸 쓸꺼 아냐 ㅠ.ㅠ 이런 바로.. 그럼 일단 src랑 test랑 같은 DB를 사용하게 설정해보자.(원래 이럼 안되는 건데..)

2. 같은 DB를 사용하지만 여전히 동일한 상황.

@_@ 뭐지.. 왜 이럴까? DBUnit이 데이터를 넣고 확인하는 DB와 서버가 참조하는 DB가 완전히 별개 인 것처럼 보이는데, 트랜잭션이 아예 달라서 그런건가. @_@ 어찌해야 되나.. 아 괴룹네요. 괴로워..
top

Write a comment.


Why OSAF 1. 테스트 코드를 익힐 수 있습니다.

OSAF : 2008.11.10 22:04


OSAF를 공개한지 한 달이 아직 안 됐습니다. 10월 23일에 공개했었죠. 지금까지 약 200에 가까운 다운로드를 기록하고 있지만, 전혀... 아무런... 반응이 없다는 것에는 가히 놀라울 뿐입니다. 그냥 제가 쓴 글의 댓글 몇 개 정도 뿐의 관심이 저에게 한 편으로는 아쉬움으로 또 다른 한 편으로는 오기로 다가옵니다.

완전 최첨단 프레임워크인 OSAF에 왜 이렇게 관심이 없을까. 고민을 많이 했습니다. 어렵나? 메이븐 떄문인가? 그거 없어도 되는데. 문서가 부족하긴 부족하고. 그래도 어떻게 이렇게 조용할 수가 있지. 홈피 디자인이 좀 구리긴 한데.. 그거 때문인가? ㅋ. OSAF 발음이 너무 어려운가? 별에 별 생각을 많이 했습니다. 당연히 기운도 빠집니다. OSAF를 공개한 건 어쩌면 OSAF에게 못씁짓을 한 건 아닌지 말이죠.(Max님의 '어디가서 밥은 먹고 다녀야 할텐데..' 라는 댓글이 생각납니다.)

긍정적으로 생각하기로 했습니다. 언젠가는 빛을 보겠지. 열심히 계속 가꾸다 보면 언젠간 알아주겠지. 하고 말이죠. 그래서 OSAF가 여러분에게 어떤 도움을 줄 수 있을지 생각하고 알려드리기로 했습니다. 그 중 첫 번째가 바로 테스트 코드입니다.

OSAF의 테스트 커버리지는 60%가 조금 넘습니다. (앞으로 차차 올릴 예정입니다.) 60%의 테스트 커버리지는 전부 OSAF 개발팀에서 직접 작성한 테스트 코드입니다. 어딘가에서 배껴온 코드가 절대로 아닙니다. 테스트는 초기에 JUnit과 EasyMock을 사용해서 작성 했었습니다. 물론 스프링 테스트 기능도 사용하고 있죠. 배포 직전에는 EasyMock을 Mockito로 교체하여 비슷한 테스트를 보다 깔끔하고 직관적이며 적은 수의 코드로 대체할 수 있었습니다. DBUnit을 확장하여 OSAF가 제공하는 테스트 케이스를 이용하면 DAO 테스트가 매우 간편해질 것 입니다.

이렇게 좋은데... 한 번 들여다 보고 뭐라고 해주시지 않으시겠어요? 좋다. 잘했다. 고맙다. 이런거 말구요. 이 부분의 테스트는 이해가 안 된다. 테스트가 조금 이상하다. 이 부분의 테스트는 왜 안했냐. 어려워서 그런거냐? 이 부분의 테스트는 이렇게 고치는게 좋치 않겠냐? 이런.. 반응이 제가 가장 좋아하는 반응이자 OSAF에게 거름을 주는 방법입니다.

소스 코드는 굳이 다운 받지 않아도(장기적으론 받아 두시면 좋겠지만..)

http://www.opensprout.org:9060/browse/OSAF/osaf/trunk

위 링크로 가시면 웹에서 직접 볼 수 있습니다. 소스 코드나 OSAF 와 관련하여 문제나 제안하고 싶은 것이 있다면 주저하지 마시고 이슈를 등록해 주세요.

http://www.opensprout.org/jira/secure/Dashboard.jspa


top

  1. Favicon of https://helols.tistory.com BlogIcon is윤군 2008.11.11 02:35 신고 PERM. MOD/DEL REPLY

    하핫; 제가 이런말 하긴 좀 그런데;; OSAF(쉬운놈은 아니죠;;)를 매일 보고 있는 한 人 으로써;;
    샘플을 보고 이것 저것 구현 해보기 ;; 힘들었습니다.
    뭐 워낙허접해서 (제 눈높이를 맞추어서 이야기 하는거니^^:;) 좀 힘든것도 있었지만..
    Reference라도 있으면 한번 보면 좋겠는데;; 그것도 만만한 작업도 아니니;;
    흠냥; 차츰.. 좋아 질듯;
    어느날 문득 저의 지인이 OSAF라고 들어 봤냐고;; 물어보더라구요..(신기했음=.=;;)
    여기 블로그에 오는 분들이 많으니;; 앞으로 무럭무럭 자랄거에요^^;
    전 Spring이 나온지 몇년이 지나고서야 제대로 공부를 하고 있는걸요;;
    3기 스터디는 .. OSAF에 대해서 한번;; 도전을?

    Favicon of http://whiteship.me BlogIcon 기선 2008.11.11 08:46 PERM MOD/DEL

    새벽 세 시가 다 돼가는데 안 주무시고;;; ㄷㄷㄷ
    레퍼런스도 만들어야겠네요. 스터디는 글쎄요. 뭘 공부하면 OSAF를 더 좋게 가꿀 수 있을지 생각 중입니다. OSGi랑 스프링 DM도 재밌지 않겠어요?

  2. Favicon of http://okjsp.tistory.com BlogIcon kenu 2008.11.11 08:35 PERM. MOD/DEL REPLY

    오픈 소스들 보면 Getting Started, Tutorial, API Spec 각각 존재하는 것처럼 OSAF도 마찬가지일 겁니다.
    자 다 차려놨으니 모이세요 라고 가서 보면 봉지도 뜯지 않은 생라면만 있는 경우처럼 될 수도 있으니까요.
    사용자들은 끓인 라면에, 젓가락에 김치까지 원하고 있으니까요.
    줘도 못 먹는다고 탓해도 소용이 없죠.
    화이팅입니다.

    Favicon of http://whiteship.me BlogIcon 기선 2008.11.11 08:49 PERM MOD/DEL

    네. 불평할 시간에 좀 더 가꾸고 알려서 OSAF를 한 수저 뜰 수 있게 해야겠습니다.

    응원 감사합니다. :)

Write a comment.


8.1. DbUnit 사용하기



1. 먼저 DB에 입력할 dataset을 xml 형태로 작성 합니다.

이 때 주의 하실 점은 Entity와 Attribute의 이름들은 Object의 식별자를 사용하는 것이 아니라 Relation에서 사용되는 이름으로 사용해야 합니다.


2. 입력한 샘플 데이타를 테스트할 메소드를 만들고 DbUnit을 사용하여 DB에 넣습니다.

public void testWithSampleData() throws Exception{

     insertFlatXmlDataSet("test/src/keesun/kSampleData.xml");

}


이상태에서 test를 돌려보고 DbUnit이 동작하는데 이상은 없는지 확인합니다. 만약 위에서 작성한 xml에 매칭되는 컬럼을 못찾을 경우 에러가 발생합니다.

3. 입력한 샘플을 기반으로 간단한 쿼리를 날려서 결과를 확인해 봅니다.

public void testWithSampleData() throws Exception{

      insertFlatXmlDataSet("test/src/keesun/kSampleData.xml");

 

      assertEquals(3, kMemberDao.getAll().size());

      assertEquals(2, kGroupDao.getAll().size());

      assertEquals(4, kMemberGroupDao.getAll().size());

      assertEquals(4, kMessengerDao.getAll().size());

}


테스트는 통과 합니다~ :)
좀더 복잡한 쿼리를 날리기 위해서는 HQL과 Criteria를 공부해야 합니다. 하지만 그다지 어렵지 않다는거~

사용자 삽입 이미지
top

Write a comment.


DbUnit

Hibernate/study : 2007.01.23 17:32


참조 : http://www.dbunit.org/index.html

Test 할 때 사용할 DB에 있는 값을 XML로 뽑아 내거나 XML에 입력한 데이타를 DB로 넣을 수 있는 오픈소스입니다. JUnit이랑 이름이 비슷한데 JUnit을 확장시킨 거라고 하네요.

사용하는 방법은 여기에 나와있지만 잘 모르겠습니다.
대강 본 바로는 xml에 각 테이블에 들어갈 데이타 들을 입력하고
FlatXmlDataSet 클래스를 이용해서 xml을 을 읽어들이고(ex. IDataSet)
읽어 들인 값을 집어 넣을 DB 커넥션을 설정(ex. IDatabaseConnection)해주면 DB에 들어가는 것 같습니다.
그리고 Assertion 이라는 클래스가 만들어져 있어서 ITable이나 IDataSet 끼리 assertEqulas 메소드를 사용해서 비교할 수 있습니다.

물개 선생님의 코드중 일부를 보시면 다음과 같습니다.  

public void testSampleData() throws Exception {

      insertFlatXmlDataSet("test/src/seal/sampleData.xml");

      assertEquals(3, memberDao.getAll().size());

      memberDao.getMembers("seal").get(0).getEmail());

      assertEquals(2, memberDao.getMembers("s").size());

}


맨 위에 첫줄로 xml에 입력 해 둔 데이타를 DB에 저장하고 그 뒤로는 DB에 들어간 값들을 가지고 테스트를 할 수 있습니다.

음~ 모든 필드들을 다 채워 넣은 다음에 다음과 같은 것들을 테스트 해보고 싶습니다.

  • Agile Java 그룹에 속한 멤버들 중에 이메일에 k가 들어가는 멤버 확인(Group->MemberGroup->Member)
  • keesun이라는 멤버가 속한 그룹의 이름 확인.(Member->MemberGroup->Group)
  • keesun이라는 멤버가 가진 이메일 주소 확인.(Member->Messenger)
  • Messenger 중에 MSN을 사용하지 않는 멤버들의 email.(Messenger->Member)

이렇게 해보면 연관관계가 제대로 되어 있는지 확인 할 수 있을 것 같습니다.

'Hibernate > study' 카테고리의 다른 글

Criteria에서 Join하기  (0) 2007.01.29
숙제 2  (0) 2007.01.26
HibernateTemplate  (0) 2007.01.26
HQL과 @Entity에 있는 name 속성의 관계  (0) 2007.01.24
Fluent Interface  (2) 2007.01.24
DbUnit  (2) 2007.01.23
Hibernate에서 쿼리 날리는 방법  (0) 2007.01.19
객체들의 상태 변화(in Hibernate)  (2) 2007.01.19
숙제  (0) 2007.01.19
Transaction  (2) 2007.01.02
JUnit 으로 Hibernate 테스트  (0) 2007.01.01
top

  1. Favicon of http://blog.naver.com/paradozz BlogIcon 오승택 2007.01.24 00:43 PERM. MOD/DEL REPLY

    대부분의 파서에서 내부적으로 Reflection과 Introspect 기법을 쓰는것 같습니다.
    아시겠지만서도 쿨럭.
    저런 문자하나하나를 긁어와서 동적으로 하나하나 실행하고 언로드 시키는 기법이라고 불리웁니다.
    하지만 DBUnit은 그냥 문자열에 대해 쿼리를 만드는점이 매력인것 같습니다.

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2007.01.24 01:06 신고 PERM MOD/DEL

    reflection은 쬐끔 봤었는데요. Introspect라는 단어는 처음 봐요.

    Digester도 그렇고 DBUnit도 그렇고 유용한 오픈소스들이 많다는 것을 새삼 느끼게 됐습니다. :)

Write a comment.