Сначала я попытался запустить процесс nunit-console с помощью Process.Start и перенаправить его вывод в мое веб-приложение, однако это не очень хорошее решение, поскольку перенаправленный вывод из класса Process буферизуется, и вы не можете контролировать его очищает буфер Я обнаружил, что некоторые программы, такие как msbuild, отлично работают и постоянно сбрасываются, однако с помощью nunit-console он удерживает вывод до тех пор, пока все тестовые примеры не будут завершены, что означает, что вы не можете видеть ход выполнения тестовых примеров при их запуске.
Решением является использование класса nunit RemoteTestRunner и создание класса прослушивателя событий, который реализует интерфейс 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() + "] ";
}
}
}
После этого создайте класс TestRunner, который вызывает RemoteTestRunner и использует ваш новый класс прослушивателя событий:
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 или vanilla 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 (в том числе для stackoverflow) проходят через NullListener, что означает, что вы не можете захватить выходные данные тестового прогона.