Arquillian-Showcase その3 ui

棚卸し19日目。arquillian-showcaseのuiプロジェクトは、Selenium*1Selenium WebDriverArquillian Graphene*2を使ったUIテストのサンプル。
アプリケーションとしてはとてもシンプルな、ログイン処理を行うJSFの画面があるだけ。

Seleniumなどを使う場合、以下の手順を踏むことになる。また、URLも環境に応じて注意する必要がある。

  1. アプリケーションサーバー起動
  2. アプリケーションをデプロイ
  3. テスト実施
  4. アプリケーションをアンデプロイ
  5. アプリケーションサーバーを停止

Arquillianを使う利点は、テスト実施だけに集中できること。テストコードを見てみる。
LoginScreenWebDriverTestCase.java

@RunWith(Arquillian.class)
public class LoginScreenWebDriverTestCase {
    
    @Deployment(testable = false)
    public static WebArchive createDeployment() {
        return Deployments.createLoginScreenDeployment();
    }
    
    private static final String USERNAME = "demo";
    private static final String PASSWORD = "demo";

    private static final By LOGGED_IN = By.xpath("//li[contains(text(),'Welcome')]");
    private static final By LOGGED_OUT = By.xpath("//li[contains(text(),'Goodbye')]");

    private static final By USERNAME_FIELD = By.id("loginForm:username");
    private static final By PASSWORD_FIELD = By.id("loginForm:password");

    private static final By LOGIN_BUTTON = By.id("loginForm:login");
    private static final By LOGOUT_BUTTON = By.id("loginForm:logout");

    @ArquillianResource
    URL deploymentUrl;
    
    @Drone
    WebDriver driver;

    @Test
    public void testLoginAndLogout() {
        Assert.assertNotNull("Deployment URL should not be null", deploymentUrl);

        driver.get(deploymentUrl + "home.jsf");

        driver.findElement(USERNAME_FIELD).sendKeys(USERNAME);
        driver.findElement(PASSWORD_FIELD).sendKeys(PASSWORD);
        driver.findElement(LOGIN_BUTTON).click();
        checkElementPresent(driver, LOGGED_IN, "User should be logged in!");

        driver.findElement(LOGOUT_BUTTON).click();
        checkElementPresent(driver, LOGGED_OUT, "User should not be logged in!");
    }

    // check is element is present on page, fail otherwise
    private void checkElementPresent(WebDriver driver, By by, String errorMsg) {
        try {
            Assert.assertTrue(errorMsg, driver.findElement(by) != null);
        } catch (NoSuchElementException e) {
            Assert.fail(errorMsg);
        }
    }
}

@RunWith(Arquillian.class)はいつも通り、JUnitのテストランナーからArquillianに移譲するためのアノテーション
@Deployment(testable = false)はテストアーカイブをデプロイするためのアノテーションだが、testable=false はこのテストケースはサーバーサイドではテストしないことを示している。
@ArquillianResource URL deploymentUrl は、実行時にサーバー、ポート、コンテキストパスまでのURLがインジェクトされる。
最後に@Drone WebDriver driver でWebDriverがインジェクトされる。Droneというのは、ArquillianのExtensionの一つで、SeleniumをArquillianから利用するためのプロジェクト。
@Testメソッドのついたテストコード内はごく普通のWebDriverを利用したテストコード。
また利用するブラウザの種類など、一部の設定はarquillian.xmlに設定してある。これらが設定された状態でdriverはインジェクトされる。

arquillian.xml

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
    <defaultProtocol type="Servlet 3.0" />
    <container qualifier="jbossas-remote-7" default="true">
        <configuration>
            <property name="jbossHome">target/jboss-as-${jboss.version:7.1.1.Final}</property>
        </configuration>
    </container>
    <extension qualifier="ajocado">
        <property name="seleniumMaximize">true</property>        
    </extension>
    <extension qualifier="selenium-server">
        <property name="enable">true</property>
    </extension>   
    <extension qualifier="selenium">
        <property name="browser">*firefox</property>
    </extension>
</arquillian>

最初に書いたようにテストケースとしては、DefaultSelenium、Selenium WebDriver、Graphene ( Ajocado )があって、uiディレクトリ以下で mvn test を実行すると、それぞれのテストドライバーを利用してFirefoxが起動し、テストが実行される。

*1:旧来のSelenium RCを利用したテスト

*2:テストケースでAjocadoとあるもの。名前がGrapheneに変わった