VS2015 の IntelliTest を調べた 後編

kendik.hatenablog.com

前回の続きです。自分でもびっくりするほど尻すぼみで前後編に分けた意味がなかったです。

IntelliTest のテストコードでできること

前回までで見てきたとおり、 IntelliTest のテストコードには前提条件とアサーション (表明) を書くことが出来ますし、テストケースはそれを反映して作られます。ここらへんを使うと契約プログラミングが出来ますね。

さて、契約プログラミングと言えば Code Contracts で、実際 Pex も Code Contracts と連携するらしいんですが、 Code Contracts が動いてくれなかったのでよく分かりませんでした。 github から拡張落としてくれば VS2015 サポートって書いてあるんですけどなぜか動かず。。。 RTM になったらまた試します。

苦手なテスト

で、そんな便利な IntelliTest ですが、対象が何でもテストケースを適切に作ってくれるわけではなく、苦手なテストも存在します。

www.slideshare.net

こちらのスライドが非常に分かりやすいので説明はそちらに譲るとして、一覧するとこんな感じです。

まぁ (一部例外はあるものの) 普通にユニットテストを書くにあたって気をつけるべき点がそのまま当てはまると思えばよいと思います。

IntelliTest の制限

IntelliTest にはいくつか制限があります。

Enterprise Edition 限定

あーまーそーですよね、、、って感じ。
Fakes だって今でも Ultimate 限定な訳ですし。まぁもうこれに関してはいつものことなので言ってもしゃーないです。

テスト生成対象は .NET コード (マネージド) のみ

後述しますが IL 操作してテストケースを生成するので、対象はマネージコードのみです。

自動生成されるテストの言語は C#

だそうです。

マルチスレッドや浮動小数点数演算はテスト不可

マルチスレッドはまぁわかりますが、浮動小数点数演算がダメってのはなんででしょうね。

MSTest のみが対象

MSDN に明記してあります。マジかー。
ただ、 Pex は NUnit などにも対応しているのでおそらくそう遠くないうちに対応してくれるんじゃないでしょうか (と、期待)。対応を待ちきれない人は こちら で vote しまくってください。私もしました。

テストケース生成の仕組み

kazuktnd.wordpress.com blogs.msdn.com Visual Studio 2015 - Smart Unit Tests によるソフトウェア ビルド効率の向上

↑ を読んでなんとなく理解したことを書きます。どこまで正しいかは分かりません。難しいことは分からないのであくまでおまけ。詳しくご存じの方のフォローを待ちます。

1. テスト対象コードのインストルメンテーション

チュートリアル : インストルメンテーションを使ったコマンド ライン プロファイリング

テスト対象コードにプロファイリングのためのコードを埋め込みます。 もちろん実際にテスト対象のソースコード (.cs) が書き換わるわけではなく、 IL 書き換えです。

2. テストエンジンによる実行監視

実際に単純な入力を行ってテスト対象を走らせます。 特定の入力に対してテスト対象コードのカバレッジがどうなるかをテストエンジンが監視し、入力値と分岐処理の間にある依存関係を分析します。

3. 制約システムの構築とテストケースの生成

Constraint Solver というモジュールに問い合わせを行い、制約に基づいた新しいテストケースを生成します。 Constraint Solver というのが何者なのかははっきりは分かりませんが、おそらくここらへんで Code Contracts が関わってくるのかなーと想像。

4. 探索

2 と 3 のプロセスのことを「探索」と呼ぶようです。
C0 カバレッジが 100% になるか、事前に設定しておいた探索回数の制限を超えるまで探索処理を繰り返し行います。 なので、テスト対象コードは何度も実行されることになります。仮に最終的に生成されるテストケースが N 個だとしても、その N 個を生成するためにそれ以上の数のテストを実行します。実行回数が VS 上に表示されるのですが、基本的に 100 回は実行してるみたいですね。後述しますがこの回数も操作できます。

探索の制限

探索処理は、テスト対象コードの実装によっては実行パスがほぼ無限になることがありえるので、事前に制限を課すことが出来ます。

  • Constraint Solver への制限
    • 入力値の検索に使用できる時間とメモリを制限
  • 探索パスの制限
    • 分岐数、チェックする必要がある入力に対する条件の数、実行パスの深さ(スタックフレーム数)の制限
  • 探索そのものの制限
    • 最終的にテストケースを生成しないテストの実行回数、実行回数、探索停止までの時間の制限

この当たり全部は見れていませんが、 PexAttributeBase を継承した属性郡で操作を行うようです。

まとめ

IntelliTest でユニットテストの自動生成ができるようになりました。

なりましたが、実績値の評価は人力ですし、契約を記述して自動で検証することはできるものの特定の入力に対する実績値の検証はできません (極論、例えば複雑な四則演算を行うメソッドが本当に正しく実装できてるか分からない)。ですので、 IntelliTest は今までのユニットテストを置き換えるものでなく補助するものと考えたほうがいいでしょう。

とりあえず契約と意図しない例外が飛ぶかどうかといったポカミス的バグはわかるので、参考資料にもあったのですが、ユニットテストへの工数をいくらか削減しつつそこで浮いた工数を結合テストなどのより機能品質に直結するテストに使うのが賢いやり方だと思います。この結果にガッカリする人もいるかもしれませんが、これで「やっぱり結合テスト重要だよね」って流れになればいいなぁと個人的には思います。ソフトウェアテストの焦点が次のフェーズに進めるようになると考えればとても良い機能だと思います :) 。早くリリースされないかなぁ (Enterprise 限定だから私は使えないんですけどね!)

参考

コードの単体テストの生成 - MSDN
【VisualStudio チュートリアル】IntelliTest - MSDN
Smart Unit Tests - a mental model - Developer Tools Blogs
Smart Unit Tests によるソフトウェア ビルド効率の向上 - MSDN Magazine
Using Smart Unit Tests To Find Bugs Earlier In The Development Cycle - Channel 9
Manuel Fahndrich and Peli de Halleux - The Synergy of Code Contracts and Pex - Channel 9
Visual Studio 2015 の新機能: Pex はユニットテストの福音となるか!? - SlideShare
定量的な数値を追い求めるマネージャーを助けてあげる方法 -Visual Studio 2015 の Smart Unit Tests - - Qiita
Smart Unit Tests (Preview) and Conway's Game of Life - Jeremy Bytes
VS2010 後の世代のプログラミング (2) Pex - kazuk は null に触れてしまった