testingViewGroupのonLayout()が呼ばれた後でいろいろやるクラスを作ることになったので、ユニットテストを書きながら実装を進めることにした。onLayout()を呼んでもらうにはViewGroupをActivityにアタッチ(setConentView)しなければならない。it.setContentView(sut)}とりあえずテストする分には適当なActivityにアタッチすればいいが、MainActivityにいろんな実装が入ったりするとテストの準備が大変なことになるのでテスト用のActivityを用意しておいた方がいい。テスト用のActivityもAndroidManifest.xmlに登録しておかなければならないので、テスト用の共通モジュールを作ってmainソースの中に入れておくと便利になる。Theme込みのテストがしたければAppCompatActivityを継承し、Styleを定義して適用しておく。これが必要なければ普通のActivityでよい。4.3で入った@LooperModeというやつを使うことで、例えば1フレームの中でaddView()を複数回呼んだ時の挙動を本来のものにより近づけることができる。onLayoutが呼ばれていた。robolectric.orgLooperModeは引数を一つとるアノテーションで、テストクラスやテストメソッドにつける。Mode.PAUSEDを指定するとLooperの挙動が本来の動きに近くなる。このテストケースではこれを呼ぶごとにViewの更新ライフサイクルが進むことになる。してやることでテストが通るようになる。callのようなメッセージがでることがある。Activityがいる状態だとどうしても出てしまうので、本当にidle()を呼んで解決する状況かどうか見極めた方がいい。21:03自作のViewGroupをRobolectricでテストしつつ開発するTweet広告を非表示にするもっと読むコメントを書く2020-01-13rotationを指定したViewをEspressoでクリックできない件Androidgithub.comクローンしてエミュレータなどでandroidTestを実行してみてください。?EspressoのViewActions.click()は内部でGeneralClickActionを使ってクリックアクションを作っている。GeneralClickActionを生成する際にいくつか引数を渡す必要があるのだが、この中でクリックする位置を決めているのは2個目の引数であるCoordinatesProviderクラスのオブジェクトである。enumクラスのGeneralLocation.VISIBLE_CENTERが渡されている。この実装の中ではView.getLocationOnScreen()で得た対象のViewの左上の座標に、Viewの幅と高さの半分の値をそれぞれXとY座標に足して返している。ここで問題なのは、View.getLocationOnScreen()で取得できる座標はもともとのViewの左上の座標に回転変形のマッピング計算を施したものであること。Viewの中心を軸にして右に30度回転しているとすれば、返ってくる値も右上方向にずれることになる。そこを起点にして元々のViewの幅と高さの半分をそれぞれXとYに足しても、回転後のViewの中心にはならない。正方形のViewであれば、45度以上回転するとViewの外側に出てしまう。サンプル実装のリポジトリではView.getGlobalVisibleRect()を使って、回転したViewを内包するRectを取得してその中心座標を返すCoordinatesProviderを実装し、GeneralClickActionに渡している。これによって一応クリックできるようになっている。20:42rotationを指定したViewをEspressoでクリックできない件Tweet広告を非表示にするもっと読むコメントを書く2020-01-11UIテストでDBに入れるデータをテストアプリのassetsとして管理するAndroidモチベーションサーバーとは独立した環境でテストを行えるようにしたかった必要なデータの種類が結構多いのでテストコードの中でデータを作ってDAOからDBにInsertしまくるというのが面倒くさそうだったOkHttpのMockサーバーから返すレスポンスをテストコードの中にゴリゴリ書くのも同じ理由で面倒くさいと思われる必要なデータが入っているDBをテスト時にコピーすればいいという話もあるが、どんなデータが入っているか簡単にわかって、かつ簡単にいじったりできたらいいかなと思ってCSVでデータを管理することにしたTSVとかYamlとかでもいいかもしれないが、SQLiteにはテーブルの中身をCSV形式でダンプする機能があるので手っ取り早い。前提サーバーからとってきたデータをDBにキャッシュし、DBにあるデータを信頼できる唯一のソースとする。3.1.0どうやって?まずはDBからデータを吸い出す。sqlite3はDBファイルからテーブルのデータをCSVでダンプさせることができる。INTO...の形式でも吐き出せるので読みにくくならなさそうならこれでもいいかもしれない。table"src/androidTestの直下にassetsディレクトリを作って、ここに上のコマンドで出力したCSVファイルを置くと、それがそのままテストアプリのAPKファイルの中に入る。次のような感じでテストアプリのContextからアクセスできるようになる。これを使ってテストケースの最初にデータが読み込まれるようにする。InstrumentationRegistry.getInstrumentation().context.assetsモジュール分割のやり方によっては、UIテストを実装するモジュールが、Roomやそれを使って実装しているDaoやEntityのクラスとかを知らなかったりする。VALUES(...)を使ってCSVの行をSQLに直接流し込むことにした。SQLiteの操作はandroidxのSupportSQLiteOpenHelperやSupportSQLiteDatabaseクラスを使って行う。RoomDatabaseからSupportSQLiteOpenHelperを取得できるので、DIか何かを使ってテストクラスに渡せるようにしておく。PRAGMAをtrueにしてから流し込むとはかどる。}}DBのデータだけでなく、端末で行うテストで使うリソースファイルなら大体のことに応用できるんじゃないかと思うのでうまくいったら教えてください。*1:これのほかにもテーブル名を列挙したりする必要がありますがお好みの方法でどうぞ。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。