You've already forked linux-packaging-mono
469 lines
18 KiB
C#
469 lines
18 KiB
C#
// ***********************************************************************
|
|
// Copyright (c) 2007 Charlie Poole
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
// ***********************************************************************
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Collections;
|
|
using System.Reflection;
|
|
using NUnit.Framework.Api;
|
|
using NUnit.Framework.Internal;
|
|
using NUnit.Framework.Internal.Filters;
|
|
using System.Diagnostics;
|
|
|
|
namespace NUnitLite.Runner
|
|
{
|
|
/// <summary>
|
|
/// TextUI is a general purpose class that runs tests and
|
|
/// outputs to a TextWriter.
|
|
///
|
|
/// Call it from your Main like this:
|
|
/// new TextUI(textWriter).Execute(args);
|
|
/// OR
|
|
/// new TextUI().Execute(args);
|
|
/// The provided TextWriter is used by default, unless the
|
|
/// arguments to Execute override it using -out. The second
|
|
/// form uses the Console, provided it exists on the platform.
|
|
///
|
|
/// NOTE: When running on a platform without a Console, such
|
|
/// as Windows Phone, the results will simply not appear if
|
|
/// you fail to specify a file in the call itself or as an option.
|
|
/// </summary>
|
|
public class TextUI : ITestListener
|
|
{
|
|
private CommandLineOptions commandLineOptions;
|
|
|
|
private NUnit.ObjectList assemblies = new NUnit.ObjectList();
|
|
|
|
private TextWriter writer;
|
|
|
|
private ITestListener listener;
|
|
|
|
private ITestAssemblyRunner runner;
|
|
|
|
private FinallyDelegate finallyDelegate = new FinallyDelegate();
|
|
|
|
public bool Failure;
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="TextUI"/> class.
|
|
/// </summary>
|
|
public TextUI() : this(ConsoleWriter.Out, TestListener.NULL) { }
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="TextUI"/> class.
|
|
/// </summary>
|
|
/// <param name="writer">The TextWriter to use.</param>
|
|
public TextUI(TextWriter writer) : this(writer, TestListener.NULL) { }
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="TextUI"/> class.
|
|
/// </summary>
|
|
/// <param name="writer">The TextWriter to use.</param>
|
|
/// <param name="listener">The Test listener to use.</param>
|
|
public TextUI(TextWriter writer, ITestListener listener)
|
|
{
|
|
// Set the default writer - may be overridden by the args specified
|
|
this.writer = writer;
|
|
this.listener = listener;
|
|
}
|
|
|
|
void TopLevelHandler(object sender, UnhandledExceptionEventArgs e)
|
|
{
|
|
// Make sure that the test harness knows this exception was thrown
|
|
this.finallyDelegate.HandleUnhandledExc(e.ExceptionObject as Exception);
|
|
}
|
|
|
|
ITestAssemblyRunner DefaultRunner ()
|
|
{
|
|
return new NUnitLiteTestAssemblyRunner(new NUnitLiteTestAssemblyBuilder(), this.finallyDelegate);;
|
|
}
|
|
|
|
#if MONODROID_TOOLS
|
|
ITestAssemblyRunner AndroidRunner (string app)
|
|
{
|
|
return new Xamarin.AndroidTestAssemblyRunner(app);
|
|
}
|
|
#elif MONOTOUCH_TOOLS
|
|
ITestAssemblyRunner iOSRunner (string app)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
#elif WASM_TOOLS
|
|
ITestAssemblyRunner WebAssemblyRunner (string app)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Execute a test run based on the aruments passed
|
|
/// from Main.
|
|
/// </summary>
|
|
/// <param name="args">An array of arguments</param>
|
|
public void Execute(string[] args)
|
|
{
|
|
this.commandLineOptions = new CommandLineOptions();
|
|
commandLineOptions.Parse(args);
|
|
|
|
if (runner == null) {
|
|
#if MONODROID_TOOLS
|
|
if (!string.IsNullOrEmpty (commandLineOptions.Android)) {
|
|
runner = AndroidRunner (commandLineOptions.Android);
|
|
} else if (!string.IsNullOrEmpty (commandLineOptions.Remote) && commandLineOptions.Remote.StartsWith ("android:")) {
|
|
Xamarin.AndroidRemoteRunner.App = commandLineOptions.Remote.Substring (8);
|
|
runner = DefaultRunner ();
|
|
} else
|
|
#elif MONOTOUCH_TOOLS
|
|
if (!string.IsNullOrEmpty (commandLineOptions.iOS)) {
|
|
runner = iOSRunner (commandLineOptions.iOS);
|
|
} else if (!string.IsNullOrEmpty (commandLineOptions.Remote) && commandLineOptions.Remote.StartsWith ("ios:")) {
|
|
// Xamarin.iOSRemoteRunner.App = commandLineOptions.Remote.Substring (4);
|
|
// runner = DefaultRunner ();
|
|
throw new NotImplementedException ();
|
|
} else
|
|
#elif WASM_TOOLS
|
|
if (!string.IsNullOrEmpty (commandLineOptions.WebAssembly)) {
|
|
runner = WebAssemblyRunner (commandLineOptions.WebAssembly);
|
|
} else if (!string.IsNullOrEmpty (commandLineOptions.Remote) && commandLineOptions.Remote.StartsWith ("wasm:")) {
|
|
// Xamarin.WebAssemblyRemoteRunner.App = commandLineOptions.Remote.Substring (5);
|
|
// runner = DefaultRunner ();
|
|
throw new NotImplementedException ();
|
|
} else
|
|
#endif
|
|
{
|
|
runner = DefaultRunner ();
|
|
}
|
|
}
|
|
|
|
if (commandLineOptions.OutFile != null)
|
|
this.writer = new StreamWriter(commandLineOptions.OutFile);
|
|
|
|
if (!commandLineOptions.NoHeader)
|
|
WriteHeader(this.writer);
|
|
|
|
if (commandLineOptions.ShowHelp)
|
|
writer.Write(commandLineOptions.HelpText);
|
|
else if (commandLineOptions.Error)
|
|
{
|
|
writer.WriteLine(commandLineOptions.ErrorMessage);
|
|
writer.WriteLine(commandLineOptions.HelpText);
|
|
}
|
|
else
|
|
{
|
|
WriteRuntimeEnvironment(this.writer);
|
|
|
|
if (commandLineOptions.Wait && commandLineOptions.OutFile != null)
|
|
writer.WriteLine("Ignoring /wait option - only valid for Console");
|
|
|
|
#if SILVERLIGHT
|
|
IDictionary loadOptions = new System.Collections.Generic.Dictionary<string, string>();
|
|
#else
|
|
IDictionary loadOptions = new Hashtable();
|
|
#endif
|
|
//if (options.Load.Count > 0)
|
|
// loadOptions["LOAD"] = options.Load;
|
|
|
|
//IDictionary runOptions = new Hashtable();
|
|
//if (commandLineOptions.TestCount > 0)
|
|
// runOptions["RUN"] = commandLineOptions.Tests;
|
|
|
|
ITestFilter filter = commandLineOptions.TestCount > 0
|
|
? new SimpleNameFilter(commandLineOptions.Tests)
|
|
: TestFilter.Empty;
|
|
|
|
try
|
|
{
|
|
foreach (string name in commandLineOptions.Parameters) {
|
|
try {
|
|
assemblies.Add(Assembly.LoadFrom(name));
|
|
}
|
|
catch (FileNotFoundException/* e*/) {
|
|
assemblies.Add(Assembly.Load(name));
|
|
}
|
|
}
|
|
|
|
if (assemblies.Count == 0) {
|
|
// NOTE: Execute must be directly called from the
|
|
// test assembly in order for the mechanism to work.
|
|
Assembly callingAssembly = Assembly.GetCallingAssembly();
|
|
assemblies.Add(callingAssembly);
|
|
}
|
|
|
|
// TODO: For now, ignore all but first assembly
|
|
Assembly assembly = assemblies[0] as Assembly;
|
|
|
|
Randomizer.InitialSeed = commandLineOptions.InitialSeed;
|
|
|
|
if (!runner.Load(assembly, loadOptions))
|
|
{
|
|
AssemblyName assemblyName = AssemblyHelper.GetAssemblyName(assembly);
|
|
Console.WriteLine("No tests found in assembly {0}", assemblyName.Name);
|
|
return;
|
|
}
|
|
|
|
if (commandLineOptions.Explore)
|
|
ExploreTests();
|
|
else
|
|
{
|
|
if (commandLineOptions.Include != null && commandLineOptions.Include != string.Empty)
|
|
{
|
|
TestFilter includeFilter = new SimpleCategoryExpression(commandLineOptions.Include).Filter;
|
|
|
|
if (filter.IsEmpty)
|
|
filter = includeFilter;
|
|
else
|
|
filter = new AndFilter(filter, includeFilter);
|
|
}
|
|
|
|
if (commandLineOptions.Exclude != null && commandLineOptions.Exclude != string.Empty)
|
|
{
|
|
TestFilter excludeFilter = new NotFilter(new SimpleCategoryExpression(commandLineOptions.Exclude).Filter);
|
|
|
|
if (filter.IsEmpty)
|
|
filter = excludeFilter;
|
|
else if (filter is AndFilter)
|
|
((AndFilter)filter).Add(excludeFilter);
|
|
else
|
|
filter = new AndFilter(filter, excludeFilter);
|
|
}
|
|
|
|
#if MONO
|
|
filter = Xamarin.BabysitterSupport.AddBabysitterFilter(filter);
|
|
#endif
|
|
RunTests(filter);
|
|
}
|
|
}
|
|
catch (FileNotFoundException ex)
|
|
{
|
|
Failure = true;
|
|
writer.WriteLine(ex.Message);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Failure = true;
|
|
writer.WriteLine(ex.ToString());
|
|
}
|
|
finally
|
|
{
|
|
if (commandLineOptions.OutFile == null)
|
|
{
|
|
if (commandLineOptions.Wait)
|
|
{
|
|
Console.WriteLine("Press Enter key to continue . . .");
|
|
Console.ReadLine();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
writer.Close();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write the standard header information to a TextWriter.
|
|
/// </summary>
|
|
/// <param name="writer">The TextWriter to use</param>
|
|
public static void WriteHeader(TextWriter writer)
|
|
{
|
|
Assembly executingAssembly = Assembly.GetExecutingAssembly();
|
|
#if NUNITLITE
|
|
string title = "NUnitLite";
|
|
#else
|
|
string title = "NUNit Framework";
|
|
#endif
|
|
AssemblyName assemblyName = AssemblyHelper.GetAssemblyName(executingAssembly);
|
|
System.Version version = assemblyName.Version;
|
|
string copyright = "Copyright (C) 2012, Charlie Poole";
|
|
string build = "";
|
|
|
|
object[] attrs = executingAssembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
|
|
if (attrs.Length > 0)
|
|
{
|
|
AssemblyTitleAttribute titleAttr = (AssemblyTitleAttribute)attrs[0];
|
|
title = titleAttr.Title;
|
|
}
|
|
|
|
attrs = executingAssembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
|
|
if (attrs.Length > 0)
|
|
{
|
|
AssemblyCopyrightAttribute copyrightAttr = (AssemblyCopyrightAttribute)attrs[0];
|
|
copyright = copyrightAttr.Copyright;
|
|
}
|
|
|
|
attrs = executingAssembly.GetCustomAttributes(typeof(AssemblyConfigurationAttribute), false);
|
|
if (attrs.Length > 0)
|
|
{
|
|
AssemblyConfigurationAttribute configAttr = (AssemblyConfigurationAttribute)attrs[0];
|
|
if (configAttr.Configuration.Length > 0)
|
|
build = string.Format("({0})", configAttr.Configuration);
|
|
}
|
|
|
|
writer.WriteLine(String.Format("{0} {1} {2}", title, version.ToString(3), build));
|
|
writer.WriteLine(copyright);
|
|
writer.WriteLine();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write information about the current runtime environment
|
|
/// </summary>
|
|
/// <param name="writer">The TextWriter to be used</param>
|
|
public static void WriteRuntimeEnvironment(TextWriter writer)
|
|
{
|
|
string clrPlatform = Type.GetType("Mono.Runtime", false) == null ? ".NET" : "Mono";
|
|
|
|
writer.WriteLine("Runtime Environment -");
|
|
writer.WriteLine(" OS Version: {0}", Environment.OSVersion);
|
|
writer.WriteLine(" {0} Version: {1}", clrPlatform, Environment.Version);
|
|
writer.WriteLine();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helper Methods
|
|
|
|
private void RunTests(ITestFilter filter)
|
|
{
|
|
DateTime startTime = DateTime.Now;
|
|
|
|
var crashHandler = new UnhandledExceptionEventHandler(TopLevelHandler);
|
|
AppDomain.CurrentDomain.UnhandledException += crashHandler;
|
|
|
|
ITestResult result = runner.Run(this, filter);
|
|
new ResultReporter(result, writer).ReportResults();
|
|
string resultFile = commandLineOptions.ResultFile;
|
|
string resultFormat = commandLineOptions.ResultFormat;
|
|
|
|
this.Failure = (result.ResultState.Equals(ResultState.Failure) || result.ResultState.Equals(ResultState.Error));
|
|
|
|
if (resultFile != null || commandLineOptions.ResultFormat != null)
|
|
{
|
|
if (resultFile == null)
|
|
resultFile = "TestResult.xml";
|
|
|
|
if (resultFormat == "nunit2")
|
|
new NUnit2XmlOutputWriter(startTime).WriteResultFile(result, resultFile);
|
|
else if (resultFormat == "nunit3")
|
|
new NUnit3XmlOutputWriter(startTime).WriteResultFile(result, resultFile);
|
|
#if MONO
|
|
else if (resultFormat == "xunit")
|
|
new XunitXmlOutputWriter(startTime).WriteResultFile(result, resultFile);
|
|
#endif
|
|
else
|
|
throw new Exception("Unknown resultFormat.");
|
|
|
|
Console.WriteLine();
|
|
Console.WriteLine("Results saved as {0}.", resultFile);
|
|
}
|
|
|
|
AppDomain.CurrentDomain.UnhandledException -= crashHandler;
|
|
}
|
|
|
|
private void ExploreTests()
|
|
{
|
|
XmlNode testNode = runner.LoadedTest.ToXml(true);
|
|
|
|
string listFile = commandLineOptions.ExploreFile;
|
|
TextWriter textWriter = listFile != null && listFile.Length > 0
|
|
? new StreamWriter(listFile)
|
|
: Console.Out;
|
|
|
|
#if CLR_2_0 || CLR_4_0
|
|
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
|
|
settings.Indent = true;
|
|
settings.Encoding = System.Text.Encoding.UTF8;
|
|
System.Xml.XmlWriter testWriter = System.Xml.XmlWriter.Create(textWriter, settings);
|
|
#else
|
|
System.Xml.XmlTextWriter testWriter = new System.Xml.XmlTextWriter(textWriter);
|
|
testWriter.Formatting = System.Xml.Formatting.Indented;
|
|
#endif
|
|
|
|
testNode.WriteTo(testWriter);
|
|
testWriter.Close();
|
|
|
|
Console.WriteLine();
|
|
Console.WriteLine("Test info saved as {0}.", listFile);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ITestListener Members
|
|
|
|
/// <summary>
|
|
/// A test has just started
|
|
/// </summary>
|
|
/// <param name="test">The test</param>
|
|
public void TestStarted(ITest test)
|
|
{
|
|
#if MONO
|
|
if (!test.IsSuite)
|
|
Xamarin.BabysitterSupport.RecordEnterTest(test.FullName);
|
|
|
|
if (commandLineOptions.LabelTestsInOutput)
|
|
writer.WriteLine("***** {0}", test.FullName);
|
|
else
|
|
writer.Write(".");
|
|
#else
|
|
if (commandLineOptions.LabelTestsInOutput)
|
|
writer.WriteLine("***** {0}", test.Name);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// A test has just finished
|
|
/// </summary>
|
|
/// <param name="result">The result of the test</param>
|
|
public void TestFinished(ITestResult result)
|
|
{
|
|
#if MONO
|
|
if (!result.Test.IsSuite) {
|
|
Xamarin.BabysitterSupport.RecordLeaveTest (result.Test.FullName);
|
|
if (result.ResultState.Status == TestStatus.Failed)
|
|
{
|
|
Xamarin.BabysitterSupport.RecordFailedTest (result.Test.FullName);
|
|
if (!commandLineOptions.LabelTestsInOutput)
|
|
writer.Write("F");
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// A test has produced some text output
|
|
/// </summary>
|
|
/// <param name="testOutput">A TestOutput object holding the text that was written</param>
|
|
public void TestOutput(TestOutput testOutput)
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|