FsCheckのこまごまとしたこと #FsAdvent

全国のF#erの皆様こんにちは、もみあげことなかやんぺんぎんです。

ここからは F# Advent Calendar 2014の延長戦(25日目)です。 英語圏と張り合ってるわけじゃ、ないんだからね!?

今回は今年めでたく正式版がリリースされた FsCheck についてちょっとした変更点などの紹介です。

利用実績

名古屋某社のいくつかのプロジェクトで利用実績があります。 OSS での利用例は…たくさんあるので割愛します。

FsCheck の target .NET Framework verison

FsCheck は Release Note 的には 1.0.0 より(実際は 0.9.3 あたりからだった気がする)、.NET Framework 4.5 以降のみをサポートするようになりました。 これは、 コード内で使われている ExceptionDispatchInfo が 4.5 以降にしかない機能だからです。 まぁ、テストプロジェクトのバージョンが指定されることはほとんどないので、レガシー環境でない限りはそんなに気にならないかと。

string generator の挙動

0.9.3 までは、Default で提供されている string generator は null を入力として含みませんでしたが、 0.9.4 からは null も生成対象になりました。

これはこれで正しいと思う一方で、面倒くさい null を生成しない generator がほしいという意見もちらほら見かけました。

そこで、 1.0.4 からは NonNull 型を導入することで、null を含まない ランダムな値の生成が可能になりました。 たとえば string なら

  check <| fun (s: NonNull<string>) ->
    let s = s.Get // 値の取得
    ...

こんな感じにすればよいです。 いちいち束縛するのが面倒な場合はアクティブパターンでいい感じにするとはかどるかもしれません。

let (|NonNullStr|) (s: NonNull<string>) = s.Get

...

  // s は string
  check <| fun (NonNullStr s) ->
    ...

IRunner と 拡張ライブラリ

他テスティングフレームワークと連携する方法としては、0.9系までは IRunner を実装する一択だったわけですが、 1.0.0 以降は FsCheck.NUnit や FsCheck.Xunit という拡張ライブラリが登場したため、簡単に使いたいならこれらのライブラリを使うほうが楽です。

とはいえ、出力の制御をおこないたい場合などはやっぱりIRunner を実装する必要があるのでお役御免というわけではないです。

FsCheck.NUnit と FsCheck.Xunit

NUnit と Xunit は公式から拡張ライブラリが公開されています。

このライブラリを入れることでどのように記述がかわるのかは…具体例を見てみましょう。

https://github.com/pocketberserker/FsAttoparsec/commit/5b8861f95ebdadf8a57b4c8cb8402788b8be9f59

FsCheckAddin 型の部分が FsCheck.NUnit をインストールした際についてくるコードです*1

上記コードで目立つ変更点としては、 NUnitTestAttribute から FsCheck.NUnitPropertyAttribute に変わっているところでしょうか。 PropertyAttribute を使うことで、テストごとの設定を変更できたり、ラムダ式を使わずにテストできます。 変更できる値は

  • MaxTest
  • MaxFail
  • StartSize
  • EndSize
  • Verbose
  • QuietOnSuccess
  • Arbitrary

です。各設定の意味については公式ドキュメントを読んでください。

FsCheck.Xunit のみの機能として、 ArbitraryAttribute が存在します。 こいつはクラスやモジュールをターゲットに、 Arbitrary を指定できるものです。 NUnit 拡張にはこの機能はないので、いちいちメソッドに Arbitrary を書くか、 Arb.register するしかありません(後者はグローバル汚染しちゃうけど…)。

2014/12/24 時点での NUnit の注意事項

完全に余談ですが、2014/12/17 に NUnit 2.6.4 がリリースされました。

が、対応する NUnit Test Adapter(Visual Studio拡張)がまだなく、かつ FsCheck.NUnit との相性が悪いのか、VS Test Explorer 上でテストが実行できません。

でも NUnit.Runners 2.6.4 に同梱されている nunit-console なら実行できるだろうと慢心していましたが、こちらはこちらで "nunit-core-interface 2.6.3 をよこせ"と言って落ちる…。

というわけで、いろいろ環境が追いつくまでは大人しく 2.6.3 を使いましょう…。

CSharp Wrapper

あるらしいですが、使ったことがないので使用感がわからず…そのうち試してみたいところです。

MSTest 用の拡張もあるらしいです。

ツールや環境整備

1.0.0 リリースのタイミングで整備されました。 具体的には

  • FAKE を使って自動リリース
  • FSharo.Formatting によるドキュメント作成
  • non Windows 環境での mono でのビルド
  • CIサービス(AppVeyor, Travis)との連携

です。 最近の オープンソース F# プロジェクトはだいたい正式リリースまでの間にこの辺りを用意するみたいですね。*2

その他

README の一説に以下の記述があります。

Since v0.5, scalacheck has influenced FsCheck as well. Scalacheck is itself a port of QuickCheck to Scala.

FsCheck はだいたい QuickCheck と scalacheck の影響を受けている、と。 出現時期がわかる一文ですね。

おわりに

良い property based test ライフを!

*1:本来は別のファイルに入っているのですが、FsAttoparsecでは移動させました

*2:私は FAKE は使わないことにしていますが…