input type=file 欄を、Selenium で操作する (IE6/7限定)

先日、↓これを使ってブラウザからサーバにファイルをアップロードするという画面を作っていました。

作るまではよかったんですが、それを SeleniumRC でテストしようと思ったら・・・ファイル欄の操作はできないそうです(Selenium Core FAQ - Selenium - OpenQA Wiki)


Firefoxならできるとのことですが、テストしたいブラウザはIE6/7/8。


しょうがないので、こんな力技で突破しました。

/**
 * ファイル入力欄(input[@type=file])に、アップロードファイルを設定します。
 * このメソッドは、IE6/7でのみ実行できます。
 * 実行中は、Javaでブラウザを直接操作するため、PCに触れてはいけません。
 * アクティブウィンドウが別のウィンドウになっていた場合、この処理は失敗します。
 * 
 * @param locator ファイル入力欄
 * @param file アップロードするファイル
 */
protected void attachFileForIE(String locator, File file) {
    String path = file.getAbsolutePath();

    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    StringSelection selection = new StringSelection(path);
    clipboard .setContents(selection, null);
    
    selenium.focus(locator);
    
    selenium.keyDownNative(String.valueOf(KeyEvent.VK_CONTROL));
    selenium.keyPressNative(String.valueOf(KeyEvent.VK_V));
    selenium.keyUpNative(String.valueOf(KeyEvent.VK_CONTROL));
}

ファイルのパスをクリップボードにコピーして、ブラウザの input type=file に貼り付けるという力技。
元になったアイディア(Selenium RC > how to upload file using attachFile() - Stack Overflow)では、一文字ずつ入力していましたがこっちのほうが手っ取り早いです。
IE6/7のみ、この欄に直接入力が可能なので、この方法がとれます。


ただ、IE8からはセキュリティ上の理由で、この方法もできなくなっています。

ファイルのアップロード制御
歴史的に見て、HTML の ファイル アップロード コントロール (input type=file) はかなりの数の公開された脆弱性の温床であり続けました。この問題を解決するため、このコントロールの動作について二つの変更を加えました。

ユーザーの入力するローカルのファイル パスをキーストロークの監視によって盗む攻撃を防ぐため、ファイル パスの編集ボックスを読み取り専用としました。ファイルをアップロードする場合、ファイルの参照ダイアログを利用して、ファイルを指定する必要があります。

http://msdn.microsoft.com/ja-jp/ie/dd218483.aspx

IE8からはinput type=fileのテキストボックスに直接入力できなくなった - 大人になったら肺呼吸から知りました)


ブラウザの自動テストは、なにかとめんどくさいですね・・・。