diff --git a/src/AddIns/Analysis/UnitTesting/Commands/AbstractRunTestCommand.cs b/src/AddIns/Analysis/UnitTesting/Commands/AbstractRunTestCommand.cs
deleted file mode 100644
index d78df247b0..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Commands/AbstractRunTestCommand.cs
+++ /dev/null
@@ -1,398 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using ICSharpCode.Core;
-using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Gui;
-using ICSharpCode.SharpDevelop.Project;
-using ICSharpCode.SharpDevelop.Project.Commands;
-
-namespace ICSharpCode.UnitTesting
-{
- public abstract class AbstractRunTestCommand : AbstractMenuCommand
- {
- static AbstractRunTestCommand runningTestCommand;
- IUnitTestsPad unitTestsPad;
- SelectedTests selectedTests;
- IRunTestCommandContext context;
- ITestRunner testRunner;
- IProgressMonitor testProgressMonitor;
- int totalProjectCount;
-
- public AbstractRunTestCommand()
- : this(new RunTestCommandContext())
- {
- }
-
- public AbstractRunTestCommand(IRunTestCommandContext context)
- {
- this.context = context;
- }
-
- protected IRunTestCommandContext Context {
- get { return context; }
- }
-
- ///
- /// Gets the running test command.
- ///
- public static AbstractRunTestCommand RunningTestCommand {
- get { return runningTestCommand; }
- set { runningTestCommand = value; }
- }
-
- ///
- /// Gets whether a test is currently running.
- ///
- public static bool IsRunningTest {
- get { return runningTestCommand != null; }
- }
-
- public override void Run()
- {
- GetUnitTestsPad();
-
- selectedTests = GetSelectedTests();
- if (selectedTests.HasProjects) {
- runningTestCommand = this;
- BeforeRun();
- BuildAndRunTests();
- }
- }
-
- SelectedTests GetSelectedTests()
- {
- return new SelectedTests(Owner, unitTestsPad.GetProjects());
- }
-
- void GetUnitTestsPad()
- {
- unitTestsPad = context.OpenUnitTestsPad;
- if (unitTestsPad == null) {
- unitTestsPad = CreateEmptyUnitTestsPad();
- }
- }
-
- EmptyUnitTestsPad CreateEmptyUnitTestsPad()
- {
- return new EmptyUnitTestsPad(context.OpenSolution);
- }
-
- ///
- /// Sets the initial workbench state before starting
- /// a test run.
- ///
- void BeforeRun()
- {
- ClearTasks();
- ClearUnitTestCategoryText();
-
- ShowUnitTestsPad();
- ShowOutputPad();
-
- UpdateUnitTestsPadToolbar();
- ResetAllTestResultsInUnitTestsPad();
-
- OnBeforeBuild();
- }
-
- void BuildAndRunTests()
- {
- if (IsBuildNeededBeforeTestRun()) {
- BuildProjectBeforeRunningTests(selectedTests);
- } else {
- context.SaveAllFilesCommand.SaveAllFiles();
- RunTests(selectedTests);
- }
- }
-
- bool IsBuildNeededBeforeTestRun()
- {
- return selectedTests.Projects.Any(p => context.RegisteredTestFrameworks.IsBuildNeededBeforeTestRunForProject(p));
- }
-
- void ClearTasks()
- {
- context.TaskService.BuildMessageViewCategory.ClearText();
- context.TaskService.InUpdate = true;
- context.TaskService.ClearExceptCommentTasks();
- context.TaskService.InUpdate = false;
- }
-
- void ClearUnitTestCategoryText()
- {
- context.UnitTestCategory.ClearText();
- }
-
- void ShowUnitTestsPad()
- {
- unitTestsPad.BringToFront();
- }
-
- void StopProgressMonitor()
- {
- if (testProgressMonitor != null) {
- testProgressMonitor.Dispose();
- testProgressMonitor = null;
- }
- }
-
- void UpdateUnitTestsPadToolbar()
- {
- unitTestsPad.UpdateToolbar();
- }
-
- ///
- /// Called before the build is started (even if no build needs to be performed).
- /// If multiple projects are to be tested this is called only once.
- ///
- protected virtual void OnBeforeBuild()
- {
- }
-
- ///
- /// Called before all tests are run (after the build has finished successfully).
- /// If multiple projects are to be tested this is called only once.
- ///
- protected virtual void OnBeforeRunTests()
- {
- }
-
- ///
- /// Runs the tests after building the project(s) under test.
- ///
- void BuildProjectBeforeRunningTests(SelectedTests selectedTests)
- {
- BuildProject build = CreateBuildProjectBeforeTestRun(selectedTests);
- build.BuildComplete += delegate {
- OnBuildComplete(build.LastBuildResults, selectedTests);
- };
- build.Run();
- }
-
- BuildProject CreateBuildProjectBeforeTestRun(SelectedTests selectedTests)
- {
- IEnumerable projects = GetProjectsRequiringBuildBeforeTestRun(selectedTests);
- return context.BuildProjectFactory.CreateBuildProjectBeforeTestRun(projects);
- }
-
- IEnumerable GetProjectsRequiringBuildBeforeTestRun(SelectedTests selectedTests)
- {
- return selectedTests
- .Projects
- .Where(p => context.RegisteredTestFrameworks.IsBuildNeededBeforeTestRunForProject(p));
- }
-
- ///
- /// Stops running the tests.
- ///
- public void Stop()
- {
- StopActiveTestRunner();
-
- runningTestCommand = null;
- UpdateUnitTestsPadToolbar();
-
- OnStop();
- }
-
- void StopActiveTestRunner()
- {
- if (testRunner != null) {
- testRunner.Stop();
- testRunner.Dispose();
- testRunner = null;
- }
- }
-
- ///
- /// Called after all tests have been run even if there have
- /// been errors. If multiple projects are to be tested this is called only once.
- ///
- protected virtual void OnAfterRunTests()
- {
- }
-
- ///
- /// Called by derived classes when a single test run
- /// is finished.
- ///
- protected void TestRunCompleted()
- {
- StopActiveTestRunner();
- selectedTests.RemoveFirstProject();
- if (selectedTests.HasProjects) {
- RunTests(selectedTests);
- } else {
- StopProgressMonitor();
- runningTestCommand = null;
- UpdateUnitTestsPadToolbar();
- ShowErrorList();
- OnAfterRunTests();
- }
- }
-
- void TestFinished(object source, TestFinishedEventArgs e)
- {
- context.Workbench.SafeThreadAsyncCall(ShowResult, e.Result);
- }
-
- protected void ShowResult(TestResult result)
- {
- if (IsTestResultFailureOrIsIgnored(result)) {
- AddTaskForTestResult(result);
- UpdateProgressMonitorStatus(result);
- }
- UpdateTestResult(result);
- }
-
- bool IsTestResultFailureOrIsIgnored(TestResult result)
- {
- return result.IsFailure || result.IsIgnored;
- }
-
- void AddTaskForTestResult(TestResult testResult)
- {
- TestProject project = GetTestProjectForProject(selectedTests.Project);
- SDTask task = TestResultTask.Create(testResult, project);
- context.TaskService.Add(task);
- }
-
- ///
- /// Called when the test run should be stopped.
- ///
- protected virtual void OnStop()
- {
- }
-
- void ShowOutputPad()
- {
- ShowPad(context.Workbench.GetPad(typeof(CompilerMessageView)));
- }
-
- protected void ShowPad(PadDescriptor padDescriptor)
- {
- context.Workbench.SafeThreadAsyncCall(padDescriptor.BringPadToFront);
- }
-
- void ShowErrorList()
- {
- if (HasErrorsThatShouldBeDisplayed()) {
- ShowPad(context.Workbench.GetPad(typeof(ErrorListPad)));
- }
- }
-
- bool HasErrorsThatShouldBeDisplayed()
- {
- return context.TaskService.SomethingWentWrong &&
- context.BuildOptions.ShowErrorListAfterBuild;
- }
-
- ///
- /// Runs the test for the project after a successful build.
- ///
- void OnBuildComplete(BuildResults results, SelectedTests selectedTests)
- {
- if (BuildHasNoErrorsAndStillRunningTests(results)) {
- RunTests(selectedTests);
- } else {
- if (IsRunningTest) {
- Stop();
- }
- ShowErrorList();
- }
- }
-
- bool BuildHasNoErrorsAndStillRunningTests(BuildResults results)
- {
- return (results.ErrorCount == 0) && IsRunningTest;
- }
-
- void RunTests(SelectedTests selectedTests)
- {
- if (testProgressMonitor == null) {
- OnBeforeRunTests();
- testProgressMonitor = context.StatusBarService.CreateProgressMonitor();
- totalProjectCount = selectedTests.ProjectsCount;
- }
- testProgressMonitor.TaskName = GetProgressMonitorLabel(selectedTests.Project);
- testProgressMonitor.Progress = GetProgress(selectedTests.ProjectsCount);
-
- testRunner = CreateTestRunner(selectedTests.Project);
- if (testRunner != null) {
- StartTestRunner();
- }
- }
-
- void StartTestRunner()
- {
- testRunner.MessageReceived += TestRunnerMessageReceived;
- testRunner.AllTestsFinished += AllTestsFinished;
- testRunner.TestFinished += TestFinished;
- testRunner.Start(selectedTests);
- }
-
- string GetProgressMonitorLabel(IProject project)
- {
- StringTagPair tagPair = new StringTagPair("Name", project.Name);
- return StringParser.Parse("${res:ICSharpCode.UnitTesting.StatusBarProgressLabel}", tagPair);
- }
-
- double GetProgress(int projectsLeftToRunCount)
- {
- return (double)(totalProjectCount - projectsLeftToRunCount) / totalProjectCount;
- }
-
- protected virtual ITestRunner CreateTestRunner(IProject project)
- {
- return null;
- }
-
- protected virtual void TestRunnerMessageReceived(object source, MessageReceivedEventArgs e)
- {
- context.UnitTestCategory.AppendLine(e.Message);
- }
-
- void AllTestsFinished(object source, EventArgs e)
- {
- context.Workbench.SafeThreadAsyncCall(TestRunCompleted);
- }
-
- ///
- /// Clears the test results in the test tree view for all the
- /// displayed projects.
- ///
- void ResetAllTestResultsInUnitTestsPad()
- {
- unitTestsPad.ResetTestResults();
- }
-
- TestProject GetTestProjectForProject(IProject project)
- {
- return unitTestsPad.GetTestProject(project);
- }
-
- void UpdateTestResult(TestResult result)
- {
- TestProject testProject = GetTestProjectForProject(selectedTests.Project);
- if (testProject != null) {
- testProject.UpdateTestResult(result);
- }
- }
-
- void UpdateProgressMonitorStatus(TestResult result)
- {
- if (testProgressMonitor != null) {
- if (result.IsFailure) {
- testProgressMonitor.Status = OperationStatus.Error;
- } else if (result.IsIgnored && testProgressMonitor.Status == OperationStatus.Normal) {
- testProgressMonitor.Status = OperationStatus.Warning;
- }
- }
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/IRunTestCommandContext.cs b/src/AddIns/Analysis/UnitTesting/Commands/IRunTestCommandContext.cs
deleted file mode 100644
index 7621e22718..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Commands/IRunTestCommandContext.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.Core;
-using ICSharpCode.SharpDevelop.Gui;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public interface IRunTestCommandContext
- {
- IRegisteredTestFrameworks RegisteredTestFrameworks { get; }
- IUnitTestTaskService TaskService { get; }
- IUnitTestWorkbench Workbench { get; }
- IBuildProjectFactory BuildProjectFactory { get; }
- IBuildOptions BuildOptions { get; }
- MessageViewCategory UnitTestCategory { get; }
- IUnitTestsPad OpenUnitTestsPad { get; }
- IMessageService MessageService { get; }
- IUnitTestSaveAllFilesCommand SaveAllFilesCommand { get; }
- IStatusBarService StatusBarService { get; }
- Solution OpenSolution { get; }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/PadCommands.cs b/src/AddIns/Analysis/UnitTesting/Commands/PadCommands.cs
new file mode 100644
index 0000000000..6ccce2bb70
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Commands/PadCommands.cs
@@ -0,0 +1,56 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Linq;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Project;
+using ICSharpCode.TreeView;
+
+namespace ICSharpCode.UnitTesting
+{
+ public class AddNUnitReferenceCommand : AbstractMenuCommand
+ {
+ public void Run(IProject project)
+ {
+ if (project != null) {
+ ReferenceProjectItem nunitRef = new ReferenceProjectItem(project, "nunit.framework");
+ ProjectService.AddProjectItem(project, nunitRef);
+ project.Save();
+ }
+ }
+
+ public override void Run()
+ {
+ Run(ProjectService.CurrentProject);
+ }
+ }
+
+ public class GotoDefinitionCommand : AbstractMenuCommand
+ {
+ public override void Run()
+ {
+ ITestTreeView treeView = Owner as ITestTreeView;
+ if (treeView != null) {
+ ITest test = treeView.SelectedTests.FirstOrDefault();
+ if (test != null && test.SupportsGoToDefinition)
+ test.GoToDefinition();
+ }
+ }
+ }
+
+ public class CollapseAllTestsCommand : AbstractMenuCommand
+ {
+ public override void Run()
+ {
+ if (!(this.Owner is SharpTreeView))
+ return;
+
+ var treeView = (SharpTreeView)this.Owner;
+ if (treeView.Root != null) {
+ foreach (var n in treeView.Root.Descendants())
+ n.IsExpanded = false;
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/RunAllTestsInPadCommand.cs b/src/AddIns/Analysis/UnitTesting/Commands/RunAllTestsInPadCommand.cs
deleted file mode 100644
index 8f57ff0a83..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Commands/RunAllTestsInPadCommand.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-
-namespace ICSharpCode.UnitTesting
-{
- public class RunAllTestsInPadCommand : RunTestInPadCommand
- {
- public RunAllTestsInPadCommand()
- {
- }
-
- public RunAllTestsInPadCommand(IRunTestCommandContext context)
- : base(context)
- {
- }
-
- public override void Run()
- {
- // To make sure all tests are run we set the Owner to null.
- Owner = null;
- base.Run();
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/RunProjectTestsInPadCommand.cs b/src/AddIns/Analysis/UnitTesting/Commands/RunProjectTestsInPadCommand.cs
deleted file mode 100644
index ad01f23285..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Commands/RunProjectTestsInPadCommand.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public class RunProjectTestsInPadCommand : RunTestInPadCommand, ITestTreeView
- {
- public RunProjectTestsInPadCommand()
- {
- }
-
- public RunProjectTestsInPadCommand(IRunTestCommandContext context)
- : base(context)
- {
- }
-
- public override void Run()
- {
- Owner = this;
- base.Run();
- }
-
- public TestMember SelectedMember {
- get { return null; }
- }
-
- public TestClass SelectedClass {
- get { return null; }
- }
-
- public TestProject SelectedProject {
- get { return TestService.Solution.GetTestProject(ProjectService.CurrentProject); }
- }
-
- public string SelectedNamespace {
- get { return null; }
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/RunTestCommandContext.cs b/src/AddIns/Analysis/UnitTesting/Commands/RunTestCommandContext.cs
deleted file mode 100644
index c2d00a4fc0..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Commands/RunTestCommandContext.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.Core;
-using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Gui;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public class RunTestCommandContext : IRunTestCommandContext
- {
- UnitTestingOptions options = UnitTestingOptions.Instance.Clone();
- IRegisteredTestFrameworks testFrameworks = TestService.RegisteredTestFrameworks;
- UnitTestTaskService taskService = new UnitTestTaskService();
- UnitTestWorkbench workbench = new UnitTestWorkbench();
- UnitTestBuildProjectFactory buildProjectFactory = new UnitTestBuildProjectFactory();
- UnitTestBuildOptions buildOptions = new UnitTestBuildOptions();
- MessageViewCategory unitTestCategory = TestService.UnitTestMessageView;
- UnitTestSaveAllFilesCommand saveAllFilesCommand = new UnitTestSaveAllFilesCommand();
- IStatusBarService statusBarService = SD.StatusBar;
-
- public IRegisteredTestFrameworks RegisteredTestFrameworks {
- get { return testFrameworks; }
- }
-
- public IUnitTestTaskService TaskService {
- get { return taskService; }
- }
-
- public IUnitTestWorkbench Workbench {
- get { return workbench; }
- }
-
- public IBuildProjectFactory BuildProjectFactory {
- get { return buildProjectFactory; }
- }
-
- public IBuildOptions BuildOptions {
- get { return buildOptions; }
- }
-
- public MessageViewCategory UnitTestCategory {
- get { return unitTestCategory; }
- }
-
- public IUnitTestsPad OpenUnitTestsPad {
- get { return null; }
- }
-
- public IMessageService MessageService {
- get { return SD.MessageService; }
- }
-
- public IUnitTestSaveAllFilesCommand SaveAllFilesCommand {
- get { return saveAllFilesCommand; }
- }
-
- public IStatusBarService StatusBarService {
- get { return statusBarService; }
- }
-
- public Solution OpenSolution {
- get { return ProjectService.OpenSolution; }
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/RunTestInPadCommand.cs b/src/AddIns/Analysis/UnitTesting/Commands/RunTestInPadCommand.cs
deleted file mode 100644
index 6da879c82e..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Commands/RunTestInPadCommand.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.SharpDevelop.Project;
-using ICSharpCode.SharpDevelop.Util;
-
-namespace ICSharpCode.UnitTesting
-{
- public class RunTestInPadCommand : AbstractRunTestCommand
- {
- public RunTestInPadCommand()
- {
- }
-
- public RunTestInPadCommand(IRunTestCommandContext context)
- : base(context)
- {
- }
-
- protected override ITestRunner CreateTestRunner(IProject project)
- {
- return Context.RegisteredTestFrameworks.CreateTestRunner(project);
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/RunTestWithDebuggerCommand.cs b/src/AddIns/Analysis/UnitTesting/Commands/RunTestWithDebuggerCommand.cs
deleted file mode 100644
index a4b0b7ca78..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Commands/RunTestWithDebuggerCommand.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Diagnostics;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public class RunTestWithDebuggerCommand : AbstractRunTestCommand
- {
- public RunTestWithDebuggerCommand()
- {
- }
-
- public RunTestWithDebuggerCommand(IRunTestCommandContext context)
- : base(context)
- {
- }
-
- protected override ITestRunner CreateTestRunner(IProject project)
- {
- return Context.RegisteredTestFrameworks.CreateTestDebugger(project);
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/RunningTestsCondition.cs b/src/AddIns/Analysis/UnitTesting/Commands/RunningTestsCondition.cs
index e1b2e6a00c..ac046a2a81 100644
--- a/src/AddIns/Analysis/UnitTesting/Commands/RunningTestsCondition.cs
+++ b/src/AddIns/Analysis/UnitTesting/Commands/RunningTestsCondition.cs
@@ -3,6 +3,7 @@
using System;
using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop;
namespace ICSharpCode.UnitTesting
{
@@ -13,7 +14,8 @@ namespace ICSharpCode.UnitTesting
{
public bool IsValid(object caller, Condition condition)
{
- return AbstractRunTestCommand.IsRunningTest;
+ ITestService testService = SD.GetRequiredService();
+ return testService.IsRunningTests;
}
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/TestableCondition.cs b/src/AddIns/Analysis/UnitTesting/Commands/TestableCondition.cs
index af6e7d9b69..d668b550cd 100644
--- a/src/AddIns/Analysis/UnitTesting/Commands/TestableCondition.cs
+++ b/src/AddIns/Analysis/UnitTesting/Commands/TestableCondition.cs
@@ -2,13 +2,13 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
+using System.Linq;
+
using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Editor.Commands;
-using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
@@ -17,90 +17,36 @@ namespace ICSharpCode.UnitTesting
///
public class TestableCondition : IConditionEvaluator
{
- IRegisteredTestFrameworks testFrameworks;
-
- public TestableCondition(IRegisteredTestFrameworks testFrameworks)
- {
- this.testFrameworks = testFrameworks;
- }
+ readonly ITestService testService;
public TestableCondition()
- : this(TestService.RegisteredTestFrameworks)
- {
- }
-
- public static IMember GetMember(object caller)
- {
- ITestTreeView testTreeView = caller as ITestTreeView;
- if (testTreeView != null && testTreeView.SelectedMember != null) {
- return testTreeView.SelectedMember.Resolve(testTreeView.SelectedProject);
- }
- IEntity entity = ResolveResultMenuCommand.GetEntity(caller);
- return entity as IMember;
- }
-
- public static ITypeDefinition GetClass(object caller)
- {
- ITestTreeView testTreeView = caller as ITestTreeView;
- if (testTreeView != null && testTreeView.SelectedClass != null) {
- return testTreeView.SelectedClass.Resolve(testTreeView.SelectedProject);
- }
- IEntity entity = ResolveResultMenuCommand.GetEntity(caller);
- return entity as ITypeDefinition;
- }
-
- public static IProject GetProject(object caller)
{
- ITestTreeView testTreeView = caller as ITestTreeView;
- if (testTreeView != null) {
- return testTreeView.SelectedProject != null ? testTreeView.SelectedProject.Project : null;
- }
- ITypeDefinition c = GetClassFromMemberOrCaller(caller);
- return GetProject(c);
+ this.testService = SD.GetRequiredService();
}
- public static ITypeDefinition GetClassFromMemberOrCaller(object caller)
+ public TestableCondition(ITestService testService)
{
- IMember m = GetMember(caller);
- if (m != null) {
- return m.DeclaringTypeDefinition;
- }
- return GetClass(caller);
+ this.testService = testService;
}
- static IProject GetProject(ITypeDefinition c)
+ public bool IsValid(object caller, Condition condition)
{
- return c != null ? c.ParentAssembly.GetProject() : null;
+ return GetTests(testService.OpenSolution, caller).Any();
}
- ///
- /// Returns the namespace selected if any.
- ///
- public static string GetNamespace(object caller)
+ public static IEnumerable GetTests(ITestSolution testSolution, object caller)
{
ITestTreeView testTreeView = caller as ITestTreeView;
if (testTreeView != null) {
- return testTreeView.SelectedNamespace;
+ return testTreeView.SelectedTests;
}
- return null;
- }
-
- public bool IsValid(object caller, Condition condition)
- {
- IMember m = GetMember(caller);
- if (m != null) {
- return testFrameworks.IsTestMember(m);
- }
- ITypeDefinition c = GetClass(caller);
- if (ClassHasProject(c)) {
- return testFrameworks.IsTestClass(c);
+ if (testSolution != null) {
+ IEntity entity = ResolveResultMenuCommand.GetEntity(caller);
+ ITest test = testSolution.GetTestForEntity(entity);
+ if (test != null)
+ return new[] { test };
}
- return false;
- }
-
- static bool ClassHasProject(ITypeDefinition c)
- {
- return (c != null) && (c.ParentAssembly.GetProject() != null);
+ return Enumerable.Empty();
}
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/UnitTestCommands.cs b/src/AddIns/Analysis/UnitTesting/Commands/UnitTestCommands.cs
index a830a8019c..cd666366b1 100644
--- a/src/AddIns/Analysis/UnitTesting/Commands/UnitTestCommands.cs
+++ b/src/AddIns/Analysis/UnitTesting/Commands/UnitTestCommands.cs
@@ -2,78 +2,64 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
+using System.Linq;
+
using ICSharpCode.Core;
-using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
-using ICSharpCode.TreeView;
namespace ICSharpCode.UnitTesting
{
- public class StopTestsCommand : AbstractMenuCommand
+ public class RunAllTestsInProjectCommand : AbstractMenuCommand
{
public override void Run()
{
- AbstractRunTestCommand runTestCommand = AbstractRunTestCommand.RunningTestCommand;
- if (runTestCommand != null) {
- runTestCommand.Stop();
+ ITestService testService = SD.GetRequiredService();
+ if (testService.OpenSolution != null) {
+ ITestProject project = testService.OpenSolution.GetTestProject(ProjectService.CurrentProject);
+ if (project != null)
+ testService.RunTestsAsync(new [] { project }, new TestExecutionOptions()).FireAndForget();
}
}
}
- public class AddNUnitReferenceCommand : AbstractMenuCommand
+ public class RunAllTestsInSolutionCommand : AbstractMenuCommand
{
- public void Run(IProject project)
+ public override void Run()
{
- if (project != null) {
- ReferenceProjectItem nunitRef = new ReferenceProjectItem(project, "nunit.framework");
- ProjectService.AddProjectItem(project, nunitRef);
- project.Save();
- }
+ ITestService testService = SD.GetRequiredService();
+ if (testService.OpenSolution != null)
+ testService.RunTestsAsync(new [] { testService.OpenSolution }, new TestExecutionOptions()).FireAndForget();
}
-
+ }
+
+ public class RunSelectedTestCommand : AbstractMenuCommand
+ {
public override void Run()
{
- Run(ProjectService.CurrentProject);
+ ITestService testService = SD.GetRequiredService();
+ IEnumerable tests = TestableCondition.GetTests(testService.OpenSolution, Owner);
+ testService.RunTestsAsync(tests, new TestExecutionOptions()).FireAndForget();
}
}
- public class GotoDefinitionCommand : AbstractMenuCommand
+ public class RunSelectedTestWithDebuggerCommand : AbstractMenuCommand
{
public override void Run()
{
- ITestTreeView treeView = Owner as ITestTreeView;
- if (treeView != null) {
- var member = treeView.SelectedMember;
- var c = treeView.SelectedClass;
- IEntity entity;
- if (member != null) {
- entity = member.Resolve(treeView.SelectedProject);
- } else if (c != null) {
- entity = c.Resolve(treeView.SelectedProject);
- } else {
- entity = null;
- }
- if (entity != null) {
- NavigationService.NavigateTo(entity);
- }
- }
+ ITestService testService = SD.GetRequiredService();
+ IEnumerable tests = TestableCondition.GetTests(testService.OpenSolution, Owner);
+ testService.RunTestsAsync(tests, new TestExecutionOptions { UseDebugger = true }).FireAndForget();
}
}
- public class CollapseAllTestsCommand : AbstractMenuCommand
+ public class StopTestsCommand : AbstractMenuCommand
{
public override void Run()
{
- if (!(this.Owner is SharpTreeView))
- return;
-
- var treeView = (SharpTreeView)this.Owner;
- if (treeView.Root != null) {
- foreach (var n in treeView.Root.Descendants())
- n.IsExpanded = false;
- }
+ ITestService testService = SD.GetRequiredService();
+ testService.CancelRunningTests();
}
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/IRegisteredTestFrameworks.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/IRegisteredTestFrameworks.cs
deleted file mode 100644
index b8e39e0a97..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Frameworks/IRegisteredTestFrameworks.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Collections.Generic;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public interface IRegisteredTestFrameworks
- {
- ITestFramework GetTestFrameworkForProject(IProject project);
- ITestRunner CreateTestRunner(IProject project);
- ITestRunner CreateTestDebugger(IProject project);
-
- bool IsTestMember(IMember member);
- bool IsTestClass(ITypeDefinition typeDefinition);
- bool IsTestProject(IProject project);
-
- bool IsBuildNeededBeforeTestRunForProject(IProject project);
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/ITestFramework.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/ITestFramework.cs
index e5281ea8f5..af59cc24a9 100644
--- a/src/AddIns/Analysis/UnitTesting/Frameworks/ITestFramework.cs
+++ b/src/AddIns/Analysis/UnitTesting/Frameworks/ITestFramework.cs
@@ -10,15 +10,25 @@ namespace ICSharpCode.UnitTesting
{
public interface ITestFramework
{
+ ///
+ /// Gets whether this test framework supports the specified project.
+ ///
+ bool IsTestProject(IProject project);
+
+ ///
+ /// Creates a new test project based on the specified project.
+ ///
+ ITestProject CreateTestProject(ITestSolution parentSolution, IProject project);
+
+ /*
bool IsTestMember(IMember member);
bool IsTestClass(ITypeDefinition testClass);
- bool IsTestProject(IProject project);
IEnumerable GetTestMembersFor(ITypeDefinition typeDefinition);
ITestRunner CreateTestRunner();
ITestRunner CreateTestDebugger();
- bool IsBuildNeededBeforeTestRun { get; }
+ bool IsBuildNeededBeforeTestRun { get; }*/
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/ITestFrameworkFactory.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/ITestFrameworkFactory.cs
deleted file mode 100644
index 8f240a664d..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Frameworks/ITestFrameworkFactory.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-
-namespace ICSharpCode.UnitTesting
-{
- public interface ITestFrameworkFactory
- {
- ITestFramework Create(string className);
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/ITestService.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/ITestService.cs
new file mode 100644
index 0000000000..16ffb6cdb6
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Frameworks/ITestService.cs
@@ -0,0 +1,51 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.UnitTesting
+{
+ [SDService]
+ public interface ITestService
+ {
+ ///
+ /// Gets the test framework that supports the specified project.
+ ///
+ ITestFramework GetTestFrameworkForProject(IProject project);
+
+ MessageViewCategory UnitTestMessageView { get; }
+
+ ///
+ /// Gets the current test solution.
+ /// This property should only be accessed by the main thread.
+ ///
+ ITestSolution OpenSolution { get; }
+
+ ///
+ /// Occurs when the open test solution has changed.
+ ///
+ event EventHandler OpenSolutionChanged;
+
+ ///
+ /// Builds the project (if necessary) and runs the specified tests.
+ /// If tests are already running, the existing run is cancelled.
+ ///
+ Task RunTestsAsync(IEnumerable selectedTests, TestExecutionOptions options);
+
+ ///
+ /// Gets whether tests are currently running.
+ ///
+ bool IsRunningTests { get; }
+
+ ///
+ /// Aborts the current test run.
+ /// This method has no effect if no tests are running.
+ ///
+ void CancelRunningTests();
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/RegisteredTestFrameworks.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/RegisteredTestFrameworks.cs
deleted file mode 100644
index 55f46a2d28..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Frameworks/RegisteredTestFrameworks.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using ICSharpCode.Core;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public class RegisteredTestFrameworks : IRegisteredTestFrameworks
- {
- IReadOnlyList testFrameworkDescriptors;
- public const string AddInPath = "/SharpDevelop/UnitTesting/TestFrameworks";
-
- public RegisteredTestFrameworks(IAddInTree addInTree)
- {
- testFrameworkDescriptors = addInTree.BuildItems(AddInPath, null);
- }
-
- public ITestFramework GetTestFrameworkForProject(IProject project)
- {
- if (project != null) {
- foreach (TestFrameworkDescriptor descriptor in testFrameworkDescriptors) {
- if (descriptor.IsSupportedProject(project) && descriptor.TestFramework.IsTestProject(project)) {
- return descriptor.TestFramework;
- }
- }
- }
- return null;
- }
-
- public bool IsTestMember(IMember member)
- {
- ITestFramework testFramework = GetTestFramework(member);
- if (testFramework != null) {
- return testFramework.IsTestMember(member);
- }
- return false;
- }
-
- ITestFramework GetTestFramework(IEntity entity)
- {
- if (entity != null) {
- return GetTestFrameworkForProject(entity.ParentAssembly.GetProject());
- }
- return null;
- }
-
- public bool IsTestClass(ITypeDefinition c)
- {
- ITestFramework testFramework = GetTestFramework(c);
- if (testFramework != null) {
- return testFramework.IsTestClass(c);
- }
- return false;
- }
-
- public bool IsTestProject(IProject project)
- {
- ITestFramework testFramework = GetTestFrameworkForProject(project);
- if (testFramework != null) {
- return testFramework.IsTestProject(project);
- }
- return false;
- }
-
- public ITestRunner CreateTestRunner(IProject project)
- {
- ITestFramework testFramework = GetTestFrameworkForProject(project);
- if (testFramework != null) {
- return testFramework.CreateTestRunner();
- }
- return null;
- }
-
- public ITestRunner CreateTestDebugger(IProject project)
- {
- ITestFramework testFramework = GetTestFrameworkForProject(project);
- if (testFramework != null) {
- return testFramework.CreateTestDebugger();
- }
- return null;
- }
-
- public bool IsBuildNeededBeforeTestRunForProject(IProject project)
- {
- ITestFramework testFramework = GetTestFrameworkForProject(project);
- if (testFramework != null) {
- return testFramework.IsBuildNeededBeforeTestRun;
- }
- return true;
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/SDTestService.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/SDTestService.cs
new file mode 100644
index 0000000000..28577dd38c
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Frameworks/SDTestService.cs
@@ -0,0 +1,88 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+using ICSharpCode.UnitTesting.Frameworks;
+
+namespace ICSharpCode.UnitTesting
+{
+ sealed class SDTestService : ITestService
+ {
+ #region Test Framework Management
+ const string AddInPath = "/SharpDevelop/UnitTesting/TestFrameworks";
+ IReadOnlyList testFrameworkDescriptors = SD.AddInTree.BuildItems(AddInPath, null);
+
+ public ITestFramework GetTestFrameworkForProject(IProject project)
+ {
+ if (project != null) {
+ foreach (TestFrameworkDescriptor descriptor in testFrameworkDescriptors) {
+ if (descriptor.IsSupportedProject(project)) {
+ return descriptor.TestFramework;
+ }
+ }
+ }
+ return null;
+ }
+ #endregion
+
+ #region UnitTestMessageView
+ MessageViewCategory unitTestMessageView;
+
+ public MessageViewCategory UnitTestMessageView {
+ get {
+ if (unitTestMessageView == null) {
+ MessageViewCategory.Create(ref unitTestMessageView,
+ "UnitTesting",
+ "${res:ICSharpCode.NUnitPad.NUnitPadContent.PadName}");
+ }
+ return unitTestMessageView;
+ }
+ }
+ #endregion
+
+ #region OpenSolution
+ TestSolution solution;
+
+ public ITestSolution OpenSolution {
+ get {
+ SD.MainThread.VerifyAccess();
+ if (solution == null)
+ solution = new TestSolution(this, SD.ResourceService);
+ return solution;
+ }
+ }
+
+ public event EventHandler OpenSolutionChanged { add {} remove {} }
+ #endregion
+
+ #region RunTests
+ CancellationTokenSource runTestsCancellationTokenSource;
+
+ public bool IsRunningTests {
+ get { return runTestsCancellationTokenSource != null; }
+ }
+
+ public Task RunTestsAsync(IEnumerable selectedTests, TestExecutionOptions options)
+ {
+ CancelRunningTests();
+ runTestsCancellationTokenSource = new CancellationTokenSource();
+ var executionManager = new TestExecutionManager();
+ return executionManager.RunTestsAsync(selectedTests, options, runTestsCancellationTokenSource.Token);
+ }
+
+ public void CancelRunningTests()
+ {
+ if (runTestsCancellationTokenSource != null) {
+ runTestsCancellationTokenSource.Cancel();
+ runTestsCancellationTokenSource = null;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/TestExecutionManager.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/TestExecutionManager.cs
new file mode 100644
index 0000000000..f5c5db984c
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Frameworks/TestExecutionManager.cs
@@ -0,0 +1,149 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using ICSharpCode.Core;
+using ICSharpCode.NRefactory.Utils;
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.UnitTesting.Frameworks
+{
+ ///
+ /// Manages the execution of tests across multiple projects.
+ /// Takes care of building the projects (if necessary) and showing progress in the UI.
+ ///
+ public class TestExecutionManager
+ {
+ readonly IBuildProjectFactory buildProjectFactory;
+ readonly IUnitTestTaskService taskService;
+ readonly IUnitTestSaveAllFilesCommand saveAllFilesCommand;
+ readonly ITestService testService;
+ readonly IWorkbench workbench;
+ readonly IStatusBarService statusBarService;
+ readonly IBuildOptions buildOptions;
+
+ public TestExecutionManager()
+ {
+ this.buildProjectFactory = new UnitTestBuildProjectFactory();
+ this.taskService = new UnitTestTaskService();
+ this.saveAllFilesCommand = new UnitTestSaveAllFilesCommand();
+ this.testService = SD.GetRequiredService();
+ this.workbench = SD.Workbench;
+ this.statusBarService = SD.StatusBar;
+ this.buildOptions = new UnitTestBuildOptions();
+ }
+
+ readonly MultiDictionary testsByProject = new MultiDictionary();
+ CancellationToken cancellationToken;
+
+ public async Task RunTestsAsync(IEnumerable selectedTests, TestExecutionOptions options, CancellationToken cancellationToken)
+ {
+ this.cancellationToken = cancellationToken;
+ GroupTestsByProject(selectedTests);
+
+ ClearTasks();
+ ShowUnitTestsPad();
+ ShowOutputPad();
+
+ ResetTestResults();
+ saveAllFilesCommand.SaveAllFiles();
+
+ // Run the build, if necessary:
+ var projectsToBuild = testsByProject.Keys.Select(p => p.GetBuildableForTesting()).Where(b => b != null).ToList();
+ if (projectsToBuild.Count > 0) {
+ var buildCommand = buildProjectFactory.CreateBuildProjectBeforeTestRun(projectsToBuild);
+ var buildResults = await buildCommand.BuildAsync(cancellationToken);
+ if (buildResults.Result != BuildResultCode.Success)
+ return;
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+ using (IProgressMonitor progressMonitor = statusBarService.CreateProgressMonitor(cancellationToken)) {
+ int projectsLeftToRun = testsByProject.Count;
+ foreach (IGrouping g in testsByProject) {
+ ITestProject project = g.Key;
+ progressMonitor.TaskName = GetProgressMonitorLabel(project);
+ progressMonitor.Progress = GetProgress(projectsLeftToRun);
+ using (IProgressMonitor nested = progressMonitor.CreateSubTask(1.0 / testsByProject.Count)) {
+ await project.RunTestsAsync(g, options, nested);
+ }
+ projectsLeftToRun--;
+ progressMonitor.CancellationToken.ThrowIfCancellationRequested();
+ }
+ }
+
+ ShowErrorList();
+ }
+
+ void GroupTestsByProject(IEnumerable selectedTests)
+ {
+ foreach (ITest test in selectedTests) {
+ if (test == null)
+ continue;
+ if (test.ParentProject == null) {
+ // When a solution is selected, select all its projects individually
+ foreach (ITest project in test.NestedTests) {
+ Debug.Assert(project == project.ParentProject);
+ testsByProject.Add(project.ParentProject, project);
+ }
+ } else {
+ testsByProject.Add(test.ParentProject, test);
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+ }
+
+ void ClearTasks()
+ {
+ taskService.BuildMessageViewCategory.ClearText();
+ taskService.ClearExceptCommentTasks();
+ testService.UnitTestMessageView.ClearText();
+ }
+
+ void ShowUnitTestsPad()
+ {
+ workbench.GetPad(typeof(UnitTestsPad)).BringPadToFront();
+ }
+
+ void ShowOutputPad()
+ {
+ workbench.GetPad(typeof(CompilerMessageView)).BringPadToFront();
+ }
+
+ void ResetTestResults()
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ foreach (ITest test in testsByProject.Values) {
+ test.ResetTestResults();
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+
+ string GetProgressMonitorLabel(ITestProject project)
+ {
+ StringTagPair tagPair = new StringTagPair("Name", project.DisplayName);
+ return StringParser.Parse("${res:ICSharpCode.UnitTesting.StatusBarProgressLabel}", tagPair);
+ }
+
+ double GetProgress(int projectsLeftToRunCount)
+ {
+ int totalProjectCount = testsByProject.Count;
+ return (double)(totalProjectCount - projectsLeftToRunCount) / totalProjectCount;
+ }
+
+ void ShowErrorList()
+ {
+ if (taskService.SomethingWentWrong && buildOptions.ShowErrorListAfterBuild) {
+ workbench.GetPad(typeof(ErrorListPad)).BringPadToFront();
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/TestExecutionOptions.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/TestExecutionOptions.cs
new file mode 100644
index 0000000000..63834da005
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Frameworks/TestExecutionOptions.cs
@@ -0,0 +1,19 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// Options used for test execution.
+ ///
+ public class TestExecutionOptions
+ {
+ ///
+ /// Gets/Sets whether to debug the test execution.
+ /// The default is false.
+ ///
+ public bool UseDebugger { get; set; }
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkDescriptor.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkDescriptor.cs
index 98075981a8..0f62ac2639 100644
--- a/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkDescriptor.cs
+++ b/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkDescriptor.cs
@@ -12,14 +12,14 @@ namespace ICSharpCode.UnitTesting
public class TestFrameworkDescriptor
{
Properties properties;
- ITestFrameworkFactory factory;
+ Func objectFactory;
ITestFramework testFramework;
List supportedProjectFileExtensions = new List();
- public TestFrameworkDescriptor(Properties properties, ITestFrameworkFactory factory)
+ public TestFrameworkDescriptor(Properties properties, Func objectFactory)
{
this.properties = properties;
- this.factory = factory;
+ this.objectFactory = objectFactory;
GetSupportedProjectFileExtensions();
}
@@ -47,7 +47,7 @@ namespace ICSharpCode.UnitTesting
void CreateTestFrameworkIfNotCreated()
{
if (testFramework == null) {
- testFramework = factory.Create(ClassName);
+ testFramework = (ITestFramework)objectFactory(ClassName);
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkDoozer.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkDoozer.cs
index e613f301ba..7da0a79964 100644
--- a/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkDoozer.cs
+++ b/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkDoozer.cs
@@ -19,12 +19,7 @@ namespace ICSharpCode.UnitTesting
public object BuildItem(BuildItemArgs args)
{
- return BuildItem(args.Codon, new TestFrameworkFactory(args.AddIn));
- }
-
- public TestFrameworkDescriptor BuildItem(Codon codon, ITestFrameworkFactory factory)
- {
- return new TestFrameworkDescriptor(codon.Properties, factory);
+ return new TestFrameworkDescriptor(args.Codon.Properties, args.AddIn.CreateObject);
}
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkFactory.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkFactory.cs
deleted file mode 100644
index a23e8ea7eb..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Frameworks/TestFrameworkFactory.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.Core;
-
-namespace ICSharpCode.UnitTesting
-{
- public class TestFrameworkFactory : ITestFrameworkFactory
- {
- AddIn addin;
-
- public TestFrameworkFactory(AddIn addin)
- {
- this.addin = addin;
- }
-
- public ITestFramework Create(string className)
- {
- return addin.CreateObject(className) as ITestFramework;
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Frameworks/TestService.cs b/src/AddIns/Analysis/UnitTesting/Frameworks/TestService.cs
deleted file mode 100644
index 138da43589..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Frameworks/TestService.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Gui;
-
-namespace ICSharpCode.UnitTesting
-{
- public static class TestService
- {
- static IRegisteredTestFrameworks testFrameworks;
- static MessageViewCategory unitTestMessageView;
-
- public static IRegisteredTestFrameworks RegisteredTestFrameworks {
- get {
- CreateRegisteredTestFrameworks();
- return testFrameworks;
- }
- set { testFrameworks = value; }
- }
-
- static void CreateRegisteredTestFrameworks()
- {
- if (testFrameworks == null) {
- testFrameworks = new RegisteredTestFrameworks(SD.AddInTree);
- }
- }
-
- public static MessageViewCategory UnitTestMessageView {
- get {
- if (unitTestMessageView == null) {
- CreateUnitTestCategory();
- }
- return unitTestMessageView;
- }
- }
-
- static void CreateUnitTestCategory()
- {
- MessageViewCategory.Create(ref unitTestMessageView,
- "UnitTesting",
- "${res:ICSharpCode.NUnitPad.NUnitPadContent.PadName}");
- }
-
- static TestSolution solution;
-
- public static TestSolution Solution {
- get {
- SD.MainThread.VerifyAccess();
- if (solution == null)
- solution = new TestSolution(RegisteredTestFrameworks);
- return solution;
- }
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Interfaces/IBuildProjectFactory.cs b/src/AddIns/Analysis/UnitTesting/Interfaces/IBuildProjectFactory.cs
index 6d3f18487e..dd76aa6930 100644
--- a/src/AddIns/Analysis/UnitTesting/Interfaces/IBuildProjectFactory.cs
+++ b/src/AddIns/Analysis/UnitTesting/Interfaces/IBuildProjectFactory.cs
@@ -10,6 +10,6 @@ namespace ICSharpCode.UnitTesting
{
public interface IBuildProjectFactory
{
- BuildProject CreateBuildProjectBeforeTestRun(IEnumerable projects);
+ BuildProject CreateBuildProjectBeforeTestRun(IEnumerable projects);
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestTaskService.cs b/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestTaskService.cs
index eed3c79814..0cc610d47e 100644
--- a/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestTaskService.cs
+++ b/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestTaskService.cs
@@ -11,7 +11,6 @@ namespace ICSharpCode.UnitTesting
public interface IUnitTestTaskService
{
MessageViewCategory BuildMessageViewCategory { get; }
- bool InUpdate { get; set; }
void ClearExceptCommentTasks();
void Add(SDTask task);
bool SomethingWentWrong { get; }
diff --git a/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestWorkbench.cs b/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestWorkbench.cs
deleted file mode 100644
index eb3541512e..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestWorkbench.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.SharpDevelop;
-
-namespace ICSharpCode.UnitTesting
-{
- public interface IUnitTestWorkbench
- {
- PadDescriptor GetPad(Type type);
- void SafeThreadAsyncCall(Action method);
- void SafeThreadAsyncCall(Action method, A arg1);
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestBuildProjectFactory.cs b/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestBuildProjectFactory.cs
index 9f78ae9118..c3cd89c71a 100644
--- a/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestBuildProjectFactory.cs
+++ b/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestBuildProjectFactory.cs
@@ -10,7 +10,7 @@ namespace ICSharpCode.UnitTesting
{
public class UnitTestBuildProjectFactory : IBuildProjectFactory
{
- public BuildProject CreateBuildProjectBeforeTestRun(IEnumerable projects)
+ public BuildProject CreateBuildProjectBeforeTestRun(IEnumerable projects)
{
return new BuildProjectBeforeExecute(new MultipleProjectBuildable(projects));
}
diff --git a/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestTaskService.cs b/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestTaskService.cs
index de2078a6a4..1ba24447ad 100644
--- a/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestTaskService.cs
+++ b/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestTaskService.cs
@@ -14,11 +14,6 @@ namespace ICSharpCode.UnitTesting
TaskService.ClearExceptCommentTasks();
}
- public bool InUpdate {
- get { return TaskService.InUpdate; }
- set { TaskService.InUpdate = value; }
- }
-
public MessageViewCategory BuildMessageViewCategory {
get { return TaskService.BuildMessageViewCategory; }
}
diff --git a/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestWorkbench.cs b/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestWorkbench.cs
deleted file mode 100644
index 6e2182c6ab..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestWorkbench.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Gui;
-
-namespace ICSharpCode.UnitTesting
-{
- public class UnitTestWorkbench : IUnitTestWorkbench
- {
- public PadDescriptor GetPad(Type type)
- {
- return WorkbenchSingleton.Workbench.GetPad(type);
- }
-
- public void SafeThreadAsyncCall(Action method)
- {
- WorkbenchSingleton.SafeThreadAsyncCall(method);
- }
-
- public void SafeThreadAsyncCall(Action method, A arg1)
- {
- WorkbenchSingleton.SafeThreadAsyncCall(method, arg1);
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/ITest.cs b/src/AddIns/Analysis/UnitTesting/Model/ITest.cs
new file mode 100644
index 0000000000..a86d28494c
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Model/ITest.cs
@@ -0,0 +1,55 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.ObjectModel;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// Represents a unit test or a group of unit tests.
+ ///
+ public interface ITest
+ {
+ ///
+ /// Gets the collection of nested tests.
+ ///
+ TestCollection NestedTests { get; }
+
+ ///
+ /// Gets the parent project that owns this test.
+ ///
+ ITestProject ParentProject { get; }
+
+ ///
+ /// Name to be displayed in the tests tree view.
+ ///
+ string DisplayName { get; }
+
+ ///
+ /// Raised when the property changes.
+ ///
+ event EventHandler DisplayNameChanged;
+
+ ///
+ /// Gets the result of the previous run of this test.
+ ///
+ TestResultType Result { get; }
+
+ ///
+ /// Raised when the property changes.
+ ///
+ event EventHandler ResultChanged;
+
+ ///
+ /// Resets the test results for this test and all nested tests.
+ ///
+ void ResetTestResults();
+
+ bool SupportsGoToDefinition { get; }
+
+ void GoToDefinition();
+
+ UnitTestNode CreateTreeNode();
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/ITestProject.cs b/src/AddIns/Analysis/UnitTesting/Model/ITestProject.cs
new file mode 100644
index 0000000000..d297511f89
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Model/ITestProject.cs
@@ -0,0 +1,47 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using ICSharpCode.NRefactory.TypeSystem;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// Represents the root node of a test project.
+ ///
+ public interface ITestProject : ITest
+ {
+ ///
+ /// Gets the SharpDevelop project on which this test project is based.
+ ///
+ IProject Project { get; }
+
+ ///
+ /// Gets the test for the specified entity.
+ /// Returns null if the entity is not a unit test.
+ ///
+ ITest GetTestForEntity(IEntity entity);
+
+ ///
+ /// Returns a SharpDevelop that builds the project
+ /// for test execution.
+ /// May return null if the project does not require compilation.
+ ///
+ IBuildable GetBuildableForTesting();
+
+ ///
+ /// Notifies the project that the parse information was changed.
+ ///
+ void NotifyParseInformationChanged(IUnresolvedFile oldUnresolvedFile, IUnresolvedFile newUnresolvedFile);
+
+ ///
+ /// Runs the specified tests. The specified tests must belong to this project.
+ ///
+ Task RunTestsAsync(IEnumerable tests, TestExecutionOptions options, IProgressMonitor progressMonitor);
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/ITestSolution.cs b/src/AddIns/Analysis/UnitTesting/Model/ITestSolution.cs
new file mode 100644
index 0000000000..e5d867cee0
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Model/ITestSolution.cs
@@ -0,0 +1,33 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.ObjectModel;
+using ICSharpCode.NRefactory.TypeSystem;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// A test that represents the whole solution.
+ ///
+ public interface ITestSolution : ITest
+ {
+// ///
+// /// Gets the list of all test projects.
+// ///
+// ObservableCollection TestableProjects { get; }
+
+ ///
+ /// Gets the test project for the specified project.
+ /// Returns null if the project is not a test project.
+ ///
+ ITestProject GetTestProject(IProject project);
+
+ ///
+ /// Gets the test for the specified entity.
+ /// Returns null if the entity is not a unit test.
+ ///
+ ITest GetTestForEntity(IEntity entity);
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestBase.cs b/src/AddIns/Analysis/UnitTesting/Model/TestBase.cs
new file mode 100644
index 0000000000..7a2df43104
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Model/TestBase.cs
@@ -0,0 +1,143 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// Base class for implementations.
+ ///
+ public abstract class TestBase : ITest
+ {
+ public abstract string DisplayName { get; }
+ public virtual event EventHandler DisplayNameChanged { add {} remove {} }
+
+ public abstract ITestProject ParentProject { get; }
+
+ #region Result
+ TestResultType result;
+ bool useCompositeResultsOfNestedTests;
+
+ public event EventHandler ResultChanged;
+
+ ///
+ /// Gets/Sets the test result.
+ ///
+ ///
+ /// If the result is bound to the composite of the nested tests, setting this
+ /// property will remove the binding.
+ ///
+ public TestResultType Result {
+ get { return result; }
+ protected set {
+ if (useCompositeResultsOfNestedTests) {
+ nestedTests.PropertyChanged -= nestedTestsCollection_PropertyChanged;
+ useCompositeResultsOfNestedTests = false;
+ }
+ ChangeResult(value);
+ }
+ }
+
+ void ChangeResult(TestResultType newResult)
+ {
+ TestResultType oldResult = result;
+ if (oldResult != newResult) {
+ result = newResult;
+ OnResultChanged(new TestResultTypeChangedEventArgs(oldResult, newResult));
+ }
+ }
+
+ ///
+ /// Binds the result to the composite result of the nested tests.
+ ///
+ protected void BindResultToCompositeResultOfNestedTests()
+ {
+ if (!useCompositeResultsOfNestedTests) {
+ useCompositeResultsOfNestedTests = true;
+ if (nestedTests != null) {
+ nestedTests.PropertyChanged += nestedTestsCollection_PropertyChanged;
+ ChangeResult(nestedTests.CompositeResult);
+ } else {
+ ChangeResult(TestResultType.None);
+ }
+ }
+ }
+
+ void nestedTestsCollection_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == null || e.PropertyName == "CompositeResult") {
+ ChangeResult(nestedTests.CompositeResult);
+ }
+ }
+
+ protected virtual void OnResultChanged(TestResultTypeChangedEventArgs e)
+ {
+ if (ResultChanged != null) {
+ ResultChanged(this, e);
+ }
+ }
+ #endregion
+
+ #region NestedTests
+ TestCollection nestedTests;
+
+ public TestCollection NestedTests {
+ get {
+ if (nestedTests == null) {
+ nestedTests = InitializeNestedTests();
+ OnNestedTestsInitialized();
+ }
+ return nestedTests;
+ }
+ }
+
+ protected bool NestedTestsInitialized {
+ get { return nestedTests != null; }
+ }
+
+ protected virtual TestCollection InitializeNestedTests()
+ {
+ return new TestCollection();
+ }
+
+ protected virtual void OnNestedTestsInitialized()
+ {
+ // If we're supposed to be bound to the composite result of the nested tests,
+ // but the nested test collection wasn't initialized yet,
+ // we will recreate the binding.
+ if (useCompositeResultsOfNestedTests) {
+ useCompositeResultsOfNestedTests = false;
+ BindResultToCompositeResultOfNestedTests();
+ }
+ }
+ #endregion
+
+ public virtual void ResetTestResults()
+ {
+ if (nestedTests != null) {
+ foreach (ITest test in nestedTests) {
+ test.ResetTestResults();
+ }
+ }
+ if (!useCompositeResultsOfNestedTests)
+ this.Result = TestResultType.None;
+ }
+
+ public virtual bool SupportsGoToDefinition {
+ get { return false; }
+ }
+
+ public void GoToDefinition()
+ {
+ throw new NotSupportedException();
+ }
+
+ public virtual UnitTestNode CreateTreeNode()
+ {
+ return new UnitTestNode(this);
+ }
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestCollection.cs b/src/AddIns/Analysis/UnitTesting/Model/TestCollection.cs
new file mode 100644
index 0000000000..adbed25332
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Model/TestCollection.cs
@@ -0,0 +1,199 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// Collection of tests that monitors the amount of tests for each result type,
+ /// allowing efficient updates of the overall result.
+ ///
+ public class TestCollection : ObservableCollection
+ {
+ #region Struct TestCounts
+ struct TestCounts
+ {
+ internal int indeterminate;
+ internal int successful;
+ internal int failed;
+ internal int ignored;
+
+ public TestResultType CompositeResult {
+ get {
+ if (failed > 0)
+ return TestResultType.Failure;
+ if (indeterminate > 0)
+ return TestResultType.None;
+ if (ignored > 0)
+ return TestResultType.Ignored;
+ if (successful > 0)
+ return TestResultType.Success;
+ return TestResultType.None;
+ }
+ }
+
+ public void Add(TestResultType result)
+ {
+ switch (result) {
+ case TestResultType.None:
+ indeterminate++;
+ break;
+ case TestResultType.Success:
+ successful++;
+ break;
+ case TestResultType.Failure:
+ failed++;
+ break;
+ case TestResultType.Ignored:
+ ignored++;
+ break;
+ default:
+ throw new NotSupportedException("Invalid value for TestResultType");
+ }
+ }
+
+ public void Remove(TestResultType result)
+ {
+ switch (result) {
+ case TestResultType.None:
+ indeterminate--;
+ break;
+ case TestResultType.Success:
+ successful--;
+ break;
+ case TestResultType.Failure:
+ failed--;
+ break;
+ case TestResultType.Ignored:
+ ignored--;
+ break;
+ default:
+ throw new NotSupportedException("Invalid value for TestResultType");
+ }
+ }
+ }
+ #endregion
+
+ public static TestResultType GetCompositeResult(IEnumerable tests)
+ {
+ TestCounts c = new TestCounts();
+ foreach (ITest test in tests) {
+ c.Add(test.Result);
+ }
+ return c.CompositeResult;
+ }
+
+ #region Properties
+ TestCounts counts;
+
+ public int IndeterminateNestedTestCount {
+ get { return counts.indeterminate; }
+ }
+
+ public int SuccessfulNestedTestCount {
+ get { return counts.successful; }
+ }
+
+ public int FailedNestedTestCount {
+ get { return counts.failed; }
+ }
+
+ public int IgnoredNestedTestCount {
+ get { return counts.ignored; }
+ }
+
+ public TestResultType CompositeResult {
+ get { return counts.CompositeResult; }
+ }
+
+ static readonly PropertyChangedEventArgs indeterminateArgs = new PropertyChangedEventArgs("IndeterminateNestedTestCount");
+ static readonly PropertyChangedEventArgs successfulArgs = new PropertyChangedEventArgs("SuccessfulNestedTestCount");
+ static readonly PropertyChangedEventArgs failedArgs = new PropertyChangedEventArgs("FailedNestedTestCount");
+ static readonly PropertyChangedEventArgs ignoredArgs = new PropertyChangedEventArgs("IgnoredNestedTestCount");
+ static readonly PropertyChangedEventArgs compositeResultArgs = new PropertyChangedEventArgs("CompositeResult");
+
+ void RaiseCountChangeEvents(TestCounts old)
+ {
+ if (old.indeterminate != counts.indeterminate)
+ OnPropertyChanged(indeterminateArgs);
+ if (old.successful != counts.successful)
+ OnPropertyChanged(successfulArgs);
+ if (old.failed != counts.failed)
+ OnPropertyChanged(failedArgs);
+ if (old.ignored != counts.ignored)
+ OnPropertyChanged(ignoredArgs);
+ if (old.CompositeResult != counts.CompositeResult)
+ OnPropertyChanged(compositeResultArgs);
+ }
+
+ // change visibility of PropertyChanged event to public
+ public new event PropertyChangedEventHandler PropertyChanged {
+ add { base.PropertyChanged += value; }
+ remove { base.PropertyChanged -= value; }
+ }
+ #endregion
+
+ void item_ResultChanged(object sender, TestResultTypeChangedEventArgs e)
+ {
+ TestCounts old = counts;
+ counts.Remove(e.OldResult);
+ counts.Add(e.NewResult);
+ RaiseCountChangeEvents(old);
+ }
+
+ protected override void ClearItems()
+ {
+ TestCounts old = counts;
+ counts = default(TestCounts);
+ foreach (ITest test in Items) {
+ counts.Remove(test.Result);
+ test.ResultChanged -= item_ResultChanged;
+ }
+ base.ClearItems();
+ RaiseCountChangeEvents(old);
+ }
+
+ protected override void InsertItem(int index, ITest item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+ TestCounts old = counts;
+ counts.Add(item.Result);
+ base.InsertItem(index, item);
+ item.ResultChanged += item_ResultChanged;
+ RaiseCountChangeEvents(old);
+ }
+
+ protected override void RemoveItem(int index)
+ {
+ TestCounts old = counts;
+ ITest oldItem = Items[index];
+ counts.Remove(oldItem.Result);
+ oldItem.ResultChanged -= item_ResultChanged;
+ base.RemoveItem(index);
+ RaiseCountChangeEvents(old);
+ }
+
+ protected override void SetItem(int index, ITest item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+ TestCounts old = counts;
+
+ ITest oldItem = Items[index];
+ counts.Remove(oldItem.Result);
+ oldItem.ResultChanged -= item_ResultChanged;
+
+ counts.Add(item.Result);
+ item.ResultChanged += item_ResultChanged;
+
+ base.SetItem(index, item);
+ RaiseCountChangeEvents(old);
+ }
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestNamespace.cs b/src/AddIns/Analysis/UnitTesting/Model/TestNamespace.cs
new file mode 100644
index 0000000000..eb8a4cd4f7
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Model/TestNamespace.cs
@@ -0,0 +1,46 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.ObjectModel;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// Represents a namespace of unit tests.
+ ///
+ public class TestNamespace : TestBase
+ {
+ readonly ITestProject project;
+ readonly string namespaceName;
+ readonly string displayName;
+
+ public TestNamespace(ITestProject project, string namespaceName, string displayName = null)
+ {
+ if (project == null)
+ throw new ArgumentNullException("project");
+ if (namespaceName == null)
+ throw new ArgumentNullException("namespaceName");
+ this.project = project;
+ this.namespaceName = namespaceName;
+ if (displayName != null) {
+ this.displayName = displayName;
+ } else {
+ this.displayName = namespaceName.Substring(namespaceName.IndexOf('.') + 1);
+ }
+ BindResultToCompositeResultOfNestedTests();
+ }
+
+ public override ITestProject ParentProject {
+ get { return project; }
+ }
+
+ public string NamespaceName {
+ get { return namespaceName; }
+ }
+
+ public override string DisplayName {
+ get { return displayName; }
+ }
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestProjectBase.cs b/src/AddIns/Analysis/UnitTesting/Model/TestProjectBase.cs
new file mode 100644
index 0000000000..e86404b281
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Model/TestProjectBase.cs
@@ -0,0 +1,58 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using ICSharpCode.NRefactory.TypeSystem;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// Base class for implementations.
+ ///
+ public abstract class TestProjectBase : TestBase, ITestProject
+ {
+ IProject project;
+
+ public TestProjectBase(IProject project)
+ {
+ if (project == null)
+ throw new ArgumentNullException("project");
+ this.project = project;
+ BindResultToCompositeResultOfNestedTests();
+ }
+
+ public IProject Project {
+ get { return project; }
+ }
+
+ public override ITestProject ParentProject {
+ get { return this; }
+ }
+
+ public override string DisplayName {
+ get { return project.Name; }
+ }
+
+ public virtual ITest GetTestForEntity(IEntity entity)
+ {
+ return null;
+ }
+
+ public virtual IBuildable GetBuildableForTesting()
+ {
+ return project;
+ }
+
+ public void NotifyParseInformationChanged(IUnresolvedFile oldUnresolvedFile, IUnresolvedFile newUnresolvedFile)
+ {
+ if (!NestedTestsInitialized)
+ return;
+ }
+
+ public abstract Task RunTestsAsync(IEnumerable tests, TestExecutionOptions options, IProgressMonitor progressMonitor);
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestResultTypeChangedEventArgs.cs b/src/AddIns/Analysis/UnitTesting/Model/TestResultTypeChangedEventArgs.cs
new file mode 100644
index 0000000000..c7807587ac
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/Model/TestResultTypeChangedEventArgs.cs
@@ -0,0 +1,30 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// EventArgs for ITest.ResultChanged.
+ ///
+ public class TestResultTypeChangedEventArgs : EventArgs
+ {
+ readonly TestResultType oldResult;
+ readonly TestResultType newResult;
+
+ public TestResultTypeChangedEventArgs(TestResultType oldResult, TestResultType newResult)
+ {
+ this.oldResult = oldResult;
+ this.newResult = newResult;
+ }
+
+ public TestResultType NewResult {
+ get { return newResult; }
+ }
+
+ public TestResultType OldResult {
+ get { return oldResult; }
+ }
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestSolution.cs b/src/AddIns/Analysis/UnitTesting/Model/TestSolution.cs
index 0b266ac1fe..26ee0d7f23 100644
--- a/src/AddIns/Analysis/UnitTesting/Model/TestSolution.cs
+++ b/src/AddIns/Analysis/UnitTesting/Model/TestSolution.cs
@@ -5,7 +5,8 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
-
+using ICSharpCode.Core;
+using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
@@ -15,21 +16,20 @@ namespace ICSharpCode.UnitTesting
///
/// Manages the collection of TestProjects.
///
- public class TestSolution
+ sealed class TestSolution : TestBase, ITestSolution
{
- readonly IRegisteredTestFrameworks registeredTestFrameworks;
+ readonly IResourceService resourceService;
+ readonly ITestService testService;
readonly List changeListeners = new List();
- readonly ObservableCollection testableProjects = new ObservableCollection();
-
- public ObservableCollection TestableProjects {
- get { return testableProjects; }
- }
- public TestSolution(IRegisteredTestFrameworks registeredTestFrameworks)
+ public TestSolution(ITestService testService, IResourceService resourceService)
{
- if (registeredTestFrameworks == null)
- throw new ArgumentNullException("registeredTestFrameworks");
- this.registeredTestFrameworks = registeredTestFrameworks;
+ if (testService == null)
+ throw new ArgumentNullException("testService");
+ if (resourceService == null)
+ throw new ArgumentNullException("resourceService");
+ this.testService = testService;
+ this.resourceService = resourceService;
ProjectService.SolutionLoaded += ProjectService_SolutionLoaded;
ProjectService.SolutionClosed += ProjectService_SolutionClosed;
ProjectService.ProjectAdded += ProjectService_ProjectAdded;
@@ -40,13 +40,39 @@ namespace ICSharpCode.UnitTesting
SD_ParserService_LoadSolutionProjectsThread_Finished(null, null);
}
}
-
- ///
- /// Retrieves the TestProject for the specified project.
- ///
- public TestProject GetTestProject(IProject currentProject)
+
+ public override string DisplayName {
+ get { return resourceService.GetString("ICSharpCode.UnitTesting.AllTestsTreeNode.Text"); }
+ }
+
+ public override event EventHandler DisplayNameChanged {
+ add { resourceService.LanguageChanged += value; }
+ remove { resourceService.LanguageChanged -= value; }
+ }
+
+ public override ITestProject ParentProject {
+ get { return null; }
+ }
+
+ public ITestProject GetTestProject(IProject project)
+ {
+ for (int i = 0; i < changeListeners.Count; i++) {
+ if (changeListeners[i].project == project) {
+ return changeListeners[i].testProject;
+ }
+ }
+ return null;
+ }
+
+ public ITest GetTestForEntity(IEntity entity)
{
- return testableProjects.FirstOrDefault(p => p.Project == currentProject);
+ if (entity == null)
+ return null;
+ ITestProject testProject = GetTestProject(entity.ParentAssembly.GetProject());
+ if (testProject != null)
+ return testProject.GetTestForEntity(entity);
+ else
+ return null;
}
///
@@ -57,8 +83,9 @@ namespace ICSharpCode.UnitTesting
class ProjectChangeListener
{
readonly TestSolution testSolution;
+ ITestFramework oldTestFramework;
internal readonly IProject project;
- TestProject testProject;
+ internal ITestProject testProject;
public ProjectChangeListener(TestSolution testSolution, IProject project)
{
@@ -77,7 +104,7 @@ namespace ICSharpCode.UnitTesting
project.ParseInformationUpdated -= project_ParseInformationUpdated;
// Remove old testProject
if (testProject != null) {
- testSolution.testableProjects.Remove(testProject);
+ testSolution.NestedTests.Remove(testProject);
testProject = null;
}
}
@@ -91,20 +118,23 @@ namespace ICSharpCode.UnitTesting
internal void CheckTestFramework()
{
- ITestFramework newTestFramework = testSolution.registeredTestFrameworks.GetTestFrameworkForProject(project);
- if (newTestFramework != null && testProject != null && testProject.TestFramework == newTestFramework)
+ ITestFramework newTestFramework = testSolution.testService.GetTestFrameworkForProject(project);
+ if (newTestFramework == oldTestFramework)
return; // test framework is unchanged
// Remove old testProject
if (testProject != null) {
- testSolution.testableProjects.Remove(testProject);
+ testSolution.NestedTests.Remove(testProject);
testProject = null;
}
// Create new testProject
if (newTestFramework != null) {
- testProject = new TestProject(project, newTestFramework);
- testSolution.testableProjects.Add(testProject);
+ testProject = newTestFramework.CreateTestProject(testSolution, project);
+ if (testProject == null)
+ throw new InvalidOperationException("CreateTestProject() returned null");
+ testSolution.NestedTests.Add(testProject);
}
+ oldTestFramework = newTestFramework;
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitConsoleApplication.cs b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitConsoleApplication.cs
index a8b1207b43..7e875f5528 100644
--- a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitConsoleApplication.cs
+++ b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitConsoleApplication.cs
@@ -16,18 +16,19 @@ namespace ICSharpCode.UnitTesting
{
public class NUnitConsoleApplication
{
- public NUnitConsoleApplication(SelectedTests selectedTests, UnitTestingOptions options)
+ /*
+ public NUnitConsoleApplication(ITestProject project, IEnumerable selectedTests, UnitTestingOptions options)
{
- Initialize(selectedTests);
+ Initialize(project, selectedTests);
InitializeOptions(options);
}
- public NUnitConsoleApplication(SelectedTests selectedTests)
+ public NUnitConsoleApplication(ITestProject project, IEnumerable selectedTests)
{
- Initialize(selectedTests);
+ Initialize(project, selectedTests);
}
- void Initialize(SelectedTests selectedTests)
+ void Initialize(ITestProject project, IEnumerable selectedTests)
{
this.selectedTests = selectedTests;
this.project = selectedTests.Project;
@@ -42,6 +43,7 @@ namespace ICSharpCode.UnitTesting
}
}
}
+ */
void InitializeOptions(UnitTestingOptions options)
{
@@ -150,9 +152,9 @@ namespace ICSharpCode.UnitTesting
public string NamespaceFilter;
IProject project;
- SelectedTests selectedTests;
+ IEnumerable selectedTests;
- public SelectedTests SelectedTests {
+ public IEnumerable SelectedTests {
get { return selectedTests; }
}
diff --git a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestDebugger.cs b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestDebugger.cs
index d964f28ab6..d0886ce178 100644
--- a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestDebugger.cs
+++ b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestDebugger.cs
@@ -2,7 +2,9 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
using System.Diagnostics;
+
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
@@ -30,7 +32,7 @@ namespace ICSharpCode.UnitTesting
this.options = options;
}
- protected override ProcessStartInfo GetProcessStartInfo(SelectedTests selectedTests)
+ protected override ProcessStartInfo GetProcessStartInfo(IEnumerable selectedTests)
{
NUnitConsoleApplication app = new NUnitConsoleApplication(selectedTests, options);
app.Results = base.TestResultsMonitor.FileName;
diff --git a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestFramework.cs b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestFramework.cs
index 7ba452d939..a556cbc641 100644
--- a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestFramework.cs
+++ b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestFramework.cs
@@ -14,23 +14,9 @@ namespace ICSharpCode.UnitTesting
{
public class NUnitTestFramework : ITestFramework
{
- public bool IsBuildNeededBeforeTestRun {
- get { return true; }
- }
-
- public ITestRunner CreateTestRunner()
- {
- return new NUnitTestRunner();
- }
-
- public ITestRunner CreateTestDebugger()
- {
- return new NUnitTestDebugger();
- }
-
- static readonly ITypeReference testAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestAttribute", 0);
- static readonly ITypeReference testCaseAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestCaseAttribute", 0);
- static readonly ITypeReference testFixtureAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestFixtureAttribute", 0);
+ readonly ITypeReference testAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestAttribute", 0);
+ readonly ITypeReference testCaseAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestCaseAttribute", 0);
+ readonly ITypeReference testFixtureAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestFixtureAttribute", 0);
///
/// Determines whether the project is a test project. A project
@@ -44,6 +30,23 @@ namespace ICSharpCode.UnitTesting
return testAttributeRef.Resolve(SD.ParserService.GetCompilation(project).TypeResolveContext).Kind != TypeKind.Unknown;
}
+ public ITestProject CreateTestProject(ITestSolution parentSolution, IProject project)
+ {
+ return new NUnitTestProject(project);
+ }
+
+ /*
+ public ITestRunner CreateTestRunner()
+ {
+ return new NUnitTestRunner();
+ }
+
+ public ITestRunner CreateTestDebugger()
+ {
+ return new NUnitTestDebugger();
+ }
+
+
public bool IsTestMember(IMember member)
{
if (member == null || member.EntityType != EntityType.Method)
@@ -72,6 +75,6 @@ namespace ICSharpCode.UnitTesting
{
var project = typeDefinition.ParentAssembly.GetProject();
return typeDefinition.Methods.Where(IsTestMember).Select(m => new TestMember(m.UnresolvedMember));
- }
+ }*/
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestProject.cs b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestProject.cs
new file mode 100644
index 0000000000..818eb2b65b
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestProject.cs
@@ -0,0 +1,26 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.UnitTesting
+{
+ ///
+ /// NUnit test project.
+ ///
+ public class NUnitTestProject : TestProjectBase
+ {
+ public NUnitTestProject(IProject project) : base(project)
+ {
+ }
+
+ public override Task RunTestsAsync(IEnumerable tests, TestExecutionOptions options, IProgressMonitor progressMonitor)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestRunner.cs b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestRunner.cs
index 24ddcca895..9d35baae13 100644
--- a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestRunner.cs
+++ b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestRunner.cs
@@ -2,7 +2,9 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
using System.Diagnostics;
+
using ICSharpCode.SharpDevelop.Util;
namespace ICSharpCode.UnitTesting
@@ -23,7 +25,7 @@ namespace ICSharpCode.UnitTesting
this.options = options;
}
- protected override ProcessStartInfo GetProcessStartInfo(SelectedTests selectedTests)
+ protected override ProcessStartInfo GetProcessStartInfo(IEnumerable selectedTests)
{
NUnitConsoleApplication app = new NUnitConsoleApplication(selectedTests, options);
app.Results = base.TestResultsMonitor.FileName;
diff --git a/src/AddIns/Analysis/UnitTesting/Pad/EmptyUnitTestsPad.cs b/src/AddIns/Analysis/UnitTesting/Pad/EmptyUnitTestsPad.cs
deleted file mode 100644
index a268c37d6d..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Pad/EmptyUnitTestsPad.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Linq;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public class EmptyUnitTestsPad : IUnitTestsPad
- {
- Solution solution;
-
- public EmptyUnitTestsPad()
- : this(null)
- {
- }
-
- public EmptyUnitTestsPad(Solution solution)
- {
- this.solution = solution;
- }
-
- public void UpdateToolbar()
- {
- }
-
- public void BringToFront()
- {
- }
-
- public void ResetTestResults()
- {
- }
-
- public IProject[] GetProjects()
- {
- if (solution != null) {
- return solution.Projects.ToArray();
- }
- return new IProject[0];
- }
-
- public TestProject GetTestProject(IProject project)
- {
- return null;
- }
-
- public void CollapseAll()
- {
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Pad/IUnitTestsPad.cs b/src/AddIns/Analysis/UnitTesting/Pad/IUnitTestsPad.cs
deleted file mode 100644
index 0b94414a87..0000000000
--- a/src/AddIns/Analysis/UnitTesting/Pad/IUnitTestsPad.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public interface IUnitTestsPad
- {
- void UpdateToolbar();
- void BringToFront();
- void ResetTestResults();
- IProject[] GetProjects();
- TestProject GetTestProject(IProject project);
- void CollapseAll();
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/Pad/UnitTestsPad.cs b/src/AddIns/Analysis/UnitTesting/Pad/UnitTestsPad.cs
index 56a2d7fb08..c06a55a7cd 100644
--- a/src/AddIns/Analysis/UnitTesting/Pad/UnitTestsPad.cs
+++ b/src/AddIns/Analysis/UnitTesting/Pad/UnitTestsPad.cs
@@ -19,23 +19,20 @@ namespace ICSharpCode.UnitTesting
{
public class UnitTestsPad : AbstractPadContent
{
- TestSolution testSolution;
+ ITestService testService;
TestTreeView treeView;
- bool disposed;
DockPanel panel;
ToolBar toolBar;
List> pending = new List>();
- static UnitTestsPad instance;
public UnitTestsPad()
- : this(TestService.RegisteredTestFrameworks, TestService.Solution)
+ : this(SD.GetRequiredService())
{
}
- public UnitTestsPad(IRegisteredTestFrameworks testFrameworks, TestSolution testSolution)
+ public UnitTestsPad(ITestService testService)
{
- instance = this;
- this.testSolution = testSolution;
+ this.testService = testService;
panel = new DockPanel();
@@ -43,131 +40,28 @@ namespace ICSharpCode.UnitTesting
panel.Children.Add(toolBar);
DockPanel.SetDock(toolBar, Dock.Top);
- treeView = new TestTreeView(testFrameworks, testSolution);
+ treeView = new TestTreeView();
panel.Children.Add(treeView);
- // Add the load solution projects thread ended handler before
- // we try to display the open solution so the event does not
- // get missed.
- SD.ParserService.LoadSolutionProjectsThread.Finished += LoadSolutionProjectsThreadFinished;
- OnAddedLoadSolutionProjectsThreadEndedHandler();
-
- ProjectService.SolutionClosed += SolutionClosed;
- ProjectService.SolutionFolderRemoved += SolutionFolderRemoved;
- ProjectService.ProjectAdded += ProjectAdded;
- ProjectService.ProjectItemAdded += ProjectItemAdded;
- ProjectService.ProjectItemRemoved += ProjectItemRemoved;
-
treeView.ContextMenu = CreateContextMenu("/SharpDevelop/Pads/UnitTestsPad/ContextMenu");
- }
-
- public static UnitTestsPad Instance {
- get { return instance; }
- }
-
- public override object Control {
- get { return panel; }
+
+ testService.OpenSolutionChanged += testService_OpenSolutionChanged;
+ testService_OpenSolutionChanged(null, null);
}
public override void Dispose()
{
- if (!disposed) {
- disposed = true;
-
- ProjectService.ProjectItemRemoved -= ProjectItemRemoved;
- ProjectService.ProjectItemAdded -= ProjectItemAdded;
- ProjectService.ProjectAdded -= ProjectAdded;
- ProjectService.SolutionFolderRemoved -= SolutionFolderRemoved;
- ProjectService.SolutionClosed -= SolutionClosed;
- SD.ParserService.LoadSolutionProjectsThread.Finished -= LoadSolutionProjectsThreadFinished;
- }
+ testService.OpenSolutionChanged -= testService_OpenSolutionChanged;
+ base.Dispose();
}
-// public TestTreeView TestTreeView {
-// get { return treeView; }
-// }
-
-// public void ResetTestResults()
-// {
-// treeView.ResetTestResults();
-// }
-//
- public IProject[] GetProjects()
- {
- return testSolution.TestableProjects.Select(tp => tp.Project).ToArray();
+ public override object Control {
+ get { return panel; }
}
-// public TestProject GetTestProject(IProject project)
-// {
-// return treeView.GetTestProject(project);
-// }
-
- ///
- /// Updates the state of the buttons on the Unit Tests pad's
- /// toolbar.
- ///
- public void UpdateToolbar()
+ void testService_OpenSolutionChanged(object sender, EventArgs e)
{
-// ToolbarService.UpdateToolbar(toolBar);
- }
-
- ///
- /// Collapses all nodes.
- ///
-// public void CollapseAll()
-// {
-// if (treeView == null || treeView.Nodes == null || treeView.Nodes.Count == 0)
-// return;
-//
-// treeView.CollapseAll();
-// }
-
- ///
- /// Called when a solution has been closed.
- ///
-// protected void SolutionClosed()
-// {
-// treeView.Clear();
-// }
-//
-// protected void SolutionFolderRemoved(ISolutionFolder solutionFolder)
-// {
-// treeView.RemoveSolutionFolder(solutionFolder);
-// }
-
- ///
- /// If the project item removed is a reference to a unit
- /// test framework then the project will be removed from the
- /// test tree.
- ///
-// protected void ProjectItemRemoved(ProjectItem projectItem)
-// {
-// treeView.ProjectItemRemoved(projectItem);
-// }
-//
-// protected void ProjectItemAdded(ProjectItem projectItem)
-// {
-// treeView.ProjectItemAdded(projectItem);
-// }
-
- ///
- /// Protected method so we can test this method.
- ///
- protected void UpdateParseInfo(IUnresolvedFile oldFile, IUnresolvedFile newFile)
- {
- RootUnitTestNode root = (RootUnitTestNode)treeView.Root;
- if (root == null) {
-// SolutionLoaded(GetOpenSolution());
- root = (RootUnitTestNode)treeView.Root;
- if (root == null) return;
- }
- var solution = GetOpenSolution();
- if (solution == null)
- return;
- var project = solution.FindProjectContainingFile((oldFile ?? newFile).FileName);
- if (project == null)
- return;
- var projectNode = root.Children.OfType().FirstOrDefault(node => node.Project == project);
+ treeView.TestSolution = testService.OpenSolution;
}
///
@@ -187,107 +81,5 @@ namespace ICSharpCode.UnitTesting
{
return MenuService.CreateContextMenu(treeView, name);
}
-
-// ///
-// /// Virtual method so we can override this method and return
-// /// a dummy TestTreeView when testing.
-// ///
-// protected virtual SharpTreeView CreateTestTreeView(IRegisteredTestFrameworks testFrameworks)
-// {
-// return new SharpTreeView();
-// }
-
- ///
- /// Gets the currently open solution.
- ///
- protected virtual Solution GetOpenSolution()
- {
- return ProjectService.OpenSolution;
- }
-
- ///
- /// Determines whether the parser is currently still loading the
- /// solution.
- ///
- protected virtual bool IsParserLoadingSolution {
- get { return SD.ParserService.LoadSolutionProjectsThread.IsRunning; }
- }
-
- ///
- /// Indicates that an event handler for the ParserService's
- /// LoadSolutionProjectsThreadEnded event has been added
- ///
- protected virtual void OnAddedLoadSolutionProjectsThreadEndedHandler()
- {
- }
-
- void SolutionClosed(object source, EventArgs e)
- {
-// SolutionClosed();
- UpdateToolbar();
- }
-
- void SolutionFolderRemoved(object source, SolutionFolderEventArgs e)
- {
-// SolutionFolderRemoved(e.SolutionFolder);
- UpdateToolbar();
- }
-
- void ProjectAdded(object source, ProjectEventArgs e)
- {
- UpdateToolbar();
- }
-
- void LoadSolutionProjectsThreadFinished(object source, EventArgs e)
- {
- WorkbenchSingleton.SafeThreadAsyncCall(UpdateToolbar);
- Solution solution = ProjectService.OpenSolution;
-// WorkbenchSingleton.SafeThreadAsyncCall(SolutionLoaded, solution);
- }
-
-// void TestTreeViewKeyPress(object source, KeyPressEventArgs e)
-// {
-// if (e.KeyChar == '\r') {
-// e.Handled = true;
-// GotoDefinition();
-// } else if (e.KeyChar == ' ') {
-// e.Handled = true;
-// RunTests();
-// }
-// }
-
- void GotoDefinition()
- {
-// RunCommand(new GotoDefinitionCommand());
- }
-
- void RunTests()
- {
-// RunCommand(new RunTestInPadCommand());
- }
-
- void RunCommand(ICommand command)
- {
- command.Owner = treeView;
- command.Run();
- }
-
- void ProjectItemAdded(object source, ProjectItemEventArgs e)
- {
-// ProjectItemAdded(e.ProjectItem);
- }
-
- void ProjectItemRemoved(object source, ProjectItemEventArgs e)
- {
-// ProjectItemRemoved(e.ProjectItem);
- }
-
- public void ResetTestResults()
- {
- foreach (var testProject in testSolution.TestableProjects)
- testProject.ResetTestResults();
- }
}
-
-
}
diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/ITestRunner.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/ITestRunner.cs
index f05df18e56..8a29324c5e 100644
--- a/src/AddIns/Analysis/UnitTesting/TestRunner/ITestRunner.cs
+++ b/src/AddIns/Analysis/UnitTesting/TestRunner/ITestRunner.cs
@@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
using ICSharpCode.SharpDevelop.Util;
namespace ICSharpCode.UnitTesting
@@ -11,7 +12,7 @@ namespace ICSharpCode.UnitTesting
event EventHandler TestFinished;
event EventHandler AllTestsFinished;
event EventHandler MessageReceived;
- void Start(SelectedTests selectedTests);
+ void Start(IEnumerable selectedTests);
void Stop();
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/SelectedTests.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/SelectedTests.cs
deleted file mode 100644
index 8be2135988..0000000000
--- a/src/AddIns/Analysis/UnitTesting/TestRunner/SelectedTests.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Collections.Generic;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.SharpDevelop.Project;
-
-namespace ICSharpCode.UnitTesting
-{
- public class SelectedTests
- {
- string namespaceFilter;
- TestClass c;
- TestMember member;
- List projects = new List();
-
- public SelectedTests(IProject project, string namespaceFilter, TestClass c, TestMember member)
- {
- this.namespaceFilter = namespaceFilter;
- this.c = c;
- this.member = member;
-
- if (project != null) {
- projects.Add(project);
- }
- }
-
- public SelectedTests(IProject project)
- : this(project, null, null, null)
- {
- }
-
- public SelectedTests(object owner, IProject[] selectedProjects)
- {
- IProject project = TestableCondition.GetProject(owner);
- if (project != null) {
- projects.Add(project);
- } else {
- projects.AddRange(selectedProjects);
- }
-
- TestProject testProject = TestService.Solution.GetTestProject(project);
- if (testProject != null) {
- member = testProject.GetTestMember(TestableCondition.GetMember(owner));
- c = testProject.GetTestClass(TestableCondition.GetClassFromMemberOrCaller(owner));
- }
- namespaceFilter = TestableCondition.GetNamespace(owner);
- }
-
- public bool HasProjects {
- get { return projects.Count > 0; }
- }
-
- public void RemoveFirstProject()
- {
- if (HasProjects) {
- projects.RemoveAt(0);
- }
- }
-
- public IEnumerable Projects {
- get { return projects; }
- }
-
- public int ProjectsCount {
- get {return projects.Count;}
- }
-
- public IProject Project {
- get {
- if (projects.Count > 0) {
- return projects[0];
- }
- return null;
- }
- }
-
- public string NamespaceFilter {
- get { return namespaceFilter; }
- }
-
- public TestClass Class {
- get { return c; }
- }
-
- public TestMember Member {
- get { return member; }
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestDebuggerBase.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestDebuggerBase.cs
index 933e6900ad..865aeabfeb 100644
--- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestDebuggerBase.cs
+++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestDebuggerBase.cs
@@ -2,7 +2,9 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
using System.Diagnostics;
+
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
@@ -39,7 +41,7 @@ namespace ICSharpCode.UnitTesting
get { return testResultsMonitor; }
}
- public override void Start(SelectedTests selectedTests)
+ public override void Start(IEnumerable selectedTests)
{
ProcessStartInfo startInfo = GetProcessStartInfo(selectedTests);
if (IsDebuggerRunning) {
diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBase.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBase.cs
index 6a8dd71d4e..71ded442a7 100644
--- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBase.cs
+++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBase.cs
@@ -2,7 +2,9 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
using System.Diagnostics;
+
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Util;
@@ -62,7 +64,7 @@ namespace ICSharpCode.UnitTesting
OnMessageReceived(e.Line);
}
- public override void Start(SelectedTests selectedTests)
+ public override void Start(IEnumerable selectedTests)
{
ProcessStartInfo startInfo = GetProcessStartInfo(selectedTests);
Start(startInfo);
diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultTask.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultTask.cs
index 6e0f9bdfc5..b9fed31b2b 100644
--- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultTask.cs
+++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultTask.cs
@@ -16,7 +16,7 @@ namespace ICSharpCode.UnitTesting
{
}
- public static SDTask Create(TestResult result, TestProject project)
+ public static SDTask Create(TestResult result, ITestProject project)
{
TaskType taskType = TaskType.Warning;
FileLineReference lineRef = null;
@@ -76,7 +76,7 @@ namespace ICSharpCode.UnitTesting
/// Returns the location of the specified test member in the
/// project being tested.
///
- static FileLineReference FindTest(string memberName, TestProject testProject)
+ static FileLineReference FindTest(string memberName, ITestProject testProject)
{
// if (testProject != null) {
// TestMember testMember = testProject.TestClasses.GetTestMember(memberName);
diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestRunnerBase.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestRunnerBase.cs
index e3482f992d..1ee17d65d2 100644
--- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestRunnerBase.cs
+++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestRunnerBase.cs
@@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Collections.Generic;
using System.Diagnostics;
namespace ICSharpCode.UnitTesting
@@ -12,7 +13,7 @@ namespace ICSharpCode.UnitTesting
{
}
- protected virtual ProcessStartInfo GetProcessStartInfo(SelectedTests selectedTests)
+ protected virtual ProcessStartInfo GetProcessStartInfo(IEnumerable selectedTests)
{
return new ProcessStartInfo();
}
@@ -63,6 +64,6 @@ namespace ICSharpCode.UnitTesting
public abstract void Dispose();
public abstract void Stop();
- public abstract void Start(SelectedTests selectedTests);
+ public abstract void Start(IEnumerable selectedTests);
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/ClassUnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/TreeView/ClassUnitTestNode.cs
index 0c6e97a26a..68df61d772 100644
--- a/src/AddIns/Analysis/UnitTesting/TreeView/ClassUnitTestNode.cs
+++ b/src/AddIns/Analysis/UnitTesting/TreeView/ClassUnitTestNode.cs
@@ -12,7 +12,7 @@ namespace ICSharpCode.UnitTesting
///
/// Represents a TestClass in the tree view.
///
- public class ClassUnitTestNode : UnitTestBaseNode
+ public class ClassUnitTestNode : UnitTestNode
{
TestClass testClass;
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/ITestTreeView.cs b/src/AddIns/Analysis/UnitTesting/TreeView/ITestTreeView.cs
index d7e65035ce..80601d33a3 100644
--- a/src/AddIns/Analysis/UnitTesting/TreeView/ITestTreeView.cs
+++ b/src/AddIns/Analysis/UnitTesting/TreeView/ITestTreeView.cs
@@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Project;
using System;
@@ -11,24 +12,13 @@ namespace ICSharpCode.UnitTesting
public interface ITestTreeView
{
///
- /// Gets the selected member in the test tree view.
+ /// Gets the test solution that is being displayed in this tree view.
///
- TestMember SelectedMember {get;}
+ ITestSolution TestSolution { get; }
///
- /// Gets the selected class in the test tree view.
+ /// Gets the selected tests.
///
- TestClass SelectedClass {get;}
-
- ///
- /// Gets the selected project for the selected node
- /// in the test tree view.
- ///
- TestProject SelectedProject {get;}
-
- ///
- /// Gets the namespace for the selected namespace node.
- ///
- string SelectedNamespace {get;}
+ IEnumerable SelectedTests { get; }
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/MemberUnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/TreeView/MemberUnitTestNode.cs
index 14d943e0a5..80b1aadeb1 100644
--- a/src/AddIns/Analysis/UnitTesting/TreeView/MemberUnitTestNode.cs
+++ b/src/AddIns/Analysis/UnitTesting/TreeView/MemberUnitTestNode.cs
@@ -10,7 +10,7 @@ using ICSharpCode.TreeView;
namespace ICSharpCode.UnitTesting
{
- public class MemberUnitTestNode : UnitTestBaseNode
+ public class MemberUnitTestNode : UnitTestNode
{
TestMember testMember;
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/NamespaceUnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/TreeView/NamespaceUnitTestNode.cs
index 14af8158d0..cf8e846981 100644
--- a/src/AddIns/Analysis/UnitTesting/TreeView/NamespaceUnitTestNode.cs
+++ b/src/AddIns/Analysis/UnitTesting/TreeView/NamespaceUnitTestNode.cs
@@ -16,7 +16,7 @@ using ICSharpCode.TreeView;
namespace ICSharpCode.UnitTesting
{
- public class NamespaceUnitTestNode : UnitTestBaseNode
+ public class NamespaceUnitTestNode : UnitTestNode
{
readonly string shortName;
readonly string namespaceName;
@@ -50,11 +50,11 @@ namespace ICSharpCode.UnitTesting
internal override TestResultType TestResultType {
get {
if (Children.Count == 0) return TestResultType.None;
- if (Children.OfType().Any(node => node.TestResultType == TestResultType.Failure))
+ if (Children.OfType().Any(node => node.TestResultType == TestResultType.Failure))
return TestResultType.Failure;
- if (Children.OfType().Any(node => node.TestResultType == TestResultType.None))
+ if (Children.OfType().Any(node => node.TestResultType == TestResultType.None))
return TestResultType.None;
- if (Children.OfType().Any(node => node.TestResultType == TestResultType.Ignored))
+ if (Children.OfType().Any(node => node.TestResultType == TestResultType.Ignored))
return TestResultType.Ignored;
return TestResultType.Success;
}
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/ProjectUnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/TreeView/ProjectUnitTestNode.cs
index ab64f8bd94..c5b073843f 100644
--- a/src/AddIns/Analysis/UnitTesting/TreeView/ProjectUnitTestNode.cs
+++ b/src/AddIns/Analysis/UnitTesting/TreeView/ProjectUnitTestNode.cs
@@ -17,7 +17,7 @@ using ICSharpCode.TreeView;
namespace ICSharpCode.UnitTesting
{
- public class ProjectUnitTestNode : UnitTestBaseNode
+ public class ProjectUnitTestNode : UnitTestNode
{
TestProject project;
@@ -47,7 +47,7 @@ namespace ICSharpCode.UnitTesting
case NotifyCollectionChangedAction.Add:
foreach (TestClass c in e.NewItems) {
if (c.Namespace == "") continue;
- UnitTestBaseNode node = FindOrCreateNamespace(this, project.Project.RootNamespace, c.Namespace);
+ UnitTestNode node = FindOrCreateNamespace(this, project.Project.RootNamespace, c.Namespace);
node.Children.OrderedInsert(new ClassUnitTestNode(c), NodeTextComparer);
}
break;
@@ -70,7 +70,7 @@ namespace ICSharpCode.UnitTesting
}
}
- static UnitTestBaseNode FindOrCreateNamespace(UnitTestBaseNode parent, string parentNamespace, string @namespace)
+ static UnitTestNode FindOrCreateNamespace(UnitTestNode parent, string parentNamespace, string @namespace)
{
if (parentNamespace == @namespace)
return parent;
@@ -101,7 +101,7 @@ namespace ICSharpCode.UnitTesting
}
}
- static UnitTestBaseNode FindNamespace(UnitTestBaseNode parent, string parentNamespace, string @namespace)
+ static UnitTestNode FindNamespace(UnitTestNode parent, string parentNamespace, string @namespace)
{
if (parentNamespace == @namespace)
return parent;
@@ -120,7 +120,7 @@ namespace ICSharpCode.UnitTesting
Children.Clear();
foreach (var g in project.TestClasses.Select(c => new ClassUnitTestNode(c)).GroupBy(tc => tc.TestClass.Namespace)) {
if (g.Key == "") continue;
- UnitTestBaseNode node = FindOrCreateNamespace(this, project.Project.RootNamespace, g.Key);
+ UnitTestNode node = FindOrCreateNamespace(this, project.Project.RootNamespace, g.Key);
node.Children.AddRange(g.OrderBy(NodeTextComparer));
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/RootUnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/TreeView/RootUnitTestNode.cs
index 53ab00bb32..b300d52c2a 100644
--- a/src/AddIns/Analysis/UnitTesting/TreeView/RootUnitTestNode.cs
+++ b/src/AddIns/Analysis/UnitTesting/TreeView/RootUnitTestNode.cs
@@ -24,7 +24,7 @@ namespace ICSharpCode.UnitTesting
///
/// Description of RootUnitTestNode.
///
- public class RootUnitTestNode : UnitTestBaseNode
+ public class RootUnitTestNode : UnitTestNode
{
readonly TestSolution testSolution;
@@ -63,11 +63,11 @@ namespace ICSharpCode.UnitTesting
internal override TestResultType TestResultType {
get {
if (Children.Count == 0) return TestResultType.None;
- if (Children.OfType().Any(node => node.TestResultType == TestResultType.Failure))
+ if (Children.OfType().Any(node => node.TestResultType == TestResultType.Failure))
return TestResultType.Failure;
- if (Children.OfType().Any(node => node.TestResultType == TestResultType.None))
+ if (Children.OfType().Any(node => node.TestResultType == TestResultType.None))
return TestResultType.None;
- if (Children.OfType().Any(node => node.TestResultType == TestResultType.Ignored))
+ if (Children.OfType().Any(node => node.TestResultType == TestResultType.Ignored))
return TestResultType.Ignored;
return TestResultType.Success;
}
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/TestTreeView.cs b/src/AddIns/Analysis/UnitTesting/TreeView/TestTreeView.cs
index 374d6b346e..34a1a77c53 100644
--- a/src/AddIns/Analysis/UnitTesting/TreeView/TestTreeView.cs
+++ b/src/AddIns/Analysis/UnitTesting/TreeView/TestTreeView.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
@@ -23,100 +24,49 @@ namespace ICSharpCode.UnitTesting
[Flags]
public enum TestTreeViewState {
None = 0,
- SourceCodeItemSelected = 1
+ SupportsGoToDefinition = 1
}
- IRegisteredTestFrameworks testFrameworks;
+ ITestSolution testSolution;
- public TestTreeView(IRegisteredTestFrameworks testFrameworks, TestSolution testSolution)
- {
- this.testFrameworks = testFrameworks;
- // Show 'All Tests' root node only if there is more than one test project in the solution
- testSolution.TestableProjects.CollectionChanged += delegate { ShowRoot = testSolution.TestableProjects.Count > 1; };
- this.Root = new RootUnitTestNode(testSolution);
- }
-
- ///
- /// Gets the current state of the test tree view.
- ///
- public Enum InternalState {
- get {
- if (SelectedItem is ClassUnitTestNode || SelectedItem is MemberUnitTestNode)
- return TestTreeViewState.SourceCodeItemSelected;
- return TestTreeViewState.None;
- }
- }
-
- bool IsTestProject(IProject project)
- {
- return testFrameworks.IsTestProject(project);
- }
-
- ///
- /// Gets the member of the currently selected tree node.
- ///
- public TestMember SelectedMember {
- get {
- MemberUnitTestNode memberNode = SelectedItem as MemberUnitTestNode;
- if (memberNode != null) {
- return memberNode.TestMember;
- }
- return null;
- }
- }
-
- ///
- /// Gets the class of the currently selected tree node.
- ///
- public TestClass SelectedClass {
- get {
- ClassUnitTestNode classNode = SelectedItem as ClassUnitTestNode;
- if (classNode == null) {
- classNode = GetClassNodeFromSelectedMemberNode();
+ public ITestSolution TestSolution {
+ get { return testSolution; }
+ set {
+ if (testSolution == value)
+ return;
+ testSolution = value;
+ if (testSolution != null) {
+ this.Root = new UnitTestNode(testSolution);
+ this.Root.Children.CollectionChanged += delegate {
+ this.ShowRoot = this.Root != null && this.Root.Children.Count > 1;
+ };
+ } else {
+ this.Root = null;
}
-
- if (classNode != null) {
- return classNode.TestClass;
- }
- return null;
}
}
- ClassUnitTestNode GetClassNodeFromSelectedMemberNode()
+ public TestTreeView()
{
- MemberUnitTestNode memberNode = SelectedItem as MemberUnitTestNode;
- if (memberNode != null) {
- return memberNode.Parent as ClassUnitTestNode;
- }
- return null;
+ this.ShowRoot = false;
}
///
- /// If a namespace node is selected then the fully qualified namespace
- /// for this node is returned (i.e. includes the parent namespace prefixed
- /// to it). For all other nodes this returns null.
+ /// Gets the current state of the test tree view.
///
- public string SelectedNamespace {
+ public Enum InternalState {
get {
- NamespaceUnitTestNode selectedNode = SelectedItem as NamespaceUnitTestNode;
- if (selectedNode != null) {
- return selectedNode.NamespaceName;
- }
- return null;
+ var node = SelectedItem as UnitTestNode;
+ if (node != null && node.Test.SupportsGoToDefinition)
+ return TestTreeViewState.SupportsGoToDefinition;
+ else
+ return TestTreeViewState.None;
}
}
- ///
- /// Gets the selected test project.
- ///
- public TestProject SelectedProject {
+ public IEnumerable SelectedTests {
get {
- for (var node = SelectedItem as SharpTreeNode; node != null; node = node.Parent) {
- var projectNode = node as ProjectUnitTestNode;
- if (projectNode != null)
- return projectNode.Project;
- }
- return null;
+ return this.GetTopLevelSelection().OfType().Select(n => n.Test);
}
}
}
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/UnitTestBaseNode.cs b/src/AddIns/Analysis/UnitTesting/TreeView/UnitTestBaseNode.cs
deleted file mode 100644
index 98106fa155..0000000000
--- a/src/AddIns/Analysis/UnitTesting/TreeView/UnitTestBaseNode.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using ICSharpCode.NRefactory.Utils;
-using ICSharpCode.TreeView;
-
-namespace ICSharpCode.UnitTesting
-{
- public abstract class UnitTestBaseNode : SharpTreeNode
- {
- protected static readonly KeyComparer NodeTextComparer = KeyComparer.Create((SharpTreeNode n) => n.Text.ToString(), StringComparer.OrdinalIgnoreCase, StringComparer.OrdinalIgnoreCase);
-
- internal abstract TestResultType TestResultType { get; }
-
- public override object Icon {
- get { return GetIcon(TestResultType); }
- }
-
- object GetIcon(TestResultType testResultType)
- {
- switch (testResultType) {
- case TestResultType.None:
- return Images.Grey;
- case TestResultType.Success:
- return Images.Green;
- case TestResultType.Failure:
- return Images.Red;
- case TestResultType.Ignored:
- return Images.Yellow;
- default:
- throw new Exception("Invalid value for TestResultType");
- }
- }
- }
-}
diff --git a/src/AddIns/Analysis/UnitTesting/TreeView/UnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/TreeView/UnitTestNode.cs
new file mode 100644
index 0000000000..df565a586d
--- /dev/null
+++ b/src/AddIns/Analysis/UnitTesting/TreeView/UnitTestNode.cs
@@ -0,0 +1,128 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+
+using ICSharpCode.NRefactory.Utils;
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.TreeView;
+
+namespace ICSharpCode.UnitTesting
+{
+ public class UnitTestNode : SharpTreeNode
+ {
+ protected static readonly IComparer NodeTextComparer = KeyComparer.Create((SharpTreeNode n) => n.Text.ToString(), StringComparer.OrdinalIgnoreCase, StringComparer.OrdinalIgnoreCase);
+
+ readonly ITest test;
+
+ public UnitTestNode(ITest test)
+ {
+ if (test == null)
+ throw new ArgumentNullException("test");
+ this.test = test;
+ test.DisplayNameChanged += test_NameChanged;
+ test.ResultChanged += test_ResultChanged;
+ LazyLoading = true;
+ }
+
+ void DetachEventHandlers()
+ {
+ test.DisplayNameChanged -= test_NameChanged;
+ test.ResultChanged -= test_ResultChanged;
+ // If children loaded, also detach the collection change event handler
+ if (!LazyLoading) {
+ test.NestedTests.CollectionChanged -= test_NestedTests_CollectionChanged;
+ }
+ }
+
+ public ITest Test {
+ get { return test; }
+ }
+
+ #region Manage Children
+ protected override void LoadChildren()
+ {
+ Children.Clear();
+ InsertNestedTests(test.NestedTests);
+ test.NestedTests.CollectionChanged += test_NestedTests_CollectionChanged;
+ }
+
+ void InsertNestedTests(IEnumerable nestedTests)
+ {
+ foreach (var test in nestedTests) {
+ Children.OrderedInsert(test.CreateTreeNode(), NodeTextComparer);
+ }
+ }
+
+ void test_NestedTests_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (!IsVisible) {
+ SwitchBackToLazyLoading();
+ return;
+ }
+ switch (e.Action) {
+ case NotifyCollectionChangedAction.Add:
+ InsertNestedTests(e.NewItems.Cast());
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ Children.RemoveAll(n => e.OldItems.Contains(((UnitTestNode)n).Test));
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ if (IsExpanded) {
+ Children.Clear();
+ InsertNestedTests(test.NestedTests);
+ } else {
+ SwitchBackToLazyLoading();
+ }
+ break;
+ default:
+ throw new NotSupportedException("Invalid value for NotifyCollectionChangedAction");
+ }
+ }
+
+ void SwitchBackToLazyLoading()
+ {
+ test.NestedTests.CollectionChanged -= test_NestedTests_CollectionChanged;
+ Children.Clear();
+ LazyLoading = true;
+ }
+ #endregion
+
+ #region Icon + Text
+ public override object Icon {
+ get {
+ switch (test.Result) {
+ case TestResultType.None:
+ return Images.Grey;
+ case TestResultType.Success:
+ return Images.Green;
+ case TestResultType.Failure:
+ return Images.Red;
+ case TestResultType.Ignored:
+ return Images.Yellow;
+ default:
+ throw new NotSupportedException("Invalid value for TestResultType");
+ }
+ }
+ }
+
+ void test_ResultChanged(object sender, EventArgs e)
+ {
+ RaisePropertyChanged("Icon");
+ RaisePropertyChanged("ExpandedIcon");
+ }
+
+ public override object Text {
+ get { return test.DisplayName; }
+ }
+
+ void test_NameChanged(object sender, EventArgs e)
+ {
+ RaisePropertyChanged("Text");
+ }
+ #endregion
+ }
+}
diff --git a/src/AddIns/Analysis/UnitTesting/UnitTesting.addin b/src/AddIns/Analysis/UnitTesting/UnitTesting.addin
index 9233f2c201..41649d8fd9 100644
--- a/src/AddIns/Analysis/UnitTesting/UnitTesting.addin
+++ b/src/AddIns/Analysis/UnitTesting/UnitTesting.addin
@@ -17,6 +17,11 @@
+
+
+
+
+ class="ICSharpCode.UnitTesting.RunSelectedTestCommand"/>
@@ -63,7 +68,7 @@
+ class="ICSharpCode.UnitTesting.RunSelectedTestWithDebuggerCommand"/>
@@ -78,12 +83,12 @@
+ class="ICSharpCode.UnitTesting.RunAllTestsInSolutionCommand"/>
+ class="ICSharpCode.UnitTesting.RunSelectedTestCommand"/>
@@ -120,7 +125,7 @@
+ class="ICSharpCode.UnitTesting.RunSelectedTestCommand"/>
@@ -133,7 +138,7 @@
label="${res:NUnitPad.NUnitPadContent.StopTests}"
class="ICSharpCode.UnitTesting.StopTestsCommand"/>
-
+
@@ -152,7 +157,7 @@
+ class="ICSharpCode.UnitTesting.RunAllTestsInSolutionCommand"/>
@@ -165,7 +170,7 @@
+ class="ICSharpCode.UnitTesting.RunAllTestsInProjectCommand"/>
diff --git a/src/AddIns/Analysis/UnitTesting/UnitTesting.csproj b/src/AddIns/Analysis/UnitTesting/UnitTesting.csproj
index 62e267adb5..f2c713e547 100644
--- a/src/AddIns/Analysis/UnitTesting/UnitTesting.csproj
+++ b/src/AddIns/Analysis/UnitTesting/UnitTesting.csproj
@@ -66,79 +66,54 @@
-
-
-
-
+
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
-
-
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
UnitTestingOptionsPanel.xaml
-
-
-
-
-
-
-
Never
@@ -197,7 +172,6 @@
-
diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/MultiDictionary.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/MultiDictionary.cs
index 496b66ba9e..1eab0c73ab 100644
--- a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/MultiDictionary.cs
+++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/MultiDictionary.cs
@@ -62,6 +62,15 @@ namespace ICSharpCode.NRefactory.Utils
return false;
}
+ ///
+ /// Removes all entries with the specified key.
+ ///
+ /// Returns true if at least one entry was removed.
+ public bool RemoveAll(TKey key)
+ {
+ return dict.Remove(key);
+ }
+
public void Clear()
{
dict.Clear();
@@ -81,10 +90,21 @@ namespace ICSharpCode.NRefactory.Utils
}
}
+ ///
+ /// Returns the number of different keys.
+ ///
public int Count {
get { return dict.Count; }
}
+ public ICollection Keys {
+ get { return dict.Keys; }
+ }
+
+ public IEnumerable Values {
+ get { return dict.Values.SelectMany(list => list); }
+ }
+
IEnumerable ILookup.this[TKey key] {
get { return this[key]; }
}
diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index 329c26e2e9..ffa7493b77 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -372,6 +372,7 @@
+
diff --git a/src/Main/Base/Project/Src/Commands/BuildCommands.cs b/src/Main/Base/Project/Src/Commands/BuildCommands.cs
index 87f009699d..5ed48d0acb 100644
--- a/src/Main/Base/Project/Src/Commands/BuildCommands.cs
+++ b/src/Main/Base/Project/Src/Commands/BuildCommands.cs
@@ -3,9 +3,10 @@
using System;
using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
-
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Debugging;
@@ -76,6 +77,26 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
}
}
+ public Task BuildAsync(CancellationToken cancellationToken)
+ {
+ var registration = cancellationToken.Register(BuildEngine.CancelGuiBuild, true);
+ var tcs = new TaskCompletionSource();
+ this.BuildComplete += delegate {
+ registration.Dispose();
+ if (cancellationToken.IsCancellationRequested)
+ tcs.TrySetCanceled();
+ else
+ tcs.TrySetResult(this.LastBuildResults);
+ };
+ try {
+ StartBuild();
+ } catch (Exception ex) {
+ registration.Dispose();
+ tcs.TrySetException(ex);
+ }
+ return tcs.Task;
+ }
+
///
/// Notifies the user that #develp's internal MSBuildEngine
/// implementation only supports compiling solutions and projects;
diff --git a/src/AddIns/Analysis/UnitTesting/Commands/MultipleProjectBuildable.cs b/src/Main/Base/Project/Src/Project/MultipleProjectBuildable.cs
similarity index 92%
rename from src/AddIns/Analysis/UnitTesting/Commands/MultipleProjectBuildable.cs
rename to src/Main/Base/Project/Src/Project/MultipleProjectBuildable.cs
index 28605c0303..ec732783bd 100644
--- a/src/AddIns/Analysis/UnitTesting/Commands/MultipleProjectBuildable.cs
+++ b/src/Main/Base/Project/Src/Project/MultipleProjectBuildable.cs
@@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using ICSharpCode.SharpDevelop.Project;
-namespace ICSharpCode.UnitTesting
+namespace ICSharpCode.SharpDevelop.Project
{
///
/// IBuildable implementation that builds several projects.
@@ -17,7 +17,7 @@ namespace ICSharpCode.UnitTesting
public MultipleProjectBuildable(IEnumerable projects)
{
- this.projects = projects.ToArray();
+ this.projects = projects.Where(p => p != null).ToArray();
}
public string Name {
diff --git a/src/Main/Base/Project/Src/Services/Tasks/TaskService.cs b/src/Main/Base/Project/Src/Services/Tasks/TaskService.cs
index 0ccae06d2a..379d74f63c 100644
--- a/src/Main/Base/Project/Src/Services/Tasks/TaskService.cs
+++ b/src/Main/Base/Project/Src/Services/Tasks/TaskService.cs
@@ -110,10 +110,16 @@ namespace ICSharpCode.SharpDevelop
public static void ClearExceptCommentTasks()
{
- List commentTasks = new List(CommentTasks);
- Clear();
- foreach (SDTask t in commentTasks) {
- Add(t);
+ bool wasInUpdate = InUpdate;
+ InUpdate = true;
+ try {
+ List commentTasks = new List(CommentTasks);
+ Clear();
+ foreach (SDTask t in commentTasks) {
+ Add(t);
+ }
+ } finally {
+ InUpdate = wasInUpdate;
}
}
@@ -149,10 +155,10 @@ namespace ICSharpCode.SharpDevelop
List newTasks = new List();
foreach (TagComment tag in tagComments) {
newTasks.Add(new SDTask(fileName,
- tag.Key + tag.CommentString,
- tag.Region.BeginColumn,
- tag.Region.BeginLine,
- TaskType.Comment));
+ tag.Key + tag.CommentString,
+ tag.Region.BeginColumn,
+ tag.Region.BeginLine,
+ TaskType.Comment));
}
List oldTasks = new List();