2011-02-18 24 views
28

鑑於這種測試夾具:強制MSTest的使用單個線程

[TestClass] 
public class MSTestThreads 
{ 
    [TestMethod] 
    public void Test1() 
    { 
     Trace.WriteLine(Thread.CurrentThread.ManagedThreadId); 
    } 

    [TestMethod] 
    public void Test2() 
    { 
     Trace.WriteLine(Thread.CurrentThread.ManagedThreadId); 
    } 
} 

運行通過Visual Studio或命令行MSTest的測試打印的兩個不同的線程編號(但他們被依次無論如何運行)。

有沒有辦法強制MSTest使用單線程來運行它們?

+3

需要相同的應用程序UI線程上運行,因爲它們都必須使用自動化UI測試一個單一的靜態WPF應用程序類,不能實例化多次(WPF的限制,不是我的)。該技術適用於NUnit。 – 2011-02-18 04:10:47

+1

我通過爲每個測試創建一個新的appdomain,在該appdomain內執行測試主體,並在每個測試中創建一個新的App實例來解決此問題。我可以看到爲什麼在大多數情況下這會很痛苦,但就我而言,我編寫了自己的應用程序類,所以我沒有通過添加樣板文件來重複任何測試。 – 2011-03-29 02:50:02

+0

另外,如果你正在分享一個應用程序實例,理論上你可以爲它創建一個UI線程,並分享它。 – 2011-03-29 02:53:14

回答

10

爲了讓MSTest在一個大型項目上以單線程模式運行,我使用了nhibernate,並且它不是線程安全的(不是問題,它不是)ISession。

我們結束了更多的時間編寫代碼來支持MSTest的多線程性質,因爲 - 爲了我和我的團隊最好的知識 - 無法在單線程模式下運行MSTest。

1

雖然這是一個警察出來的答案,但我實際上鼓勵你讓你的代碼線程安全。理查德指出,MSTest的行爲是爲了確保隔離。通過單元測試遇到問題,您證明將來可能會出現一些問題。

你可以忽略它們,使用NUnit或者處理它們並繼續使用MSTest。

2

我們盡力做出彼此隔離的測試。他們中的許多人通過設置數據庫的狀態,然後恢復它來實現這一點。雖然大多數測試都設置了不同的數據,但在運行中大約有10,000個,除非測試的代碼編寫者確保其初始數據是唯一的(即不使用相同的主鍵)測試做類似的事情)。坦率地說,這是難以管理的,而且我們確實會偶爾發生第二次測試失敗。我相當肯定這是由避免嚴格按順序運行測試的碰撞造成的。

19

我解決了這個問題,鎖定:

public static class IntegrationTestsSynchronization 
{ 
    public static readonly object LockObject = new object(); 
} 

[TestClass] 
public class ATestCaseClass 
{ 
    [TestInitialize] 
    public void TestInitialize() 
    { 
     Monitor.Enter(IntegrationTestsSynchronization.LockObject); 
    } 

    [TestCleanup] 
    public void TestCleanup() 
    { 
     Monitor.Exit(IntegrationTestsSynchronization.LockObject); 
    } 

    //test methods 
} 

// possibly other test cases 
2

您可以從

public class LinearTest 
{ 
    private static readonly object SyncRoot = new object(); 

    [TestInitialize] 
    public void Initialize() 
    { 
     Monitor.Enter(SyncRoot); 
    } 

    [TestCleanup] 
    public void Cleanup() 
    { 
     Monitor.Exit(SyncRoot); 
    } 
} 
0

我嘗試了一下不同的方式獲得您的測試類,因爲基礎問題是管道的名稱是問題。所以我製作了一個假的Pipe,從我在程序中使用的那個派生出來。並用測試名稱命名管道。

[TestClass] 
public class PipeCommunicationContractTests { 
    private PipeDummy pipe; 

    /// <summary> 
    ///Gets or sets the test context which provides 
    ///information about and functionality for the current test run. 
    ///</summary> 
    public TestContext TestContext { get; set; } 

    [TestInitialize] 
    public void TestInitialize() { 
    pipe = new PipeDummy(TestContext.TestName); 
    pipe.Start(); 
    } 

    [TestCleanup] 
    public void TestCleanup() { 
    { 
    pipe.Stop(); 
    pipe = null; 
    } 
    ... 
    [TestMethod] 
    public void CallXxOnPipeExpectResult(){ 
     var result = pipe.Xx(); 
     Assert.AreEqual("Result",result); 
    } 
} 

這似乎是有點快,因爲我們可以在多個內核和線程運行...