2020/12/03 このエントリーをはてなブックマークに追加 はてなブックマーク - KotlinのsortedByを使っているとIntelliJ IDEAのテストカバレッジ機能が変になるっぽい

KotlinのsortedByを使っているとIntelliJ IDEAのテストカバレッジ機能が変になるっぽい

カテゴリ:

Kotlinアドベントカレンダー2020(https://qiita.com/advent-calendar/2020/kotlin)の3日目の記事です。






あのー、みんな書いて!僕よりもKotlinキャッキャッ楽しいしてるビギナーとかの人でも全然書いて良いと思うんです。
アドベントカレンダーって割と誰が書いてもいいし誰が書いても注目が集まる良い場だと思ってるので、興味関心がある人は是非に書いてほしい。


とまぁ、前置きはこんなところで。

Kotlinには関数をインライン化するための修飾子があります。inlineです。
この修飾子をつけておくことで、Javaのクラスバイナリにコンパイルされた時にいい感じにインライン展開してくれる的なやつですね。
ただし、インライン関数の特定のラムダ引数はインライン化したくない場合などもあると思います。その場合はnoinline修飾子を指定することで対処可能です。
また、インライン関数で引数として渡すラムダがインラインされると別のラムダやオブジェクトのコンテキストから呼び出すことが難しくなります。そのため、インライン関数の引数をcrossinline修飾子でマークしたりします。
とても雑に書いてしまったんですが、このあたりは公式サイトかKotlinインアクションに詳しいことが載ってた記憶があるのでそちらを参照ということで…!


で、どうやらinlineとcrossinlineが使われてる関数を呼び出すコードをテスト対象として実行するとファイル内の全てのカバレッジが取れなくなるようでした。
具体的には、今回遭遇したのはsortedByという関数。
ちなみにsortedByはこんな感じです。

inline fun <T, R : Comparable<R>> Array<out T>.sortedBy(
    crossinline selector: (T) -> R?
): List<T>
inline fun <T, R : Comparable<R>> Iterable<T>.sortedBy(
    crossinline selector: (T) -> R?
): List<T>

これに限らずinlineとcrossinlineを使ってる関数を呼び出してる場合に発生するのではと思ってます(もしかして単なるインライン関数でも発生する?)。

  • ItrableやMutableListの拡張関数で
  • かつcrossinlineの場合のみ起こっている

ことまでは調査した感じわかりました。
groupingByでは同事象が再現したけど、自分でインライン関数作成したりてきとうな拡張関数作成してもなかなか再現しなかった…。

ちなみにこれはIntelliJ IDEAのIDE側のカバレッジをサクッと試してみるかーって感じだったので他のカバレッジツールで同じ事象が起こるか分かりません。
検証全然してなくて申し訳ない🙏


Kotlinコード上で実装とインライン化された実際のコードシグネチャが不一致になってカバレッジの対応付けが出来ないんじゃないかなと予想しました。これは全然内部実装を追ってないので合ってるか分かりません。単にIntelliJ IDEAのIDE機能が対応しきれてないとも言えます。これは本当は既存のissueがあるか確認した上でyoutrackに投げるみたいなムーブが望ましそうなんですが…ちょっとやれる人是非やってみてください!(他力本願)


いい解決方法は思いつかないんですが(すみません)、一応誰でも思いつきそうなワークアラウンドを書いておきます。

1、sortedByを使わずsortedWithとかにする


sortedWithに書き換えることで解決や!
とはいえ、プロダクションコードいじりたくないな…

2、sortedBy使ってるところのテストは通さない


テスト時に呼び出さなければカバレッジ表示がおかしくはならんのや!しかし、これだと色々テストしたいのにテストコード側で調整しないとダメか…となってしまいますね。


ということで、微妙な挙動についての話でした!モヤモヤする内容ですみません!(正直ネタがなかった…!)

最後に、申し訳程度にKotlinビギナー向け情報収集場所でも書いてみます。

0 件のコメント:

コメントを投稿

GA