スポンサーリンク

ブラウザの自動テスト中に,テスト結果をExcelに記録させる(UWSCでIEを自動操作するライブラリ 1.3)



下記のライブラリを改良した。

ブラウザ上で,マウスのドラッグ&ドロップも自動化できるスクリプト(UWSCでIEを自動操作するライブラリ 1.2)
http://d.hatena.ne.jp/language_and_engineering/20090826/p1

この時あった機能:

  • IE上でのDOM操作
  • IE上での任意のJavaScript実行と,その実行結果の取得
  • IE上でのファイルのアップロード+ダウンロード
  • IE上でのDOM要素のドラッグドロップ
  • IE上でのブラウザテスト(assertionを実行)


今回の追加機能:

  • ブラウザテストを実行しながら,その実行結果ログをExcelに記録することが可能に。


・・・assert系のコマンドを実行した際に,

  • 結果がOKかNGか
  • 詳細(値が違った場合は現実の値がなんだったかなど)
  • 時刻

を,指定したExcelファイルの好きな位置に記録できる。


以下サンプルコード。


ログをとらない場合: hoge1.uws

call .\IEManipulation.uws


// 新規IE
_ie = IE.new();
IE.show( _ie )

// Yahooへ
IE.jump( _ie, "http://www.yahoo.co.jp/")

// 要素が存在するかどうかをテスト
IE.assert_element_present( _ie, "srchtxt" )
IE.assert_element_not_present( _ie, "hoge" )

// 検索
IE.type( _ie, "srchtxt", "hogeraccho" )
IE.click_and_wait( _ie, "srchbtn" )

// 文字列をテスト
IE.assert_text( _ie, "ygmalogo", "Yahoo! JAPAN" )
//IE.assert_text( _ie, "ygmalogo", "ほげ" )

// 終了
IE.end_manipulation()

msgbox( "終了しました。" )


ログをとる場合: hoge2.uws

call .\IEManipulation.uws


// ロギングを有効にする
IE.use_log( True )
IE.open_xls_as_logfile( "D:\temp\a.xls" ) // 保存先ファイル

// 新規IE
_ie = IE.new();
IE.show( _ie )

// Yahooへ
IE.jump( _ie, "http://www.yahoo.co.jp/")

// 要素が存在するかどうかをテスト(set_pgcountで,ログの記録場所を設定している)
IE.set_pgcount( "Sheet1", 1, 1 )
IE.assert_element_present( _ie, "srchtxt" )

IE.set_pgcount( "Sheet1", 2, 1 )
IE.assert_element_not_present( _ie, "hoge" )

// 検索
IE.type( _ie, "srchtxt", "hogeraccho" )
IE.click_and_wait( _ie, "srchbtn" )

// 文字列をテスト
IE.set_pgcount( "Sheet1", 3, 1 )
IE.assert_text( _ie, "ygmalogo", "Yahoo! JAPAN" )
//IE.set_pgcount( "Sheet1", 4, 1 )
//IE.assert_text( _ie, "ygmalogo", "ほげ" )

// ログファイルを保存
IE.save_and_close_logfile()

// 終了(ログファイルを閲覧するかどうか質問される)
IE.end_manipulation()


UWSC.exeにそれぞれのファイルをドラッグドロップして動作が開始する。


ログのとり方:

  • use_log(True)でロギングが有効になる
  • open_xls_as_logfileで,テスト結果保存先のExcelファイルを指定
  • set_pgcountで,次のassertion結果を記録したいシート名と,セルの行番号,列番号を指定
    • assertが実行されるたびに,そのセル(から2つ右までのセル)に結果が書き込まれる。
  • save_and_close_logfileで,ログ用のExcelを保存
  • ロギングが有効ならば,end_manipulation時に,ログを閲覧するかどうか聞かれる。

自動テスト+自動結果記録。


このためのライブラリ:



IEManipulation.uws

//
//  IEを自動操作するためのライブラリ ver 1.32
//
//  機能:
//    ・IE上でのDOM操作
//    ・IE上での任意のJavaScript実行と,その実行結果の取得
//    ・IE上でのファイルのアップロード+ダウンロード
//    ・IE上でのDOM要素のドラッグドロップ
//    ・IE上でのブラウザテスト(assertionを実行+テスト結果ログをExcelに記録)
//
//  パッチ:
//    ・1.31 wait_for_element_presentのバグを修正
//    ・1.32 gidとjumpを安定化


class IE


  // -------------------- 制御 --------------------


  // 新規IEオブジェクトを作成して返す
  function new()
    result = createOLEobj("InternetExplorer.Application")
  fend


  // 起動中のIEを見えるように
  procedure show( browser )
    browser.visible = True
    
    // 位置調整
    wid = hndtoid( browser.hwnd )
    acw( wid, 0, 0 )
    
    // 最大化
    ctrlwin( wid, MAX )
    
    // マウス相対座標をこのブラウザ基準に設定
    MouseOrg( wid )
    
    pause( browser )
  fend


  // IEがビジー状態の間待ちます
  procedure wait( browser )
    repeat
      sleep( 0.1 )
    until ( ! browser.busy ) and ( browser.readystate = 4 )
    pause( browser )
  fend


  // URLにジャンプ
  procedure jump( browser, url )
    browser.navigate( url )
    
    total_wait_sec = 0
    loop_flag = True
    while loop_flag
      // 読みこみ完了したか?
      ifb ( ! browser.busy ) and ( browser.readystate = 4 ) then
        loop_flag = False
      else
        sleep( 0.2 )
        total_wait_sec = total_wait_sec + 0.2
      endif
      
      // タイムアウトか?
      ifb total_wait_sec > 10 then
        // 読み込みなおし
        browser.navigate( url )
        
        total_wait_sec = 0
      endif
    wend
    
    pause( browser )
  fend


  // ポーズ
  procedure pause( browser )
    sleep( 0.2 )
  fend


  // 要素が出現するまで待ちます
  procedure wait_for_element_present( browser, dom_id, timeout_sec )
    interval_sec = 0.2
    total_wait_sec = 0
    loop_flag = True

    while loop_flag
    
      // 要素は現れたか
      ifb is_element_present( browser, dom_id ) then
        // 出現したのでループ終了
        loop_flag = false
      else
        // 出現していないのでスリープ
        sleep( interval_sec )
        total_wait_sec = total_wait_sec + interval_sec
      endif
    
      // タイムアウトか
      ifb total_wait_sec > timeout_sec then
        msgbox( "element '" + dom_id + "' did not appear." )
        end_manipulation()
      endif
    wend
  
  fend


  // 要素が存在するかどうか判定
  function is_element_present( browser, dom_id )
    ifb ( browser.document = Nothing ) or ( browser.document.getElementById( dom_id ) = Nothing ) then
      result = False
    else
      result = True
    endif
  fend


  // IEの操作スクリプトを終了します
  procedure end_manipulation()
    ifb _use_log_flag = True then
      confirm_show_logging_result()
    endif
    
    exitexit
  fend


  // -------------------- DOM操作 --------------------


  // IDが渡された場合はDOM要素にして返します
  function to_elem( browser, locator )
    ifb VarType( locator ) = 8 then
      // 変数の型が文字列の場合はDOM IDとみなす
      result = gid( browser, locator )
    else
      // それ以外の場合はスルー
      result = locator
    endif

      // VarTypeのヘルプ:http://msdn.microsoft.com/ja-jp/library/cc392346.aspx
  fend


  // $
  function gid( browser, dom_id )
  
    total_wait_sec = 0
    elem = Nothing
    while total_wait_sec < 10 

      // 要素はあるか?
      ifb is_element_present( browser, dom_id ) then
        elem = browser.document.getElementById( dom_id )
        break
      else
        // 無いので,ちょっと待ってから再試行
        sleep( 0.2 )
        total_wait_sec = total_wait_sec + 0.2
      endif
      
    wend
    
    result = elem
  fend


  // 入力
  procedure type( browser, locator, str )
    elem = to_elem( browser, locator )
    elem.value = str
    pause( browser )
  fend


  // クリック
  procedure click( browser, locator )
    elem = to_elem( browser, locator )
    elem.click
    pause( browser )
  fend


  // クリックして待機
  procedure click_and_wait( browser, locator )
    click( browser, locator )
    wait( browser )
  fend


  // 文言ベースでセレクトボックスを選択
  procedure select_by_label( browser, locator, label )
    elem = to_elem( browser, locator )
    for i = 0 to elem.options.length - 1
      ifb elem.options[ i ].innerText = label then
        elem.options[ i ].selected = True
      endif
    next
    pause( browser )
  fend


  // 値ベースでセレクトボックスを選択
  procedure select_by_value( browser, locator, val )
    elem = to_elem( browser, locator )
    for i = 0 to elem.options.length - 1
      ifb elem.options[ i ].Value = val then
        elem.options[ i ].selected = True
      endif
    next
    pause( browser )
  fend


  // indexベースでセレクトボックスを選択
  procedure select_by_index( browser, locator, index )
    elem = to_elem( browser, locator )
    elem.options[ index ].selected = True
    pause( browser )
  fend


  // ファイルアップロード
  // DOM IDではなくnameで要素を指定するので注意
  procedure file_upload( browser, post_name, file_path )
    IESetData( browser, file_path, post_name )
    pause( browser )
  fend


  // -------------------- JavaScriptの制御 --------------------


  // URLにジャンプし,WebページにJSコードを注入する
  procedure jump_with_js( browser, url )
    
    IE.jump( browser, url )
    IE.create_js_proxy( browser )
    
  fend


  // Webページ中にJS経由用のオブジェクトを生成して返す
  procedure create_js_proxy( browser )
    doc = browser.document
    
    TextBlock js_proxy_code
    
// UWSCからコード注入するためのオブジェクト
document._uwsc_proxy = {
  global : this,
  _window : window,
  eval_code : function( str ){
    try{
      return eval( str );
    }catch( e ){
      // エラーメッセージを表示
      alert( e.number + " : " + e.description );
      return null;
    }
    
  }
};
    
    endTextBlock
    
    // 生成
    elem_s = doc.createElement("script")
    elem_s.text = js_proxy_code;
    elem_s.type = "text/javascript";
    
    // 注入
    doc.getElementsByTagName("head").Item(0).appendChild( elem_s );

  fend


  // 文字列をJSコードとしてブラウザ側で評価
  procedure export_js( browser, str_jscode )
    browser.document._uwsc_proxy.eval_code( str_jscode )
  fend


  // 文字列をJSコードとして評価した結果をUWSC側へ読み込み
  function import_js( browser, str_jscode )
    // いったん文字列をブラウザ側にexportし,その結果をUWSC側にimport
    result = browser.document._uwsc_proxy.eval_code( str_jscode )
  fend


  // -------------------- ファイルダウンロード用 --------------------


  // ダイアログが現れるまで待機
  procedure wait_for_dialog( dialog_title, timeout_sec )
    interval_sec = 0.2
    total_wait_sec = 0
    loop_flag = True

    while loop_flag
    
      // ダイアログは現れたか
      ifb getid( dialog_title, "#32770", -1 ) > -1 then
        loop_flag = false
      else
        sleep( interval_sec )
        total_wait_sec = total_wait_sec + interval_sec
      endif
    
      // タイムアウトか
      ifb total_wait_sec > timeout_sec then
        msgbox( "dialog '" + dialog_title + "' did not appear." )
        end_manipulation()
      endif
      
    wend
      
  fend
  
  
  // ダイアログにキーを送信
  procedure send_dialog( dialog_title, key_code )
    // 出現を待つ
    wait_for_dialog( dialog_title, 10 )
    sleep(1)
    
    // キー押下
    id = getid( dialog_title, "#32770", -1 )
    sckey( id, key_code )
  fend
  
  
  // ファイルのダウンロードダイアログが出たときに,ダウンロード+保存を実行
  procedure save_downloaded_file( browser )
    sleep(2)
    IE.send_dialog( "ファイルのダウンロード", vk_s )
    IE.send_dialog( "名前を付けて保存", vk_return )
  fend


  // -------------------- マウス操作用 --------------------


  // ブラウザのbody(表示領域)からwindowまでの余白長を計算
  procedure get_client_margins( browser, var xy_margin[] )

    // mousemove時の挙動を定義
    IE.export_js( _
      browser, _
      "document.onmousemove = function(){ " _
      + "document._uwsc_proxy._mouse_x = event.x;" _
      + "document._uwsc_proxy._mouse_y = event.y;" _
      + "};" _
    ) // 可視領域中だけの座標を見ればよいので,document.scrollTopを足さない

    // mousemoveイベントを発生させて,body内の座標を取得
    LockHard(True)
    mouse_screen_x = 500
    mouse_screen_y = 500
    mmv( mouse_screen_x, mouse_screen_y )
    mouse_client_x = IE.import_js( browser, "document._uwsc_proxy._mouse_x" )
    mouse_client_y = IE.import_js( browser, "document._uwsc_proxy._mouse_y" )
    LockHard(False)
    
    // 差分を取得
    client_margin_x = mouse_screen_x - mouse_client_x
    client_margin_y = mouse_screen_y - mouse_client_y

    // 返却
    xy_margin["x"] = client_margin_x
    xy_margin["y"] = client_margin_y
    
  fend


  // DOM要素のスクリーン上での座標を取得
  procedure get_element_screen_position( browser, locator, var xy_elem_screen[] )
    
    // 余白長を取得
    HashTbl xy_margin
    IE.get_client_margins( browser, xy_margin )
    client_margin_x = xy_margin["x"]
    client_margin_y = xy_margin["y"]

    // 要素のスクリーン上位置を計算
    elem = IE.to_elem( browser, locator )
    elem_client_y = elem.offsetTop  - IE.import_js( browser, "document.body.scrollTop" )
    elem_client_x = elem.offsetLeft - IE.import_js( browser, "document.body.scrollLeft" )
    elem_screen_y = elem_client_y + client_margin_y
    elem_screen_x = elem_client_x + client_margin_x
  
    // 返却
    xy_elem_screen["x"] = elem_screen_x
    xy_elem_screen["y"] = elem_screen_y
  
  fend


  // 要素の上にマウスを移動
  procedure mouse_over_on_elem( browser, locator, var xy_elem_center_screen[] )
  
    elem = IE.to_elem( browser, locator )

    // 要素のスクリーン上の位置を取得
    HashTbl xy_elem_screen
    IE.get_element_screen_position( browser, elem, xy_elem_screen )
    elem_screen_x = xy_elem_screen["x"]
    elem_screen_y = xy_elem_screen["y"]
      //msgbox( elem_screen_x + " " + elem_screen_y )

    // 要素の中心へマウス移動
    elem_center_x = elem_screen_x + ( Val( ChgMoj( elem.offsetWidth, "px", "" ) ) / 2 )
    elem_center_y = elem_screen_y + ( Val( ChgMoj( elem.offsetHeight, "px", "" ) ) / 2 )
      //msgbox( elem_center_x + " " + elem_center_y )
    mmv( elem_center_x, elem_center_y )
    sleep(1)
    
    // 開始点を返す
    xy_elem_center_screen["x"] = elem_center_x
    xy_elem_center_screen["y"] = elem_center_y
  fend



  // 指定要素のドラッグを開始
  procedure start_drag( browser, locator, var xy_start_screen[] )
  
    elem = IE.to_elem( browser, locator )

    // 要素の中心へマウス移動
    HashTbl xy_elem_center_screen
    IE.mouse_over_on_elem( browser, elem, xy_elem_center_screen )
    drag_start_x = xy_elem_center_screen["x"]
    drag_start_y = xy_elem_center_screen["y"]
    
    // 要素をクリック
    btn( LEFT, DOWN, drag_start_x, drag_start_y )
    sleep(1)
    
    // 開始点を返す
    xy_start_screen["x"] = drag_start_x
    xy_start_screen["y"] = drag_start_y

  fend


  // 指定要素をドラッグドロップ
  // 要素と,移動距離と,所要時間を指定
  procedure drag_drop( browser, locator, move_by_x, move_by_y, total_sec )
    elem = IE.to_elem( browser, locator )
    
    // ドラッグ開始
    HashTbl xy_start_screen
    IE.start_drag( browser, elem, xy_start_screen )
    start_screen_x = xy_start_screen["x"]
    start_screen_y = xy_start_screen["y"]
    
    // 移動
    LockHard(True)
    interval_sec = 0.2 // ループ一回にかかる秒数
    move_step_num = total_sec / interval_sec // 移動に要するステップ数
    step_x = move_by_x / move_step_num // 1ステップの移動距離
    step_y = move_by_y / move_step_num
    moved_x = 0 // 累積移動距離
    moved_y = 0
    i = 0
    while i < move_step_num
      moved_x = step_x * ( i + 1 )
      moved_y = step_y * ( i + 1 )
      mmv( start_screen_x + moved_x, start_screen_y + moved_y )
      sleep( interval_sec )
      i = i + 1
    wend
    
    // 左ボタンを上げる
    btn( LEFT, UP, start_screen_x + move_by_x, start_screen_y + move_by_y )
    LockHard(False)
    sleep(1)
    
  fend


  // -------------------- テスト実行用 --------------------


  // 要素の値を検証
  procedure assert_value( browser, locator, val_expected )
  
    elem = to_elem( browser, locator )
    val_real = elem.value
    
    assert_str( val_expected, val_real )
  
  fend


  // 要素内の文字列を検証
  procedure assert_text( browser, locator, val_expected )
  
    elem = to_elem( browser, locator )
    val_real = elem.innerText
    
    assert_str( val_expected, val_real )
  
  fend


  // 文字列同士を比較
  procedure assert_str( val_expected, val_real )
  
    log_str = "期待値 : '" + val_expected + "', 実際の値 : '" +  val_real + "'"
  
    // 一致するか
    ifb val_expected = val_real then
      // OK
      try_assert_log( "OK", log_str )
    else
      try_assert_log( "NG", log_str )
      msgbox( "NG : " + log_str )
      
      quit_by_fail_assert()
    endif
  
  fend
  
  
  // assert失敗時に強制終了
  procedure quit_by_fail_assert()
    // ログを閉じる
    save_and_close_logfile()
  
    // スクリプトを強制終了
    end_manipulation()
  fend
  
  
  // 要素が存在することを検証
  procedure assert_element_present( browser, dom_id )

    ifb is_element_present( browser, dom_id ) then
      try_assert_log( "OK", "DOM要素 '" + dom_id + "' は存在" )
    else
      ng_str = "DOM要素 '" + dom_id + "' は非存在"
      try_assert_log( "NG", ng_str )
      msgbox( "NG : " + ng_str )
      
      quit_by_fail_assert()
    endif

  fend
  
  
  // 要素が存在しないことを検証
  procedure assert_element_not_present( browser, dom_id )

    ifb is_element_present( browser, dom_id ) then
      ng_str = "DOM要素 '" + dom_id + "' は存在"
      try_assert_log( "NG", ng_str )
      msgbox( "NG : " + ng_str )
      
      quit_by_fail_assert()
    else
      try_assert_log( "OK", "DOM要素 '" + dom_id + "' は非存在" )
    endif

  fend

  
  // JavaScriptの実行結果を検証
  procedure assert_jscode( browser, str_jscode, str_expected )
  
    val_expected = import_js( browser, str_expected )
    val_real = import_js( browser, str_jscode )
    
    ifb val_expected = val_real then
      // OK
      try_assert_log( "OK", "一致" )
    else
      try_assert_log( "NG", "不一致" )
      msgbox( "NG : " + "不一致" )
      
      quit_by_fail_assert()
    endif
  
  fend
  

  // -------------------- ロギング用 --------------------


  // ログを取るかどうかのフラグ
  dim _use_log_flag = False
  
  
  // ログ用のExcelファイル名
  dim _log_xls_path
  
  
  // ログ用のExcelファイルオブジェクト
  dim _log_xls_obj = Nothing
  
  
  // 現在のログ出力先シート
  dim _log_sheet_name
  
  
  // 現在のログ出力先行番号
  dim _log_col_num
  
  
  // 現在のログ出力先列番号
  dim _log_row_num
  
  
  // ログを取るかどうか設定する
  procedure use_log( flag )
    
    _use_log_flag = flag
  
  fend


  // assert時のログ出力
  procedure try_assert_log( summary_str, log_str )
  
    ifb _use_log_flag = True then
      record_log( summary_str, log_str )
    endif
  
  fend


  // ログ出力
  procedure record_log( summary_str, log_str )
  
      //msgbox( summary_str )
    target_sheet = _log_xls_obj.Sheets( _log_sheet_name )

    // 1列目にはサマリ(OK/NG)
    target_sheet.Cells( _log_col_num, _log_row_num ).Value = summary_str
    // 2列目には詳細
    target_sheet.Cells( _log_col_num, _log_row_num + 1 ).Value = log_str
    // 3列目には日付
    target_sheet.Cells( _log_col_num, _log_row_num + 2 ).Value = "'" + current_time_for_log()

  fend
  
  
  // ログ出力用のExcelを設定して開く
  procedure open_xls_as_logfile( xls_path )
  
    // 開く
    _log_xls_obj = open_logfile_with_new_excel( xls_path )
    _log_xls_path = xls_path
  
    ifb _log_xls_obj.ActiveWorkBook.ReadOnly = -1 then
      msgbox( "エラー:記録用のExcelファイルが二重に開かれています。閉じてから再実行してください。" )
      close_logfile()
      exitexit
    endif
    
    // 最小化
    xlMinimized = -4140
    _log_xls_obj.WindowState = xlMinimized
    
  fend
  
  
  // ログファイルを開く
  function open_logfile_with_new_excel( xls_path )
    excel = createOLEobj("Excel.Application")
    excel.Visible = True
    excel.WorkBooks.Open( xls_path )
    
    result = excel
  fend
  
  
  // ログ出力用のExcelを保存
  procedure save_xls_as_logfile()
  
    ifb !( _log_xls_obj = Nothing ) then
      _log_xls_obj.DisplayAlerts = False
      book = _log_xls_obj.Workbooks( _log_xls_obj.Workbooks.Count )
      // 上書き保存
      book.SaveAs( _log_xls_path )
      _log_xls_obj.DisplayAlerts = True
    endif
    
  fend
  
  
  // ログ出力用のExcelを閉じる
  procedure close_logfile()
  
    ifb !( _log_xls_obj = Nothing ) then
      book = _log_xls_obj.Workbooks( _log_xls_obj.Workbooks.Count )
      // 閉じる
      book.Close
      _log_xls_obj.Quit()
    endif
  
  fend
  
  
  // ログを保存して閉じる
  procedure save_and_close_logfile()
    
    ifb !( _log_xls_obj = Nothing ) then
      save_xls_as_logfile()
      close_logfile()
    endif
    
  fend
  
  
  // ログ出力先のシート名とセル位置をセット
  procedure set_pgcount( sheet_name, xls_col_num, xls_row_num )
  
    // 保持
    _log_sheet_name = sheet_name
    _log_col_num = xls_col_num
    _log_row_num = xls_row_num
  
  fend


  // ログの結果を閲覧するかどうか確認
  procedure confirm_show_logging_result()
    
    ifb MsgBox("終了しました。ログを閲覧しますか?", BTN_YES or BTN_NO) = BTN_YES then
      excel = open_logfile_with_new_excel( _log_xls_path )
      excel.ActiveWorkbook.Saved = True
    endif
  
  fend


  // -------------------- 共通ユーティリティ --------------------


  // 現在時刻をログ用に文字列で返す
  function current_time_for_log()
    GetTime()
    result = G_TIME_YY4 _
      + "/" _
      + dig2( G_TIME_MM ) _
      + "/" _
      + dig2( G_TIME_DD ) _
      + " " _
      + dig2( G_TIME_HH ) _
      + ":" _
      + dig2( G_TIME_NN ) _
      + ":" _
      + dig2( G_TIME_SS ) _
      + ":" _
      + dig3( G_TIME_ZZ )
  fend
  
  
  // 数値を2桁に0埋め
  function dig2( num )
  
    ifb num < 10 then
      str = "0" + num
    else
      str = "" + num
    endif
    
    result = str
  
  fend
  
  
  // 数値を3桁に0埋め
  function dig3( num )
  
    ifb num < 10 then
      str = "00" + num
    elseif num < 100 then
      str = "0" + num
    else
      str = "" + num
    endif
    
    result = str
  
  fend
  
  
endclass

700行もある。

本当は部分モジュールごとに分割したいが,UWSCの仕様上無理なので1つのファイルにした。

ある程度リファクタリングしておいたつもり。


実装のツボ:

  • クラス変数は先頭に_をつけておく。でないと,何の変数なのかわからなくなってしまう。(this.とか無しに呼び出せるので)
  • Excelを二重に開かないようにするためのチェックが面倒だった。

補足

assertのたびにset_pgcount()を書く必要がある。

自動的に書く対象のセルをずらしていけばいいじゃないか?と言われそうだが,そうしないのには訳がある。

その理由は,いずれ明らかにされる。


→追記:下記で明らかにしました。

IE AutoTester で,UIの回帰テストを完全自動化
http://d.hatena.ne.jp/language_and_engineering/20090922/p1

関連する記事:

UWSCのマクロで,IEを起動して自動操作するサンプルコード - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20140204/controlIeBrowserbyUWSC


JScript / VBScript (WSH)で,IEを自動操作しよう - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20090713/p1


IE AutoTester で,UIの回帰テストを完全自動化 - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20090922/p1