5

基本的に2つのスレッドを実行する単体テストのサンプルコードがあります。メインのテストスレッドと、しばらくしてからテストの実行に失敗するはずの起動中の別のスレッドです(これは基本的にタイムアウトスレッドです)。

コードは次のとおりです。

[TestClass]
public class SomeTestClass
{
    [TestInitialize]
    public void BeforeTest()
    {
        var task = new Task(abortIfTestStilRunsAfterTimeout);
        task.Start();
    }

    [TestMethod]
    public void TestMethod()
    {
        Thread.Sleep(5000);
    }

    private void abortIfTestStilRunsAfterTimeout()
    {
        Assert.Fail("timeout passed!");

    }
}

テストが失敗することを期待していましたTestMethod()が、実際には、Assert.Failメソッドを実行するタスク スレッドが例外を取得し、他のスレッドが実行を続けてテストに合格するということが起こります。

テストメソッドを失敗させる方法を探しています

4

3 に答える 3

3

テストスレッドへの参照を取得して呼び出すことができますAbort()Abort()失敗メッセージを渡すために使用できる例外状態オブジェクトを渡すことができます。

[TestClass]
public class SomeTestClass
{
    Thread testThread;

    [TestInitialize]
    public void BeforeTest()
    {
        testThread = Thread.CurrentThread;
        var task = new Task(abortIfTestStilRunsAfterTimeout);
        task.Start();
    }

    [TestMethod]
    public void TestMethod()
    {
        try
        {
            Thread.Sleep(5000);
        }
        catch (ThreadAbortException e)
        {
             Assert.Fail((string)e.ExceptionState);
        }
    }

    private void abortIfTestStilRunsAfterTimeout()
    {
        testThread.Abort("timeout passed!");
    }
}

100個のテストを変更したくない場合は、PostSharpなどのツールを使用して、try {} catch {}各テストケースの周囲にロジックを挿入することでテストケースを変更できます。つまり、属性を記述し、それを使用してテストアセンブリを装飾するだけです(アスペクト指向プログラミングと呼ばれ、PostSharpのフレームワークはLaosと呼ばれます)。

于 2012-04-10T09:12:37.077 に答える
1

アイデアは単純です。タスク/スレッドでメインのテスト ロジックを実行し、タイムアウト処理コードをテスト メソッド/テストの初期化に配置するだけです。ある種の制御の反転:

// Test class level
ManualResetEvent mre = new ManualResetEvent(false);                                

[TestMethod]     
public void TestMethod()     
{                     
    // start waiting task
    Task task = Task.Factory.StartNew(() =>
        {
            // Test Body HERE!
            // ... 

            // if test passed - set event explicitly
            mre.Set();
        });


    // Timeout handling logic, 
    // !!! I believe you can put it once in the TestInitialize, just check
    // whether Assert.Fail() fails the test when called from TestInitialize
    mre.WaitOne(5000);

    // Check whether ManualResetEvent was set explicitly or was timeouted
    if (!mre.WaitOne(0))
    {
        task.Dispose();
        Assert.Fail("Timeout");
    }                
}                    

PS:WaitOne(0)トリックについて、MSDN

millisecondsTimeout がゼロの場合、メソッドはブロックされません。待機ハンドルの状態をテストし、すぐに戻ります。

于 2012-04-10T09:09:56.633 に答える