2011-08-19 82 views
1

我有一個ASP.NET MVC Web應用程序,用於監視我公司系統的狀態 - Windows服務,wcf服務,Web應用程序等...我有一個C#NUnit測試項目具有檢查系統內不同事物的測試用例。目前我使用TestDriven.Net在Visual Studio中運行測試用例,或者我可以使用nunit gui運行測試用例。在ASP.NET MVC應用程序中調用nunit測試用例

我想要做的是將測試項目DLL導入到我的ASP.NET MVC Web應用程序中,並以某種方式調用它來運行項目中的所有測試用例,並輸出每個測試的測試用例名稱,持續時間和結果案件到一個網頁。這可能嗎?如果是這樣,我該怎麼去做,或者是否有一些預製框架可以提供這種能力?我知道像teamCity這樣的CI框架可以運行測試用例並輸出到網頁上,但是我正在尋找它在我自己的Web應用程序中,並且對我來說,對輸出的設計有一定程度的控制。

回答

4

我第一次嘗試使用Process.Start啓動nunit控制檯進程並將其輸出重定向到我的web應用程序,但這不是一個好的解決方案,因爲Process類的重定向輸出被緩衝,並且您無法控制何時它沖刷緩衝區。我發現像msbuild這樣的程序工作得很好,並且不斷刷新,但是使用nunit-console它會保留在輸出中,直到所有測試用例都完成爲止,這意味着在測試用例運行時無法看到測試用例的進度。

的解決方案是使用RemoteTestRunner NUnit的類和創建實現NUnit.Core.EventListener接口的事件監聽器類:

public class NUnitEventListener : NUnit.Core.EventListener 
    { 
     public event EventHandler CompletedRun; 
     public StringBuilder Output; 
     private int TotalTestsPassed = 0; 
     private int TotalTestsErrored = 0; 

     public void RunStarted(string name, int testCount) 
     { 
      Output.AppendLine(TimeStamp + "Running " + testCount + " tests in " + name + "<br/><br/>"); 
      TotalTestsPassed = 0; 
      TotalTestsErrored = 0; 
     } 

     public void RunFinished(System.Exception exception) 
     { 
      Output.AppendLine(TimeStamp + "Run errored: " + exception.ToString() + "<br/>"); 
      //notify event consumers. 
      if (CompletedRun != null) 
       CompletedRun(exception, new EventArgs()); 
     } 

     public void RunFinished(TestResult result) 
     { 
      Output.AppendLine(TimeStamp + "<label class='normal " + (TotalTestsErrored == 0 ? "green" : "red") 
       + "'>" + TotalTestsPassed + " tests passed, " + TotalTestsErrored + " tests failed</label><br/>"); 
      Output.AppendLine(TimeStamp + "Run completed in " + result.Time + " seconds<br/>"); 
      //notify event consumers. 
      if (CompletedRun != null) 
       CompletedRun(result, new EventArgs()); 
     } 

     public void TestStarted(TestName testName) 
     { 
      Output.AppendLine(TimeStamp + testName.FullName + "<br/>"); 
     } 

     public void TestOutput(TestOutput testOutput) 
     { 
      if(testOutput.Text.IndexOf("NHibernate:") == -1) 
       Output.AppendLine(TimeStamp + testOutput.Text + "<br/>"); 
     } 

     public void TestFinished(TestResult result) 
     { 
      if (result.IsSuccess) 
      { 
       Output.AppendLine(TimeStamp + "<label class='green normal'>Test Passed!</label><br/><br/>"); 
       TotalTestsPassed++; 
      } 
      else 
      { 
       Output.AppendLine(TimeStamp + "<label class='red normal'>Test Failed!<br/>" + result.Message.Replace(Environment.NewLine, "<br/>") + "</label><br/>"); 
       TotalTestsErrored++; 
      } 
     } 

     public void UnhandledException(System.Exception exception) 
     { 
      Output.AppendLine(TimeStamp + "Unhandled Exception: " + exception.ToString() + "<br/>"); 
     } 

     public void SuiteStarted(TestName testName) 
     { 
     } 

     public void SuiteFinished(TestResult result) 
     { 
     } 

     private string TimeStamp 
     { 
      get 
      { 
       return "[" + DateTime.Now.ToString() + "] "; 
      } 
     } 
    } 

之後,創建調用RemoteTestRunner和使用您的性感的TestRunner類新的事件監聽器類:

public static class TestRunner 
    { 
     public static bool InProgress = false; 
     public static StringBuilder Output = new StringBuilder(); 
     private static RemoteTestRunner Runner; 

     public static void Start(string fileName) 
     { 
      InProgress = true; 
      Output = new StringBuilder(); 
      StartTests(fileName); 
     } 

     private static void StartTests(string fileName) 
     { 
      //start nunit. 
      var testPackage = new TestPackage(fileName); 
      Runner = new RemoteTestRunner(); 
      Runner.Load(testPackage); 
      var nunitEventListener = new NUnitEventListener(); 
      nunitEventListener.CompletedRun += new EventHandler(nunitEventListener_CompletedRun); 
      nunitEventListener.Output = Output; 
      Runner.BeginRun(nunitEventListener); 
     } 

     static void nunitEventListener_CompletedRun(object sender, EventArgs e) 
     { 
      if (Runner != null) 
      { 
       Runner.CancelRun(); 
       Runner = null; 
      } 
      InProgress = false; 
     } 
    } 

現在調用的TestRunner類在ASP.NET MVC控制器:

public class TestController : ApplicationController 
    { 
     //GET: /Test/Index/ 
     public ActionResult Index() 
     { 
      TestRunner.Start(@"C:\PathToTestProject\bin\Release\SystemTest.dll"); 
      return View(); 
     } 

     //POST: /Test/GetOutput/ 
     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult GetOutput() 
     { 
      var result = new 
      { 
       InProgress = TestRunner.InProgress, 
       Output = TestRunner.Output.ToString() 
      }; 
      return Json(result); 
     } 
    } 

最後,創建一個簡單的視圖,將輸出顯示爲測試用例運行。礦用道場,但它可以很容易地修改與jQuery或香草JavaScript來的工作:

<script type="test/javascript"> 
var nunit = { 

    init: function() { 

     nunit.get(); 

    }, 

    get: function() { 

     //ajax call. 
     ajax.post("test/getoutput/", {}, nunit.display); 

    }, 

    display: function (result) { 

     console.debug(result); 
     dojo.byId("output").innerHTML = result.Output.length > 0 ? result.Output : dojo.byId("output").innerHTML; 
     if (result.InProgress) 
      window.setTimeout(nunit.get, 10000); 

    } 

}; 

dojo.addOnLoad(nunit.init); 
</script> 

<div id="output"> 
    The tests are running, please wait.... 
</div> 

就是這樣......希望這可以幫助一些人,因爲所有的在線的例子RemoteTestRunner的(包括計算器)傳遞一個NullListener,這意味着你不能捕獲測試運行的輸出。

1

我不知道你是否知道CruiseControl.NET是一個CI的開源項目。如果沒有,請檢查其Web應用程序的構建報告管理器http://sourceforge.net/projects/ccnet/,你將能夠看到他們是如何實現你想要做的。

+0

是的,我確實知道CC.NET,在使用它之前多年使用它,然後才切換到更現代的CI解決方案 - TeamCity。我在SVN目錄中瀏覽了一會兒,但無法找到我要找的內容。 – Justin

+0

CC.NET運行包含單元測試的構建腳本,並在網頁上顯示其結果。這不是你想要的嗎? –