Ajaxのテスト Selenium
7.Ajaxのテスト
Ajaxで動作するプログラムは、いままでの方法ではテストできません。サーバ側だけでプロセスが完了せずブラウザ側にあるJavaScriptと連動して動作しているからです。では、どのような方法でテストしたらよいでしょうか。簡単なプログラムを作成し、その方法を学びましょう。
7-1.プロジェクトの複写
プロジェクトAppli002を新しいプロジェクトTest004へコピーします。
(1) Appli002上で右クリックしてコピーを選択する
(2) プロジェクト名(N)を新しいプロジェクトTest004にする
(3) データベースの再作成
テストの場合はProject_testの環境で実施されるため、Project_developmentだけでは動作しません。
ここではProject_developmentを一旦ドロップし、再度DB環境をクリエイトしましょう。
・Netbeansで[Rakeタスクを実行/デバック..]を選択
フィルタ(F):
パラメータ(P):
一致するタスク(M): db:drop
・Netbeansで[Rakeタスクを実行/デバック..]を選択
フィルタ(F):
パラメータ(P):
一致するタスク(M): db:create:all
7-2.Ajaxを利用するための修正
(1) レイアウトファイルの作成
Ajaxを利用するため、基本的なレイアウトファイルを作成します。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Test004: <%= controller.action_name %></title>
<%= javascript_include_tag :defaults %>
</head>
<body><%= yield %></body>
</html>
(2) ビューの修正
(3) コントローラの修正
class TriangleController < ApplicationController
def index
enddef calculate
@triangle = Triangle.new(params[:triangle])
if @triangle.valid?
x=@triangle.a.to_f
y=@triangle.b.to_f
z=@triangle.c.to_f
fg="ON"
fg="off" if x+y<=z
fg="off" if x+z<=y
fg="off" if y+z<=xif fg=="ON" then
s=(x+y+z)/2
area=Math.sqrt(s*(s-x)*(s-y)*(s-z))
@result = "辺の長さ #{x}, #{y}, #{z} の三角形の面積は#{area}"
else
@result = "辺の長さ #{x}, #{y}, #{z} では三角形はできない"
end
render :partial => "results" # 結果はパーシャルで返す
else
render :partial => "error_messages"
end
endend
(4) 結果の対応
<%= "#{@result}" %>
<%= error_messages_for :triangle %>
7-3.テストパターンの作成
(1) NGのテスト(その1)
三角形が成り立たない場合のテストを考えましょう。三辺が1,2,3では成り立たないので、これをテストケースにします。
Ajaxを使用してメソッドを呼ぶときはxhrという命令を使って呼びます。まずは正常に戻ってくるか確認しましょう。
require 'test_helper'class TriangleControllerTest < ActionController::TestCase
test "NG data" do
xhr :post, :calculate, :triangle=>{:a=>"1", :b=>"2", :C=>"3"}
assert_response :success
end
end
・NetBeansで[テスト]を選択し実行します。
(2) NGのテスト(その2)
次にテンプレートが正しく利用されたか確認しましょう。
require 'test_helper'class TriangleControllerTest < ActionController::TestCase
test "NG data" do
xhr :post, :calculate, :triangle=>{:a=>"1", :b=>"2", :C=>"3"}
assert_response :success
assert_template "_results"
end
end
・NetBeansで[テスト]を選択し実行します。
renderingはindex.htmlになっています。これはパーシャルhtmlである_results.htmlはAjaxによってindex.htmlに取り込まれ、それがレスポンスとなるからです。
(3) NGのテスト(その3)
確認するテンプレートをindex.htmlに変更します。
require 'test_helper'class TriangleControllerTest < ActionController::TestCase
test "NG data" do
xhr :post, :calculate, :triangle=>{:a=>"1", :b=>"2", :C=>"3"}
assert_response :success
assert_template "index"
end
end
・NetBeansで[テスト]を選択し実行します。
(4) NGのテスト(その4)
最後に内容を検証しましょう。ここでは“面積は”という字句がないことを確認します。
class TriangleControllerTest < ActionController::TestCase
test "NG data" do
xhr :post, :calculate, :triangle=>{:a=>"1", :b=>"2", :C=>"3"}
assert_response :success
assert_template "index"
assert_nil assigns(:result).index("面積は")
end
end
・NetBeansで[テスト]を選択し実行します。
assigns(:result)がnilオブシェクトとなっています。_resultarea.html からindex.htmlへ状態が遷移してしまったためでしょうか。
(5) NGのテスト(その5)
最後的に表示するhtmlの内容で検証しましょう。ここでは“できない”という字句があることを確認します。
class TriangleControllerTest < ActionController::TestCase
test "NG data" do
xhr :post, :calculate, :triangle=>{:a=>"1", :b=>"2", :C=>"3"}
assert_response :success
assert_template "index"
assert_select "div#results", /できない/
end
end
・NetBeansで[テスト]を選択し実行します。
<div id=results></div>の中は“”だとの判定です。確かに実行時のhtmlソースも空のままです。Ajaxを利用したプログラムは詳細なテストできないようです。
7-4.Selenium IDEのインストール
(1) Firefoxのインストール
SeleniumIDEはFirefox3.5上で動作するので、Firefox3.5をインストールします。
・Firefoxの公式サイトhttp://mozilla.jp/firefox/ から「旧バ−ジョンのダウンロード」を選択し、Firefox Setup 3.5.8.exe をダウンロードします。
・タウンロードしたexeファイルを実行します。
(2) Seleniumのインストール
・同じサイトでアドオンボタンを押し、「Selenium」を検索します。
・結果画面に[firefoxへインストール]ボタンがあるのでクリックします。
7-5.Selenium IDEの起動
(1) まずFirefoxを立ち上げ、ツールから[selenium IDE(N)]を選択します。
7-6.テストパターンの自動作成
(1) SeleniumIDE画面の右上にある赤いボタンが「記録中」であることを確認します。
(2) Fairfox画面に戻って、想定しているテストパターン1を実行します。
入力したデータがすべて記録されていくのがここから分かります。
(3) 動作の検証を組み込みます。
Firefox画面で「三角形はできない」を選択し右クリックします。その中から[verifyTextPresent 三角形はできない]を選びます。
これで、1,2,3というデータを入力すると、”三角形はできない”と表示されることを確認するコマンドとなります。
(4) 記録されたコマンドの実行
SeleniumIDE画面の[テストスイート全体を実行]ボタンをクリックします。
コマンドが実行され、Firefox画面も変化していくのが分かります。
(5) Ajaxでの問題点の解消
記録されたコマンドを繰り返し実行できることが分かったが、問題点もでてきました。検証がエラーとなっています。正しければ緑色の背景色がつくはずです。
これはAjaxを利用した場合、Webページ全体のリロードが発生しないため検証タイミングなく、非同期に検証コマンドを実行してしまい、“三角形ができない”という結果表示の前に判断しているからです。
そこで表示されるまで待つコマンドを追加します。
(6) テストの実行
検証も正しく動作し背景色が緑になっています。
7-7.主なコマンド
Seleniumのコマンドは大きく分けてActionとCheckの二種類があります。ActionはWebアプリケーションにリクエストを行うためのもので、CheckはWebアプリケーションからのレスポンス内容を検証するためのものです。
(1) Action
コマンド | 意味 |
---|---|
open [url] [ ] | urlを開く |
type [id] [text] | input要素の内容を設定する |
select [id] [lavel=text] | select要素の選択肢として表示される文字列を設定する。 |
select [id] [value=value値] | select要素のvalue値を設定する |
select [id] [index=index番号] | select要素の位置(0から始まる)を設定する |
check [id] [ ] | チェックボックスやラジオボタンにチェックを付ける |
uncheck [id] [ ] | チェックボックスやラジオボタンのチェックを外す |
click [id] [ ] | リンクやボタンをクリックする |
submit [id] [ ] | formのsubmitを行う。submitボタンがないとき使う |
keyPress[id][keycode] | キーボードのキーを押した設定をする |
clickAndWait [id] [ ] | リンクやボタンをクリックしページがリロードされるのを待つ |
waitForPageToLoad [ timeout ] [ ] | ページがリロードされるのを待つ |
waitForTextPresent [text] [ ] | 設定した文字列が表示されるまで待つ |
・ url の書式
url | (例)/triangle/ (相対パス) (例)http://127.0.0.1:3000/triangle/ (絶対パス) |
・ id の書式
identifier=id属性値またはname属性値 | (例/デフォルト)identifier=commit (または) commit |
id=id属性値 | (例)id=triangle_a |
name=name属性値 | (例)name=commit |
xpath=xpath表現 | (例)xpath=//div[@id=”results”] (または) //div[@id=”results”] |
link=リンクの文字列 | (例)link=戻る |
・ textの書式
ワイルドカード使用の文字列(* と ?) | (例/デフォルト)glob:面積は* (または) 面積は* |
正規表現 | (例)regexp:面積は\d+\.\d+ (意味)数字.数字 |
文字そのもの | (例)exact:面積は6.0 |
・ select の書式
<select name="city">
<option value="1">東京
<option value="2">大阪
<option value="3">名古屋
</select>
label=text | (例/デフォルト)label=東京 (または) 東京 (東京を選択) |
value=value値 | (例)value=2 (大阪を選択) |
index=index値 | (例)index=2 (名古屋を選択) |
・ keycode の書式
keycode | (例)a (例)\49 (キーコード\49は1) (例)\82 (キーコード\82はU) |
・ 〜AndWait の書式
・ waitForPageToLoadの書式
(注意点)リロードしないAjaxなどはタイムアウトとなる
・ timeout の書式
timeout | (例/デフォルト)無指定は30秒で指定値を超えるとエラー (例)60 (60ミリ秒) |
(2) Check
コマンド | 意味 |
---|---|
verifyTitle [text] | titleを確認する |
verifyText [id] [text] | 要素の文字列を確認する |
verifyValue [id] [value] | フォーム要素の内容を確認する。(セレクトボックス含む) |
verifyElementPresent [id] | 要素が存在することを確認する |
verifyElementNotPresent [id] | 要素が存在しないことを確認する |
verifyVisible [id] | 要素が存在して見えることを確認する |
verifyNotVisible [id] [] | 要素が見えないことを確認する |
verifyAttribute [id@属性名] [text] | 要素の属性を確認する |
verifyTable [テーブルのid.行.列] [text] | テーブル内のテキストを確認する |
verifyForTextPresent [text] | 表示されているテキストがあることを確認する |
verifyTextNotPresent [text] | 設定した文字列が表示されていないことを確認する |
・ verifyText の書式
<div id=”triangle”>
<form>
辺a:<input >
辺b:<input >
辺c:<input >
</form>
</div>
<div id=”results”>
</div>
[id@属性名][text] | (例)//div[@id=”triangle”] regexp:辺a (注意点) 対象要素の中のすべてのテキストが選ばれ評価される。 ここでは”辺a: 辺b: 辺c:” |
・ verifyAttribute の書式
<div id="triangle">
:
:
</div>
<div id="results">
</div>
[id@属性名][text] | (例)//div@id triangle (注意点) 最初に合致したものが選択される |
・ verifyTable の書式
<table>
<tr><th>都市名</th><th>郵便番号</th><th>電話番号</th></th>
<tr><td>長野市</td><td>380-xxxx</td><td>026-xxx-xxxx</td></tr>
<tr><td>松本市</td><td>390-xxxx</td><td>0263-xx-xxxx</td></tr>
<tr><td>上田市</td><td>386-xxxx</td><td>0268-xx-xxxx</td></tr>
</table>
[テーブルのid.行.列] [text] | (例)//table.1.0 長野市 (注意点)セルアドレスは行・列ともに0から始まる |
<table>
<tr><th>0.0</th><th>0.1</th><th>0.2</th></th>
<tr><td>1.0</td><td>1.1</td><td>1.2</td></tr>
<tr><td>2.0</td><td>2.1</td><td>2.2</td></tr>
<tr><td>3.0</td><td>3.1</td><td>3.2</td></tr>
</table>