2011-09-05 85 views
1

我們使用WatiN測試了我們想要在CruiseControl.NET服務器上運行的測試。我們已經完成了一個單一的構建。當我們在其他版本中啓用這些測試時,它們在同時運行時會失敗。我們希望避免將所有運行這些測試的構建放在同一個cc.net隊列中,因爲這些測試只是整個構建時間的一小部分。我們還希望避免爲這些測試分開構建項目,因爲這會使cc.net安裝中的構建量翻番。在單個CruiseControl.NET服務器上使用WatiN測試運行並行構建

我們有什麼選擇?

  1. 是否有任何方法可以將這些測試放入自己的cc.net任務中,並將該任務放在隊列中?
  2. 是否有任何msbuild/nant/ccnet任務或任何處理排隊?
  3. 是否有任何命令行工具可以從我們的msbuild腳本運行來處理命令行任務的排隊,以便我們可以使用nunit命令行調用運行我們的測試?
  4. 是否有任何其他智能解決方案來解決這個問題?

如果我們沒有找到任何現有的解決方案來解決這個問題,我們可能會自己建立一些東西,如果是的話,哪個解決方案會被推薦?

編輯: 這是我最後執行互斥:

public class SystemLevelLock : IDisposable 
{ 
    private readonly string _id; 
    private bool _isAquired; 
    private Mutex _mutex; 

    public SystemLevelLock(string id) 
    { 
     _id = id; 
     Aquire(); 
    } 

    public SystemLevelLock() : this(GetApplicationId()) { } 

    private void Aquire() 
    { 
     try 
     { 
      var mutex = GetMutex(); 
      _isAquired = mutex.WaitOne(TimeSpan.FromMinutes(1), false); 
      if (!_isAquired) 
       throw new Exception("System level mutex could not be aquired"); 
     } 
     catch (AbandonedMutexException) 
     { 
      // Mutex was abandoned by another process (it probably crashed) 
      // Mutex was aquired by this process instead 
     } 
    } 

    private Mutex GetMutex() { return _mutex ?? (_mutex = MakeMutex()); } 

    private Mutex MakeMutex() 
    { 
     var mutexId = string.Format("Global\\{{{0}}}", _id); 
     var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow); 
     var securitySettings = new MutexSecurity(); 
     securitySettings.AddAccessRule(allowEveryoneRule); 
     var mutex = new Mutex(false, mutexId); 
     mutex.SetAccessControl(securitySettings); 
     return mutex; 
    } 

    private void Release() 
    { 
     if (_isAquired) 
      _mutex.ReleaseMutex(); 
    } 

    public void Dispose() { Release(); } 

} 

這是使用互斥瀏覽器類的實現。這也使用SpecFlow scenariocontext來存儲瀏覽器實例併爲此場景鎖定。

public static class Browser 
{ 

    public static IE Current 
    { 
     get 
     { 
      if (!IsStarted()) 
       Start(); 
      return ScenarioBrowser; 
     } 
    } 

    private static IE ScenarioBrowser 
    { 
     get 
     { 
      if (ScenarioContext.Current.ContainsKey("browser")) 
       return ScenarioContext.Current["browser"] as IE; 
      return null; 
     } 
     set 
     { 
      if (value == null) 
      { 
       if (ScenarioContext.Current.ContainsKey("browser")) 
        ScenarioContext.Current.Remove("browser"); 
      } 
      else 
       ScenarioContext.Current["browser"] = value; 
     } 
    } 

    private static IDisposable BrowserLock 
    { 
     get 
     { 
      if (ScenarioContext.Current.ContainsKey("browserLock")) 
       return ScenarioContext.Current["browserLock"] as IDisposable; 
      return null; 
     } 
     set 
     { 
      if (value == null) 
      { 
       if (ScenarioContext.Current.ContainsKey("browserLock")) 
        ScenarioContext.Current.Remove("browserLock"); 
      } 
      else 
       ScenarioContext.Current["browserLock"] = value; 
     } 
    } 

    private static void LockBrowser() 
    { 
     BrowserLock = MakeBrowserLock(); 
    } 

    private static void ReleaseBrowser() 
    { 
     BrowserLock.Dispose(); 
     BrowserLock = null; 
    } 

    private static SystemLevelLock MakeBrowserLock() { return new SystemLevelLock("WatiNBrowserLock"); } 

    private static void Start() 
    { 
     LockBrowser(); 
     var browser = new IE(); 
     ScenarioBrowser = browser; 
    } 

    public static bool IsStarted() { return ScenarioBrowser != null; } 

    public static void Close() 
    { 
     try 
     { 
      var browser = ScenarioBrowser; 
      ScenarioBrowser = null; 
      browser.Close(); 
      browser.Dispose(); 
     } 
     finally 
     { 
      ReleaseBrowser(); 
     } 
    } 

} 
+0

請將解決方案添加到您自己的問題中,而不是答案。 –

+0

有人說編輯答案,一些編輯問題=) – MatteS

+0

我更喜歡常識..這是你的問題。如果完整的解決方案是由答案中的其他人提供的,所以它很好。但是,如果您是最終解決方案的參與者,那麼您可以期望它在原始問題中顯示爲後續內容,或者由您單獨回答。 –

回答

1

好像你的測試都不是孤立的。您需要確保測試的設置和運行以及在他們自己的孤立環境中。測試依賴於共享資源嗎?測試/服務器/網址等?

由於你的IE是一個共享資源(你確定它不是該網站)。也許你可以用一個自定義任務來暫停進程,該自定義任務在名爲mutex的系統級別上等待。

編輯: 這是我(遮罩)最終實現互斥的:

public class SystemLevelLock : IDisposable 
{ 
    private readonly string _id; 
    private bool _isAquired; 
    private Mutex _mutex; 

    public SystemLevelLock(string id) 
    { 
     _id = id; 
     Aquire(); 
    } 

    public SystemLevelLock() : this(GetApplicationId()) { } 

    private void Aquire() 
    { 
     try 
     { 
      var mutex = GetMutex(); 
      _isAquired = mutex.WaitOne(TimeSpan.FromMinutes(1), false); 
      if (!_isAquired) 
       throw new Exception("System level mutex could not be aquired"); 
     } 
     catch (AbandonedMutexException) 
     { 
      // Mutex was abandoned by another process (it probably crashed) 
      // Mutex was aquired by this process instead 
     } 
    } 

    private Mutex GetMutex() { return _mutex ?? (_mutex = MakeMutex()); } 

    private Mutex MakeMutex() 
    { 
     var mutexId = string.Format("Global\\{{{0}}}", _id); 
     var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow); 
     var securitySettings = new MutexSecurity(); 
     securitySettings.AddAccessRule(allowEveryoneRule); 
     var mutex = new Mutex(false, mutexId); 
     mutex.SetAccessControl(securitySettings); 
     return mutex; 
    } 

    private void Release() 
    { 
     if (_isAquired) 
      _mutex.ReleaseMutex(); 
    } 

    public void Dispose() { Release(); } 

} 

這是使用互斥瀏覽器類的實現。這也使用SpecFlow scenariocontext來存儲瀏覽器實例併爲此場景鎖定。

public static class Browser 
{ 

    public static IE Current 
    { 
     get 
     { 
      if (!IsStarted()) 
       Start(); 
      return ScenarioBrowser; 
     } 
    } 

    private static IE ScenarioBrowser 
    { 
     get 
     { 
      if (ScenarioContext.Current.ContainsKey("browser")) 
       return ScenarioContext.Current["browser"] as IE; 
      return null; 
     } 
     set 
     { 
      if (value == null) 
      { 
       if (ScenarioContext.Current.ContainsKey("browser")) 
        ScenarioContext.Current.Remove("browser"); 
      } 
      else 
       ScenarioContext.Current["browser"] = value; 
     } 
    } 

    private static IDisposable BrowserLock 
    { 
     get 
     { 
      if (ScenarioContext.Current.ContainsKey("browserLock")) 
       return ScenarioContext.Current["browserLock"] as IDisposable; 
      return null; 
     } 
     set 
     { 
      if (value == null) 
      { 
       if (ScenarioContext.Current.ContainsKey("browserLock")) 
        ScenarioContext.Current.Remove("browserLock"); 
      } 
      else 
       ScenarioContext.Current["browserLock"] = value; 
     } 
    } 

    private static void LockBrowser() 
    { 
     BrowserLock = MakeBrowserLock(); 
    } 

    private static void ReleaseBrowser() 
    { 
     BrowserLock.Dispose(); 
     BrowserLock = null; 
    } 

    private static SystemLevelLock MakeBrowserLock() { return new SystemLevelLock("WatiNBrowserLock"); } 

    private static void Start() 
    { 
     LockBrowser(); 
     var browser = new IE(); 
     ScenarioBrowser = browser; 
    } 

    public static bool IsStarted() { return ScenarioBrowser != null; } 

    public static void Close() 
    { 
     try 
     { 
      var browser = ScenarioBrowser; 
      ScenarioBrowser = null; 
      browser.Close(); 
      browser.Dispose(); 
     } 
     finally 
     { 
      ReleaseBrowser(); 
     } 
    } 

} 
+0

是的,我知道,那是WatiN的本質。 IE是一個共享資源.. – MatteS

+0

是的確定它不是該網站。雖然測試可以在同一個網站上正常運行,但它們可以在自己的網站上運行。我在我的機器上覆制了這個場景,試圖在並行中運行2個WatiN測試,並且它不起作用。 Google'v告訴我,由於不同的原因WatiN無法處理並行運行的多個測試,無論是共享會話狀態,共享Windows會話,即驅動程序問題,還是不是。 無論如何,你可以告訴我如何使用C#代碼做互斥魔法嗎? – MatteS

+0

發現了一些關於該互斥體的信息,生病嘗試爲此編寫一個MSBuild任務並進行評估。 – MatteS

相關問題