定量的な数値を追い求めるマネージャーを助けてあげる方法 -Visual Studio 2015 の Smart Unit Tests -


リーダとマネージャーの違い。

リーダとマネージャーの違いは、現状を打破した人間と現状に屈伏した人間の違いだと言われています。
この他にも、両者はいくつかの重要かつ決定的な点で異なります。

  • マネージャーは管理し、リーダは改革する。
  • マネージャーはコピーであり、リーダはオリジナルである。
  • マネージャーは維持し、リーダは発展させる。
  • マネージャーはシステムと構造に焦点をあわせ、リーダは人間に焦点をあわせる。
  • マネージャーは管理に頼り、リーダは信頼を呼び起こす。
  • マネージャーは目先のことしか考えず、リーダは長期的視点を持つ。
  • マネージャーは「いつ、どのように」に注目し、リーダは「何を、なぜ」に注目する。
  • マネージャーは数字を追いかけ、リーダは未来を見据える。
  • マネージャーは模倣し、リーダは創造する。
  • マネージャーは現状を受け入れ、リーダは現状に挑戦する。
  • マネージャーは優秀な軍人であり、リーダはその人自身である。
  • マネージャーはものごとを正しく処理し、リーダは正しいことをする。

「リーダーになる ON CECOMING A LEADER ウォレン・ベニス」より。

マネージャーは数字を追いかけます。それは仕方のないことです。
だって説明責任ですから。
説明するには数値が手っ取り早いし、論理的です。数字は嘘をつかないはず。

プログラムの場合、カバレッジという指標があります。
真偽はともかく、カバレッジが高ければ、それなりの品質だということです。
確かに何かにすがりたい気持ちはわかります。

はい、朗報です。
そんなマネージャーを間接的に助けるツールがVisual Studio 2015に搭載されます。(ただし、Ultimateなどの上位エディション限定だと思われます)
※この記事は、Visual Studio 2015 CTP6で試しています。

Smart Unit Testsです。
旧名:Pex

一言で言うと、コードのカバレッジを上げるためのUnitTestコードを自動で作成してくれます。
コードのカバレッジX%以上という自業自得ルールを作ってしまったけど、なかなかそれを達成できないチームに対して、ものすごいパワーを発揮してくれると思います。

使い方

簡単な例で恐縮ですが、フィボナッチ数列を求めるコードがあるとします。これのカバレッジを高めましょう。

fibonacci.cs
namespace FibonacciSample
{
    public class Fibonacci
    {
        public decimal Calc( int n)
        {
            if (n == 0)
            {
                return 0;
            }
            if (n == 1)
            {
                return 1;
            }
            return Calc(n - 1) + Calc(n - 2);
        }

    }
}

テストケースは数パターンでしょうか。
Visual Studio上で、 メソッド上にキャレットを置き、右クリックすると「Smart Unit Tests」というコンテキストメニューが出てきます。

そうすると、何やら「Smart Unit Test Exploration ウィンドウが表示され、計算しています。
数秒待つと、以下の結果が表示されます。

テストケースを5つ作ってくれたみたいです。各行を選択すると、Detailsに、テストコードらしきものが!
targetにテストクラス名
nは、引数
resultには 結果の値が表示されています。

Saveアイコンを押すと、自動的にテストモジュールを作ってくれます。

残念なのが、テストコードのインデントがおかしいです。(CTP版だからでしょうか?)

テストコードのファイルは、自動生成コードだとわかるように、
FibonacciTest.Calc.g.cs
という命名になっています。

PexClass
PexAllowedExceptionFromTypeUnderTest
PexMethod
PexAssumeUnderTest

と言った様々な属性が登場しますが、あんまり考えなくてもいいかも知れません。
仕組みはNUnitの
http://www.nunit.org/index.php?p=testCaseSource&r=2.5
TestCaseSourceと似ている感がありますね。

自動生成されるPexAssemblyInfo.csに興味深いコードがありました。

PexAssemblyInfo.cs
// <copyright file="PexAssemblyInfo.cs">Copyright ゥ  2015</copyright>
using Microsoft.Pex.Framework.Creatable;
using Microsoft.Pex.Framework.Instrumentation;
using Microsoft.Pex.Framework.Settings;
using Microsoft.Pex.Framework.Validation;

// Microsoft.Pex.Framework.Settings
[assembly: PexAssemblySettings(TestFramework = "VisualStudioUnitTest")]

// Microsoft.Pex.Framework.Instrumentation
[assembly: PexAssemblyUnderTest( "FibonacciSample")]

// Microsoft.Pex.Framework.Creatable
[assembly: PexCreatableFactoryForDelegates]

// Microsoft.Pex.Framework.Validation
[assembly: PexAllowedContractRequiresFailureAtTypeUnderTestSurface]
[assembly: PexAllowedXmlDocumentedException]

TestFramework ?

これはNUnit使えるのではないか?
・・・と思ったらできそうです!Visual Studio統合には対応していないかも知れませんが。
http://pex.codeplex.com/wikipage?title=NUnit%20Extension&referringTitle=Home
これはまた別の機会に・・・。


Testメニューから、Analyze Code Coverageで、コードカバレッジを計測してみます。

テストはすべて成功し、カバレッジ100%! 
気持ちいい!!
※カバレッジ計測はVisual Studio Premiumエディション以上じゃないと計測できませんのでご注意ください。

メリットとデメリット

メリット

なんといっても自動で生成してくれることですね。テストケースの思案に一役買ってくれる感もあります。
ただ、そんなに複雑なメソッドになるならリファクタしようとということになるので、
「レガシーコードでリファクタ不可、だけどカバレッジを求められる」
という古典企業にありがちなシチュエーションには重宝しそうです。ただそのような場合VS2015は使えないか。。 

デメリット

・Pexの仕組み自体が複雑
・外部リソース(DBやWindowsファイル等)と依存しているメソッドの場合は、テストケースを作れなそう
・機械的すぎる(テストケース名がランダム発番みたいな)
・おそらくVisual Studioの上位エディションのみ利用可能(初期コストが高い)
ということが挙げられると思います。

デザインパターン

Separated-SmartUnitTest

もしSmartUnitTestを使うなら、SmartUnitTestを分離したほうが良いと考えます。
モジュール数は増えて管理が煩雑にはなりますが、以下の様な感じです。

SmartUnitTestは、オプション指定できず、いきなり
プロジェクト名.Tests
というテストプロジェクトを作成してしまうので、
他の命名規則を作り(上の例では"UnitTest") 新たにテストプロジェクトを作成します。
そこに自分で作ったテストを配置し、メンテナンスします。
Pexへの依存も不要になるので、単体でのビルドも軽いです。

Test Explorerで、Project毎にテストケースを表示できるので、PexとPex以外の実行を分けることもできます。
フィルタが色々かけられるので、何にせよ命名規則は重要です。

まとめ

UTは、プログラマにとっての「精神的支柱」です。
UTの良いところは、「自身のコードと真摯に向き合う時間を増やせる」ことですので、Smart Unit Testでテストケースを作っておしまいというのは全く有り得ないと思います。
単に、カバレッジを追い求める場合のみの利用をオススメします。
そのときは、自身のUTとごちゃごちゃにならないように、Separated-SmartUnitTestパターンを用いることをオススメします。

参考サイト

http://blogs.msdn.com/b/visualstudioalm/archive/2014/12/11/smart-unit-tests-a-mental-model.aspx
https://msdn.microsoft.com/en-us/library/dn823749(v=vs.140).aspx
https://msdn.microsoft.com/ja-jp/magazine/dn904672.aspx
http://blogs.msdn.com/b/somasegar/archive/2014/11/12/opening-up-visual-studio-and-net-to-every-developer-any-application-net-server-core-open-source-and-cross-platform-visual-studio-community-2013-and-preview-of-visual-studio-2015-and-net-2015.aspx