ビルド済みアセンブリへの対応

Apr 22, 2011 at 4:44 AM

MSTest 版の話なのですが、故あって、ChainingAssertion.MSTest.cs をビルド済みアセンブリ(仮にtest.dllとします)にして使ってます。

このような状況で、パラメタライズドテストを実行したところ、下記のコードの先でnull参照例外になってしまいました。

var classType = Type.GetType(context.FullyQualifiedTestClassName);

すなわち、このコードがテストプロジェクトのアセンブリでは無く、test.dll に棲息するようになったため、テストクラスの名前で Type.GetType しても、test.dll の中のクラス群を探索することになり、みつからないわけです(結果、classType に null が返されます)。

そこで、いまのところ、下記のように、現在のアプリケーションドメインに読み込まれているすべてのアセンブリを愚直に探索するメソッドを用意して、これを使って classType を求めるようにしました。

public static Type GetTestClassType(this TestContext context)
{
    var testCalssQuery = AppDomain.CurrentDomain.GetAssemblies()
        .Select(asm => asm.GetType(context.FullyQualifiedTestClassName))
        .Where(type => type != null);
    return testCalssQuery.First();
}

以上、そもそも、ビルド済みアセンブリとして使うことを Chaining Assertion 公式プロジェクト本体としてどう考えるかによると思いますが、もし使いでがあるようでしたら、上記コード、使って頂ければ幸いです。

なお、上記コードは、毎回、愚直に全アセンブリを舐めますので、処理速度的には不利です。
もし上記コードに取り組むとしても、もう少しチューニングすべきとは思います(キャッシュするとか、"mscorlib." や "System." などで始まる名前のアセンブリは除外するとか)。

Coordinator
Apr 22, 2011 at 12:00 PM

ありがとうございます。
詳細な原因説明、更には解決策までありがとうございます!
// この辺に疎いので、解説を頂かなければさっくり諦めていたかもです……

TestContext.Runを呼ぶのはテストメソッドだけだと考えると、
各Runメソッドの先頭に

var type = Assembly.GetCallingAssembly()
    .GetType(context.FullyQualifiedTestClassName);

とすることで、正しいTypeが取得できると考えましたが、どうでしょうか。
それで大丈夫そうなら、特に処理の重さとして変わらなさそうなので、組み込みたいと思います。

Apr 22, 2011 at 2:08 PM

ああ、そうか、そうですね。

GetCallingAssembly() メソッドの存在について無知でした。(やはり言ってみるものですね、本題とは逸れるのですが、お陰様で大変勉強になります)

Assembly.GetCallingAssembly() 経由でテストクラスの Type を獲得するということで、問題無いと思います。

先に書きましたとおり、そもそもビルド済みの形態での利用を公式プロジェクトとしてどう捉えるのか("サポートしない"ということだってアリだと思うんです、オーナの指針次第で。)という前段はありますが、もしビルド済みの形態での利用サポートも考えていくのでしたら、はい、上記措置は素敵だと思います。

Coordinator
Apr 22, 2011 at 2:50 PM

csファイル一つのみの配布でやっているのは、それがDLL一つよりも何よりも、一番手軽だから
ということなので、ユーザーにとってDLLの形での利用のほうが便利であるなら、
そうして使えたほうがいいな、と思っています。
VB.NETからとか、を考えるとdllなら使えるけれど.csでは無理ってこともありそうですし。
なので、断然採用です!
とりあえず変更したものをSource Codeのほうには上げましたー。

なので、ビルド済みアセンプリとして使用する場合は、
そちらから取得してビルドして頂ければ。

新しいReleaseは、今回は影響範囲が別アセンブリにした場合のみ、という小さなものなので、
とりあえず見送りで、新しく何か変更を加えて際に一緒に、という形にしたいと思います。

今回は一つ不具合を発見&潰せたということで、ありがとうございました!
今後もよろしくお願いします。