3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「Kotlin/Androidでテスト駆動開発をはじめよう」のセッション補足について

Last updated at Posted at 2024-06-24

MagicPodさん主催のイベントモバイルアプリ開発における良いテストコードの考え方に「Kotlin/Androidでテスト駆動開発をはじめよう」という内容で、スピーカーとして参加させていただきました。今回はそのセッションの補足内容となります。テストというテーマは深く、考え方もいろいろあるので、15分のセッションに収めるのは大変なので、補足を書きました。

TDDのやり方

TODOリスト

Kent Beckの「テスト駆動開発」では、TODOリストを作りながらTDDを実践していきます。これは、Greenのフェーズでコードをきれいにする方法を思いついているが、このフェーズではまだ実施できない、のようなときに作るTODOリストです。TDDでは各フェーズでやるべきことが決まっているので、将来に手を付けるべきことを棚上げにしておかないといけません。
そのときにTODOリストとしてメモ書きを残しておくとよいです。頭の中で短期記憶しているだけだと、忘れてしまいそうで、不安になります。TODOリストはその不安を取さってくれます。

内から外へ向かってTDDをやるか、その逆か

TDDには外から内へ向かうやり方と、内から外へのやり方があります。外から内とは、最初に受け入れテストを書き、それを満たすようにUI、ViewModel、データレイヤーように内側へテストを書きながら実装をしてくスタイルです。内から外は逆で、最初にドメインやモデルのテストを書き、データレイヤーからUIへと向かっていきます。
ここで両者メリット・デメリットがありますが、外側のほうが依存関係が多いので、外から内へ向かうやり方だといろいろな依存関係をテストダブルで補ってあげる必要があります。逆方向だと、既に依存ができているので、やりやすいところがあるはずです。本物の依存関係、すなわちプロダクションで使うそのままのRepositoryを使ったりすることもできるでしょう。
セッションではAndroidならではのテストを示したかったのでViewModelを作りましたが、最初に内側を作ったほうが、その点のやりやすさはあると思います。

高速化の重要性

TDDはよくテストを回します。小さなステップのたびに、テストを回します。なので高速化が非常に重要になってきます。
できるだけ実機のテストは避けて通常のJunitのテストだけで賄うのが理想的でしょう。
また、マルチモジュールにしてキャシュを活用したり、テストを並列化したりすると良いかもしれません。それができないなら、変更をプッシュする前は、変わったテストだけ実行するようにするとよいと思います。

TDDの注意点

TDDを試すには簡単な所からやってみることをおすすめします。TDDはどこでもやりやすいわけではなく、適さない場合もあります。
例えば技術やドメインへの理解が少ないうちは、難しいと思います。ある程度コードの予想がつくようになる必要があるからです。
技術やドメインへの理解が少ないときはコードを書いてみながら動くか試すようなことをやると思います。そうしたほうが、知識の定着は早いと思います。また知識が乏しい内はテストがどうなるかの予想も難しい場合があると思います。
TDDは特に既存のコードが有るときに有力だと思います。初めて見るなら既存のコードが有り、別の振る舞いを増やすようなときに、やってみると良いと思います。

またチームでTDDを導入するのは慎重になるべきだと思います。TDDはスタイルであって、人に強要されると反感が起きてしまうかもしれません。チームとしてはあくまで啓蒙活動を留めるというのが良いように思います。
しかしチームにそもそもテストを書く習慣がない、といった事情には話は変わるかもしれません。チーム状況に合わせて、どのような運用をすればよいか考える必要があります。

コードサンプルについて

hiroaki404/tddKotlinにコードサンプルを載せています。
セッションはsecondStepまでの紹介で、thirdStepにローディングのテスト、lastに季節でのクエリーの機能を、もちろんTDDで実装しています。
lastではTurbineのテストでexpectMostRecentItem()を使っています。
こちらを使うとstateFlowの最後の値だけ検証できるようになります。
skipItem()やawaitItem()を使うやり方だと、内部実装に寄ってしまうと思うので、こちらを使うと脆くないテストを書くことができると思っています。
thirdStep以前はawaitItem()を使ったやり方のテストとなっているので注意してください。

Fakeについて

これは深くなるので、また機会がありましたら話すか、記事にしたいと思います。
セッションではViewModelのテストしか紹介する時間がなかった関係上RepositoryはFakeを使いましたが、
実際のクラスを使ったほうがよいこともあります。
ViewModelが複雑になってきた場合にRepositoryにFakeを使い、ViewModelクラスの検証に集中するのが良いと思っています。

Flowのテストについて

Flowの出力をテストから制御する内容を説明しましたが、
あまりやりすぎると内部実装に深く寄ってしまう事があるのではないかと思います。
簡単なところは同期的に値を返すようにして、乱用しすぎないようにしましょう。

ViewModelの実装について

initブロックが良くないという話をしましたが、Googleでもよくないとされています。

また、ViewModelの設計パターンは、こちらの記事も役に立ちます。シリーズでは、やるべきこと、やってはいけないことが書かれています。初回で、initブロックを避けるというテーマが書かれています。
Mastering Android ViewModels: Essential Dos and Don’ts Part 1 🛠️ | by Reza | ProAndroidDev

参考文献について

以上挙げて来ましたがここでもまだ言い足りない部分があります。やはり文献にあたってみることをおすすめします。
共有スライドではハイパーリンクが押せないので、こちらからたどると早いと思います。

Android developer guide

参考にしたリポジトリ
android/nowinandroid
android/architecture-samples
DroidKaigi/conference-app-2023

おわりに

こういう公の場で技術の発表をするのは初めてだったので、良い経験になりました。
大変でしたが、正確性を機するためいろいろな資料に目を通していったり、サンプルを作ったりしました。
その中で学びとなり、テストに関して自信を持つことができたので、やはり技術をアウトプットする機会を持つことは大事だと思いました。
機会があればまた挑戦したいと思います。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?