Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

Web画面で表示に時間がかかる場合の確認をWebDriverを使って行う

toshiです。

Selenium WebDriverで遊んでみよう、第三回目ぐらいかな。

今回のテーマは、
「Webの表示に時間がかかる場合(すぐには表示されない場合)に、
 どのように確認処理を行うか。」
です。

例えばボタンクリックして、
Ajaxでデータ取ってきて、
1,2秒後に結果が表示されるみたいなケース。

こんな場合に、Java的にはThread.sleep ?
ちょっと待っていればいいかと思うわけですが。。。

しかし、Seleniumのページを見てみると書いてありました。
表示を待つのにThread.sleepはあまり良くないと^^;

では、どうするか。

表示されるのを待つ例

Seleniumでは以下のように書くことができるみたいです。

★waitする処理の例

	WebElement addDynamicElement = (new WebDriverWait(driver, 7))
			.until(new ExpectedCondition<WebElement>() {
				@Override
				public WebElement apply(WebDriver d) {
					return d.findElement(By.id("add"));
				}
			});

実験用サンプル例

それでは、試してみます。
試すサンプルはテキトウに
以下のサーブレットJavascriptを用意しました。

★画面表示用のサーブレット(HelloWorld.java)

package com.example.tests;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {

		response.setContentType("text/html");

		StringBuilder text = new StringBuilder();
		text.append("<html>");
		text.append("<head>");
		text.append("<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">");
		text.append("<title>Hello World!</title>");
		text.append("<script type=\"text/javascript\" src=\"js/delay.js\"></script>");
		text.append("<script type=\"text/javascript\" src=\"js/prototype.js\"></script>");
		text.append("</head>");
		text.append("<body>");
		text.append("<h1>Hello World!</h1><div id=\"result\"></div>");
		text.append("</body>");
		text.append("</html>");

		PrintWriter out = response.getWriter();
		out.print(text.toString());
		
	}
}

★web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">  

  <display-name>Test Sample</display-name>
  <description>For Selenium</description>

  <servlet>
    <servlet-name>Hello</servlet-name>
    <servlet-class>com.example.tests.HelloWorld</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Hello</servlet-name>
      <url-pattern>/hello</url-pattern>
  </servlet-mapping>

</web-app>

★遅延処理(5秒後にid=addの要素を追加)させるJavascript(delay.js)

window.onload = function() {
	// 画面開いて、5秒後に処理。
	setTimeout( bar , 5000);
}

function bar(){

	// id=addの要素を追加。
	addObj = document.createElement("div");
	addObj.setAttribute("id", "add");
	addObj.innerHTML = "SampleText";
	$("result").appendChild(addObj);
	
}

WebDriverを動かす。

WebDriverを用いてどのように処理するのかを下に書いてみました。
JUnitで動かします。

package com.example.tests;

import static org.junit.Assert.*;

import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

public class DelayCaseTest {

	private WebDriver driver;
	// テストアドレス
	private String testUrl = "http://localhost:8080/WebTest/hello";
	// 表示される予定の文字列
	private String expected = "SampleText";
	
	private StringBuffer verificationErrors = new StringBuffer();
	
	@Before
	public void setUp() throws Exception {
		driver = new FirefoxDriver();
	}
	

	/**
	 * そもそも待たないケース
	 */
	@Test
	public void testMethod1() {

		driver.get(testUrl);

		WebElement addDynamicElement = driver.findElement(By.id("add"));

		String actual = addDynamicElement.getText();

		assertEquals(expected, actual);
	}

	/**
	 * 待つ条件を指定するケース
	 * (id=addが取得できるまで待っている)
	 */
	@Test
	public void testMethod2() {

		driver.get(testUrl);
		
		// 指定した状態に変わるまで待つ(タイムアウトを7秒と指定)
		WebElement addDynamicElement = (new WebDriverWait(driver, 7))
				.until(new ExpectedCondition<WebElement>() {
					@Override
					public WebElement apply(WebDriver d) {
						return d.findElement(By.id("add"));
					}
				});

		String actual = addDynamicElement.getText();

		assertEquals(expected, actual);
	}
	
	/**
	 * とりあえず最初に待っているケース
	 */
	@Test
	public void testMethod3() {
		
		// 画面表示を待つように指定(タイムアウトを10秒と指定)
		driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
		
		driver.get(testUrl);
		
		WebElement addDynamicElement = driver.findElement(By.id("add"));
		
		String actual = addDynamicElement.getText();

		assertEquals(expected, actual);
	}
	
	@After
	public void tearDown() throws Exception {
		driver.quit();
		String verificationErrorString = verificationErrors.toString();
		if (!"".equals(verificationErrorString)) {
			fail(verificationErrorString);
		}
	}
}

結果、実行してみると

testMethod1は全く待たないため、失敗になります。
testMethod2とtestMethod3は待っている処理が異なりますが
要素(id=add)が表示された後に処理をするため成功になりました。

というわけで想定したように動いたみたいです^^

では〜。