Integration Testing

Integration testing is often painful. That’s why we’re trying to mimimize the need for integration tests by making the view logic completely unit testable. Still you also need to make sure that your data-bind attributes are correct, or that you dind’t introduce any bugs when changing the view. That’s why we’ve created selenium-webdriver. It allows you to test your application using the Selenium API.

In order to allow that, we created a Selenium Webdriver that works with DukeScripts BrwsrCtx, so you can easily run and debug your tests, without caring ( a lot ) about threading. Let’s start by writing a test for the DukeScript Demo Application.

Prerequisites

  1. The selenium-webdriver isn’t officially released yet, so you need to clone it on github and build it:

https://github.com/dukescript/selenium-webdriver

  1. Use the DukeScript Wizard in NetBeans to create a new DukeScript Project named “IntegrationTest”, and make sure you include the sample code on the last wizard page.

  2. In Project “IntegrationTest General Client Code” open the pom.xml and add this to register a System.property. This will help us later locating the index.html :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.18</version>
    <configuration>
        <systemPropertyVariables>
            <browser.rootdir>${basedir}/src/main/webapp/</browser.rootdir>
        </systemPropertyVariables>
    </configuration>
</plugin>

Implementing the Test

  1. Open the project “IntegrationTest General Client Code”

  2. Create a “New File” -> “Unit Tests” -> “JUnit Test”.

  3. Name it “IntegrationTest” and check “Create Class Initializer” and “Create Class Finalizer”. Deselect the other options and click “Finish”.

  4. The file opens in the editor. Now we need to set up the application window:

private static WebDriverFX driver;
private static Data testModel;

@BeforeClass
public static void init() throws InterruptedException, Exception {
    driver = new WebDriverFX(findURL("pages/index.html"));
    driver.executeAndWait(new Runnable() {
        @Override
        public void run() {
            testModel = new Data("Hello World from DukeScript !", true);
            testModel.applyBindings();
        }
    });
}

private static URL findURL(String resource) {
    String baseURL = System.getProperty("browser.rootdir"); // NOI18N
    System.out.println("browser.rootdir=" + baseURL);
    if (baseURL != null) {
        try {
            URL u = new File(baseURL, resource).toURI().toURL();
            return u;
        } catch (MalformedURLException ex) {
            Logger.getLogger(IntegrationTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    return null;
}

The method findURL simply helps you locating the index.html. It uses the System property we registered via the Maven surefire plugin. Our init method will be executed first. It starts the webdriver, loads index.html, creates our viewmodel and binds it to the page.

  1. We’ll also make sure the driver is closed in the end:
@AfterClass
public static void close(){
    driver.close();
}
  1. Now we can write our test. You can find elements via their id, css, or xpath expressions. To simulate user input, you can either manipulate the model directly, or simulate clicks and typing. The API is pretty self explaning:
    @Test
    public void testWithModel() {
        List<WebElement> findElements = driver.findElements(By.cssSelector(".rotate"));
        Assert.assertEquals(6, findElements.size());
        WebElement get = findElements.get(1);
        Assert.assertEquals("World", get.getText());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
            Logger.getLogger(IntegrationTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        testModel.setRotating(false);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
            Logger.getLogger(IntegrationTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        List<WebElement> findElements2 = driver.findElements(By.cssSelector(".rotate"));
        Assert.assertEquals(0, findElements2.size());
        WebElement input = driver.findElement(By.tagName("input"));
        input.clear();
        input.sendKeys("Hello DukeScript, this is fantastic");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
            Logger.getLogger(IntegrationTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        List<WebElement> byXPath = driver.findElements(By.xpath("/html/body/div/span/span"));
        Assert.assertEquals(6, byXPath.size());
    }

I’ve added some Thread.sleeps, so you can actually see what happens in the UI. Now right-click your test class and choose “Test File” or “Debug Test File” from the context menu and enjoy the show :-).