using System; using System.Collections.Generic; using System.Reflection; using JetBrains.ReSharper.TaskRunnerFramework; using MbUnit.Core.Filters; using MbUnit.Core.Remoting; using MbUnit.Core.Reports.Serialization; namespace MbUnit.ReSharperRunner.MbUnit { public class MbUnitTestActionRunner : IMbUnitTestActionRunner { private Assembly currentAssembly = null; public void Execute(MbUnitTestAction testAction) { currentAssembly = Assembly.Load(testAction.AssemblyName); if (testAction is MbUnitTestMethodAction) { Execute((MbUnitTestMethodAction)testAction); } else if (testAction is MbUnitTestFixtureAction) { Execute((MbUnitTestFixtureAction)testAction); } } private void Execute(MbUnitTestFixtureAction methodAction) { TypeFixtureFilter fixtureFilter = new TypeFixtureFilter(methodAction.TypeName); TypeFilterBase filterBase = TypeFilters.Type(methodAction.TypeName); Execute(currentAssembly, fixtureFilter, new AnyRunPipeFilter(), filterBase); } private void Execute(MbUnitTestMethodAction methodAction) { MemberInfo mi = ReflectionUtility.FindMethod(methodAction.AssemblyName, string.Format("{0}.{1}", methodAction.TypeName, methodAction.MethodName)); TypeFixtureFilter fixtureFilter = new TypeFixtureFilter(methodAction.TypeName); TypeFilterBase filterBase = TypeFilters.Type(methodAction.TypeName); ContainsMemberRunPipeFilter pipeFilter = new ContainsMemberRunPipeFilter(mi); Execute(currentAssembly, fixtureFilter, pipeFilter, filterBase); } private void Execute(Assembly assembly, IFixtureFilter filter, IRunPipeFilter runPipeFilter, ITypeFilter typeFilter) { try { using (AssemblyTestDomain domain = new AssemblyTestDomain(assembly)) { domain.TypeFilter = typeFilter; domain.Filter = filter; domain.RunPipeFilter = runPipeFilter; domain.Load(); domain.TestEngine.FixtureRunner.TestFixtureSetUp += FixtureRunner_OnTestFixtureSetUp; domain.TestEngine.FixtureRunner.TestFixtureTearDown += FixtureRunner_OnTestFixtureTearDown; domain.TestEngine.FixtureRunner.AssemblySetUp += FixtureRunner_AssemblySetUp; domain.TestEngine.FixtureRunner.AssemblyTearDown += FixtureRunner_AssemblyTearDown; domain.TestEngine.FixtureRunner.RunResult += FixtureRunner_RunResult; try { domain.TestEngine.RunPipes(); } catch (Exception e) { OnException(null, e); } finally { if (domain.TestEngine != null) { domain.TestEngine.FixtureRunner.TestFixtureSetUp -= FixtureRunner_OnTestFixtureSetUp; domain.TestEngine.FixtureRunner.TestFixtureTearDown -= FixtureRunner_OnTestFixtureTearDown; domain.TestEngine.FixtureRunner.AssemblySetUp -= FixtureRunner_AssemblySetUp; domain.TestEngine.FixtureRunner.AssemblyTearDown -= FixtureRunner_AssemblyTearDown; domain.TestEngine.FixtureRunner.RunResult -= FixtureRunner_RunResult; } } } } catch (Exception e) { OnException(null, e); } } private void FixtureRunner_RunResult(object sender, ReportRunEventArgs e) { if (RunResult != null) { MbUnitRunEventArgs ea = new MbUnitRunEventArgs(e.Run.Name, TaskResultFromMbUnitResult(e.Run.Result), e.Run.Duration, e.Run.Description, e.Run.ConsoleOut, e.Run.ConsoleError, ConvertExceptions(e.Run.Exception)); RunResult(sender, ea); } } private void FixtureRunner_AssemblyTearDown(object sender, ReportSetUpAndTearDownEventArgs e) { if (AssemblyTearDown != null) { AssemblyTearDown(sender, e); } } private void FixtureRunner_AssemblySetUp(object sender, ReportSetUpAndTearDownEventArgs e) { if (AssemblySetup != null) { AssemblySetup(sender, e); } } private void FixtureRunner_OnTestFixtureSetUp(object sender, ReportSetUpAndTearDownEventArgs e) { if (TestFixtureSetup != null) { TestFixtureSetup(sender, e); } } private void OnException(object sender, Exception exception) { if (Exception != null) { Exception(sender, new RunnerExceptionEventArgs(exception)); } } private void FixtureRunner_OnTestFixtureTearDown(object sender, ReportSetUpAndTearDownEventArgs e) { if (TestFixtureTearDown != null) { TestFixtureTearDown(sender, e); } } public event EventHandler MbUnitRunResult; public event EventHandler RunResult; public event EventHandler TestFixtureSetup; public event EventHandler TestFixtureTearDown; public event EventHandler AssemblySetup; public event EventHandler AssemblyTearDown; public event EventHandler Exception; private static TaskException[] ConvertExceptions(ReportException ex) { ReportException current; List exceptions = new List(); // message = null; current = ex; while (current != null) { // if (message == null) { // message = string.Format("{0}: {1}", current.GetType().Name, current.Message); } TaskException exception = new TaskException(new RunnerException(current)); exceptions.Add(exception); current = current.Exception; } return exceptions.ToArray(); } private static TaskResult TaskResultFromMbUnitResult(ReportRunResult result) { switch (result) { case ReportRunResult.Success: return TaskResult.Success; case ReportRunResult.Failure: return TaskResult.Exception; case ReportRunResult.Ignore: return TaskResult.Skipped; case ReportRunResult.Skip: return TaskResult.Skipped; case ReportRunResult.NotRun: return TaskResult.Error; default: throw new ArgumentOutOfRangeException("result"); } } } public class RunnerExceptionEventArgs : EventArgs { private readonly Exception exception; public RunnerExceptionEventArgs(Exception exception) { this.exception = exception; } public Exception Exception { get { return exception; } } } internal class RunnerException : Exception { private readonly ReportException reportException; private string exceptionType; private static Exception FromReportException(ReportException e) { if (e == null) { return null; } else { return new RunnerException(e); } } public RunnerException(ReportException e) : base(e.Message, FromReportException(e.Exception)) { exceptionType = e.Type; reportException = e; } public override string Message { get { return string.Format("{0}: {1}", exceptionType, base.Message); } } public override string StackTrace { get { return reportException.Type + Environment.NewLine + reportException.StackTrace; } } public override string ToString() { return reportException.Type; } public override string Source { get { return reportException.Source; } set { reportException.Source = value; } } } }