- PR -

Web自動テスト(IFRAMEのエラートラップ)

投稿者投稿内容
たむら
会議室デビュー日: 2006/07/31
投稿数: 6
投稿日時: 2006-07-31 13:09
はじめまして。

Webアプリの自動テストツールの試作を行っています。

現在、考えている方法はテスト対象のWebアプリと同じ
ドメインにテストツールを配置します。
テストツールからIFRAMEに対象のWebアプリを読み込んで
テストケーススクリプトからIEの自動操作を行うツール
を作成しました。

親フレームから子フレーム(iframe)のスクリプトエラーを
トラップする方法がわからず、ここで質問させて頂いてい
ます。
複数のテストケースを一括して処理したいため、スクリプト
エラーのダイアログを表示したくないのです。
(同様にalert,confirm,showModalDialogもオーバーロード
する必要があります)



通常のエラートラップなら下記のようなコードになると
思うのですが
function ErrTrapFnc(){}
window.onerror = ErrTrapFnc;


子フレームの場合
<iframe id="if1" name="if1"></iframe>

この方法は駄目でした。
if1.onerror = ErrTrapFnc;

この方法も駄目でした。
var test = window.open("hoge.html");
test.onerror = ErrTrapFnc;


次の方法は惜しいのですが、子画面ロード時(body.onloadのスクリ
プトエラーをトラップ出来ません)
var strScript = "window.onerror = top.ErrTrapFnc;";
if1.execScript( strScript );

テスト対象のWebアプリがスクリプトエラーでも処理続行できるよ
うな上手い方法はないでしょうか?

iframeへのエラートラップ、iframeでなくても
同様な自動テストツール作成の方法などご存知であれば
ご教授下さい。

冬寂
ぬし
会議室デビュー日: 2002/09/17
投稿数: 449
投稿日時: 2006-07-31 14:25
うーん。どう答えたらいいのやら・・・

とりあえず、try 〜 catch

後、
>window.onerror = ErrTrapFnc;
とかやっている辺りからすると、ひょっとしたら(何と言ったらいいのかよく分からないけど)何かを誤解しているかもしれません。
(そうだとしたら、別のページに、document.createElementでノード追加してみる実験をしてみると理解に近づくかもしれません。)
たむら
会議室デビュー日: 2006/07/31
投稿数: 6
投稿日時: 2006-07-31 18:03
ご返事ありがとうございます。

>うーん。どう答えたらいいのやら・・・
説明が悪く、すみません。

A.aspx
B.aspx
があったとして A.aspxのあるボタンを押したら
B.aspxへリダイレクトされる処理があるます。

テスト制御フレームから A.aspxのページ内容にアクセスして
そのボタンを蹴飛ばし、readyStateを監視しながらB.aspxを
読み込んでまた、テストアクションを起こすなどを考えています。

テスト制御フレームが主となって起こしたアクションにはtry__catchで
対応できますが テスト対象となっているアプリ側が主導で発生した
イベント(Boyd.onload, Form.onsubmit, Timerイベントなど)
はtry__catchで囲めないですよね。

テスト対象となるWebアプリに修正を加えずに
テスト制御フレームからエラートラップを行うには
子フレームのwindowオブジェクトに対して onerrorイベントを
定義すれば、良いのではないかと思いましたが、そのやり方が
分からずとうい状況です。

テスト制御フレームからは、ユーザーアクションを代行させて
Webアプリの応答を監視したいと考えています。

冬寂
ぬし
会議室デビュー日: 2002/09/17
投稿数: 449
投稿日時: 2006-07-31 18:59
えーっと。リッチクライアントの会議室で質問されているので単純なJavascriptの問題かと思っていたら、ASP.NETあたりの話ですか?
だとしたら、すみませんが私には全然分かりません。

まぁ、とりあえず
>イベント(Boyd.onload, Form.onsubmit, Timerイベントなど)
>はtry__catchで囲めないですよね。
Javascriptなら囲めますよ。

.NETがどういう体系なのか知りませんが(&今回たむらさんが使われている方法がどういうものか分かりませんが)、単純にデバッグ用のスクリプトと実稼動用のスクリプトを別に用意すれば出来ませんか?
たむら
会議室デビュー日: 2006/07/31
投稿数: 6
投稿日時: 2006-08-01 10:16
>えーっと。リッチクライアントの会議室で質問されているので単純なJavascriptの
>問題かと思っていたら、ASP.NETあたりの話ですか?

いえ、先ほど説明で出した***.aspxはたとえばの例として
書いたもので、テスト対象となるWebアプリケーションは
ASPX,ASP,PHP,JSPや、純粋なHTMLでも構わないです。

>>イベント(Boyd.onload, Form.onsubmit, Timerイベントなど)
>>はtry__catchで囲めないですよね。
>Javascriptなら囲めますよ。

そうですね、確かに囲めますが処理の経過によってはエラー補足はできない事
があると思います。

A.jsp
B.jspがあったとして
Aには テキスト入力欄とボタンがあり
ボタンを押すと、B.jspに遷移してAで入力したテキスト内容が
Bの画面に表示されるといったサンプルを想定した場合。


テスト制御フレームからは人間のアクションを代行するため
テキスト入力欄に 入力を行い、ボタンを押すことを行動を

Aのtext1.value = "hoge";
Aのbotton.onclick();

上のスクリプトで現します。

確かに
try{
Aのtext1.value = "hoge";
Aのbotton.onclick();
}catch(e){
alert(e)
}

と囲むことができ、Aが主導で引き起こしたスクリプトエラーは補足可能です。
しかし、その後A.jspはサーバーへサブミットを行い
入力内容に従って動的に変化したB.jspを返すならば
B.jspを読み込んだ時点で発生するクライアントエラーは補足出来ませんよね。

画面遷移など行っても、子フレーム(テスト対象のWebアプリ)で起こった全てのエラー
または、イベントをトラップ出来るようにしたいと考えています。



##補足
また、その後も調べてたのですが
私の試作しているWebテストツールっというのは
オープンソースプロジェクトのseleniumと概念的には近そうです。
http://www.openqa.org/selenium/index.html

ただ、そのseleniumもテスト対象のスクリプトエラーなどはトラップ出来てないようです。
変わりに、alert,confirmのオーバーライドの仕掛けなど参考になりました。
sawat
大ベテラン
会議室デビュー日: 2006/08/02
投稿数: 112
投稿日時: 2006-08-02 09:56
どうも始めまして。
面白そうな話だったのと、冬寂さんに話が伝わってなくてかわいそうだったのでつくってみました。

こんなんで、どうでしょう?ちょっと長いですが。
コード:

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=sjis">
<script type="text/javascript" src="prototype.js"></script>
<style type="text/css">
form#input_form {
margin: 5px;
padding: 5px 0px;
border: 1px solid gray;
background: #F7FFFF;

}
form#input_form input#url {
width: 70%;
white-space: pre;
}
iframe#ifr {
margin: 5px;
width: 100%;
height: 60%;
}
ol#errorlist {
margin: 5px;
width: 100%;
height: 30%;
overflow: auto;
border: 1px solid gray;
background: #FFFFE7;
}
ol#errorlist li {
border: 1px dashed gray;
border-width: 0px 0px 1px 0px;
}
</style>
</head>
<body>
<script type="text/javascript">
window.onerror = handle_error;

function handle_error(mes,file,num){
try {
var ol = top.document.getElementById("errorlist");
var li = top.document.createElement("li");
li.innerHTML = [file, num, mes].join(" ").replace(/[<>&"]/,
function(c) {
switch(c) {
case "<" : return "<";
case ">" : return ">";
case "&" : return "&";
case "\"" : return "&qoute;";
}
});
ol.appendChild(li);
} catch(e) {
alert(e.message + "\n" + mes);
}
return true;
}

function open_at_frame() {
var ifr = document.getElementById("ifr");
ifr.url="about:blank";
var url = document.getElementById("url").value;

new Ajax.Request(url, {onComplete: function(req){
var ifr = document.getElementById("ifr");
var rep = "<head><script type=\"text/javascript\">" +
"window.onerror = top.handle_error;\n" +
"</" + "script>";
var html = req.responseText.replace("<head>",rep);
var doc = (ifr.contentDocument || ifr.contentWindow.document);
doc.open();
doc.write(html);
doc.close();
}});
}
</script>
<form name="f" id="input_form">
<label>url:</label><input id="url" type="text" value="error.html">
<input type="button" value="open" onclick="open_at_frame()">
</form>
<iframe src="about:blank" id="ifr"></iframe>
<ol id="errorlist"></ol>
</body>
</html>



XmlHTTPRequestで被テスト対象のページを取得して、onerrorハンドラの書き換えスクリプトを追加して、about:blankのdocumentに書き込んでいます。
ちなみに上記コードではXmlHTTPRequestを直接使う代わりに、prototype.jsのAjax.Requestを使っています。WinIE6とFirefox1.5で動作しました。

ただし、テスト対象によっては正しく動作しなくなることはいろいろあると思います。
(リファラを見てたりとか、topを使ってたりとか...)


# バックスラッシュの数がおかしくなってたので修正。

[ メッセージ編集済み 編集者: sawat 編集日時 2006-08-02 09:59 ]
たむら
会議室デビュー日: 2006/07/31
投稿数: 6
投稿日時: 2006-08-02 11:32
sawatさん、ありがとうございます。

ご提示していただいたサンプル、こちらでも確認致しました。
ありがとうございます。

なるほど、テスト対象が行う通信を全て、トラップして
やれば制御可能ですね。

開いた時点で発生したエラーの通達も出来ますしね。
テスト対象のsubmitイベントを取り上げて
XmlHttpRequestにして応答を受け取り、毎度にテストツール用コードを埋め込んで(略)

submitイベントで本来送られる筈だったリクエストヘッダを
自分で作成して、テスト対象を完全に制御下に置く
リクエストヘッダを作る時にリファラも本来の物に置き換えてしまうとして

topへの参照も偽装できるような気がします。
テスト対象window.top = テスト対象window;(こんな感じでしょうか)

分かりにくい説明の中、相談に乗って頂いた 冬寂さん
サンプルの提示までして頂いた sawatさん
どうもありがとうございました。

###
実はテスト対象となっているWebアプリ(私が作ったもの複数)
の中で共通に呼んでいるJScriptライブラリに

if( top.AutoTest ){
//テスト制御フレームにAutoTest変数を定義しておく
window.onerror = top.ErraTrapFnc;
}

上のようなコードでお茶を濁そうかと考えていたのです。
が、テスト対象のWebアプリに変更を加えたくなかったので
助かりました m(_ _)m

sawat
大ベテラン
会議室デビュー日: 2006/08/02
投稿数: 112
投稿日時: 2006-08-02 13:44
ども。お役に立てて光栄です。
実際にそこまでやるなら、全部Javascriptでやろうとするのではなくて、WEBRickのようなプロキシを使った方がよいのではないかと思います。

Rubyist Magazine - WEBrickでプロキシサーバを作って遊ぶ -

スキルアップ/キャリアアップ(JOB@IT)