なのログ

だから見てて下さい・・・俺の・・・変身

Robolectric v4.3 導入の後ろの話

よくある話題:「外部に書こうかな~~自分のブログに書こうかな~~」
弊ブログでの回答:「両方で」

というわけで、この記事⇩と同じ話題の蛇足バージョンです。
最新のRobolectric (v4.3)の導入で迷える子羊を俺が救う[ Android / testing ] - Qiita


f:id:nanoyatsu:20190615025435p:plain

というわけで、Qiitaのほうには手順だけまとめると思うので、
こっちではダラダラと時系列に情けない様子を綴ります。

たぶん作業には役立たないんですけど、理解が進んでいく様子とかが伺えると思います。
他の作業が間に挟まりながらとはいえ実に1.5営業日くらいをこの作業に溶かしてしまい、
記録を残すことで禊としたいと考えています。大変に勉強になりました。


「テストって何するんスか」編

[過去数ヶ月の状況]

  • 参加プロジェクト:テスト無し
  • リファクタ対象コードの山
  • チーム内から「作り直したい」の声
  • 1ファイル1クラス13000行.javaの存在

これを受けて出る言葉。それは。
「テストを用意しなきゃならねえ。」

リファクタリングするにも何をするにもテストが欲しい。その様子です。

とは言いつつも、知識レベルは「なに?JUnit?使うかんじでいい?」くらい。
これがたぶんここ半年とかの話です。

この期間をぬるく過ごしながら、いつかきたるリファクタ・テスト整備に備えてググった知識は、

このへん⇩の話題を読みつつの

アプリのテスト  |  Android Developers qiita.com

「ロジックのテストとView絡むテストとで別枠なんか しんど」
「あ~JUnitくんとモック伊藤くんをな~~扱わなアカンのやな~~」
「結合検査まわり、なにこれ、魔法なん?(まだやってなくて今なお詳しく知りません)」とかでした。

そう、この時すでにRobolectricは視野に写っているのです。ガン無視してますね。

「Robolectricとかいうの使いたい」編

そういった中で、ぼちぼちと奴の名前を目にし始めます。このあたりです。⇩
Android How to Test - Qiita < Robo…?なにそれ…?
Android Test は “Write once, run everywhere.” の夢を見るか < Robolectric強ない????

いや、ちゃんと言うと、テストの実行に成功したのが6月13日で、
この「目にした」というのは12日です。ド直近じゃねえか。

ここから戦いは始まってしまいました。

ここで何が起きているかというと、上の2記事目の話題あたりがピンポイントでそれなんですが、
Robolectricというもの、大変素晴らしい機能を提供してくれているものですが、
この時の話題は「その素晴らしいRobolectricsさんがインターフェイスをandroidxとフュージョンさせたで」
というもので、それはつまり「書き方が変わりました~~!!」なわけです。

であれば当然といえば当然なんですが、ド最新の資料じゃなければ意味がなくなるんですよ。
むしろ無垢な顔をして書かれた数ヶ月前の記事の書き方が全部沼なんですよ。こわ。素人がやることじゃない。

ついでにこの18年10月25日の更新が大きなバージョンアップなので、
それはそれは色々変わってるんですよね。ぶっちゃけ公式の内容もおかしい。(た、たぶん)

参照なんもわからん編

というわけで、ここで大いに沼にハマりました。
理解が半端なせいでRobolectric公式を見てもTestRunnerの指定が要るのか要らないのか全然わからなかったり、
(GetStartedのページとAndroidXTestのページでサンプル内容が全然違わないですか???)
いざ指定して実行してみたら「こんなん単体テストですんなや」と⇩ブチギレられたり、

java.lang.IllegalStateException: No instrumentation registered! Must run under a registering instrumentation.

そもそもbuild.gradleでのテスト系の参照をtest/以下(implementation)にしていたのに無意識に作成していたテストクラスがandroidTest/以下だったりして「そもそもJUnitが使えねえ・・・」とかってなったりもしていました。

並行して、そもそもテストに使われるクラスの概念なんかにも触れました。
間違いなく一番のキモはActivityScenarioですね。シナリオというのも完全に納得だし、
ライフサイクルの遷移の操作を受け付けてるのとかはもう「テストだこれ~!!」となりました。キッズか。

そしてこの時手始めにと選んでいたテスト内容が 「Intentで値を渡されるちょっとしたActivityで、そのボタン動作をテスト」 というものだったのでContextの生成方法についても調べていたんですが、

ここまで挙げたやつらが合わさって、同時に複数箇所にわからんポイントが頻出するわけですね。

Writing Your First Test | Robolectric < Robolectricのチュートリアル
AndroidX Test | Robolectric < 今回やりたいRobolectricの使い方のページ
JUnit4 rules with AndroidX Test  |  Android DevelopersGoogle側が用意したandroidx.testの書き方
Test your app's activities  |  Android Developers < 「Activityのテストのしかた」
AndroidでContextが必要な機能のテストコードを簡単に書こうとしてとても時間がかかった話 - Qiita < モチベーションが近い

もう全部書き方違うんすよこいつら。地獄か。

そんな中で、たとえばまあContextに関して言えば3つくらい書き方あるな??となったわけですけど、

InstrumentationRegistry  |  Android Developers < 現在非推奨 InstrumentationRegistry  |  Android Developers < 直接使うのはオススメしないって書いてあったのでやめた 今わかるのは、こいつはAndroidTest側のやつ
ApplicationProvider  |  Android Developers < これが正解なのでは・・・?(最後に採用)

みたいな感じにがんばって絞り込みました。
そろそろ信じられるドキュメントと信じられないドキュメントがわからなくなってきたところです。

そしてテスト内容側の書き方が「こんな感じか・・・?」となったところに、
最後の刺客が現れました。

~~2019/07/13訂正~~

はいここ↓ウソ!(ウソではない)

JDKどいつやねん編

JDKJava Development KitJava開発者ツール。
Androidでマトモに意識したこともなかったよ。
(AndroidStudio組み込みだからね)

で。はい。
さっきまでの手順で、いざテストまわりの書き方(ライブラリの使い方)を「こんなもんか・・・?」として、
「もうイケるやろ」とテストを走らせた僕に、非常な刃が襲いかかります。

[Robolectric] WARN: Android SDK 10000 requires Java 9 (have Java 8). Tests won't be run on SDK 10000 unless explicitly requested.

あーなんか書いてありましたね!!ほんとに色々立ちふさがるなと思いました。やべえよこの作業。
そんな訳でJDKのダウンロードに走りました。これさえちょっとコケた。

具体的には、
JDKほしい! よくわかんない! Oracleたすけて!
→引き続きよくわかってないので「最新で12でいいんじゃね?」と拾う
→ダメ(後述)(java 9 warnings (illegal reflective access operation) · Issue #4776 · robolectric/robolectric · GitHub
→えっじゃあ・・・と思って11を拾いたい
→ なんかOracleのサービスの認証始まったけど!?
→ こ、これがJavaマネタイズ・・・

こんなん。

それからなんとかOpenJDKにたどり着きまして、
OpenJDK12がダメ、11がダメと過ごして、かなり絶望的な気持ちになりながらOpenJDK 9。

テストが・・・動きました・・・・・・。

Java 9にしてや」っていうのがまさか文字通りJava9じゃないと動かないとはな・・・。

ざっくり言うと、
「Robolectricくんが動いてくれへん・・・」
JDKがどうとか怒っとる・・・公式にはAndroidQのときだけ要るって・・・」
「とりあえずOpenJDKためそ・・・」
「なんでためすだけでこんな時間かかってん・・・(OpenJDK12)」

みたいなことを延々としていました。
結果、Gradleのローカルキャッシュが悪かったり(たしかに90MBくらいって書いてあるダウンロードにクソ時間かかって1回チェックサム間違いで落とし直しとかやってた)、別のバグをただただ踏んでいたりしていただけでした。
あと怖いのでバージョン指定はテストコードの方に書くようにしたりしました。バージョン指定前にローカルキャッシュ消したほうがいいとおもいます。

なのでトラブルがあったといえばあったんですが、それはJDKのせいではないぜ・・・という結果です。AndroidStudio組み込みのやつから変えなくていいのはとてもたすかる。

~~2019/07/13訂正ここまで~~

おわり

というわけで、途中諦めそうになりながらなんとかテストを動かすことができました。
Activityのテストも、test/以下の階層で元気に動いています。涙無しには語れません。

しかしほんと、こうも苦戦してしまったのは、
いろいろ細かい部分で不理解があったり、都合よく考えたりした結果の積み重ねなんでしょうね。
できる人は絶対もっとスマートにできるもんな・・・。

あ、あとちなみに、このissueの例に漏れず、ウチでもWARNINGの5行が元気に踊っています。

お疲れ様でした。久しぶりの記事は技術記録の顔をした日記でした。
完。今月なんとかまた仕事振り返り記事書きます。(四半期1回感が出てきた)