2024-04-14

F# の Inline Functions のカバレッジを計測する

最近あんま週末時間取れず開発できてないので小ネタ。

CI test coverage of F# unit tests · Issue #3579 · dotnet/fsharp

この中で触れられてるのだけど、 F# の Inline Functions は code coverage を計測できない。 コンパイル時点で使われてる箇所に inline 展開され、展開前の情報を捨て去るので追えないみたい。 krymtkts/pocof の開発でも Inline を使ってる箇所があって、そこは長らく code coverage 取れないので網羅率がちょっと低くなるという状態だった。

ただ計測のためのちょっとした hack はある。 ここで触れられてる #if ディレクティブ を使って Debug モードのビルドのときだけ inline を外す方法だ。 静的にジェネリック型が解決されるようなパターンだと使えないようだが、 pocof では使えた。 こんな感じ

    let
#if !DEBUG
inline
#endif
private (?->)
(x: PSObject)
(prop: string)
=
try
Some (x.Properties.Item prop).Value
with _ ->
None

ただやっぱコード見た目意味わかんなくなるし Fantomas もフォーマットに困るみたい(ガタガタ)なので、あんま良くないなと。仕方なくやってる。

F# は coverlet とあまり相性いい感じしない。個人的には以下が相性良くないと感じてる点だ。他にもあるんかな。

ここまで来ると F# では code coverage や複雑度などのメトリクスはあまり意識しない方がいいのか?と思えてくる。

FSharplint の issue でも「みんな使ってないし手続き型ほど重要じゃない」という意見で、過去に循環的複雑度の計測をなくしたことがあるみたいだし(復活したようだが)。 cyclomatic complexity removed? · Issue #195 · fsprojects/FSharpLint

code coverage も、テスト書くならどのコードがテストされたかを計測したいのは当然だと思ったが...

pocof の場合で考えたら、毎日連続的に開発してるわけじゃないし、品質を維持できる指標があると、すっぱり忘れてしまってても安心して取り組めるのであった方が良い。

興味は尽きませんな。