Browse Source
A lot of functionality gets moved from the main portion of the AddIn into the framework-specific providers. We no longer deal with test classes and members, but instead use the new ITest interface. A test can be a whole project, namespace, class, or just a single method. This can be used to support features like the NUnit [TestCase] attribute, where a single method might result in multiple tests.newNRvisualizers
68 changed files with 1447 additions and 1649 deletions
@ -1,398 +0,0 @@
@@ -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; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the running test command.
|
||||
/// </summary>
|
||||
public static AbstractRunTestCommand RunningTestCommand { |
||||
get { return runningTestCommand; } |
||||
set { runningTestCommand = value; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets whether a test is currently running.
|
||||
/// </summary>
|
||||
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); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sets the initial workbench state before starting
|
||||
/// a test run.
|
||||
/// </summary>
|
||||
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(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
protected virtual void OnBeforeBuild() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called before all tests are run (after the build has finished successfully).
|
||||
/// If multiple projects are to be tested this is called only once.
|
||||
/// </summary>
|
||||
protected virtual void OnBeforeRunTests() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Runs the tests after building the project(s) under test.
|
||||
/// </summary>
|
||||
void BuildProjectBeforeRunningTests(SelectedTests selectedTests) |
||||
{ |
||||
BuildProject build = CreateBuildProjectBeforeTestRun(selectedTests); |
||||
build.BuildComplete += delegate { |
||||
OnBuildComplete(build.LastBuildResults, selectedTests); |
||||
}; |
||||
build.Run(); |
||||
} |
||||
|
||||
BuildProject CreateBuildProjectBeforeTestRun(SelectedTests selectedTests) |
||||
{ |
||||
IEnumerable<IProject> projects = GetProjectsRequiringBuildBeforeTestRun(selectedTests); |
||||
return context.BuildProjectFactory.CreateBuildProjectBeforeTestRun(projects); |
||||
} |
||||
|
||||
IEnumerable<IProject> GetProjectsRequiringBuildBeforeTestRun(SelectedTests selectedTests) |
||||
{ |
||||
return selectedTests |
||||
.Projects |
||||
.Where(p => context.RegisteredTestFrameworks.IsBuildNeededBeforeTestRunForProject(p)); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Stops running the tests.
|
||||
/// </summary>
|
||||
public void Stop() |
||||
{ |
||||
StopActiveTestRunner(); |
||||
|
||||
runningTestCommand = null; |
||||
UpdateUnitTestsPadToolbar(); |
||||
|
||||
OnStop(); |
||||
} |
||||
|
||||
void StopActiveTestRunner() |
||||
{ |
||||
if (testRunner != null) { |
||||
testRunner.Stop(); |
||||
testRunner.Dispose(); |
||||
testRunner = null; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
protected virtual void OnAfterRunTests() |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called by derived classes when a single test run
|
||||
/// is finished.
|
||||
/// </summary>
|
||||
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); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called when the test run should be stopped.
|
||||
/// </summary>
|
||||
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; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Runs the test for the project after a successful build.
|
||||
/// </summary>
|
||||
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); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Clears the test results in the test tree view for all the
|
||||
/// displayed projects.
|
||||
/// </summary>
|
||||
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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,25 +0,0 @@
@@ -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; } |
||||
} |
||||
} |
||||
@ -0,0 +1,56 @@
@@ -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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,26 +0,0 @@
@@ -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(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,42 +0,0 @@
@@ -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; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,68 +0,0 @@
@@ -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; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,26 +0,0 @@
@@ -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); |
||||
} |
||||
} |
||||
} |
||||
@ -1,26 +0,0 @@
@@ -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); |
||||
} |
||||
} |
||||
} |
||||
@ -1,23 +0,0 @@
@@ -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); |
||||
} |
||||
} |
||||
@ -1,12 +0,0 @@
@@ -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); |
||||
} |
||||
} |
||||
@ -0,0 +1,51 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Gets the test framework that supports the specified project.
|
||||
/// </summary>
|
||||
ITestFramework GetTestFrameworkForProject(IProject project); |
||||
|
||||
MessageViewCategory UnitTestMessageView { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the current test solution.
|
||||
/// This property should only be accessed by the main thread.
|
||||
/// </summary>
|
||||
ITestSolution OpenSolution { get; } |
||||
|
||||
/// <summary>
|
||||
/// Occurs when the open test solution has changed.
|
||||
/// </summary>
|
||||
event EventHandler OpenSolutionChanged; |
||||
|
||||
/// <summary>
|
||||
/// Builds the project (if necessary) and runs the specified tests.
|
||||
/// If tests are already running, the existing run is cancelled.
|
||||
/// </summary>
|
||||
Task RunTestsAsync(IEnumerable<ITest> selectedTests, TestExecutionOptions options); |
||||
|
||||
/// <summary>
|
||||
/// Gets whether tests are currently running.
|
||||
/// </summary>
|
||||
bool IsRunningTests { get; } |
||||
|
||||
/// <summary>
|
||||
/// Aborts the current test run.
|
||||
/// This method has no effect if no tests are running.
|
||||
/// </summary>
|
||||
void CancelRunningTests(); |
||||
} |
||||
} |
||||
@ -1,99 +0,0 @@
@@ -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<TestFrameworkDescriptor> testFrameworkDescriptors; |
||||
public const string AddInPath = "/SharpDevelop/UnitTesting/TestFrameworks"; |
||||
|
||||
public RegisteredTestFrameworks(IAddInTree addInTree) |
||||
{ |
||||
testFrameworkDescriptors = addInTree.BuildItems<TestFrameworkDescriptor>(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; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,88 @@
@@ -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<TestFrameworkDescriptor> testFrameworkDescriptors = SD.AddInTree.BuildItems<TestFrameworkDescriptor>(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<ITest> 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
|
||||
} |
||||
} |
||||
@ -0,0 +1,149 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Manages the execution of tests across multiple projects.
|
||||
/// Takes care of building the projects (if necessary) and showing progress in the UI.
|
||||
/// </summary>
|
||||
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<ITestService>(); |
||||
this.workbench = SD.Workbench; |
||||
this.statusBarService = SD.StatusBar; |
||||
this.buildOptions = new UnitTestBuildOptions(); |
||||
} |
||||
|
||||
readonly MultiDictionary<ITestProject, ITest> testsByProject = new MultiDictionary<ITestProject, ITest>(); |
||||
CancellationToken cancellationToken; |
||||
|
||||
public async Task RunTestsAsync(IEnumerable<ITest> 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<ITestProject, ITest> 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<ITest> 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(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,19 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Options used for test execution.
|
||||
/// </summary>
|
||||
public class TestExecutionOptions |
||||
{ |
||||
/// <summary>
|
||||
/// Gets/Sets whether to debug the test execution.
|
||||
/// The default is <c>false</c>.
|
||||
/// </summary>
|
||||
public bool UseDebugger { get; set; } |
||||
} |
||||
} |
||||
@ -1,23 +0,0 @@
@@ -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; |
||||
} |
||||
} |
||||
} |
||||
@ -1,57 +0,0 @@
@@ -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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,15 +0,0 @@
@@ -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<A>(Action<A> method, A arg1); |
||||
} |
||||
} |
||||
@ -1,27 +0,0 @@
@@ -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<A>(Action<A> method, A arg1) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall(method, arg1); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a unit test or a group of unit tests.
|
||||
/// </summary>
|
||||
public interface ITest |
||||
{ |
||||
/// <summary>
|
||||
/// Gets the collection of nested tests.
|
||||
/// </summary>
|
||||
TestCollection NestedTests { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the parent project that owns this test.
|
||||
/// </summary>
|
||||
ITestProject ParentProject { get; } |
||||
|
||||
/// <summary>
|
||||
/// Name to be displayed in the tests tree view.
|
||||
/// </summary>
|
||||
string DisplayName { get; } |
||||
|
||||
/// <summary>
|
||||
/// Raised when the <see cref="Name"/> property changes.
|
||||
/// </summary>
|
||||
event EventHandler DisplayNameChanged; |
||||
|
||||
/// <summary>
|
||||
/// Gets the result of the previous run of this test.
|
||||
/// </summary>
|
||||
TestResultType Result { get; } |
||||
|
||||
/// <summary>
|
||||
/// Raised when the <see cref="Result"/> property changes.
|
||||
/// </summary>
|
||||
event EventHandler<TestResultTypeChangedEventArgs> ResultChanged; |
||||
|
||||
/// <summary>
|
||||
/// Resets the test results for this test and all nested tests.
|
||||
/// </summary>
|
||||
void ResetTestResults(); |
||||
|
||||
bool SupportsGoToDefinition { get; } |
||||
|
||||
void GoToDefinition(); |
||||
|
||||
UnitTestNode CreateTreeNode(); |
||||
} |
||||
} |
||||
@ -0,0 +1,47 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Represents the root node of a test project.
|
||||
/// </summary>
|
||||
public interface ITestProject : ITest |
||||
{ |
||||
/// <summary>
|
||||
/// Gets the SharpDevelop project on which this test project is based.
|
||||
/// </summary>
|
||||
IProject Project { get; } |
||||
|
||||
/// <summary>
|
||||
/// Gets the test for the specified entity.
|
||||
/// Returns null if the entity is not a unit test.
|
||||
/// </summary>
|
||||
ITest GetTestForEntity(IEntity entity); |
||||
|
||||
/// <summary>
|
||||
/// Returns a SharpDevelop <see cref="IBuildable"/> that builds the project
|
||||
/// for test execution.
|
||||
/// May return null if the project does not require compilation.
|
||||
/// </summary>
|
||||
IBuildable GetBuildableForTesting(); |
||||
|
||||
/// <summary>
|
||||
/// Notifies the project that the parse information was changed.
|
||||
/// </summary>
|
||||
void NotifyParseInformationChanged(IUnresolvedFile oldUnresolvedFile, IUnresolvedFile newUnresolvedFile); |
||||
|
||||
/// <summary>
|
||||
/// Runs the specified tests. The specified tests must belong to this project.
|
||||
/// </summary>
|
||||
Task RunTestsAsync(IEnumerable<ITest> tests, TestExecutionOptions options, IProgressMonitor progressMonitor); |
||||
} |
||||
} |
||||
@ -0,0 +1,33 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// A test that represents the whole solution.
|
||||
/// </summary>
|
||||
public interface ITestSolution : ITest |
||||
{ |
||||
// /// <summary>
|
||||
// /// Gets the list of all test projects.
|
||||
// /// </summary>
|
||||
// ObservableCollection<ITestProject> TestableProjects { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the test project for the specified project.
|
||||
/// Returns null if the project is not a test project.
|
||||
/// </summary>
|
||||
ITestProject GetTestProject(IProject project); |
||||
|
||||
/// <summary>
|
||||
/// Gets the test for the specified entity.
|
||||
/// Returns null if the entity is not a unit test.
|
||||
/// </summary>
|
||||
ITest GetTestForEntity(IEntity entity); |
||||
} |
||||
} |
||||
@ -0,0 +1,143 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Base class for <see cref="ITest"/> implementations.
|
||||
/// </summary>
|
||||
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<TestResultTypeChangedEventArgs> ResultChanged; |
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the test result.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the result is bound to the composite of the nested tests, setting this
|
||||
/// property will remove the binding.
|
||||
/// </remarks>
|
||||
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)); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Binds the result to the composite result of the nested tests.
|
||||
/// </summary>
|
||||
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); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,199 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Collection of tests that monitors the amount of tests for each result type,
|
||||
/// allowing efficient updates of the overall result.
|
||||
/// </summary>
|
||||
public class TestCollection : ObservableCollection<ITest> |
||||
{ |
||||
#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<ITest> 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); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,46 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a namespace of unit tests.
|
||||
/// </summary>
|
||||
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; } |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,58 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Base class for <see cref="ITestProject"/> implementations.
|
||||
/// </summary>
|
||||
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<ITest> tests, TestExecutionOptions options, IProgressMonitor progressMonitor); |
||||
} |
||||
} |
||||
@ -0,0 +1,30 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// EventArgs for ITest.ResultChanged.
|
||||
/// </summary>
|
||||
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; } |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// NUnit test project.
|
||||
/// </summary>
|
||||
public class NUnitTestProject : TestProjectBase |
||||
{ |
||||
public NUnitTestProject(IProject project) : base(project) |
||||
{ |
||||
} |
||||
|
||||
public override Task RunTestsAsync(IEnumerable<ITest> tests, TestExecutionOptions options, IProgressMonitor progressMonitor) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,53 +0,0 @@
@@ -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() |
||||
{ |
||||
} |
||||
} |
||||
} |
||||
@ -1,18 +0,0 @@
@@ -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(); |
||||
} |
||||
} |
||||
@ -1,91 +0,0 @@
@@ -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<IProject> projects = new List<IProject>(); |
||||
|
||||
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<IProject> 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; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,38 +0,0 @@
@@ -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<SharpTreeNode, string> 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"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,128 @@
@@ -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<SharpTreeNode> 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<ITest> 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<ITest>()); |
||||
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
|
||||
} |
||||
} |
||||
Loading…
Reference in new issue