diff --git a/.gitignore b/.gitignore index 6c8304f..b23ad87 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ *.user _ReSharper.*/ output/* +resharper.log +TestResults/ \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/AgUnit.Runner.Resharper60.TaskRunner.csproj b/src/AgUnit.Runner.Resharper60.TaskRunner/AgUnit.Runner.Resharper60.TaskRunner.csproj index f628203..02b34a7 100644 --- a/src/AgUnit.Runner.Resharper60.TaskRunner/AgUnit.Runner.Resharper60.TaskRunner.csproj +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/AgUnit.Runner.Resharper60.TaskRunner.csproj @@ -12,11 +12,11 @@ AgUnit.Runner.Resharper60.TaskRunner v4.0 512 - - $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\JetBrains\ReSharper\v6.0\vs10.0@InstallDir) - Program - $(DevEnvDir)devenv.exe - /ReSharper.Plugin AgUnit.Runner.Resharper60.dll /ReSharper.LogFile C:\resharper.log /ReSharper.LogLevel Verbose ..\src\DummyTests\VS2010\DummyTests.sln + + $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\JetBrains\ReSharper\v6.0\vs10.0@InstallDir) + Program + $(DevEnvDir)devenv.exe + /ReSharper.Plugin AgUnit.Runner.Resharper60.dll /ReSharper.LogFile C:\resharper.log /ReSharper.LogLevel Verbose ..\src\DummyTests\VS2010\DummyTests.sln ..\..\output\ @@ -54,9 +54,23 @@ + + + + + + + + + + + Code + + + diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestAssemblyTaskProvider.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestAssemblyTaskProvider.cs new file mode 100644 index 0000000..7329903 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestAssemblyTaskProvider.cs @@ -0,0 +1,26 @@ +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers; +using JetBrains.ReSharper.TaskRunnerFramework; +using JetBrains.ReSharper.UnitTestRunner.MSTest; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestProvider.MSTest +{ + public class MsTestAssemblyTaskProvider : IAssemblyTaskProvider + { + public bool IsAssemblyTask(RemoteTask task) + { + return task is MsTestTestAssemblyTask; + } + + private MsTestTestAssemblyTask GetTask(RemoteTask task) + { + return (MsTestTestAssemblyTask)task; + } + + public string GetXapPath(RemoteTask task) + { + var assemblyTask = GetTask(task); + + return assemblyTask.AssemblyLocation.Replace(".dll", ".xap"); // TODO: Find a way to get this from the project settings. + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestClassTaskProvider.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestClassTaskProvider.cs new file mode 100644 index 0000000..7e5e429 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestClassTaskProvider.cs @@ -0,0 +1,26 @@ +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers; +using JetBrains.ReSharper.TaskRunnerFramework; +using JetBrains.ReSharper.UnitTestRunner.MSTest; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestProvider.MSTest +{ + public class MsTestClassTaskProvider : IClassTaskProvider + { + public bool IsClassTask(RemoteTask task) + { + return task is MsTestTestClassTask; + } + + private MsTestTestClassTask GetTask(RemoteTask task) + { + return (MsTestTestClassTask)task; + } + + public string GetFullClassName(RemoteTask task) + { + var classTask = GetTask(task); + + return classTask.TypeName; + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestMethodTaskProvider.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestMethodTaskProvider.cs new file mode 100644 index 0000000..e07b673 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestProvider/MSTest/MsTestMethodTaskProvider.cs @@ -0,0 +1,26 @@ +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers; +using JetBrains.ReSharper.TaskRunnerFramework; +using JetBrains.ReSharper.UnitTestRunner.MSTest; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestProvider.MSTest +{ + public class MsTestMethodTaskProvider : IMethodTaskProvider + { + public bool IsMethodTask(RemoteTask task) + { + return task is MsTestTestMethodTask; + } + + private MsTestTestMethodTask GetTask(RemoteTask task) + { + return (MsTestTestMethodTask)task; + } + + public string GetFullMethodName(RemoteTask task) + { + var methodTask = GetTask(task); + + return string.Format("{0}.{1}", methodTask.TypeName, methodTask.ShortName); + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/DebugLogger.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/DebugLogger.cs new file mode 100644 index 0000000..7a25ba3 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/DebugLogger.cs @@ -0,0 +1,69 @@ +using StatLight.Core.Common; +using StatLight.Core.Properties; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight +{ + // TODO: Move this to StatLight + public class DebugLogger : LoggerBase + { + private readonly Settings settings; + + public DebugLogger() + : this(LogChatterLevels.Error | LogChatterLevels.Warning | LogChatterLevels.Information, Settings.Default) + { } + + public DebugLogger(LogChatterLevels logChatterLevel) + : this(logChatterLevel, Settings.Default) + { } + + public DebugLogger(LogChatterLevels logChatterLevel, Settings settings) + : base(logChatterLevel) + { + this.settings = settings; + } + + public override void Information(string message) + { + if (ShouldLog(LogChatterLevels.Information)) + Write(message, "Information", false); + } + + public override void Debug(string message) + { + if (ShouldLog(LogChatterLevels.Debug)) + Write(message, "Debug", true); + } + + public override void Debug(string message, bool writeNewLine) + { + if (ShouldLog(LogChatterLevels.Debug)) + Write(message, "Debug", writeNewLine); + } + + public override void Warning(string message) + { + if (ShouldLog(LogChatterLevels.Warning)) + Write(message, "Warning", false); + } + + public override void Error(string message) + { + if (ShouldLog(LogChatterLevels.Error)) + Write(message, "Error", true); + } + + private void Write(string message, string type, bool useNewLine) + { + message = string.Format("[{0}]: {1}", type, message); + + if (useNewLine) + { + System.Diagnostics.Debug.WriteLine(message); + } + else + { + System.Diagnostics.Debug.Write(message); + } + } + } +} diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/AssemblyTask.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/AssemblyTask.cs new file mode 100644 index 0000000..c643f11 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/AssemblyTask.cs @@ -0,0 +1,27 @@ +using System; +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Execution +{ + public class AssemblyTask + { + public TaskNode Node { get; private set; } + public IAssemblyTaskProvider AssemblyTaskProvider { get; private set; } + + public AssemblyTask(TaskNode node, IAssemblyTaskProvider assemblyTaskProvider) + { + Node = node; + AssemblyTaskProvider = assemblyTaskProvider; + } + + public void Execute(Action execute) + { + Node.Execute(execute, this); + } + + public string GetXapPath() + { + return AssemblyTaskProvider.GetXapPath(Node.Task); + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/ClassTask.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/ClassTask.cs new file mode 100644 index 0000000..97ea8d9 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/ClassTask.cs @@ -0,0 +1,21 @@ +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Execution +{ + public class ClassTask + { + public TaskNode Node { get; private set; } + public IClassTaskProvider ClassTaskProvider { get; private set; } + + public ClassTask(TaskNode node, IClassTaskProvider classTaskProvider) + { + Node = node; + ClassTaskProvider = classTaskProvider; + } + + public string GetFullClassName() + { + return ClassTaskProvider.GetFullClassName(Node.Task); + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/MethodTask.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/MethodTask.cs new file mode 100644 index 0000000..b087367 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/MethodTask.cs @@ -0,0 +1,21 @@ +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Execution +{ + public class MethodTask + { + public TaskNode Node { get; private set; } + public IMethodTaskProvider MethodTaskProvider { get; private set; } + + public MethodTask(TaskNode node, IMethodTaskProvider methodTaskProvider) + { + Node = node; + MethodTaskProvider = methodTaskProvider; + } + + public string GetFullMethodName() + { + return MethodTaskProvider.GetFullMethodName(Node.Task); + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/TaskEnvironment.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/TaskEnvironment.cs new file mode 100644 index 0000000..a8808be --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/TaskEnvironment.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers; +using JetBrains.ReSharper.TaskRunnerFramework; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Execution +{ + public class TaskEnvironment + { + public IRemoteTaskServer Server { get; private set; } + public IEnumerable AssemblyTaskProviders { get; private set; } + public IEnumerable ClassTaskProviders { get; private set; } + public IEnumerable MethodTaskProviders { get; private set; } + + public TaskEnvironment(IRemoteTaskServer server, + IEnumerable assemblyTaskProviders, + IEnumerable classTaskProviders, + IEnumerable methodTaskProviders) + { + Server = server; + AssemblyTaskProviders = assemblyTaskProviders; + ClassTaskProviders = classTaskProviders; + MethodTaskProviders = methodTaskProviders; + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/TaskNode.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/TaskNode.cs new file mode 100644 index 0000000..05122cd --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Execution/TaskNode.cs @@ -0,0 +1,107 @@ +using System; +using System.Linq; +using JetBrains.ReSharper.TaskRunnerFramework; +using StatLight.Client.Harness.Events; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Execution +{ + public enum TaskStatus + { + NotStarted, + Running, + Finished + } + + public class TaskNode + { + public RemoteTask Task { get; private set; } + public TaskEnvironment Environment { get; private set; } + public TaskNode Parent { get; private set; } + public TaskNode[] Children { get; private set; } + public TaskStatus Status { get; private set; } + public TaskResult Result { get; private set; } + + public TaskNode(TaskExecutionNode node, TaskEnvironment environment, TaskNode parent = null) + { + Task = node.RemoteTask; + Environment = environment; + Parent = parent; + Status = TaskStatus.NotStarted; + Result = TaskResult.Skipped; + Children = node.Children.Select(child => new TaskNode(child, environment, this)).ToArray(); + } + + public void Execute(Action execute, T task) + { + try + { + NotifyStarting(); + execute(task); + NotifyFinished(null, TaskResult.Success); + } + catch (Exception e) + { + NotifyFinishedWithException(e); + throw; + } + } + + public void NotifyStarting() + { + if (Status == TaskStatus.NotStarted) + { + if (Parent != null) + { + Parent.NotifyStarting(); + } + + Status = TaskStatus.Running; + + Environment.Server.TaskStarting(Task); + } + } + + public void NotifyFinished(string output = null, TaskResult? result = null) + { + NotifyStarting(); + + if (Status == TaskStatus.Running) + { + Status = TaskStatus.Finished; + Result = result ?? (Children.Any() ? Children.Max(c => c.Result) : TaskResult.Success); + + foreach (var child in Children) + { + child.NotifyFinished(null, TaskResult.Skipped); + } + + Environment.Server.TaskFinished(Task, output, Result); + + if (Parent != null && Parent.Children.All(c => c.Status == TaskStatus.Finished)) + { + Parent.NotifyFinished(null); + } + } + } + + public void NotifyFinishedWithException(Exception e, TaskResult result = TaskResult.Exception) + { + NotifyStarting(); + + Environment.Server.TaskException(Task, new[] { new TaskException(e) }); + + NotifyFinished(e.Message, result); + } + + public void NotifyFinishedWithException(ExceptionInfo e, TaskResult result = TaskResult.Exception) + { + NotifyStarting(); + + // TODO: We should pass the TypeName instead of FullMessage + // TODO: Report inner exceptions recursively + Environment.Server.TaskException(Task, new[] { new TaskException(e.FullMessage, e.Message, e.StackTrace) }); + + NotifyFinished(e.Message, result); + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IAssemblyTaskProvider.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IAssemblyTaskProvider.cs new file mode 100644 index 0000000..e44ea33 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IAssemblyTaskProvider.cs @@ -0,0 +1,10 @@ +using JetBrains.ReSharper.TaskRunnerFramework; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers +{ + public interface IAssemblyTaskProvider + { + bool IsAssemblyTask(RemoteTask task); + string GetXapPath(RemoteTask task); + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IClassTaskProvider.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IClassTaskProvider.cs new file mode 100644 index 0000000..84d6310 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IClassTaskProvider.cs @@ -0,0 +1,10 @@ +using JetBrains.ReSharper.TaskRunnerFramework; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers +{ + public interface IClassTaskProvider + { + bool IsClassTask(RemoteTask task); + string GetFullClassName(RemoteTask task); + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IMethodTaskProvider.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IMethodTaskProvider.cs new file mode 100644 index 0000000..3c5e42c --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/IMethodTaskProvider.cs @@ -0,0 +1,10 @@ +using JetBrains.ReSharper.TaskRunnerFramework; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers +{ + public interface IMethodTaskProvider + { + bool IsMethodTask(RemoteTask task); + string GetFullMethodName(RemoteTask task); + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/TaskNodeExtensions.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/TaskNodeExtensions.cs new file mode 100644 index 0000000..5171d43 --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/Providers/TaskNodeExtensions.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Linq; +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Execution; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers +{ + public static class TaskNodeExtensions + { + public static IEnumerable GetAssemblyTasks(this TaskNode node) + { + foreach (var assemblyTaskProvider in node.Environment.AssemblyTaskProviders) + { + if (assemblyTaskProvider.IsAssemblyTask(node.Task)) + { + yield return new AssemblyTask(node, assemblyTaskProvider); + } + } + + foreach (var child in node.Children.SelectMany(child => child.GetAssemblyTasks())) + { + yield return child; + } + } + + public static IEnumerable GetClassTasks(this TaskNode node) + { + foreach (var classTaskProvider in node.Environment.ClassTaskProviders) + { + if (classTaskProvider.IsClassTask(node.Task)) + { + yield return new ClassTask(node, classTaskProvider); + } + } + + foreach (var child in node.Children.SelectMany(child => child.GetClassTasks())) + { + yield return child; + } + } + + public static IEnumerable GetMethodTasks(this TaskNode node) + { + foreach (var methodTaskProvider in node.Environment.MethodTaskProviders) + { + if (methodTaskProvider.IsMethodTask(node.Task)) + { + yield return new MethodTask(node, methodTaskProvider); + } + } + + foreach (var child in node.Children.SelectMany(child => child.GetMethodTasks())) + { + yield return child; + } + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/SilverlightResultsHandler.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/SilverlightResultsHandler.cs new file mode 100644 index 0000000..1b2b65c --- /dev/null +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/SilverlightResultsHandler.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Execution; +using EventAggregatorNet; +using JetBrains.ReSharper.TaskRunnerFramework; +using StatLight.Client.Harness.Events; +using StatLight.Core.Events; + +namespace AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight +{ + public class SilverlightResultsHandler : ITestingReportEvents, + IListener, + IListener, + IListener + { + public IEnumerable TestClasses { get; private set; } + public IEnumerable TestMethods { get; private set; } + + public SilverlightResultsHandler(IEnumerable testClasses, IEnumerable testMethods) + { + TestClasses = testClasses; + TestMethods = testMethods; + } + + public void Handle(TestCaseResult message) + { + if (message.MethodName != null) + { + var testMethod = GetTestMethod(message.FullMethodName()); + if (testMethod != null) + { + var taskResult = ToTaskResult(message.ResultType); + + if (message.ExceptionInfo != null) + { + testMethod.Node.NotifyFinishedWithException(message.ExceptionInfo, taskResult); + } + else + { + testMethod.Node.NotifyFinished(null, taskResult); + } + } + } + } + + private TaskResult ToTaskResult(ResultType resultType) + { + switch (resultType) + { + case ResultType.Passed: + return TaskResult.Success; + case ResultType.Failed: + return TaskResult.Exception; + case ResultType.Ignored: + return TaskResult.Skipped; + case ResultType.SystemGeneratedFailure: + return TaskResult.Error; + } + + throw new ArgumentOutOfRangeException(); + } + + public void Handle(TraceClientEvent message) + { + // TODO: Note sure what to do with this, maybe ask Jason Jarrett ... + // TODO: Apparently a test method with ExpectedException, that is not throwing an exception, is not returning a test result (See TestFixture1.FailingTest3 in DummyTests) + } + + public void Handle(BrowserHostCommunicationTimeoutServerEvent message) + { + throw new Exception(message.Message); + } + + public void Handle(FatalSilverlightExceptionServerEvent message) + { + throw new Exception(message.Message); + } + + public void Handle(UnhandledExceptionClientEvent message) + { + throw new Exception(message.ExceptionInfo.FullMessage); + } + + public void Handle(TestExecutionClassBeginClientEvent message) + { + var testClass = GetTestClass(message); + if (testClass != null) + { + testClass.Node.NotifyStarting(); + } + } + + public void Handle(TestExecutionClassCompletedClientEvent message) + { + var testClass = GetTestClass(message); + if (testClass != null) + { + testClass.Node.NotifyFinished(); + } + } + + public void Handle(TestExecutionMethodBeginClientEvent message) + { + // TODO: For some reason this is triggered AFTER the method is run, so the test timings are incorrect + var testMethod = GetTestMethod(message.FullMethodName); + if (testMethod != null) + { + testMethod.Node.NotifyStarting(); + } + } + + private ClassTask GetTestClass(TestExecutionClass message) + { + var fullClassName = string.Format("{0}.{1}", message.NamespaceName, message.ClassName); + return TestClasses.FirstOrDefault(c => c.GetFullClassName() == fullClassName); + } + + private MethodTask GetTestMethod(string fullMethodName) + { + return TestMethods.FirstOrDefault(c => c.GetFullMethodName() == fullMethodName); + } + } +} \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/SilverlightUnitTestTaskRunner.cs b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/SilverlightUnitTestTaskRunner.cs index d6f698d..8246080 100644 --- a/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/SilverlightUnitTestTaskRunner.cs +++ b/src/AgUnit.Runner.Resharper60.TaskRunner/UnitTestRunner/Silverlight/SilverlightUnitTestTaskRunner.cs @@ -1,14 +1,14 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestProvider.MSTest; +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Execution; +using AgUnit.Runner.Resharper60.TaskRunner.UnitTestRunner.Silverlight.Providers; +using EventAggregatorNet; using JetBrains.ReSharper.TaskRunnerFramework; -using JetBrains.ReSharper.UnitTestRunner.MSTest; -using StatLight.Client.Harness.Events; using StatLight.Core.Common; using StatLight.Core.Configuration; -using StatLight.Core.Events; using StatLight.Core.Runners; using StatLight.Core.WebBrowser; @@ -39,201 +39,72 @@ public override void ExecuteRecursive(TaskExecutionNode node) { //Debugger.Break(); - try - { - Server.TaskStarting(node.RemoteTask); - - foreach (var assemblyTaskNode in node.Children) - { - Execute(assemblyTaskNode, (MsTestTestAssemblyTask)assemblyTaskNode.RemoteTask); - } - - Server.TaskFinished(node.RemoteTask, null, TaskResult.Success); - } - catch (Exception e) - { - Server.TaskException(node.RemoteTask, new[] { new TaskException(e) }); - Server.TaskFinished(node.RemoteTask, null, TaskResult.Exception); - - throw; - } - } - - private void Execute(TaskExecutionNode assemblyTaskNode, MsTestTestAssemblyTask assemblyTask) - { - try - { - Server.TaskStarting(assemblyTask); - - var xapPath = assemblyTask.AssemblyLocation.Replace(".dll", ".xap"); - var testMethods = assemblyTaskNode.GetTasks().Select(m => m.GetFullMethodName()).ToList(); - - ILogger logger = new ConsoleLogger(LogChatterLevels.Full); - var eventAggregator = EventAggregatorFactory.Create(logger); - - // Create our custom listener and add it to the event aggregator - var reSharperTestingReportEventsHandler = new ReSharperTestingReportEventsHandler(Server, assemblyTaskNode, testMethods); - eventAggregator.AddListener(reSharperTestingReportEventsHandler); - - var statLightConfigurationFactory = new StatLightConfigurationFactory(logger); - - var config = statLightConfigurationFactory.GetStatLightConfigurationForXap( - unitTestProviderType: UnitTestProviderType.Undefined, // Let StatLight figure it out - xapPath: xapPath, - microsoftTestingFrameworkVersion: null, // Let StatLight figure it out - methodsToTest: new Collection(testMethods), - tagFilters: null, - numberOfBrowserHosts: 1, // Maybe you spin up 3 or 4 here if you know you're running a ton of tests - isRemoteRun: false, - queryString: "", // This is passed to the browser host page (say your test need some configuration - could be passed here - probably not a use case in ReSharper runner) - webBrowserType: WebBrowserType.SelfHosted, - forceBrowserStart: false, - showTestingBrowserHost: false // If you need UI support this needs to be true - ); - - var statLightRunnerFactory = new StatLightRunnerFactory(logger, eventAggregator, eventAggregator); - - var onetimeConsoleRunner = statLightRunnerFactory.CreateOnetimeConsoleRunner(config); - - // This will be the blocking/slow operation that runs the tests... - var testReport = onetimeConsoleRunner.Run(); - - reSharperTestingReportEventsHandler.ReportIgnoredMethods(); - reSharperTestingReportEventsHandler.ReportOtherTasks(); - - Server.TaskFinished(assemblyTask, null, TaskResult.Success); - } - catch (Exception e) - { - Server.TaskException(assemblyTask, new[] { new TaskException(e) }); - Server.TaskFinished(assemblyTask, null, TaskResult.Exception); - - throw; - } - } - } - - public class ReSharperTestingReportEventsHandler : ITestingReportEvents - { - private readonly IRemoteTaskServer server; - private readonly TaskExecutionNode rootNode; - private readonly IList methodsToRun; - private readonly IList finishedTasks; + var assemblyProviders = new IAssemblyTaskProvider[] { new MsTestAssemblyTaskProvider() }; + var classProviders = new IClassTaskProvider[] { new MsTestClassTaskProvider() }; + var methodProviders = new IMethodTaskProvider[] { new MsTestMethodTaskProvider() }; - public ReSharperTestingReportEventsHandler(IRemoteTaskServer server, TaskExecutionNode rootNode, IList methodsToRun) - { - this.server = server; - this.rootNode = rootNode; - this.methodsToRun = methodsToRun; - - finishedTasks = new List(); - } + var taskEnvironment = new TaskEnvironment(Server, assemblyProviders, classProviders, methodProviders); + var taskNode = new TaskNode(node, taskEnvironment); - public void Handle(TestCaseResult message) - { - if (message.MethodName != null) + foreach (var assemblyTaskNode in taskNode.GetAssemblyTasks()) { - var remoteTask = rootNode.GetTasks().FirstOrDefault(t => t.GetFullMethodName() == message.FullMethodName()); - if (remoteTask != null) - { - server.TaskStarting(remoteTask); - var output = message.ExceptionInfo != null ? message.ExceptionInfo.ToString() : null; - methodsToRun.Remove(message.FullMethodName()); - server.TaskFinished(remoteTask, output, ToTaskResult(message.ResultType)); - finishedTasks.Add(remoteTask); - } + assemblyTaskNode.Execute(Execute); } } - private TaskResult ToTaskResult(ResultType resultType) + private void Execute(AssemblyTask assemblyTask) { - switch (resultType) - { - case ResultType.Passed: - return TaskResult.Success; - case ResultType.Failed: - return TaskResult.Exception; - case ResultType.Ignored: - return TaskResult.Skipped; - case ResultType.SystemGeneratedFailure: - return TaskResult.Error; - } + var xapPath = assemblyTask.GetXapPath(); + var testMethods = assemblyTask.Node.GetMethodTasks().ToArray(); + var testClasses = assemblyTask.Node.GetClassTasks().ToArray(); - throw new ArgumentOutOfRangeException(); - } + var logger = CreateStatLightLogger(); + var eventAggregator = CreateStatLightEventAggregator(testClasses, testMethods, logger); + var configuration = CreateStatLightConfiguration(testMethods, logger, xapPath); + var runner = CreateStatLightRunner(configuration, logger, eventAggregator); - public void Handle(TraceClientEvent message) - { - server.TaskOutput(rootNode.RemoteTask, message.Message, TaskOutputType.STDOUT); + var testReport = runner.Run(); } - public void Handle(BrowserHostCommunicationTimeoutServerEvent message) + private static DebugLogger CreateStatLightLogger() { - server.TaskError(rootNode.RemoteTask, message.Message); + return new DebugLogger(LogChatterLevels.Full); } - public void Handle(FatalSilverlightExceptionServerEvent message) + private static EventAggregator CreateStatLightEventAggregator(IEnumerable testClasses, IEnumerable testMethods, ILogger logger) { - server.TaskError(rootNode.RemoteTask, message.Message); - } + var eventsHandler = new SilverlightResultsHandler(testClasses, testMethods); + var eventAggregator = EventAggregatorFactory.Create(logger); - public void Handle(UnhandledExceptionClientEvent message) - { - server.TaskError(rootNode.RemoteTask, message.ExceptionInfo.FullMessage); - } + eventAggregator.AddListener(eventsHandler); - public void ReportIgnoredMethods() - { - foreach (var method in methodsToRun) - { - var remoteTask = rootNode.GetTasks().FirstOrDefault(t => t.GetFullMethodName() == method); - if (remoteTask != null) - { - server.TaskFinished(remoteTask, null, TaskResult.Skipped); - finishedTasks.Add(remoteTask); - } - } + return eventAggregator; } - public void ReportOtherTasks() + private static StatLightConfiguration CreateStatLightConfiguration(IEnumerable testMethods, ILogger logger, string xapPath) { - var allTaskNodes = rootNode.Children.FlattenNodesHierarchy().ToList(); + var configurationFactory = new StatLightConfigurationFactory(logger); - foreach (var taskNode in allTaskNodes.Where(t => !finishedTasks.Contains(t.RemoteTask))) - { - server.TaskFinished(taskNode.RemoteTask, null, TaskResult.Success); - } - } - } - - public static class TaskExecutionNodeHelper - { - public static IEnumerable GetTasks(this TaskExecutionNode parentNode) where T : RemoteTask - { - return FlattenNodesHierarchy(new[] { parentNode }).Select(node => node.RemoteTask).OfType(); - } - - public static IEnumerable GetNodesWithTask(this TaskExecutionNode parentNode) where T : RemoteTask - { - return FlattenNodesHierarchy(new[] { parentNode }).Where(node => node.RemoteTask is T); + return configurationFactory.GetStatLightConfigurationForXap( + unitTestProviderType: UnitTestProviderType.Undefined, // Let StatLight figure it out + xapPath: xapPath, + microsoftTestingFrameworkVersion: null, // Let StatLight figure it out + methodsToTest: new Collection(testMethods.Select(m => m.GetFullMethodName()).ToList()), + tagFilters: null, + numberOfBrowserHosts: 1, // Maybe you spin up 3 or 4 here if you know you're running a ton of tests + isRemoteRun: false, + queryString: "", // This is passed to the browser host page (say your test need some configuration - could be passed here - probably not a use case in ReSharper runner) + webBrowserType: WebBrowserType.SelfHosted, + forceBrowserStart: false, + showTestingBrowserHost: false // If you need UI support this needs to be true + ); } - public static IEnumerable FlattenNodesHierarchy(this IEnumerable nodes) + private static IRunner CreateStatLightRunner(StatLightConfiguration config, ILogger logger, EventAggregator eventAggregator) { - foreach (var node in nodes) - { - foreach (var childNode in FlattenNodesHierarchy(node.Children)) - { - yield return childNode; - } + var runnerFactory = new StatLightRunnerFactory(logger, eventAggregator, eventAggregator); - yield return node; - } - } - - public static string GetFullMethodName(this MsTestTestMethodTask methodTask) - { - return string.Format("{0}.{1}", methodTask.TypeName, methodTask.ShortName); + return runnerFactory.CreateOnetimeConsoleRunner(config); } } } \ No newline at end of file diff --git a/src/AgUnit.Runner.Resharper60/AgUnit.Runner.Resharper60.csproj b/src/AgUnit.Runner.Resharper60/AgUnit.Runner.Resharper60.csproj index 67098e9..720ef70 100644 --- a/src/AgUnit.Runner.Resharper60/AgUnit.Runner.Resharper60.csproj +++ b/src/AgUnit.Runner.Resharper60/AgUnit.Runner.Resharper60.csproj @@ -16,7 +16,7 @@ $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\JetBrains\ReSharper\v6.0\vs10.0@InstallDir) Program $(DevEnvDir)devenv.exe - /ReSharper.Plugin AgUnit.Runner.Resharper60.dll /ReSharper.LogFile C:\resharper.log /ReSharper.LogLevel Verbose ..\src\DummyTests\VS2010\DummyTests.sln + /ReSharper.Plugin AgUnit.Runner.Resharper60.dll /ReSharper.LogFile "..\resharper.log" /ReSharper.LogLevel Verbose ..\src\DummyTests\VS2010\DummyTests.sln ..\..\output\ diff --git a/src/DummyTests/VS2010/DummyTests.DotNetMSTest/DummyTests1.cs b/src/DummyTests/VS2010/DummyTests.DotNetMSTest/DummyTests1.cs index 1f24cc4..aebff2a 100644 --- a/src/DummyTests/VS2010/DummyTests.DotNetMSTest/DummyTests1.cs +++ b/src/DummyTests/VS2010/DummyTests.DotNetMSTest/DummyTests1.cs @@ -58,6 +58,12 @@ public void FailingTest3() { } + [TestMethod] + public void FailingTest4() + { + throw new InvalidOperationException(); + } + [TestCleanup] public void TestCleanup1() { diff --git a/src/DummyTests/VS2010/DummyTests.DotNetNUnit/DummyTests1NUnit.cs b/src/DummyTests/VS2010/DummyTests.DotNetNUnit/DummyTests1NUnit.cs index dd53744..2054284 100644 --- a/src/DummyTests/VS2010/DummyTests.DotNetNUnit/DummyTests1NUnit.cs +++ b/src/DummyTests/VS2010/DummyTests.DotNetNUnit/DummyTests1NUnit.cs @@ -53,6 +53,12 @@ public void FailingTest3() { } + [Test] + public void FailingTest4() + { + throw new InvalidOperationException(); + } + [TearDown] public void TestCleanup1() { diff --git a/src/DummyTests/VS2010/DummyTests.Silverlight3/DummyTests1.cs b/src/DummyTests/VS2010/DummyTests.Silverlight3/DummyTests1.cs index ab71bc2..6392cc3 100644 --- a/src/DummyTests/VS2010/DummyTests.Silverlight3/DummyTests1.cs +++ b/src/DummyTests/VS2010/DummyTests.Silverlight3/DummyTests1.cs @@ -58,6 +58,12 @@ public void FailingTest3() { } + [TestMethod] + public void FailingTest4() + { + throw new InvalidOperationException(); + } + [TestCleanup] public void TestCleanup1() { diff --git a/src/DummyTests/VS2010/DummyTests.Silverlight4.Other/DummyTests1.cs b/src/DummyTests/VS2010/DummyTests.Silverlight4.Other/DummyTests1.cs index 597df1a..6534a85 100644 --- a/src/DummyTests/VS2010/DummyTests.Silverlight4.Other/DummyTests1.cs +++ b/src/DummyTests/VS2010/DummyTests.Silverlight4.Other/DummyTests1.cs @@ -58,6 +58,12 @@ public void FailingTest3() { } + [TestMethod] + public void FailingTest4() + { + throw new InvalidOperationException(); + } + [TestCleanup] public void TestCleanup1() { diff --git a/src/DummyTests/VS2010/DummyTests.Silverlight4/DummyTests1.cs b/src/DummyTests/VS2010/DummyTests.Silverlight4/DummyTests1.cs index 569e6a5..b4bd8e5 100644 --- a/src/DummyTests/VS2010/DummyTests.Silverlight4/DummyTests1.cs +++ b/src/DummyTests/VS2010/DummyTests.Silverlight4/DummyTests1.cs @@ -24,6 +24,8 @@ public void TestInitialize1() [TestMethod] public void PassingTest1() { + + System.Threading.Thread.Sleep(2000); } [TestMethod] @@ -58,6 +60,12 @@ public void FailingTest3() { } + [TestMethod] + public void FailingTest4() + { + throw new InvalidOperationException(); + } + [TestCleanup] public void TestCleanup1() {