Android Bindingについて、前回のエントリで作成したアプリのテストはどうやるのがいいか考えてみました。
このエントリでの最終的なコミットはこちら
https://github.com/nakaji/AndroidBindingSample/commit/9fef17ef46bbcd73493497aa91c2d12bb7746ba3
テスト対象
テストの対象となる部分は大きく以下の2つに分かれます。
- BMI計算に関するロジック
- UI周り
BMI計算に関するロジック
ViewとViewModelに分離していますので、ここでテストする対象はViewModelとなります。これをJUnitでテストするにはどうすればいいのか?というのがこのエントリの目的です。
UI周り
ロジックについてはViewModelのテストで保証されているので、ここでは主に「ViewとViewModelのバインドがちゃんと行えているか」という観点でのテストになります。
こればっかりはエミュレータや実機等で実際に操作するしか今の自分にはできません。AndroidのテストプロジェクトやMonkeyRunnerなど使って自動化できそうですが、今の私にはそこまでの知識はないので、またそのうち…
どうテストするか
CommandクラスのInvokeメソッドの引数でAndroid固有のViewクラスを使用しているので、通常のクラスとしてのテストは難しそうです。
以前のエントリで触れたRobolectricを使用すればAndroidのエミュレータを使用せずにテストできそうです。
試してみた内容
Javaのビルド・パスにandroid.jarを追加
Invokeメソッドで使われてるViewクラスの解決が行えないので、Windows環境であれば \android-sdk-windows\platforms\android-10 等の配下にある android.jar をビルドパスに追加しておきます。
JUnitテストクラスを作成してテスト実行
以下のようなテストクラスを作成しました。
public class BMIViewModelTest { private BMIViewModel viewModel; @Before public void setUp() { viewModel = new BMIViewModel(); } @Test public void Calc() { viewModel.height.set("172"); viewModel.weight.set("60"); viewModel.Calculate.Invoke(null, (Object[]) null); Assert.assertEquals(60 / Math.pow(172 / 100.0, 2), viewModel.BMI.get()); } }
ViewModel側で実装したInvokeメソッドでは引数に渡されたViewを使用していませんので、ここではあえてnullを渡しています。
逆に、Invokeメソッドで使用してしまうとテストコード内でViewのインスタンスを生成することになりますので、Androidのテストプロジェクトを使用する必要が出てきます。そうなると本来の目的を満たせないのでダメ。ゼッタイ。
所感
PojoViewModelでシンプルに実装できるのが一番いいのかもしれませんが、片方向しかバンドできないのはやっぱりメリットが少ないと感じました。今回のようなやり方ででも双方向バインドが行えるライブラリを使った方がコードもすっきりするし、個人的には好きかな。と個人で野良アプリしか作ったことのない私は思ってみる。