我第一次嘗試使用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,這意味着你不能捕獲測試運行的輸出。
是的,我確實知道CC.NET,在使用它之前多年使用它,然後才切換到更現代的CI解決方案 - TeamCity。我在SVN目錄中瀏覽了一會兒,但無法找到我要找的內容。 – Justin
CC.NET運行包含單元測試的構建腳本,並在網頁上顯示其結果。這不是你想要的嗎? –