Whiteship's Note


WebTUnit 1.0 M1 배포합니다.

모하니?/Coding : 2009.05.19 21:43


아래 매뉴얼을 참조하세요.
영어로 작성했는데, 너그러이 봐주세요.

이번 주 내로 배포하고 싶은.. M2 버전에서는 다음 두 가지를 중점접으로 다루겠습니다.
- 샘플 애플리케이션을 추가
- Jetty 추가

저저번주 금요일부터 오늘까지 달렸으니까..
금,  월~금, 월, 화. 8일이네요.
이제 쬐끔 쓸만해져서 공개했습니다.

웹 테스트 하실 때 조금이나마 보탬이 되었음 합니다.
막심 므라비차의 축하공연을 들으며 찬찬히 읽어 보세요. 간단합니다.



0. add repository setting to pom.xml or settings.xml

        <repository>
            <id>opensprout nexus</id>
            <name>OpenSprout Nexus public</name>
            <url>http://www.opensprout.org/nexus/content/groups/public</url>
        </repository>

        WebTUnit is provided by OpenSprout Nexus.

1. add dependency to pom.xml

        <!-- WebTUnit -->
        <dependency>
            <groupId>org.opensprout</groupId>
            <artifactId>webtunit</artifactId>
            <version>1.0-M1</version>
        </dependency>

2. add cargo-maven-plugin and maven-surefire-plugin to pom.xml

    2-1. cargo-maven-plugin configuraion

        <build>
        ...
            <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven2-plugin</artifactId>
                <version>1.0.1-SNAPSHOT</version>
                <configuration>
                    <wait>false</wait>
                    <container>
                        <containerId>tomcat6x</containerId>
                        <type>installed</type>
                        <home>tomcat/apache-tomcat-6.0.18</home>
                    </container>
                    <deployer>
                        <type>installed</type>
                    </deployer>
                    <configuration>
                        <properties>
                            <cargo.servlet.port>8080</cargo.servlet.port>
                        </properties>
                    </configuration>
                </configuration>
                <executions>
                    <execution>
                        <id>start-container</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>stop-container</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        First, you must set up your tomcat home to <home> element above or,
        just download and unzip tomcat archive to project/tomcat folder.

        If you set <wait> to true, then when you run a test server by 'mvn cargo:start',
        the console will be wait untile you stop the process by CTRL + C.
        This is useful when you want to test on Eclipse by CTRL + ALT + X -> T or CTRL + F11.
        But, you shold be careful when you use phase that through pre-integration-test phase.
        That process will stop and wait in pre-integration-test until you stop the test server.

        By default setting, you can use cargo with phases thar through pre-integration-test phase.
        For example, when you run 'mvn verify', you will pass pre-integration-test phase,
        but you will not be stopped by process, because it dooesn't wait.
        This will help you when you set up this project in continuous integration environment.

    2-2. maven-surefire-plugin configuration

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>**/*WebTest.java</exclude>
                    </excludes>
                </configuration>
                <executions>
                    <execution>
                        <id>integration-test</id>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <phase>integration-test</phase>
                        <configuration>
                            <excludes>
                                <exclude>none</exclude>
                            </excludes>
                            <includes>
                                <include>**/*WebTest.java</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        ...
        </build>

        If you want to use another naming pattern, or package pattern,
        change '**/*WebTest.java' value to what you want.

3. make some web test with webdriver.

    @RunWith(WebTestRunner.class)
    @WarConfiguration("opensprout")
    public class MemberWebTest {

        @WebTest
        public void memberPages(){
            WebDriver driver = new HtmlUnitDriver();
            driver.get("http://localhost:8090/springsprout/member/list.do");
            MemberListPage listPage = PageFactory.initElements(driver, MemberListPage.class);
            assertEquals(2, listPage.getTableRows());
        }
    }

    If you want to feel comfortable when you write some web test codes,
    I recommend Page Object Pattern(http://code.google.com/p/webdriver/wiki/PageObjects).
   
    You can also use @DataConfiguration when you want to input and delete some test data.
    Check some usecases.
    - http://whiteship.me/2237
    - http://whiteship.me/2238
    - http://whiteship.me/2239

4. run test.

    Open a console, type 'mvn verify'.
    Or, modify, cargo-maven-plugin's <wait> to true, and run it with JUnit in Eclipse.
   
5. give me a feedback

    http://github.com/whiteship/WebTUnit/issues
   

top


WebTUnit에 CoC 적용 결과

모하니?/Coding : 2009.05.19 15:39


한 가지를 더 수정해서 이제는 WarConfiguration 설정이 더 간편해졌다. 8080 포트를 사용하여 웹 테스트를 할 때는 appName이라는 속성을 명시하지 않고 그냥 애플리케이션 이름만 명시하면 된다.

@RunWith(WebTestRunner.class)
@WarConfiguration("springsprout")
@DataConfiguration
public class MemberWebTest {

    @WebTest
    public void memberPages(){
       ...
    }
}

이제 한 가지만 더 정리하면 1.0-M1 버전을 공개할 수 있을 듯 하다. 캬캬캬

--------------------------------
@RunWith(WebTestRunner.class)
@WarConfiguration(appName="springsprout")
@DataConfiguration(dataType=DataType.XML, location="org/springsprout/testData.xml")
public class MemberWebTest {

    @WebTest
    public void memberPages(){
       ...
    }

설정하는 방법을 위와 같은 형태에서 아래와 같이 변경됐습니다.

@RunWith(WebTestRunner.class)
@WarConfiguration(appName="springsprout")
@DataConfiguration
public class MemberWebTest {

    @WebTest
    public void memberPages(){
          ...
    }
}

이 것이 전부입니다.

먼저, 바뀐 내용 중 하나는 파일 확장자를 통해 데이터 타입을 짐작한다는 것입니다. CoC라기 보다는 아예 바뀐 내용입니다.

1. 적용한 CoC는 우선, 기본 테스트 데이터 파일 이름을 testData.xml로 생각하며, 테스트하려는 클래스와 동일한 패키지에 들어있다고 가정합니다.

2. 하지만, /를 사용하여 파일 이름을 명시 했을 때에는 해당 패키지 경로에서 테스트 파일을 찾게 합니다.

@RunWith(WebTestRunner.class)
@WarConfiguration(appName="springsprout")
@DataConfiguration(fileName="integration/member/testData.xml")
public class MemberWebTest {

    @WebTest
    public void memberPages(){
          ...
    }
}

이런식으로 말이죠.
top


Page Object 패턴을 이용한 웹 CRUD 테스트 with WebTUint

모하니?/Coding : 2009.05.18 20:32


참조
http://code.google.com/p/webdriver/wiki/PageObjects
http://code.google.com/p/webdriver/wiki/PageFactory

화면의 페이지를 나타내는 Page 객체들을 작성합니다. 화면에서 테스트할 주요 엘리먼트들은 WebElement로 표현하고, 각각의 엘리먼트를 애노테이션으로 찾을 수 있게 id나 name 또는 xpath를 사용하여 지정해 줍니다.
public class MemberForm {

    protected WebElement name;

    protected WebElement email;

    protected WebElement password;

    @FindBy(how = How.ID, using = "name.errors")
    protected WebElement nameError;

    @FindBy(how = How.ID, using = "email.errors")
    protected WebElement emailError;

    @FindBy(how = How.ID, using = "password.errors")
    protected WebElement passwordError;

    @FindBy(how = How.XPATH, using = "//input[@type='submit']")
    protected WebElement submit;

    public WebElement getName() {
        return name;
    }

...

}

원랜 Page 클래스에 있어야 할 속성들인데, 다른 Page에서도 공통으로 사용하는 속성들이라 상위 클래스로 빼냈습니다. 애노테이션을 붙이지 않으면, 자동은 화면에서 클래스의 변수명에 해당하는 id를 가진 엘리먼트를 찾아줍니다.
 
그 다음으로, 페이지에서 일어나는 사용자 액션을 메서드로 표현합니다.

public class MemberAddPage extends MemberForm {

    private WebDriver driver;

    public MemberAddPage(WebDriver driver) {
        this.driver = driver;
    }

    public MemberAddPage addFail() {
        name.sendKeys("keesun");
        submit.submit();
        return PageFactory.initElements(driver, MemberAddPage.class);
    }

    public MemberListPage addSuccess() {
        password.sendKeys("123");
        email.sendKeys("keesun@whiteship.me");
        submit.submit();
        return PageFactory.initElements(driver, MemberListPage.class);
    }

}

이것을 이용하여 다음과 같은 테스트를 작성할 수 있습니다.

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

    @WebTest
    public void memberPages(){
        WebDriver driver = new HtmlUnitDriver();
        driver.get("http://localhost:8080/springsprout/member/list.do");
        MemberListPage listPage = PageFactory.initElements(driver, MemberListPage.class);
        assertEquals(2, listPage.getTableRows());

        MemberAddPage addPage = listPage.toAddForm();
        assertNotNull(addPage);

        MemberAddPage failedAddPage = addPage.addFail();
        assertNotNull(failedAddPage);
        assertEquals("required", failedAddPage.getEmailError().getText());
        assertEquals("required", failedAddPage.getPasswordError().getText());

        listPage = failedAddPage.addSuccess();
        assertNotNull(listPage);
        assertEquals(3, listPage.getTableRows());

...

}

물론, WebTUnit이 없다면, 수동으로 서버를 켜고, 데이터 넣고, 저 테스트를 실행하고, 다시 테스트 데이터를 정리하고, 서버를 내리는 작업을 반복해야겠지만.. WebTUnit이 있기 때문에 메이븐 콘솔에서 mvn verify를 실행하기만 하면 위의 작업들을 자동화 할 수 있습니다. 조금더 빠르고 이클립스에서 실행해 보고 싶다면, pom.xml을 약간 수정하여 cargo.wait 속성을 true로 바꾸고 mvn cargo:start로 서버를 실행한 다음, 이클립스에서 JUnit 테스트로 실행하면 됩니다.
top


WebTUnit 사용 시나리오 3. 테스트 데이터가 필요 없는 경우

모하니?/Coding : 2009.05.15 14:05


제일 간단한 경우 입니다. 테스트 데이터가 필요 없기 때문에 @WarConfiguration만 사용하면 됩니다.

@RunWith(WebTestRunner.class)
@WarConfiguration(appName="springsprout")
public class SampleWebTest {

    @WebTest
    public void sinario1(){
        System.out.println("test1");
    }

    @WebTest
    public void sinario2(){
        System.out.println("test2");
    }

}

이렇게만 하면,

1. WAR 패키징
2. WAR 배포
3. 테스트~
4. WAR un배포

과정을 거치게 됩니다~ 이건 뭐 너무 간단해서 더 설명할 것도 없네요~


이제부터 본격적인 테스트는 WebDriver나 Selenium을 이용해서 작성하면 되겠죠. ㄱㄱㅆ~
top