137

この質問は、単体テスト フレームワークxUnit.net に関するものです。

テストを実行する前にいくつかのコードを実行する必要があり、すべてのテストが完了した後にもいくつかのコードを実行する必要があります。グローバルな初期化および終了コードを示す何らかの属性またはマーカー インターフェイスが必要であると考えましたが、それらを見つけることができませんでした。

または、xUnit をプログラムで呼び出すと、次のコードを使用して目的を達成することもできます。

static void Main()
{
    try
    {
        MyGlobalSetup();
        RunAllTests();  // What goes into this method?
    }
    finally
    {
        MyGlobalTeardown();
    }
}

グローバルなセットアップ/分解コードを宣言的またはプログラム的に実行する方法について、誰かヒントを教えてもらえますか?

4

5 に答える 5

166

私の知る限り、xUnit にはグローバルな初期化/ティアダウン拡張ポイントがありません。ただし、作成するのは簡単です。実装するベース テスト クラスを作成し、コンストラクターで初期化を実行し、メソッドIDisposableでティアダウンを実行するだけです。IDisposable.Disposeこれは次のようになります。

public abstract class TestsBase : IDisposable
{
    protected TestsBase()
    {
        // Do "global" initialization here; Called before every test method.
    }

    public void Dispose()
    {
        // Do "global" teardown here; Called after every test method.
    }
}

public class DummyTests : TestsBase
{
    // Add test methods
}

ただし、基本クラスのセットアップと破棄のコードは呼び出しごとに実行されます。これはあまり効率的ではないため、望ましくない場合があります。より最適化されたバージョンでは、IClassFixture<T>インターフェイスを使用して、グローバルな初期化/ティアダウン機能が 1 回だけ呼び出されるようにします。このバージョンでは、テスト クラスから基本クラスを拡張するのではなく、フィクスチャ クラスを参照するIClassFixture<T>インターフェイスを実装します。T

using Xunit;

public class TestsFixture : IDisposable
{
    public TestsFixture ()
    {
        // Do "global" initialization here; Only called once.
    }

    public void Dispose()
    {
        // Do "global" teardown here; Only called once.
    }
}

public class DummyTests : IClassFixture<TestsFixture>
{
    public DummyTests(TestsFixture data)
    {
    }
}

これにより、コンストラクターはTestsFixtureテスト対象のクラスごとに 1 回だけ実行されます。したがって、2 つの方法のどちらを選択するかによって異なります。

于 2013-05-16T14:48:16.560 に答える
14

簡単で簡単な解決策があります。Fody.ModuleInit プラグインを使用する

https://github.com/Fody/ModuleInit

これは nuget パッケージであり、インストールするとModuleInitializer.cs、プロジェクトに呼び出される新しいファイルが追加されます。ここには、ビルド後にアセンブリに織り込まれ、アセンブリが読み込まれるとすぐに何かが実行される前に実行される静的メソッドが 1 つあります。

これを使用して、購入したライブラリのソフトウェア ライセンスのロックを解除します。私はいつも、各テストでライセンスのロックを解除するのを忘れていました。さらに、ライセンスのロックを解除する基本クラスからテストを派生させるのを忘れていました。このライブラリを作成した輝かしい火花は、ライセンスがロックされていることを伝えるのではなく、微妙な数値エラーを導入し、テストが失敗したり、テストをパスしたりしてはいけません。ライブラリのロックを正しく解除したかどうかはわかりません。だから今、私のモジュールの初期化は次のようになります

/// <summary>
/// Used by the ModuleInit. All code inside the Initialize method is ran as soon as the assembly is loaded.
/// </summary>
public static class ModuleInitializer
{
    /// <summary>
    /// Initializes the module.
    /// </summary>
    public static void Initialize()
    {
            SomeLibrary.LicenceUtility.Unlock("XXXX-XXXX-XXXX-XXXX-XXXX");
    }
}

このアセンブリに配置されたすべてのテストでは、ライセンスが正しくロック解除されます。

于 2014-03-26T12:10:58.107 に答える
12

複数のクラス間で SetUp/TearDown コードを共有するには、xUnit のCollectionFixtureを使用できます。

見積もり:

コレクション フィクスチャを使用するには、次の手順を実行する必要があります。

  • フィクスチャ クラスを作成し、スタートアップ コードをフィクスチャ クラス コンストラクターに配置します。
  • フィクスチャ クラスでクリーンアップを実行する必要がある場合は、フィクスチャ クラスに IDisposable を実装し、Dispose() メソッドにクリーンアップ コードを配置します。
  • コレクション定義クラスを作成し、[CollectionDefinition] 属性で装飾して、テスト コレクションを識別する一意の名前を付けます。
  • コレクション定義クラスに ICollectionFixture<> を追加します。
  • テスト コレクション定義クラスの [CollectionDefinition] 属性に指定した一意の名前を使用して、コレクションの一部となるすべてのテスト クラスに [Collection] 属性を追加します。
  • テスト クラスがフィクスチャ インスタンスにアクセスする必要がある場合は、それをコンストラクタ引数として追加すると、自動的に提供されます。
于 2015-11-04T07:40:38.787 に答える
3

グローバルな初期化関数とグローバルなクリーンアップ関数が 1 つある場合は、次のようにクラスを記述できます。

[CollectionDefinition("TestEngine")]
public class TestEngineInitializer: IDisposable, ICollectionFixture<TestEngineInitializer>
{
    public TestEngineInitializer()
    {
        MyOwnTestEngine.Init();
    }

    public void Dispose()
    {
        MyOwnTestEngine.Cleanup();
    }
}

そして、この初期化を実行する必要がある各テスト クラスに対して、追加の属性を追加する必要があります。

[Collection("TestEngine")]
public class MyTests
{

重要:CollectionおよびCollectionDefinition-attributes で使用される名前は一致する必要があります。

たとえば、次のように、TestEngine クラス インスタンスをコンストラクターに提供することもできます。

[Collection("TestEngine")]
public class MyTests
{
     public MyTests(TestEngineInitializer initializer)
     {
     }

ただし、これは必須ではありません。

問題に関するドキュメント全体は、次の場所にあります。

https://xunit.net/docs/shared-context

于 2020-11-26T13:50:45.613 に答える