Titanium 製アプリで NativeDriver を試す(Android 編)
Titanium 製 Android アプリで NativeDriver を試したメモ。
(追記)iPhone 編
Titanium 製アプリで NativeDriver を試す(iPhone 編) - vaccho's blog
NativeDriver とは
NativeDriver とは、アプリを自動操作してテストが行えるツール。
Web アプリに対して Selenium で行うのと同じ。
というか Selenium に統合された WebDriver API を実装している。
http://code.google.com/p/nativedriver/
自動操作されている様子の動画。
すごい。しかも Android/iOS 両対応。
これをぜひ Titanium 製アプリでもやりたい!
Titanium 製アプリで対応する
チュートリアルにあるように、
1. server-standalone.jar を作成してアプリに取り込む
2. アプリインストール後、コマンドを叩いてサーバを起動する
という手順でアプリ側の準備が整う。
http://code.google.com/p/nativedriver/wiki/AndroidMakeAnAppTestable
jar のインポートはどうやったものかと思ったけど、
以前たまたま見つけた Titanium SDK 内に配置して dependency.json に記載する方法でやってみた。
http://vaccho.hatenablog.com/entry/2011/12/19/125712
すると、インポートしようとはしてくれたけど、以下のエラー。。
[WARN] warning: Ignoring InnerClasses attribute for an anonymous inner class [ERROR] (org.mortbay.jetty.AbstractBuffers$1) that doesn't come with an [ERROR] associated EnclosingMethod attribute. This class was probably produced by a [ERROR] compiler that did not target the modern .class file format. The recommended [ERROR] solution is to recompile the class from source, using an up-to-date compiler [ERROR] and without specifying any "-target" type options. The consequence of ignoring [ERROR] this warning is that reflective operations on this class will incorrectly [ERROR] indicate that it is *not* an inner class.
どうやら、JDK 1.4 以前でビルドした jar が含まれていると発生するらしい。
エラーの内容を見ると
jetty-6.1.22.jar
jetty-util-6.1.22.jar
が原因のようなので、これを手元でビルドする必要がある。
この辺を参考にビルド。
http://docs.codehaus.org/display/JETTY/Building+from+Source
記載通りにやるとエラーになったので必要なものだけ jar を作るように。
jetty-6.1.22.jar なら以下。
$ svn checkout http://svn.codehaus.org/jetty/jetty/tags/jetty-6.1.22/ jetty-6.1.22 $ cd jetty-6.1.22/modules/jetty $ mvn install
これを NativeDriver の nativedriver/third_party/jetty 以下に持っていって
改めて server-standalone.jar をビルド。
これを使ったらうまくインポートされた。
Titanium 製アプリを操作する
アプリに jar をインポートして、サーバを起動したら、あとはテストコード経由で操作。
サンプルだとこんな風に記載されている。
driver.startActivity("com.google.android.testing.nativedriver" + ".simplelayouts.TextValueActivity"); WebElement textEditView = driver.findElement(By.id("EditText01")); textEditView.sendKyes("test");
Titanium でも AndroidManifest.xml に Activity の名前は定義されているので
これを使うようにすれば良い。
だけど Titanium だと id が設定できないようで、findElement(By.id()) が使えない。
なので ClassNames を使ってみたらうまくいった。
例えば、こんな画面があったとしたら
こんな感じでメールアドレスとパスワードを入力して、ログインボタンが押せる。
// 入力欄をすべて取得 List<WebElement> textEditViewList = driver.findElements(AndroidNativeBy.className(ClassNames.EDIT_TEXT)); // 一つ目の入力欄がメールアドレス WebElement mailAddressEditView = textEditViewList.get(0); mailAddressEditView.click(); mailAddressEditView.sendKeys(mailAddress); // 二つ目の入力欄がパスワード WebElement passwordEditView = textEditViewList.get(1); passwordEditView.click(); passwordEditView.sendKeys(password); driver.findElement(AndroidNativeBy.className(ClassNames.BUTTON)).click();
ただ、画面の変更に弱い実装になるので、良い方法を模索したいところ。。
ということで
Titanium 製 Android アプリで NativeDriver が利用できた!
iPhone/Android 両対応だとコードを変更したら iPhone/Android 両方で確認しないとなので
こういう自動化テストはすごく役立つはず。。!