You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
11 KiB
351 lines
11 KiB
// **************************************************************** |
|
// This is free software licensed under the NUnit license. You |
|
// may obtain a copy of the license as well as information regarding |
|
// copyright ownership at http://nunit.org. |
|
// **************************************************************** |
|
|
|
// This version of NUnit-console is modified to support: |
|
// 1) Writing all tests results to a file as the test results are known. |
|
|
|
namespace NUnit.ConsoleRunner |
|
{ |
|
using System; |
|
using System.IO; |
|
using System.Reflection; |
|
using System.Xml; |
|
using System.Resources; |
|
using System.Text; |
|
using NUnit.Core; |
|
using NUnit.Core.Filters; |
|
using NUnit.Util; |
|
|
|
/// <summary> |
|
/// Summary description for ConsoleUi. |
|
/// </summary> |
|
public class ExtendedConsoleUi |
|
{ |
|
public static readonly int OK = 0; |
|
public static readonly int INVALID_ARG = -1; |
|
public static readonly int FILE_NOT_FOUND = -2; |
|
public static readonly int FIXTURE_NOT_FOUND = -3; |
|
public static readonly int UNEXPECTED_ERROR = -100; |
|
|
|
public ExtendedConsoleUi() |
|
{ |
|
} |
|
|
|
public int Execute( ExtendedConsoleOptions options ) |
|
{ |
|
TextWriter outWriter = Console.Out; |
|
bool redirectOutput = options.output != null && options.output != string.Empty; |
|
if ( redirectOutput ) |
|
{ |
|
StreamWriter outStreamWriter = new StreamWriter( options.output ); |
|
outStreamWriter.AutoFlush = true; |
|
outWriter = outStreamWriter; |
|
} |
|
|
|
TextWriter errorWriter = Console.Error; |
|
bool redirectError = options.err != null && options.err != string.Empty; |
|
if ( redirectError ) |
|
{ |
|
StreamWriter errorStreamWriter = new StreamWriter( options.err ); |
|
errorStreamWriter.AutoFlush = true; |
|
errorWriter = errorStreamWriter; |
|
} |
|
|
|
TextWriter testResultWriter = null; |
|
if ( options.IsResults ) |
|
{ |
|
testResultWriter = new StreamWriter ( options.results, false, Encoding.UTF8 ); |
|
((StreamWriter)testResultWriter).AutoFlush = true; |
|
} |
|
|
|
TestPackage package = MakeTestPackage(options); |
|
|
|
Console.WriteLine("ProcessModel: {0} DomainUsage: {1}", |
|
package.Settings.Contains("ProcessModel") |
|
? package.Settings["ProcessModel"] |
|
: "Default", |
|
package.Settings.Contains("DomainUsage") |
|
? package.Settings["DomainUsage"] |
|
: "Default"); |
|
|
|
Console.WriteLine("Execution Runtime: {0}", |
|
package.Settings.Contains("RuntimeFramework") |
|
? package.Settings["RuntimeFramework"] |
|
: "Default"); |
|
|
|
TestRunner testRunner = new DefaultTestRunnerFactory().MakeTestRunner(package); |
|
testRunner.Load(package); |
|
|
|
try |
|
{ |
|
if (testRunner.Test == null) |
|
{ |
|
testRunner.Unload(); |
|
Console.Error.WriteLine("Unable to locate fixture {0}", options.fixture); |
|
return FIXTURE_NOT_FOUND; |
|
} |
|
|
|
ExtendedEventCollector collector = new ExtendedEventCollector( options, outWriter, errorWriter, testResultWriter ); |
|
|
|
TestFilter testFilter = TestFilter.Empty; |
|
if ( options.run != null && options.run != string.Empty ) |
|
{ |
|
Console.WriteLine( "Selected test(s): " + options.run ); |
|
testFilter = new SimpleNameFilter( options.run ); |
|
} |
|
|
|
if ( options.include != null && options.include != string.Empty ) |
|
{ |
|
Console.WriteLine( "Included categories: " + options.include ); |
|
TestFilter includeFilter = new CategoryExpression( options.include ).Filter; |
|
if ( testFilter.IsEmpty ) |
|
testFilter = includeFilter; |
|
else |
|
testFilter = new AndFilter( testFilter, includeFilter ); |
|
} |
|
|
|
if ( options.exclude != null && options.exclude != string.Empty ) |
|
{ |
|
Console.WriteLine( "Excluded categories: " + options.exclude ); |
|
TestFilter excludeFilter = new NotFilter( new CategoryExpression( options.exclude ).Filter ); |
|
if ( testFilter.IsEmpty ) |
|
testFilter = excludeFilter; |
|
else if ( testFilter is AndFilter ) |
|
((AndFilter)testFilter).Add( excludeFilter ); |
|
else |
|
testFilter = new AndFilter( testFilter, excludeFilter ); |
|
} |
|
|
|
if (testFilter is NotFilter) |
|
((NotFilter)testFilter).TopLevel = true; |
|
|
|
TestResult result = null; |
|
string savedDirectory = Environment.CurrentDirectory; |
|
TextWriter savedOut = Console.Out; |
|
TextWriter savedError = Console.Error; |
|
|
|
try |
|
{ |
|
result = testRunner.Run( collector, testFilter ); |
|
} |
|
finally |
|
{ |
|
outWriter.Flush(); |
|
errorWriter.Flush(); |
|
|
|
if ( redirectOutput ) |
|
outWriter.Close(); |
|
if ( redirectError ) |
|
errorWriter.Close(); |
|
if ( options.IsResults ) |
|
testResultWriter.Close(); |
|
|
|
Environment.CurrentDirectory = savedDirectory; |
|
Console.SetOut( savedOut ); |
|
Console.SetError( savedError ); |
|
} |
|
|
|
Console.WriteLine(); |
|
|
|
int returnCode = UNEXPECTED_ERROR; |
|
|
|
if (result != null) |
|
{ |
|
string xmlOutput = CreateXmlOutput(result); |
|
ResultSummarizer summary = new ResultSummarizer(result); |
|
|
|
if (options.xmlConsole) |
|
{ |
|
Console.WriteLine(xmlOutput); |
|
} |
|
else |
|
{ |
|
WriteSummaryReport(summary); |
|
if (summary.ErrorsAndFailures > 0) |
|
WriteErrorsAndFailuresReport(result); |
|
if (summary.TestsNotRun > 0) |
|
WriteNotRunReport(result); |
|
} |
|
|
|
// Write xml output here |
|
string xmlResultFile = options.xml == null || options.xml == string.Empty |
|
? "TestResult.xml" : options.xml; |
|
|
|
if (!String.IsNullOrEmpty(options.xml)) |
|
{ |
|
using (StreamWriter writer = new StreamWriter(xmlResultFile)) |
|
{ |
|
writer.Write(xmlOutput); |
|
} |
|
} |
|
returnCode = summary.ErrorsAndFailures; |
|
} |
|
|
|
if ( collector.HasExceptions ) |
|
{ |
|
collector.WriteExceptions(); |
|
returnCode = UNEXPECTED_ERROR; |
|
} |
|
|
|
return returnCode; |
|
} |
|
finally |
|
{ |
|
testRunner.Unload(); |
|
} |
|
} |
|
|
|
#region Helper Methods |
|
// TODO: See if this can be unified with the Gui's MakeTestPackage |
|
private static TestPackage MakeTestPackage( ConsoleOptions options ) |
|
{ |
|
TestPackage package; |
|
DomainUsage domainUsage = DomainUsage.Default; |
|
ProcessModel processModel = ProcessModel.Default; |
|
RuntimeFramework framework = null; |
|
|
|
if (options.IsTestProject) |
|
{ |
|
NUnitProject project = |
|
Services.ProjectService.LoadProject((string)options.Parameters[0]); |
|
|
|
string configName = options.config; |
|
if (configName != null) |
|
project.SetActiveConfig(configName); |
|
|
|
package = project.ActiveConfig.MakeTestPackage(); |
|
processModel = project.ProcessModel; |
|
domainUsage = project.DomainUsage; |
|
framework = project.ActiveConfig.RuntimeFramework; |
|
} |
|
else if (options.Parameters.Count == 1) |
|
{ |
|
package = new TestPackage((string)options.Parameters[0]); |
|
domainUsage = DomainUsage.Single; |
|
} |
|
else |
|
{ |
|
// TODO: Figure out a better way to handle "anonymous" packages |
|
package = new TestPackage(null, options.Parameters); |
|
package.AutoBinPath = true; |
|
domainUsage = DomainUsage.Multiple; |
|
} |
|
|
|
if (options.process != ProcessModel.Default) |
|
processModel = options.process; |
|
|
|
if (options.domain != DomainUsage.Default) |
|
domainUsage = options.domain; |
|
|
|
if (options.framework != null) |
|
framework = RuntimeFramework.Parse(options.framework); |
|
|
|
package.TestName = options.fixture; |
|
|
|
package.Settings["ProcessModel"] = processModel; |
|
package.Settings["DomainUsage"] = domainUsage; |
|
if (framework != null) |
|
package.Settings["RuntimeFramework"] = framework; |
|
|
|
|
|
|
|
if (domainUsage == DomainUsage.None) |
|
{ |
|
// Make sure that addins are available |
|
CoreExtensions.Host.AddinRegistry = Services.AddinRegistry; |
|
} |
|
|
|
package.Settings["ShadowCopyFiles"] = !options.noshadow; |
|
package.Settings["UseThreadedRunner"] = !options.nothread; |
|
package.Settings["DefaultTimeout"] = options.timeout; |
|
|
|
return package; |
|
} |
|
|
|
private static string CreateXmlOutput( TestResult result ) |
|
{ |
|
StringBuilder builder = new StringBuilder(); |
|
new XmlResultWriter(new StringWriter( builder )).SaveTestResult(result); |
|
|
|
return builder.ToString(); |
|
} |
|
|
|
private static void WriteSummaryReport( ResultSummarizer summary ) |
|
{ |
|
Console.WriteLine( |
|
"Tests run: {0}, Errors: {1}, Failures: {2}, Inconclusive: {3}, Time: {4} seconds", |
|
summary.TestsRun, summary.Errors, summary.Failures, summary.Inconclusive, summary.Time); |
|
Console.WriteLine( |
|
" Not run: {0}, Invalid: {1}, Ignored: {2}, Skipped: {3}", |
|
summary.TestsNotRun, summary.NotRunnable, summary.Ignored, summary.Skipped); |
|
Console.WriteLine(); |
|
} |
|
|
|
private void WriteErrorsAndFailuresReport(TestResult result) |
|
{ |
|
reportIndex = 0; |
|
Console.WriteLine("Errors and Failures:"); |
|
WriteErrorsAndFailures(result); |
|
Console.WriteLine(); |
|
} |
|
|
|
private void WriteErrorsAndFailures(TestResult result) |
|
{ |
|
if (result.Executed) |
|
{ |
|
if (result.HasResults) |
|
{ |
|
if ( (result.IsFailure || result.IsError) && result.FailureSite == FailureSite.SetUp) |
|
WriteSingleResult(result); |
|
|
|
foreach (TestResult childResult in result.Results) |
|
WriteErrorsAndFailures(childResult); |
|
} |
|
else if (result.IsFailure || result.IsError) |
|
{ |
|
WriteSingleResult(result); |
|
} |
|
} |
|
} |
|
|
|
private void WriteNotRunReport(TestResult result) |
|
{ |
|
reportIndex = 0; |
|
Console.WriteLine("Tests Not Run:"); |
|
WriteNotRunResults(result); |
|
Console.WriteLine(); |
|
} |
|
|
|
private int reportIndex = 0; |
|
private void WriteNotRunResults(TestResult result) |
|
{ |
|
if (result.HasResults) |
|
foreach (TestResult childResult in result.Results) |
|
WriteNotRunResults(childResult); |
|
else if (!result.Executed) |
|
WriteSingleResult( result ); |
|
} |
|
|
|
private void WriteSingleResult( TestResult result ) |
|
{ |
|
string status = result.IsFailure || result.IsError |
|
? string.Format("{0} {1}", result.FailureSite, result.ResultState) |
|
: result.ResultState.ToString(); |
|
|
|
Console.WriteLine("{0}) {1} : {2}", ++reportIndex, status, result.FullName); |
|
|
|
if ( result.Message != null && result.Message != string.Empty ) |
|
Console.WriteLine(" {0}", result.Message); |
|
|
|
if (result.StackTrace != null && result.StackTrace != string.Empty) |
|
Console.WriteLine( result.IsFailure |
|
? StackTraceFilter.Filter(result.StackTrace) |
|
: result.StackTrace + Environment.NewLine ); |
|
} |
|
#endregion |
|
} |
|
} |
|
|
|
|