p_chinのおっぱいブログ

UnityとPerlなど

SharpUnitの処理の解説~Unity3D_TestRunnnerについて

職場の先輩方がSharpUnitをUnityのテスト用に色々改造してたので、自分もやりたいな〜と思っててコード読んでたけど、一回読んだ内容を忘れて読み直したのでメモしておこう。

一つの記事に全て書くと分かりにくいし長文読むの怠いから、分けて書く。

今回はSharpUnitで各UnitTestの処理をを発火させる所の解説する。

TestRunnerがSharpUnit本家のコード


 

コードに解説を追加した

Unity3D_TestRunnner.cs
void Start() 
{
    // Create test suite
    TestSuite suite = new TestSuite();

    // For each assembly in this app domain
    // 現在のアプリケーションドメインに読み込まれている
    // すべてのアセンブリの完全限定名を表示する
    // この状態でassemをログ出力してもよく分からない
    foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
    {
        // For each type in the assembly
        // ここのtypeをログ出力するとSystem.Genericsとかなじみ深い名前が出てくる
        foreach (Type type in assem.GetTypes())
        {
            // If this is a valid test case
            // i.e. derived from TestCase and instantiable
            // typeがTestCase型を継承してるクラスか調べる
            // TestCase本人はinterfaceだし除外するよ
            if (typeof(TestCase).IsAssignableFrom(type) &&
                type != typeof(TestCase) &&
                !type.IsAbstract)
            {
                // Add tests to suite
                // UnitTestが書いてあるtype情報をTestSuiteに渡してテスト実行して貰おう
                // typeからコンストラクタ探してきてnewしてTestCaseのinstanceを作って引数にしてるよ
                suite.AddAll(type.GetConstructor(new Type[0]).Invoke(new object[0]) as TestCase);
            }
        }
    }

/////TestSuiteのListにたまった全てのUnitTestを走らせる
    // Run the tests
    TestResult res = suite.Run(null);

    // Report results
    Unity3D_TestReporter reporter = new Unity3D_TestReporter();
    reporter.LogResults(res);
}

まとめ(処理の流れ)

  1. アプリケーションドメイン内の全てのアセンブリを取得する

  2. 取得したアセンブリから詳細な型情報を取り出す

  3. 1~2の処理はTestCaseクラスと親子関係にあるクラスの型を炙り出す為の処理だったのだ!!

  4. typeから型のコンストラクタを検索して,newしたTestCaseのinstanceを引数に渡してる

    • superクラスにもbaseクラスも静的型情報が含まれるというc#多様性という性質を利用してる

 

こんな手法が有るのは知らなかった。

ゲームは難しいかもだけど、ツール作る時に役立ちそう。

参考にさせていただいたサイト