Browse Source

WIP on Unit Testing

newNRvisualizers
Siegfried Pammer 13 years ago
parent
commit
cd3ba55f09
  1. 20
      SharpDevelop.sln
  2. 73
      src/AddIns/Analysis/UnitTesting/Resources/UnitTestingOptionsPanel.xfrm
  3. 398
      src/AddIns/Analysis/UnitTesting/Src/AbstractRunTestCommand.cs
  4. 71
      src/AddIns/Analysis/UnitTesting/Src/BaseTestMember.cs
  5. 13
      src/AddIns/Analysis/UnitTesting/Src/IAddInTree.cs
  6. 12
      src/AddIns/Analysis/UnitTesting/Src/IBuildOptions.cs
  7. 15
      src/AddIns/Analysis/UnitTesting/Src/IBuildProjectFactory.cs
  8. 12
      src/AddIns/Analysis/UnitTesting/Src/IFileSystem.cs
  9. 25
      src/AddIns/Analysis/UnitTesting/Src/IRegisteredTestFrameworks.cs
  10. 25
      src/AddIns/Analysis/UnitTesting/Src/IRunTestCommandContext.cs
  11. 12
      src/AddIns/Analysis/UnitTesting/Src/ITestFrameworkFactory.cs
  12. 20
      src/AddIns/Analysis/UnitTesting/Src/ITestResultsMonitor.cs
  13. 17
      src/AddIns/Analysis/UnitTesting/Src/ITestRunner.cs
  14. 33
      src/AddIns/Analysis/UnitTesting/Src/ITestTreeView.cs
  15. 15
      src/AddIns/Analysis/UnitTesting/Src/IUnitTestDebuggerService.cs
  16. 13
      src/AddIns/Analysis/UnitTesting/Src/IUnitTestFileService.cs
  17. 13
      src/AddIns/Analysis/UnitTesting/Src/IUnitTestMessageService.cs
  18. 24
      src/AddIns/Analysis/UnitTesting/Src/IUnitTestProcessRunner.cs
  19. 12
      src/AddIns/Analysis/UnitTesting/Src/IUnitTestSaveAllFilesCommand.cs
  20. 20
      src/AddIns/Analysis/UnitTesting/Src/IUnitTestTaskService.cs
  21. 15
      src/AddIns/Analysis/UnitTesting/Src/IUnitTestWorkbench.cs
  22. 18
      src/AddIns/Analysis/UnitTesting/Src/IUnitTestsPad.cs
  23. 47
      src/AddIns/Analysis/UnitTesting/Src/InnerClassEnumerator.cs
  24. 250
      src/AddIns/Analysis/UnitTesting/Src/NUnitConsoleCommandLine.cs
  25. 44
      src/AddIns/Analysis/UnitTesting/Src/NUnitTestDebugger.cs
  26. 132
      src/AddIns/Analysis/UnitTesting/Src/NUnitTestFramework.cs
  27. 37
      src/AddIns/Analysis/UnitTesting/Src/NUnitTestResult.cs
  28. 38
      src/AddIns/Analysis/UnitTesting/Src/NUnitTestRunner.cs
  29. 116
      src/AddIns/Analysis/UnitTesting/Src/RegisteredTestFrameworks.cs
  30. 52
      src/AddIns/Analysis/UnitTesting/Src/RemovedClasses.cs
  31. 43
      src/AddIns/Analysis/UnitTesting/Src/RunProjectTestsInPadCommand.cs
  32. 69
      src/AddIns/Analysis/UnitTesting/Src/RunTestCommandContext.cs
  33. 96
      src/AddIns/Analysis/UnitTesting/Src/SelectedTests.cs
  34. 50
      src/AddIns/Analysis/UnitTesting/Src/TestAttributeName.cs
  35. 382
      src/AddIns/Analysis/UnitTesting/Src/TestClass.cs
  36. 98
      src/AddIns/Analysis/UnitTesting/Src/TestClassTreeNode.cs
  37. 24
      src/AddIns/Analysis/UnitTesting/Src/TestFramework.cs
  38. 155
      src/AddIns/Analysis/UnitTesting/Src/TestMember.cs
  39. 53
      src/AddIns/Analysis/UnitTesting/Src/TestMemberTreeNode.cs
  40. 337
      src/AddIns/Analysis/UnitTesting/Src/TestNamespaceTreeNode.cs
  41. 291
      src/AddIns/Analysis/UnitTesting/Src/TestProject.cs
  42. 113
      src/AddIns/Analysis/UnitTesting/Src/TestProjectTreeNode.cs
  43. 92
      src/AddIns/Analysis/UnitTesting/Src/TestResult.cs
  44. 97
      src/AddIns/Analysis/UnitTesting/Src/TestResultTask.cs
  45. 102
      src/AddIns/Analysis/UnitTesting/Src/TestTreeNode.cs
  46. 435
      src/AddIns/Analysis/UnitTesting/Src/TestTreeView.cs
  47. 55
      src/AddIns/Analysis/UnitTesting/Src/TestTreeViewImageList.cs
  48. 123
      src/AddIns/Analysis/UnitTesting/Src/TestableCondition.cs
  49. 119
      src/AddIns/Analysis/UnitTesting/Src/UnitTestCommands.cs
  50. 40
      src/AddIns/Analysis/UnitTesting/Src/UnitTestTaskService.cs
  51. 106
      src/AddIns/Analysis/UnitTesting/Src/UnitTestingOptions.cs
  52. 77
      src/AddIns/Analysis/UnitTesting/Src/UnitTestingOptionsPanel.cs
  53. 332
      src/AddIns/Analysis/UnitTesting/Src/UnitTestsPad.cs
  54. 208
      src/AddIns/Analysis/UnitTesting/UnitTesting.csproj
  55. 18
      src/Main/ICSharpCode.Core.Presentation/OptionBinding.cs

20
SharpDevelop.sln

@ -107,6 +107,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexEditor", "src\AddIns\Dis @@ -107,6 +107,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexEditor", "src\AddIns\Dis
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlEditor", "src\AddIns\DisplayBindings\XmlEditor\Project\XmlEditor.csproj", "{DCA2703D-250A-463E-A68A-07ED105AE6BD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Analysis", "Analysis", "{7019F43E-DFD7-4D1C-8C96-E75D55646DE7}"
ProjectSection(SolutionItems) = postProject
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTesting", "src\AddIns\Analysis\UnitTesting\UnitTesting.csproj", "{1F261725-6318-4434-A1B1-6C70CE4CD324}"
EndProject
Project("{00000000-0000-0000-0000-000000000000}") = "Tools", "src\Tools\Tools.build", "{3DF4060F-5EE0-41CF-8096-F27355FD5511}"
EndProject
Global
@ -419,6 +425,18 @@ Global @@ -419,6 +425,18 @@ Global
{1152B71B-3C05-4598-B20D-823B5D40559E}.Release|Win32.ActiveCfg = Release|Any CPU
{1152B71B-3C05-4598-B20D-823B5D40559E}.Release|x86.Build.0 = Release|Any CPU
{1152B71B-3C05-4598-B20D-823B5D40559E}.Release|x86.ActiveCfg = Release|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|Win32.Build.0 = Debug|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|Win32.ActiveCfg = Debug|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|x86.Build.0 = Debug|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Debug|x86.ActiveCfg = Debug|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|Any CPU.Build.0 = Release|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|Win32.Build.0 = Release|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|Win32.ActiveCfg = Release|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|x86.Build.0 = Release|Any CPU
{1F261725-6318-4434-A1B1-6C70CE4CD324}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -445,6 +463,7 @@ Global @@ -445,6 +463,7 @@ Global
{E0646C25-36F2-4524-969F-FA621353AB94} = {39327899-ED91-4F7F-988C-4FE4E17C014D}
{F3662720-9EA2-4591-BBC6-97361DCE50A9} = {39327899-ED91-4F7F-988C-4FE4E17C014D}
{11BF9245-88A3-4A0A-9A8A-EC9D98036B0F} = {39327899-ED91-4F7F-988C-4FE4E17C014D}
{7019F43E-DFD7-4D1C-8C96-E75D55646DE7} = {39327899-ED91-4F7F-988C-4FE4E17C014D}
{83F15BA7-8478-4664-81BB-A82F146D88B3} = {F208FF4F-E5D8-41D5-A7C7-B463976F156E}
{17F4D7E0-6933-4C2E-8714-FD7E98D625D5} = {F208FF4F-E5D8-41D5-A7C7-B463976F156E}
{1F1AC7CD-D154-45BB-8EAF-804CA8055F5A} = {E0646C25-36F2-4524-969F-FA621353AB94}
@ -464,5 +483,6 @@ Global @@ -464,5 +483,6 @@ Global
{0162E499-42D0-409B-AA25-EED21F75336B} = {11BF9245-88A3-4A0A-9A8A-EC9D98036B0F}
{E618A9CD-A39F-4925-A538-E8A3FEF24E54} = {11BF9245-88A3-4A0A-9A8A-EC9D98036B0F}
{DCA2703D-250A-463E-A68A-07ED105AE6BD} = {11BF9245-88A3-4A0A-9A8A-EC9D98036B0F}
{1F261725-6318-4434-A1B1-6C70CE4CD324} = {7019F43E-DFD7-4D1C-8C96-E75D55646DE7}
EndGlobalSection
EndGlobal

73
src/AddIns/Analysis/UnitTesting/Resources/UnitTestingOptionsPanel.xfrm

@ -1,73 +0,0 @@ @@ -1,73 +0,0 @@
<Components version="1.0">
<System.Windows.Forms.UserControl>
<Name value="UnitTestingOptionsPanel" />
<ClientSize value="{Width=450, Height=281}" />
<Controls>
<System.Windows.Forms.GroupBox>
<Name value="groupBox" />
<Location value="10, 13" />
<UseCompatibleTextRendering value="True" />
<Text value="${res:ICSharpCode.NUnitPad.NUnitPadContent.PadName}" />
<Size value="432, 241" />
<Anchor value="Top, Left, Right" />
<TabIndex value="1" />
<Controls>
<System.Windows.Forms.CheckBox>
<Name value="createXmlOutputFileCheckBox" />
<Location value="6, 179" />
<Text value="${res:ICSharpCode.UnitTesting.OptionsPanel.CreateXmlOutputFile}" />
<TabIndex value="6" />
<Size value="420, 24" />
<UseVisualStyleBackColor value="True" />
<Anchor value="Top, Left, Right" />
</System.Windows.Forms.CheckBox>
<System.Windows.Forms.CheckBox>
<Name value="threadCheckBox" />
<Location value="6, 149" />
<Text value="${res:ICSharpCode.UnitTesting.OptionsPanel.Thread}" />
<TabIndex value="5" />
<Size value="420, 24" />
<UseVisualStyleBackColor value="True" />
<Anchor value="Top, Left, Right" />
</System.Windows.Forms.CheckBox>
<System.Windows.Forms.CheckBox>
<Name value="shadowCopyCheckBox" />
<Location value="6, 119" />
<Text value="${res:ICSharpCode.UnitTesting.OptionsPanel.ShadowCopy}" />
<TabIndex value="4" />
<Size value="420, 24" />
<UseVisualStyleBackColor value="True" />
<Anchor value="Top, Left, Right" />
</System.Windows.Forms.CheckBox>
<System.Windows.Forms.CheckBox>
<Name value="showProgressCheckBox" />
<Location value="6, 89" />
<Text value="${res:ICSharpCode.UnitTesting.OptionsPanel.ShowProgress}" />
<TabIndex value="3" />
<Size value="420, 24" />
<UseVisualStyleBackColor value="True" />
<Anchor value="Top, Left, Right" />
</System.Windows.Forms.CheckBox>
<System.Windows.Forms.CheckBox>
<Name value="labelsCheckBox" />
<Location value="6, 29" />
<Text value="${res:ICSharpCode.UnitTesting.OptionsPanel.LabelEachTest}" />
<TabIndex value="2" />
<Size value="420, 24" />
<UseVisualStyleBackColor value="True" />
<Anchor value="Top, Left, Right" />
</System.Windows.Forms.CheckBox>
<System.Windows.Forms.CheckBox>
<Name value="showLogoCheckBox" />
<Location value="6, 59" />
<Text value="${res:ICSharpCode.UnitTesting.OptionsPanel.ShowLogo}" />
<TabIndex value="1" />
<Size value="420, 24" />
<UseVisualStyleBackColor value="True" />
<Anchor value="Top, Left, Right" />
</System.Windows.Forms.CheckBox>
</Controls>
</System.Windows.Forms.GroupBox>
</Controls>
</System.Windows.Forms.UserControl>
</Components>

398
src/AddIns/Analysis/UnitTesting/Src/AbstractRunTestCommand.cs

@ -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);
Task 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;
}
}
}
}
}

71
src/AddIns/Analysis/UnitTesting/Src/BaseTestMember.cs

@ -1,71 +0,0 @@ @@ -1,71 +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.Dom;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Represents a test member that exists in a base class.
/// </summary>
/// <remarks>
/// In order to have the Unit Test tree run the correct
/// test when we have a class that has a base class with
/// test members is to return the derived class from the
/// DeclaringType's property. Otherwise the base class
/// member is tested and the derived class is not used.
/// </remarks>
public class BaseTestMember : AbstractMember
{
IMember member;
/// <summary>
/// Creates a new instance of the BaseTestMember.
/// </summary>
/// <param name="derivedClass">The derived class and not
/// the class where the method is actually defined.</param>
/// <param name="method">The base class's test member.</param>
public BaseTestMember(IClass derivedClass, IMember member)
: this(derivedClass, member, member.DeclaringType.Name + "." + member.Name)
{
}
protected BaseTestMember(IClass derivedClass, IMember member, string name)
: base(derivedClass, name)
{
this.member = member;
this.ReturnType = member.ReturnType;
this.Modifiers = member.Modifiers;
this.Region = member.Region;
this.BodyRegion = member.BodyRegion;
this.Documentation = member.Documentation;
}
/// <summary>
/// Gets the actual method used to create this object.
/// </summary>
public IMember Member {
get { return member; }
}
public override EntityType EntityType {
get {
return member.EntityType;
}
}
public override string DocumentationTag {
get {
return null;
}
}
public override string Documentation {get;set;}
public override IMember Clone()
{
return new BaseTestMember(DeclaringType, Member);
}
}
}

13
src/AddIns/Analysis/UnitTesting/Src/IAddInTree.cs

@ -1,13 +0,0 @@ @@ -1,13 +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;
namespace ICSharpCode.UnitTesting
{
public interface IAddInTree
{
List<T> BuildItems<T>(string path, object caller);
}
}

12
src/AddIns/Analysis/UnitTesting/Src/IBuildOptions.cs

@ -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 IBuildOptions
{
bool ShowErrorListAfterBuild { get; }
}
}

15
src/AddIns/Analysis/UnitTesting/Src/IBuildProjectFactory.cs

@ -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 System.Collections.Generic;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Project.Commands;
namespace ICSharpCode.UnitTesting
{
public interface IBuildProjectFactory
{
BuildProject CreateBuildProjectBeforeTestRun(IEnumerable<IProject> projects);
}
}

12
src/AddIns/Analysis/UnitTesting/Src/IFileSystem.cs

@ -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 IFileSystem
{
bool FileExists(string fileName);
}
}

25
src/AddIns/Analysis/UnitTesting/Src/IRegisteredTestFrameworks.cs

@ -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 System.Collections.Generic;
using ICSharpCode.SharpDevelop.Dom;
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(IClass c);
bool IsTestProject(IProject project);
IEnumerable<TestMember> GetTestMembersFor(IClass @class);
bool IsBuildNeededBeforeTestRunForProject(IProject project);
}
}

25
src/AddIns/Analysis/UnitTesting/Src/IRunTestCommandContext.cs

@ -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.Services;
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; }
IUnitTestMessageService MessageService { get; }
IUnitTestSaveAllFilesCommand SaveAllFilesCommand { get; }
IStatusBarService StatusBarService { get; }
Solution OpenSolution { get; }
}
}

12
src/AddIns/Analysis/UnitTesting/Src/ITestFrameworkFactory.cs

@ -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);
}
}

20
src/AddIns/Analysis/UnitTesting/Src/ITestResultsMonitor.cs

@ -1,20 +0,0 @@ @@ -1,20 +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 ITestResultsMonitor : IDisposable
{
event TestFinishedEventHandler TestFinished;
string FileName { get; set; }
void Stop();
void Start();
void Read();
long InitialFilePosition { get; set; }
}
}

17
src/AddIns/Analysis/UnitTesting/Src/ITestRunner.cs

@ -1,17 +0,0 @@ @@ -1,17 +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.Util;
namespace ICSharpCode.UnitTesting
{
public interface ITestRunner : IDisposable
{
event TestFinishedEventHandler TestFinished;
event EventHandler AllTestsFinished;
event MessageReceivedEventHandler MessageReceived;
void Start(SelectedTests selectedTests);
void Stop();
}
}

33
src/AddIns/Analysis/UnitTesting/Src/ITestTreeView.cs

@ -1,33 +0,0 @@ @@ -1,33 +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 ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
using System;
namespace ICSharpCode.UnitTesting
{
public interface ITestTreeView
{
/// <summary>
/// Gets the selected member in the test tree view.
/// </summary>
IMember SelectedMember {get;}
/// <summary>
/// Gets the selected class in the test tree view.
/// </summary>
IClass SelectedClass {get;}
/// <summary>
/// Gets the selected project for the selected node
/// in the test tree view.
/// </summary>
IProject SelectedProject {get;}
/// <summary>
/// Gets the namespace for the selected namespace node.
/// </summary>
string SelectedNamespace {get;}
}
}

15
src/AddIns/Analysis/UnitTesting/Src/IUnitTestDebuggerService.cs

@ -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 System.Data;
using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.UnitTesting
{
public interface IUnitTestDebuggerService
{
bool IsDebuggerLoaded { get; }
IDebugger CurrentDebugger { get; }
}
}

13
src/AddIns/Analysis/UnitTesting/Src/IUnitTestFileService.cs

@ -1,13 +0,0 @@ @@ -1,13 +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 IUnitTestFileService : IFileSystem
{
void OpenFile(string fileName);
void JumpToFilePosition(string fileName, int line, int column);
}
}

13
src/AddIns/Analysis/UnitTesting/Src/IUnitTestMessageService.cs

@ -1,13 +0,0 @@ @@ -1,13 +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 IUnitTestMessageService
{
bool AskQuestion(string question, string caption);
void ShowFormattedErrorMessage(string format, string item);
}
}

24
src/AddIns/Analysis/UnitTesting/Src/IUnitTestProcessRunner.cs

@ -1,24 +0,0 @@ @@ -1,24 +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.SharpDevelop.Util;
namespace ICSharpCode.UnitTesting
{
public interface IUnitTestProcessRunner
{
bool LogStandardOutputAndError { get; set; }
string WorkingDirectory { get; set; }
Dictionary<string, string> EnvironmentVariables { get; }
void Start(string command, string arguments);
void Kill();
event LineReceivedEventHandler OutputLineReceived;
event LineReceivedEventHandler ErrorLineReceived;
event EventHandler ProcessExited;
}
}

12
src/AddIns/Analysis/UnitTesting/Src/IUnitTestSaveAllFilesCommand.cs

@ -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 IUnitTestSaveAllFilesCommand
{
void SaveAllFiles();
}
}

20
src/AddIns/Analysis/UnitTesting/Src/IUnitTestTaskService.cs

@ -1,20 +0,0 @@ @@ -1,20 +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;
namespace ICSharpCode.UnitTesting
{
public interface IUnitTestTaskService
{
MessageViewCategory BuildMessageViewCategory { get; }
bool InUpdate { get; set; }
void ClearExceptCommentTasks();
void Add(Task task);
bool SomethingWentWrong { get; }
bool HasCriticalErrors(bool treatWarningsAsErrors);
}
}

15
src/AddIns/Analysis/UnitTesting/Src/IUnitTestWorkbench.cs

@ -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);
}
}

18
src/AddIns/Analysis/UnitTesting/Src/IUnitTestsPad.cs

@ -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();
}
}

47
src/AddIns/Analysis/UnitTesting/Src/InnerClassEnumerator.cs

@ -1,47 +0,0 @@ @@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.UnitTesting
{
public class InnerClassEnumerator : IEnumerable<IClass>
{
readonly IClass _c;
public InnerClassEnumerator(IClass c)
{
_c = c;
}
#region IEnumerable<IClass> Members
public IEnumerator<IClass> GetEnumerator()
{
var result = new List<IClass>();
Visit(_c, result);
return result.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
private void Visit(IClass c, List<IClass> resultList)
{
foreach (var innerClass in c.InnerClasses)
{
resultList.Add(innerClass);
Visit(innerClass, resultList);
}
}
}
}

250
src/AddIns/Analysis/UnitTesting/Src/NUnitConsoleCommandLine.cs

@ -1,250 +0,0 @@ @@ -1,250 +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.Diagnostics;
using System.IO;
using System.Text;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
public class NUnitConsoleApplication
{
public NUnitConsoleApplication(SelectedTests selectedTests, UnitTestingOptions options)
{
Initialize(selectedTests);
InitializeOptions(options);
}
public NUnitConsoleApplication(SelectedTests selectedTests)
{
Initialize(selectedTests);
}
void Initialize(SelectedTests selectedTests)
{
this.selectedTests = selectedTests;
this.project = selectedTests.Project;
Assemblies.Add(project.OutputAssemblyFullPath);
if (selectedTests.NamespaceFilter != null) {
NamespaceFilter = selectedTests.NamespaceFilter;
}
if (selectedTests.Class != null) {
Fixture = selectedTests.Class.DotNetName;
if (selectedTests.Member != null) {
Test = selectedTests.Member.Name;
}
}
}
void InitializeOptions(UnitTestingOptions options)
{
NoThread = options.NoThread;
NoLogo = options.NoLogo;
NoDots = options.NoDots;
Labels = options.Labels;
ShadowCopy = !options.NoShadow;
if (options.CreateXmlOutputFile) {
GenerateXmlOutputFileName();
}
}
void GenerateXmlOutputFileName()
{
string directory = Path.GetDirectoryName(project.OutputAssemblyFullPath);
string fileName = project.AssemblyName + "-TestResult.xml";
XmlOutputFile = Path.Combine(directory, fileName);
}
/// <summary>
/// returns full/path/to/Tools/NUnit
/// </summary>
string WorkingDirectory {
get { return Path.Combine(FileUtility.ApplicationRootPath, @"bin\Tools\NUnit"); }
}
/// <summary>
/// returns full/path/to/Tools/NUnit/nunit-console.exe or nunit-console-x86.exe if the
/// project platform target is x86.
/// </summary>
public string FileName {
get {
string exe = "nunit-console";
if (ProjectUsesDotnet20Runtime(project)) {
exe += "-dotnet2";
}
if (IsPlatformTarget32Bit(project)) {
exe += "-x86";
}
exe += ".exe";
return Path.Combine(WorkingDirectory, exe);
}
}
public readonly List<string> Assemblies = new List<string>();
/// <summary>
/// Use shadow copy assemblies. Default = true.
/// </summary>
public bool ShadowCopy = true;
/// <summary>
/// Disables the use of a separate thread to run tests on separate thread. Default = false;
/// </summary>
public bool NoThread = false;
/// <summary>
/// Use /nologo directive.
/// </summary>
public bool NoLogo = false;
/// <summary>
/// Use /labels directive.
/// </summary>
public bool Labels = false;
/// <summary>
/// Use /nodots directive.
/// </summary>
public bool NoDots = false;
/// <summary>
/// File to write xml output to. Default = null.
/// </summary>
public string XmlOutputFile;
/// <summary>
/// Fixture to test. Null = test all fixtures.
/// </summary>
public string Fixture;
/// <summary>
/// Test to run. Null = run all tests. Only valid together with the Fixture property.
/// </summary>
public string Test;
/// <summary>
/// File to write test results to.
/// </summary>
public string Results;
/// <summary>
/// The namespace that tests need to be a part of if they are to
/// be run.
/// </summary>
public string NamespaceFilter;
IProject project;
SelectedTests selectedTests;
public SelectedTests SelectedTests {
get { return selectedTests; }
}
public IProject Project {
get { return project; }
}
public ProcessStartInfo GetProcessStartInfo()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = FileName;
startInfo.Arguments = GetArguments();
startInfo.WorkingDirectory = WorkingDirectory;
return startInfo;
}
/// <summary>
/// Gets the full command line to run the unit test application.
/// This is the combination of the UnitTestApplication and
/// the command line arguments.
/// </summary>
public string GetCommandLine()
{
return String.Format("\"{0}\" {1}", FileName, GetArguments());
}
/// <summary>
/// Gets the arguments to use on the command line to run NUnit.
/// </summary>
public string GetArguments()
{
StringBuilder b = new StringBuilder();
foreach (string assembly in Assemblies) {
if (b.Length > 0)
b.Append(' ');
b.Append('"');
b.Append(assembly);
b.Append('"');
}
if (!ShadowCopy)
b.Append(" /noshadow");
if (NoThread)
b.Append(" /nothread");
if (NoLogo)
b.Append(" /nologo");
if (Labels)
b.Append(" /labels");
if (NoDots)
b.Append(" /nodots");
if (XmlOutputFile != null) {
b.Append(" /xml=\"");
b.Append(XmlOutputFile);
b.Append('"');
}
if (Results != null) {
b.Append(" /results=\"");
b.Append(Results);
b.Append('"');
}
string run = null;
if (NamespaceFilter != null) {
run = NamespaceFilter;
} else if (Fixture != null) {
if (Test != null) {
run = Fixture + "." + Test;
} else {
run = Fixture;
}
} else if (Test != null) {
run = Test;
}
if (run != null) {
b.Append(" /run=\"");
b.Append(run);
b.Append('"');
}
return b.ToString();
}
/// <summary>
/// Checks that the project's PlatformTarget is x86 for the active configuration.
/// </summary>
bool IsPlatformTarget32Bit(IProject project)
{
MSBuildBasedProject msbuildProject = project as MSBuildBasedProject;
if (msbuildProject != null) {
string platformTarget = msbuildProject.GetEvaluatedProperty("PlatformTarget");
return String.Compare(platformTarget, "x86", true) == 0;
}
return false;
}
bool ProjectUsesDotnet20Runtime(IProject project)
{
var p = project as ICSharpCode.SharpDevelop.Project.Converter.IUpgradableProject;
if (p != null && p.CurrentTargetFramework != null) {
return p.CurrentTargetFramework.SupportedRuntimeVersion == "v2.0.50727";
}
return false;
}
}
}

44
src/AddIns/Analysis/UnitTesting/Src/NUnitTestDebugger.cs

@ -1,44 +0,0 @@ @@ -1,44 +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.Core.Services;
using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.UnitTesting
{
public class NUnitTestDebugger : TestDebuggerBase
{
UnitTestingOptions options;
public NUnitTestDebugger()
: this(new UnitTestDebuggerService(),
new UnitTestMessageService(),
new TestResultsMonitor(),
new UnitTestingOptions())
{
}
public NUnitTestDebugger(IUnitTestDebuggerService debuggerService,
IUnitTestMessageService messageService,
ITestResultsMonitor testResultsMonitor,
UnitTestingOptions options)
: base(debuggerService, messageService, testResultsMonitor)
{
this.options = options;
}
protected override ProcessStartInfo GetProcessStartInfo(SelectedTests selectedTests)
{
NUnitConsoleApplication app = new NUnitConsoleApplication(selectedTests, options);
app.Results = base.TestResultsMonitor.FileName;
return app.GetProcessStartInfo();
}
protected override TestResult CreateTestResultForTestFramework(TestResult testResult)
{
return new NUnitTestResult(testResult);
}
}
}

132
src/AddIns/Analysis/UnitTesting/Src/NUnitTestFramework.cs

@ -1,132 +0,0 @@ @@ -1,132 +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 System.Collections.Generic;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
public class NUnitTestFramework : ITestFramework
{
/// <summary>
/// Determines whether the project is a test project. A project
/// is considered to be a test project if it contains a reference
/// to the NUnit.Framework assembly.
/// </summary>
public bool IsTestProject(IProject project)
{
if (project != null) {
foreach (ProjectItem projectItem in project.Items) {
var referenceProjectItem = projectItem as ReferenceProjectItem;
if (IsNUnitFrameworkAssemblyReference(referenceProjectItem)) {
return true;
}
}
}
return false;
}
bool IsNUnitFrameworkAssemblyReference(ReferenceProjectItem referenceProjectItem)
{
if (referenceProjectItem != null) {
string name = referenceProjectItem.ShortName;
return name.Equals("NUnit.Framework", StringComparison.OrdinalIgnoreCase);
}
return false;
}
/// <summary>
/// Determines whether the class is a test fixture. A class
/// is considered to be a test class if it contains a TestFixture attribute.
/// </summary>
public bool IsTestClass(IClass c)
{
if (c == null) return false;
if (c.IsAbstract) return false;
StringComparer nameComparer = GetNameComparer(c);
if (nameComparer != null) {
NUnitTestAttributeName testAttributeName = new NUnitTestAttributeName("TestFixture", nameComparer);
foreach (IAttribute attribute in c.Attributes) {
if (testAttributeName.IsEqual(attribute)) {
return true;
}
}
}
while (c != null) {
if (HasTestMethod(c)) return true;
c = c.BaseClass;
}
return false;
}
private bool HasTestMethod(IClass c) {
return GetTestMembersFor(c).Any();
}
static StringComparer GetNameComparer(IClass c)
{
if (c != null) {
IProjectContent projectContent = c.ProjectContent;
if (projectContent != null) {
LanguageProperties language = projectContent.Language;
if (language != null) {
return language.NameComparer;
}
}
}
return null;
}
/// <summary>
/// Determines whether the method is a test method. A method
/// is considered to be a test method if it contains the NUnit Test attribute.
/// If the method has parameters it cannot be a test method.
/// </summary>
public bool IsTestMember(IMember member)
{
var method = member as IMethod;
if (method != null) {
return IsTestMethod(method);
}
return false;
}
public IEnumerable<TestMember> GetTestMembersFor(IClass @class) {
return @class.Methods.Where(IsTestMethod).Select(member => new TestMember(member));
}
static bool IsTestMethod(IMethod method)
{
var nameComparer = GetNameComparer(method.DeclaringType);
if (nameComparer != null) {
var testAttribute = new NUnitTestAttributeName("Test", nameComparer);
foreach (IAttribute attribute in method.Attributes) {
if (testAttribute.IsEqual(attribute)) {
if (method.Parameters.Count == 0) {
return true;
}
}
}
}
return false;
}
public bool IsBuildNeededBeforeTestRun {
get { return true; }
}
public ITestRunner CreateTestRunner()
{
return new NUnitTestRunner();
}
public ITestRunner CreateTestDebugger()
{
return new NUnitTestDebugger();
}
}
}

37
src/AddIns/Analysis/UnitTesting/Src/NUnitTestResult.cs

@ -1,37 +0,0 @@ @@ -1,37 +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.IO;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.UnitTesting
{
public class NUnitTestResult : TestResult
{
public NUnitTestResult(TestResult testResult)
: base(testResult.Name)
{
Message = testResult.Message;
ResultType = testResult.ResultType;
StackTrace = testResult.StackTrace;
}
protected override void OnStackTraceChanged()
{
FileLineReference fileLineRef = OutputTextLineParser.GetNUnitOutputFileLineReference(StackTrace, true);
if (fileLineRef != null) {
StackTraceFilePosition = CreateFilePosition(fileLineRef);
} else {
StackTraceFilePosition = FilePosition.Empty;
}
}
FilePosition CreateFilePosition(FileLineReference fileLineRef)
{
string fileName = Path.GetFullPath(fileLineRef.FileName);
return new FilePosition(fileName, fileLineRef.Line, fileLineRef.Column + 1);
}
}
}

38
src/AddIns/Analysis/UnitTesting/Src/NUnitTestRunner.cs

@ -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.Diagnostics;
using ICSharpCode.SharpDevelop.Util;
namespace ICSharpCode.UnitTesting
{
public class NUnitTestRunner : TestProcessRunnerBase
{
UnitTestingOptions options;
public NUnitTestRunner()
: this(new TestProcessRunnerBaseContext(),
new UnitTestingOptions())
{
}
public NUnitTestRunner(TestProcessRunnerBaseContext context, UnitTestingOptions options)
: base(context)
{
this.options = options;
}
protected override ProcessStartInfo GetProcessStartInfo(SelectedTests selectedTests)
{
NUnitConsoleApplication app = new NUnitConsoleApplication(selectedTests, options);
app.Results = base.TestResultsMonitor.FileName;
return app.GetProcessStartInfo();
}
protected override TestResult CreateTestResultForTestFramework(TestResult testResult)
{
return new NUnitTestResult(testResult);
}
}
}

116
src/AddIns/Analysis/UnitTesting/Src/RegisteredTestFrameworks.cs

@ -1,116 +0,0 @@ @@ -1,116 +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.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
public class RegisteredTestFrameworks : IRegisteredTestFrameworks
{
List<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;
}
public IEnumerable<TestMember> GetTestMembersFor(IClass @class) {
ITestFramework testFramework = GetTestFramework(@class);
if (testFramework != null)
return testFramework.GetTestMembersFor(@class);
return new TestMember[0];
}
ITestFramework GetTestFramework(IMember member)
{
if (member != null) {
return GetTestFramework(member.DeclaringType);
}
return null;
}
ITestFramework GetTestFramework(IClass c)
{
IProject project = GetProject(c);
return GetTestFrameworkForProject(project);
}
IProject GetProject(IClass c)
{
if (c != null) {
return c.ProjectContent.Project as IProject;
}
return null;
}
public bool IsTestClass(IClass 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;
}
}
}

52
src/AddIns/Analysis/UnitTesting/Src/RemovedClasses.cs

@ -1,52 +0,0 @@ @@ -1,52 +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.SharpDevelop.Dom;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Used to determine which classes have been removed by the user in the project.
/// </summary>
public class RemovedClasses
{
Dictionary<string, IClass> classDictionary = new Dictionary<string, IClass>();
public RemovedClasses()
{
}
public void Add(IList<IClass> classes)
{
foreach (IClass c in classes) {
classDictionary[c.DotNetName] = c;
foreach (IClass innerClass in c.InnerClasses) {
classDictionary[innerClass.DotNetName] = innerClass;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="c"></param>
public void Remove(IClass c)
{
classDictionary.Remove(c.DotNetName);
foreach (IClass innerClass in c.InnerClasses) {
classDictionary.Remove(innerClass.DotNetName);
}
}
public IList<IClass> GetMissingClasses()
{
List<IClass> missingClasses = new List<IClass>();
foreach (IClass c in classDictionary.Values) {
missingClasses.Add(c);
}
return missingClasses;
}
}
}

43
src/AddIns/Analysis/UnitTesting/Src/RunProjectTestsInPadCommand.cs

@ -1,43 +0,0 @@ @@ -1,43 +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.Dom;
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 IMember SelectedMember {
get { return null; }
}
public IClass SelectedClass {
get { return null; }
}
public IProject SelectedProject {
get { return ProjectService.CurrentProject; }
}
public string SelectedNamespace {
get { return null; }
}
}
}

69
src/AddIns/Analysis/UnitTesting/Src/RunTestCommandContext.cs

@ -1,69 +0,0 @@ @@ -1,69 +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.Services;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
public class RunTestCommandContext : IRunTestCommandContext
{
UnitTestingOptions options = new UnitTestingOptions();
IRegisteredTestFrameworks testFrameworks = TestService.RegisteredTestFrameworks;
UnitTestTaskService taskService = new UnitTestTaskService();
UnitTestWorkbench workbench = new UnitTestWorkbench();
UnitTestBuildProjectFactory buildProjectFactory = new UnitTestBuildProjectFactory();
UnitTestBuildOptions buildOptions = new UnitTestBuildOptions();
MessageViewCategory unitTestCategory = TestService.UnitTestMessageView;
UnitTestMessageService messageService = new UnitTestMessageService();
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 UnitTestsPad.Instance; }
}
public IUnitTestMessageService MessageService {
get { return messageService; }
}
public IUnitTestSaveAllFilesCommand SaveAllFilesCommand {
get { return saveAllFilesCommand; }
}
public IStatusBarService StatusBarService {
get { return statusBarService; }
}
public Solution OpenSolution {
get { return ProjectService.OpenSolution; }
}
}
}

96
src/AddIns/Analysis/UnitTesting/Src/SelectedTests.cs

@ -1,96 +0,0 @@ @@ -1,96 +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.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
public class SelectedTests
{
string namespaceFilter;
IClass c;
IMember member;
List<IProject> projects = new List<IProject>();
public SelectedTests(IProject project, string namespaceFilter, IClass c, IMember 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);
}
member = TestableCondition.GetMember(owner);
c = GetClass(member, owner);
namespaceFilter = TestableCondition.GetNamespace(owner);
}
static IClass GetClass(IMember member, Object owner)
{
if (member != null) {
return member.DeclaringType;
}
return TestableCondition.GetClass(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 IClass Class {
get { return c; }
}
public IMember Member {
get { return member; }
}
}
}

50
src/AddIns/Analysis/UnitTesting/Src/TestAttributeName.cs

@ -1,50 +0,0 @@ @@ -1,50 +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.Dom;
namespace ICSharpCode.UnitTesting
{
public class NUnitTestAttributeName
{
string name = String.Empty;
string qualifiedName = String.Empty;
string fullyQualifiedName = String.Empty;
StringComparer nameComparer;
/// <summary>
/// Creates a new instance of the NUnit Test Attribute class.
/// </summary>
/// <param name="name">The name of the attribute (e.g. Test) not
/// the full name of the attribute (e.g. TestAttribute).</param>
/// <param name="nameComparer">The string comparer to use
/// when comparing attribute names.</param>
public NUnitTestAttributeName(string name, StringComparer nameComparer)
{
this.name = name;
this.nameComparer = nameComparer;
qualifiedName = String.Concat(name, "Attribute");
fullyQualifiedName = String.Concat("NUnit.Framework.", name, "Attribute");
}
/// <summary>
/// Determines whether the specified attribute name is a
/// match to this attribute.
/// </summary>
public bool IsEqual(string attributeName)
{
if (nameComparer.Equals(attributeName, name) ||
nameComparer.Equals(attributeName, qualifiedName) ||
nameComparer.Equals(attributeName, fullyQualifiedName)) {
return true;
}
return false;
}
public bool IsEqual(IAttribute attribute)
{
return IsEqual(attribute.AttributeType.FullyQualifiedName);
}
}
}

382
src/AddIns/Analysis/UnitTesting/Src/TestClass.cs

@ -1,382 +0,0 @@ @@ -1,382 +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 System.Collections.Generic;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Represents a class that can be tested.
/// </summary>
public class TestClass
{
IClass c;
TestMemberCollection testMembers;
TestResultType testResultType;
IRegisteredTestFrameworks testFrameworks;
/// <summary>
/// Raised when the test class result is changed.
/// </summary>
public event EventHandler ResultChanged;
public TestClass(IClass c, IRegisteredTestFrameworks testFrameworks)
{
this.c = c;
this.testFrameworks = testFrameworks;
}
/// <summary>
/// Gets the underlying IClass for this test class.
/// </summary>
public IClass Class {
get { return c; }
}
/// <summary>
/// Gets the list of other (e.g. base types) classes where from which test members included in this test class come from.
/// </summary>
private readonly ICollection<string> baseClassesFQNames = new List<string>();
/// <summary>
/// Gets the test classes that exist in the specified namespace.
/// </summary>
public static TestClass[] GetTestClasses(ICollection<TestClass> classes, string ns)
{
List<TestClass> matchedClasses = new List<TestClass>();
foreach (TestClass c in classes) {
if (c.Namespace == ns) {
matchedClasses.Add(c);
}
}
return matchedClasses.ToArray();
}
/// <summary>
/// Gets the test classes that namespaces starts with the specified
/// string.
/// </summary>
public static TestClass[] GetAllTestClasses(ICollection<TestClass> classes, string namespaceStartsWith)
{
List<TestClass> matchedClasses = new List<TestClass>();
foreach (TestClass c in classes) {
if (c.Namespace.StartsWith(namespaceStartsWith)) {
matchedClasses.Add(c);
}
}
return matchedClasses.ToArray();
}
/// <summary>
/// Gets all child namespaces that starts with the specified string.
/// </summary>
/// <remarks>
/// If the starts with string is 'ICSharpCode' and there is a code coverage
/// method with a namespace of 'ICSharpCode.XmlEditor.Tests', then this
/// method will return 'XmlEditor' as one of its strings.
/// </remarks>
public static string[] GetChildNamespaces(ICollection<TestClass> classes, string parentNamespace) {
List<string> items = new List<string>();
foreach (TestClass c in classes) {
string ns = c.GetChildNamespace(parentNamespace);
if (ns.Length > 0) {
if (!items.Contains(ns)) {
items.Add(ns);
}
}
}
return items.ToArray();
}
/// <summary>
/// Gets the name of the class.
/// </summary>
public string Name {
get
{
var currentClass = c;
var name = c.Name;
while(currentClass.DeclaringType != null)
{
name = String.Concat(currentClass.DeclaringType.Name, "+", name);
currentClass = currentClass.DeclaringType;
}
return name;
}
}
/// <summary>
/// Gets the fully qualified name of the class.
/// </summary>
public string QualifiedName {
get { return c.DotNetName; }
}
/// <summary>
/// Gets the namespace of this class.
/// </summary>
public string Namespace {
get
{
var currentClass = c;
while (currentClass.DeclaringType != null)
currentClass = currentClass.DeclaringType;
return currentClass.Namespace;
}
}
/// <summary>
/// Gets the root namespace for this class.
/// </summary>
public string RootNamespace {
get { return GetRootNamespace(c.Namespace); }
}
/// <summary>
/// Gets the test result for this class.
/// </summary>
public TestResultType Result {
get { return testResultType; }
set {
TestResultType previousTestResultType = testResultType;
testResultType = value;
if (previousTestResultType != testResultType) {
OnResultChanged();
}
}
}
/// <summary>
/// Gets the child namespace from the specified namespace
/// based on the parent namespace.
/// </summary>
/// <param name="parentNamespace">Can contain multiple namespaces
/// (e.g. ICSharpCode.XmlEditor).</param>
public static string GetChildNamespace(string ns, string parentNamespace)
{
if (parentNamespace.Length > 0) {
if (ns.StartsWith(String.Concat(parentNamespace, "."))) {
string end = ns.Substring(parentNamespace.Length + 1);
return GetRootNamespace(end);
}
return String.Empty;
}
return ns;
}
/// <summary>
/// Gets the child namespace based on the parent namespace
/// from this class.
/// </summary>
/// <param name="parentNamespace">Can contain multiple namespaces
/// (e.g. ICSharpCode.XmlEditor).</param>
public string GetChildNamespace(string parentNamespace)
{
return GetChildNamespace(Namespace, parentNamespace);
}
/// <summary>
/// Gets the test members in this class.
/// </summary>
public TestMemberCollection TestMembers {
get {
if (testMembers == null) {
GetTestMembers();
}
return testMembers;
}
}
/// <summary>
/// Gets the test member with the specified name.
/// </summary>
/// <returns>Null if the member cannot be found.</returns>
public TestMember GetTestMember(string name)
{
if (TestMembers.Contains(name)) {
return TestMembers[name];
}
return null;
}
/// <summary>
/// Updates the test member with the specified test result.
/// </summary>
public void UpdateTestResult(TestResult testResult)
{
TestMember member = null;
string memberName = TestMember.GetMemberName(testResult.Name);
if (memberName != null) {
member = GetTestMember(memberName);
if (member == null) {
member = GetPrefixedTestMember(testResult.Name);
}
}
if (member != null) {
member.Result = testResult.ResultType;
}
}
/// <summary>
/// Resets all the test results back to none.
/// </summary>
public void ResetTestResults()
{
Result = TestResultType.None;
TestMembers.ResetTestResults();
}
/// <summary>
/// Updates the members and class based on the new class
/// information that has been parsed.
/// </summary>
public void UpdateClass(IClass c)
{
this.c = c.GetCompoundClass();
// Remove missing members.
TestMemberCollection newTestMembers = GetTestMembers(this.c);
TestMemberCollection existingTestMembers = TestMembers;
for (int i = existingTestMembers.Count - 1; i >= 0; --i) {
TestMember member = existingTestMembers[i];
if (newTestMembers.Contains(member.Name)) {
member.Update(newTestMembers[member.Name].Member);
} else {
existingTestMembers.RemoveAt(i);
}
}
// Add new members.
foreach (TestMember member in newTestMembers) {
if (existingTestMembers.Contains(member.Name)) {
} else {
existingTestMembers.Add(member);
}
}
}
/// <summary>
/// Gets the first dotted part of the namespace.
/// </summary>
static string GetRootNamespace(string ns)
{
int index = ns.IndexOf('.');
if (index > 0) {
return ns.Substring(0, index);
}
return ns;
}
/// <summary>
/// Gets the test members for the class.
/// </summary>
void GetTestMembers()
{
testMembers = GetTestMembers(c);
testMembers.ResultChanged += TestMembersResultChanged;
}
/// <summary>
/// Gets the test members for the specified class.
/// </summary>
TestMemberCollection GetTestMembers(IClass c)
{
TestMemberCollection testMembers = new TestMemberCollection();
foreach (var member in testFrameworks.GetTestMembersFor(c))
if (!testMembers.Contains(member.Name)) {
testMembers.Add(member);
}
// Add base class test members.
IClass declaringType = c;
while (c.BaseClass != null)
{
foreach (var testMember in testFrameworks.GetTestMembersFor(c.BaseClass)) {
BaseTestMember baseTestMethod = new BaseTestMember(declaringType, testMember.Member);
TestMember testMethod = new TestMember(c.BaseClass, baseTestMethod);
if (testMember.Member.IsVirtual) {
if (!testMembers.Contains(testMember.Name)) {
testMembers.Add(testMethod);
}
} else {
if (!testMembers.Contains(testMethod.Name)) {
testMembers.Add(testMethod);
}
}
}
c = c.BaseClass;
}
baseClassesFQNames.Clear();
foreach (var memberDeclaringClass in testMembers.Select(member => member.DeclaringType).Distinct())
if (memberDeclaringClass.CompareTo(declaringType) != 0)
baseClassesFQNames.Add(memberDeclaringClass.FullyQualifiedName);
return testMembers;
}
/// <summary>
/// Updates the test class's test result after the test member's
/// test result has changed.
/// </summary>
void TestMembersResultChanged(object source, EventArgs e)
{
Result = testMembers.Result;
}
/// <summary>
/// Raises the ResultChanged event.
/// </summary>
void OnResultChanged()
{
if (ResultChanged != null) {
ResultChanged(this, new EventArgs());
}
}
/// <summary>
/// This function adds the base class as a prefix and tries to find
/// the corresponding test member.
///
/// Actual method name:
///
/// RootNamespace.TestFixture.TestFixtureBaseClass.TestMethod
/// </summary>
/// <remarks>
/// NUnit 2.4 uses the correct test method name when a test
/// class uses a base class with test methods. It does
/// not prefix the test method name with the base class name
/// in the test results returned from nunit-console. It still
/// displays the name in the NUnit GUI with the base class
/// name prefixed. Older versions of NUnit-console (2.2.9) returned
/// the test result with the test method name as follows:
///
/// RootNamespace.TestFixture.BaseTestFixture.TestMethod
///
/// The test method name would have the base class name prefixed
/// to it.
/// </remarks>
TestMember GetPrefixedTestMember(string testResultName)
{
IClass baseClass = c.BaseClass;
while (baseClass != null) {
string memberName = TestMember.GetMemberName(testResultName);
string actualMemberName = String.Concat(baseClass.Name, ".", memberName);
TestMember member = GetTestMember(actualMemberName);
if (member != null) {
return member;
}
baseClass = baseClass.BaseClass;
}
return null;
}
public bool IsDerivedFrom(IClass c)
{
return baseClassesFQNames.Contains(c.FullyQualifiedName);
}
}
}

98
src/AddIns/Analysis/UnitTesting/Src/TestClassTreeNode.cs

@ -1,98 +0,0 @@ @@ -1,98 +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.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Represents a class that has the [TestFixture] attribute
/// associated with it.
/// </summary>
public class TestClassTreeNode : TestTreeNode
{
TestClass testClass;
public TestClassTreeNode(TestProject project, TestClass testClass)
: base(project, testClass.Name)
{
this.testClass = testClass;
testClass.ResultChanged += TestClassResultChanged;
Nodes.Add(new ExtTreeNode());
UpdateImageListIndex(testClass.Result);
}
/// <summary>
/// Gets the underlying IClass for this test class.
/// </summary>
public IClass Class {
get { return testClass.Class; }
}
public override void Dispose()
{
if (!IsDisposed) {
testClass.ResultChanged -= TestClassResultChanged;
testClass.TestMembers.TestMemberAdded -= TestMemberAdded;
testClass.TestMembers.TestMemberRemoved -= TestMemberRemoved;
}
base.Dispose();
}
protected override void Initialize()
{
Nodes.Clear();
foreach (TestMember member in testClass.TestMembers) {
AddTestMemberTreeNode(member);
}
testClass.TestMembers.TestMemberAdded += TestMemberAdded;
testClass.TestMembers.TestMemberRemoved += TestMemberRemoved;
}
/// <summary>
/// Adds a new TestMemberTreeNode to this node.
/// </summary>
void AddTestMemberTreeNode(TestMember member)
{
TestMemberTreeNode node = new TestMemberTreeNode(TestProject, member);
node.AddTo(this);
}
/// <summary>
/// Updates the node's icon based on the test class test result.
/// </summary>
void TestClassResultChanged(object source, EventArgs e)
{
UpdateImageListIndex(testClass.Result);
}
/// <summary>
/// Adds a new test member tree node to this class node after a new
/// TestMember has been added to the TestClass.
/// </summary>
void TestMemberAdded(object source, TestMemberEventArgs e)
{
AddTestMemberTreeNode(e.TestMember);
SortChildNodes();
}
/// <summary>
/// Removes the corresponding test member node after it has been
/// removed from the TestClass.
/// </summary>
void TestMemberRemoved(object source, TestMemberEventArgs e)
{
foreach (TestMemberTreeNode memberNode in Nodes) {
if (memberNode.Text == e.TestMember.Name) {
Nodes.Remove(memberNode);
memberNode.Dispose();
break;
}
}
}
}
}

24
src/AddIns/Analysis/UnitTesting/Src/TestFramework.cs

@ -1,24 +0,0 @@ @@ -1,24 +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.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
public interface ITestFramework
{
bool IsTestMember(IMember member);
bool IsTestClass(IClass c);
bool IsTestProject(IProject project);
IEnumerable<TestMember> GetTestMembersFor(IClass @class);
ITestRunner CreateTestRunner();
ITestRunner CreateTestDebugger();
bool IsBuildNeededBeforeTestRun { get; }
}
}

155
src/AddIns/Analysis/UnitTesting/Src/TestMember.cs

@ -1,155 +0,0 @@ @@ -1,155 +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.Dom;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Represents a member that can be tested.
/// </summary>
public class TestMember
{
#if unused
string prefix = String.Empty;
#endif
IMember member;
TestResultType testResultType = TestResultType.None;
/// <summary>
/// Raised when the test result has changed.
/// </summary>
public event EventHandler ResultChanged;
public TestMember(IMember member)
{
this.member = member;
this.DeclaringType = member.DeclaringType;
}
#if unused
/// <summary>
/// Creates a new TestMember instance.
/// </summary>
/// <param name="prefix">The prefix to be added to the
/// member name with a dot character. This is specified
/// when the test member refers to a base class method. NUnit
/// refers to base class test methods by prefixing the
/// class name to it:
///
/// [TestFixture]
/// public class DerivedClass : BaseClass
///
/// Test member name:
///
/// RootNamespace.DerivedClass.BaseClass.BaseClassMethod
/// </param>
public TestMember(string prefix, IMember member)
{
this.member = member;
this.prefix = prefix;
}
#endif
public TestMember(IClass testClass, IMember member)
{
this.DeclaringType = testClass;
this.member = member;
}
/// <summary>
/// Gets the underlying IMember for this TestMember.
/// </summary>
public IMember Member {
get { return member; }
}
/// <summary>
/// Gets the class where the test member is actually declared.
/// In case of test member from base class it will be the base class not the
/// </summary>
public IClass DeclaringType { get; private set; }
/// <summary>
/// Updates the test member based on new information
/// in the specified IMember.
/// </summary>
public void Update(IMember member)
{
this.member = member;
}
/// <summary>
/// Gets the test result for this member.
/// </summary>
public TestResultType Result {
get { return testResultType; }
set {
TestResultType previousTestResultType = testResultType;
testResultType = value;
if (previousTestResultType != testResultType) {
OnResultChanged();
}
}
}
/// <summary>
/// Gets the member's name.
/// </summary>
public string Name {
get {
#if unused
if (prefix.Length > 0) {
return String.Concat(prefix, ".", member.Name);
}
#endif
return member.Name;
}
}
/// <summary>
/// Returns the member name from a fully qualified name
/// of the form:
///
/// Namespace.Class.Member
/// </summary>
public static string GetMemberName(string qualifiedName)
{
if (qualifiedName != null) {
int index = qualifiedName.LastIndexOf('.');
if (index >= 0) {
return qualifiedName.Substring(index + 1);
}
}
return null;
}
/// <summary>
/// Returns the namespace and class name from a fully qualified
/// name of the form:
///
/// Namespace.Class.Member
/// </summary>
public static string GetQualifiedClassName(string qualifiedName)
{
if (qualifiedName != null) {
int memberIndex = qualifiedName.LastIndexOf('.');
if (memberIndex >= 0) {
return qualifiedName.Substring(0, memberIndex);
}
}
return null;
}
/// <summary>
/// Raises the ResultChanged event.
/// </summary>
void OnResultChanged()
{
if (ResultChanged != null) {
ResultChanged(this, new EventArgs());
}
}
}
}

53
src/AddIns/Analysis/UnitTesting/Src/TestMemberTreeNode.cs

@ -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 ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Represents a member that has the [Test] attribute associated with it.
/// </summary>
public class TestMemberTreeNode : TestTreeNode
{
TestMember testMember;
public TestMemberTreeNode(TestProject project, TestMember testMember)
: base(project, testMember.Name)
{
this.testMember = testMember;
testMember.ResultChanged += TestMemberResultChanged;
UpdateImageListIndex(testMember.Result);
}
/// <summary>
/// Gets the underlying IMember for this test member.
/// </summary>
public IMember Member {
get { return testMember.Member; }
}
/// <summary>
/// Removes the TestMember.ResultChanged event handler.
/// </summary>
public override void Dispose()
{
if (!IsDisposed) {
testMember.ResultChanged -= TestMemberResultChanged;
}
base.Dispose();
}
/// <summary>
/// Updates the node's icon after the test member result
/// has changed.
/// </summary>
void TestMemberResultChanged(object source, EventArgs e)
{
UpdateImageListIndex(testMember.Result);
}
}
}

337
src/AddIns/Analysis/UnitTesting/Src/TestNamespaceTreeNode.cs

@ -1,337 +0,0 @@ @@ -1,337 +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.Windows.Forms;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Represents a namespace in the TestTreeView.
/// </summary>
public class TestNamespaceTreeNode : TestTreeNode
{
string ns = String.Empty;
string namespacePrefix = String.Empty;
string fullNamespace;
TestClassCollection testClasses;
List<TestNamespaceTreeNode> namespaceChildNodes = new List<TestNamespaceTreeNode>();
ExtTreeNode dummyNode;
/// <summary>
/// Creates a new TestNamespaceTreeNode
/// </summary>
/// <remarks>
/// Note that the Namespace child nodes are added in
/// the constructor not whilst the node is expanding
/// via the Initialize method. This is so the icon for the
/// node can be updated even if the parent node is not
/// expanded. The alternative is to have each namespace node,
/// even if it does not have any class child nodes, to
/// store all the classes that are below it in the tree and
/// update the icon based on their results. The assumption
/// is that there are fewer namespace nodes than classes so
/// adding the namespace nodes here does not matter.
/// </remarks>
/// <param name="namespacePrefix">The first part of the
/// namespace (including any dot characters) before this
/// particular namespace.</param>
/// <param name="name">The name of the namespace without any
/// dot characters (e.g. the name at this particular
/// location in the tree).</param>
public TestNamespaceTreeNode(TestProject testProject, string namespacePrefix, string name)
: base(testProject, name)
{
ns = name;
this.namespacePrefix = namespacePrefix;
fullNamespace = GetFullNamespace(namespacePrefix, ns);
GetTestClasses();
testProject.TestClasses.TestClassAdded += TestClassAdded;
testProject.TestClasses.TestClassRemoved += TestClassRemoved;
// Add namespace nodes - do not add them on node expansion.
foreach (string namespaceName in TestProject.GetChildNamespaces(fullNamespace)) {
TestNamespaceTreeNode node = new TestNamespaceTreeNode(TestProject, fullNamespace, namespaceName);
node.AddTo(this);
namespaceChildNodes.Add(node);
node.ImageIndexChanged += TestNamespaceNodeImageIndexChanged;
}
// Add a dummy node if there are no namespaces since
// there might be class nodes which will be added
// lazily when the node is expanded.
if (namespaceChildNodes.Count == 0) {
dummyNode = new ExtTreeNode();
Nodes.Add(dummyNode);
}
UpdateImageListIndex();
}
/// <summary>
/// Creates a new TestNamespaceTreeNode with the specified
/// namespace name. This node will have no namespace prefix.
/// </summary>
public TestNamespaceTreeNode(TestProject testProject, string name)
: this(testProject, String.Empty, name)
{
}
/// <summary>
/// Frees any resources held by this class.
/// </summary>
public override void Dispose()
{
if (!IsDisposed) {
TestProject.TestClasses.TestClassAdded -= TestClassAdded;
TestProject.TestClasses.TestClassRemoved -= TestClassRemoved;
testClasses.ResultChanged -= TestClassesResultChanged;
}
base.Dispose();
}
/// <summary>
/// Gets whether this namespace node is considered empty. If
/// the node has been expanded then the node is empty if it
/// has no child nodes. If it has not been expanded then there
/// will be a dummy child node or a set of namespace
/// nodes but no test class nodes.
/// </summary>
public bool IsEmpty {
get {
if (isInitialized) {
return Nodes.Count == 0;
} else if (dummyNode != null) {
return testClasses.Count == 0;
} else {
return Nodes.Count == 0 && testClasses.Count == 0;
}
}
}
/// <summary>
/// Gets the full namespace of this tree node. This includes any
/// parent namespaces prefixed to the namespace associated
/// with this tree node.
/// </summary>
public string FullNamespace {
get {
return fullNamespace;
}
}
/// <summary>
/// Adds the test class nodes for this namespace when the
/// node is expanded.
/// </summary>
protected override void Initialize()
{
if (dummyNode != null) {
Nodes.Clear();
}
// Add class nodes for this namespace.
foreach (TestClass c in testClasses) {
TestClassTreeNode classNode = new TestClassTreeNode(TestProject, c);
classNode.AddTo(this);
}
// Sort the nodes.
SortChildNodes();
}
/// <summary>
/// Adds the child namespace to the namespace prefix.
/// </summary>
static string GetFullNamespace(string prefix, string name)
{
if (prefix.Length > 0) {
return String.Concat(prefix, ".", name);
}
return name;
}
/// <summary>
/// Updates this node's icon because one of its child namespace nodes
/// has changed.
/// </summary>
void TestNamespaceNodeImageIndexChanged(object source, EventArgs e)
{
UpdateImageListIndex();
}
/// <summary>
/// Gets the test classes for this namespace.
/// </summary>
void GetTestClasses()
{
testClasses = new TestClassCollection();
foreach (TestClass c in TestProject.GetTestClasses(fullNamespace)) {
testClasses.Add(c);
}
testClasses.ResultChanged += TestClassesResultChanged;
}
/// <summary>
/// The overall test result for the classes in this namespace
/// have changed so the node's icon is updated.
/// </summary>
void TestClassesResultChanged(object source, EventArgs e)
{
UpdateImageListIndex();
}
/// <summary>
/// Determines the image list index for this node based
/// on the current state of all the child nodes.
/// </summary>
/// <remarks>
/// Since the test classes overall test result is
/// available via the TestClassCollection we do not
/// need to sum all the individual test classes.
/// </remarks>
void UpdateImageListIndex()
{
int ignoredCount = 0;
int passedCount = 0;
int failedCount = 0;
// Count the passes, failures and ignores for the
// namespace child nodes.
foreach (ExtTreeNode node in namespaceChildNodes) {
switch (node.ImageIndex) {
case (int)TestTreeViewImageListIndex.TestFailed:
failedCount++;
break;
case (int)TestTreeViewImageListIndex.TestIgnored:
ignoredCount++;
break;
case (int)TestTreeViewImageListIndex.TestPassed:
passedCount++;
break;
}
}
// Check the passes, failures and ignores for the
// test classes that belong to this namespace.
switch (testClasses.Result) {
case TestResultType.Failure:
failedCount++;
break;
case TestResultType.Success:
passedCount++;
break;
case TestResultType.Ignored:
ignoredCount++;
break;
}
// Work out the total number of passes we are expecting
int total = namespaceChildNodes.Count;
if (testClasses.Count > 0) {
// Only add one for the testClasses since the
// overall pass or failure is indicated via
// the TestClassCollection so we do not need
// to add all the test classes.
total++;
}
// Determine the correct image list index for this node.
if (failedCount > 0) {
UpdateImageListIndex(TestResultType.Failure);
} else if (ignoredCount > 0) {
UpdateImageListIndex(TestResultType.Ignored);
} else if (passedCount == total) {
UpdateImageListIndex(TestResultType.Success);
} else {
UpdateImageListIndex(TestResultType.None);
}
}
/// <summary>
/// A new test class has been added to the project so a new
/// tree node is added if the class belongs to this namespace.
/// </summary>
void TestClassAdded(object source, TestClassEventArgs e)
{
if (e.TestClass.Namespace == fullNamespace) {
// Add test class to our monitored test classes.
testClasses.Add(e.TestClass);
// Add a new tree node.
TestClassTreeNode classNode = new TestClassTreeNode(TestProject, e.TestClass);
classNode.AddTo(this);
// Sort the nodes.
SortChildNodes();
} else if (isInitialized && NamespaceStartsWith(e.TestClass.Namespace)) {
// Check if there is a child namespace node for the class.
string childNamespace = TestClass.GetChildNamespace(e.TestClass.Namespace, fullNamespace);
if (!NamespaceNodeExists(childNamespace)) {
// Add a new namespace node.
TestNamespaceTreeNode node = new TestNamespaceTreeNode(TestProject, fullNamespace, childNamespace);
node.AddTo(this);
// Sort the nodes.
SortChildNodes();
}
}
}
/// <summary>
/// Determines whether the namespace for this node starts
/// with the namespace specified.
/// </summary>
bool NamespaceStartsWith(string ns)
{
return ns.StartsWith(String.Concat(fullNamespace, "."));
}
/// <summary>
/// A test class has been removed from the project so the
/// corresponding tree node is removed if it belongs to this
/// namespace.
/// </summary>
void TestClassRemoved(object source, TestClassEventArgs e)
{
if (e.TestClass.Namespace == fullNamespace) {
// Remove test class from our monitored test classes.
testClasses.Remove(e.TestClass);
// Remove the corresponding tree node.
foreach (ExtTreeNode node in Nodes) {
TestClassTreeNode classNode = node as TestClassTreeNode;
if (classNode != null && classNode.Text == e.TestClass.Name) {
classNode.Remove();
classNode.Dispose();
break;
}
}
// Remove this namespace node if there are no more child nodes.
RemoveIfEmpty();
}
}
/// <summary>
/// Removes this node if it has no child nodes. This
/// method also calls the same method on the parent
/// namespace node so it can check whether it should
/// remove itself.
/// </summary>
void RemoveIfEmpty()
{
if (IsEmpty) {
Remove();
Dispose();
TestNamespaceTreeNode parentNode = Parent as TestNamespaceTreeNode;
if (parentNode != null) {
parentNode.RemoveIfEmpty();
}
}
}
}
}

291
src/AddIns/Analysis/UnitTesting/Src/TestProject.cs

@ -1,291 +0,0 @@ @@ -1,291 +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.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Represents a project that has a reference to a unit testing
/// framework assembly. Currently only NUnit is supported.
/// </summary>
public class TestProject
{
IProject project;
IProjectContent projectContent;
TestClassCollection testClasses;
List<string> rootNamespaces;
IRegisteredTestFrameworks testFrameworks;
public TestProject(IProject project, IProjectContent projectContent, IRegisteredTestFrameworks testFrameworks)
{
this.project = project;
this.projectContent = projectContent;
this.testFrameworks = testFrameworks;
}
public IProject Project {
get { return project; }
}
/// <summary>
/// Gets the test classes in this project.
/// </summary>
public TestClassCollection TestClasses {
get {
if (testClasses == null) {
GetTestClasses();
}
return testClasses;
}
}
/// <summary>
/// Gets the test classes that exist in the specified namespace.
/// </summary>
public TestClass[] GetTestClasses(string ns)
{
return TestClass.GetTestClasses(TestClasses, ns);
}
/// <summary>
/// Gets the test classes whose namespaces start with the specified string.
/// </summary>
public TestClass[] GetAllTestClasses(string namespaceStartsWith)
{
return TestClass.GetAllTestClasses(TestClasses, namespaceStartsWith);
}
/// <summary>
/// Gets all the child namespaces with the specified parent
/// namespace. The parent namespace can be one or more
/// namespaces separated with a period.
/// </summary>
public string[] GetChildNamespaces(string parentNamespace)
{
return TestClass.GetChildNamespaces(TestClasses, parentNamespace);
}
/// <summary>
/// Gets the project's name.
/// </summary>
public string Name {
get { return project.Name; }
}
/// <summary>
/// Gets the distinct root namespaces for all this project.
/// </summary>
/// <remarks>
/// If one of the namespaces is 'ICSharpCode.XmlEditor' then this
/// method will return 'ICSharpCode' as one of the root namespaces.
/// </remarks>
public IList<string> RootNamespaces {
get {
if (rootNamespaces == null) {
GetRootNamespaces();
}
return rootNamespaces;
}
}
/// <summary>
/// Updates the test method based on the test result.
/// </summary>
public void UpdateTestResult(TestResult testResult)
{
TestClasses.UpdateTestResult(testResult);
}
/// <summary>
/// Sets all the test results back to none.
/// </summary>
public void ResetTestResults()
{
TestClasses.ResetTestResults();
}
/// <summary>
/// Updates the classes and methods based on the new parse information.
/// </summary>
/// <param name="oldUnit">The old compiliation unit
/// (ParseInformationEventArgs.ParseInformation.BestCompilationUnit as ICompilationUnit)</param>
/// <param name="newUnit">The new compilation unit
/// (ParseInformationEventArgs.CompilationUnit).</param>
public void UpdateParseInfo(ICompilationUnit oldUnit, ICompilationUnit newUnit)
{
if (!IsParseInfoForThisProject(oldUnit, newUnit)) {
return;
}
RemovedClasses removedClasses = new RemovedClasses();
if (oldUnit != null) {
removedClasses.Add(oldUnit.Classes);
}
if (newUnit != null) {
foreach (IClass c in newUnit.Classes) {
UpdateTestClass(c);
foreach (IClass innerClass in new InnerClassEnumerator(c)) {
UpdateTestClass(innerClass);
removedClasses.Remove(innerClass);
}
removedClasses.Remove(c);
}
}
// Remove missing classes.
foreach (IClass c in removedClasses.GetMissingClasses()) {
IClass existingClass = GetExistingTestClassInProject(c);
if (existingClass != null) {
UpdateTestClass(existingClass);
} else {
TestClasses.Remove(c.DotNetName);
}
}
}
/// <summary>
/// Determines whether the new parse information is for this test
/// project.
/// </summary>
public bool IsParseInfoForThisProject(ICompilationUnit oldUnit, ICompilationUnit newUnit)
{
ICompilationUnit unit = oldUnit;
if (unit == null) {
unit = newUnit;
}
if (unit != null) {
return Object.ReferenceEquals(unit.ProjectContent, this.projectContent);
}
return false;
}
/// <summary>
/// Adds a new class to the test project's classes only if
/// the class is a test class.
/// </summary>
void AddNewTestClass(IClass c)
{
if (IsTestClass(c)) {
TestClass testClass = CreateTestClass(c);
TestClasses.Add(testClass);
}
}
TestClass CreateTestClass(IClass c)
{
return new TestClass(c, testFrameworks);
}
/// <summary>
/// Updates the test class methods based on the newly parsed class
/// information.
/// </summary>
void UpdateTestClass(IClass c)
{
if (TestClasses.Contains(c.DotNetName))
{
if (IsTestClass(c))
{
TestClass testClass = TestClasses[c.DotNetName];
testClass.UpdateClass(c);
}
else
{
// TestFixture attribute has been removed so
// remove the class from the set of TestClasses.
TestClasses.Remove(c.DotNetName);
}
}
else
{
// TestFixture attribute may have been recently added to
// this class so call AddNewTestClass. No need to
// check if the class is actually a test class since
// AddNewTestClass does this anyway.
AddNewTestClass(c);
}
var derivedTestClasses = GetTestClassesDerivedFrom(c);
if (derivedTestClasses.Any())
UpdateClassesFromProjectContent(derivedTestClasses);
}
private IEnumerable<IClass> GetTestClassesDerivedFrom(IClass c)
{
return TestClasses
.Where(testClass => testClass.IsDerivedFrom(c))
.Select(testClass => testClass.Class)
.ToArray();
}
private void UpdateClassesFromProjectContent(IEnumerable<IClass> classes)
{
foreach (var c in classes)
{
var classInProjectContent = projectContent.GetClass(c.FullyQualifiedName, c.TypeParameters.Count);
if (classInProjectContent != null)
UpdateTestClass(classInProjectContent);
}
}
void GetTestClasses()
{
testClasses = new TestClassCollection();
foreach (IClass c in projectContent.Classes) {
if (IsTestClass(c)) {
if (!testClasses.Contains(c.FullyQualifiedName)) {
testClasses.Add(CreateTestClass(c));
}
}
foreach (IClass innerClass in new InnerClassEnumerator(c)) {
if (IsTestClass(innerClass)) {
if (!testClasses.Contains(innerClass.DotNetName)) {
testClasses.Add(CreateTestClass(innerClass));
}
}
}
}
}
bool IsTestClass(IClass c)
{
return testFrameworks.IsTestClass(c);
}
void GetRootNamespaces()
{
rootNamespaces = new List<string>();
foreach (TestClass c in TestClasses) {
string rootNamespace = c.RootNamespace;
if ((rootNamespace.Length > 0) && !rootNamespaces.Contains(rootNamespace)) {
rootNamespaces.Add(rootNamespace);
}
}
}
/// <summary>
/// Gets an existing test class with the same name in the project. This
/// method is used to check that we do not remove a class after an existing duplicate class name
/// is changed.
/// </summary>
IClass GetExistingTestClassInProject(IClass c)
{
foreach (IClass existingClass in projectContent.Classes) {
if (IsTestClass(existingClass)) {
if (existingClass.DotNetName == c.DotNetName) {
return existingClass;
}
}
}
return null;
}
}
}

113
src/AddIns/Analysis/UnitTesting/Src/TestProjectTreeNode.cs

@ -1,113 +0,0 @@ @@ -1,113 +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.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// The root tree node for a project that has tests.
/// </summary>
public class TestProjectTreeNode : TestTreeNode
{
public TestProjectTreeNode(TestProject project)
: base(project, project.Name)
{
Nodes.Add(new ExtTreeNode());
TestProject.TestClasses.ResultChanged += TestClassesResultChanged;
TestProject.TestClasses.TestClassAdded += TestClassAdded;
TestProject.TestClasses.TestClassRemoved += TestClassRemoved;
}
public override void Dispose()
{
if (!IsDisposed) {
TestProject.TestClasses.ResultChanged -= TestClassesResultChanged;
TestProject.TestClasses.TestClassAdded -= TestClassAdded;
TestProject.TestClasses.TestClassRemoved -= TestClassRemoved;
}
base.Dispose();
}
/// <summary>
/// Adds the child nodes after this node has been expanded.
/// </summary>
protected override void Initialize()
{
Nodes.Clear();
// Add namespace nodes.
foreach (string rootNamespace in TestProject.RootNamespaces) {
TestNamespaceTreeNode node = new TestNamespaceTreeNode(TestProject, rootNamespace);
node.AddTo(this);
}
// Add class nodes.
foreach (TestClass c in TestProject.GetTestClasses(String.Empty)) {
AddClassNode(c);
}
// Sort the nodes.
SortChildNodes();
}
/// <summary>
/// Updates this node's icon based on the overall result of the
/// test classes.
/// </summary>
void TestClassesResultChanged(object source, EventArgs e)
{
UpdateImageListIndex(TestProject.TestClasses.Result);
}
/// <summary>
/// Adds a new class node to this project node if the
/// class added has no root namespace.
/// </summary>
void TestClassAdded(object source, TestClassEventArgs e)
{
if (e.TestClass.Namespace == String.Empty) {
AddClassNode(e.TestClass);
SortChildNodes();
} else if (isInitialized) {
// Check that we have a namespace node for this class.
if (!NamespaceNodeExists(e.TestClass.RootNamespace)) {
// Add a new namespace node.
TestNamespaceTreeNode node = new TestNamespaceTreeNode(TestProject, e.TestClass.RootNamespace);
node.AddTo(this);
SortChildNodes();
}
}
}
/// <summary>
/// Removes the corresponding tree node that is a child of
/// this project tree node if the class has no root namespace.
/// </summary>
void TestClassRemoved(object source, TestClassEventArgs e)
{
if (e.TestClass.Namespace == String.Empty) {
foreach (ExtTreeNode node in Nodes) {
TestClassTreeNode classNode = node as TestClassTreeNode;
if (classNode != null && classNode.Text == e.TestClass.Name) {
classNode.Remove();
classNode.Dispose();
break;
}
}
}
}
/// <summary>
/// Adds a new TestClassTreeNode to this node.
/// </summary>
void AddClassNode(TestClass c)
{
TestClassTreeNode node = new TestClassTreeNode(TestProject, c);
node.AddTo(this);
}
}
}

92
src/AddIns/Analysis/UnitTesting/Src/TestResult.cs

@ -1,92 +0,0 @@ @@ -1,92 +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.Dom;
namespace ICSharpCode.UnitTesting
{
public enum TestResultType {
/// <summary>
/// The test has not been run.
/// </summary>
None = 0,
/// <summary>
/// The test passed.
/// </summary>
Success = 1,
/// <summary>
/// The test failed.
/// </summary>
Failure = 2,
/// <summary>
/// The test was ignored.
/// </summary>
Ignored = 3
}
/// <summary>
/// Holds the information about a single test result.
/// </summary>
public class TestResult
{
string name = String.Empty;
string message = String.Empty;
string stackTrace = String.Empty;
TestResultType resultType = TestResultType.None;
FilePosition stackTraceFilePosition = FilePosition.Empty;
public TestResult(string name)
{
this.name = name;
}
public string Name {
get { return name; }
}
public bool IsSuccess {
get { return resultType == TestResultType.Success; }
}
public bool IsFailure {
get { return resultType == TestResultType.Failure; }
}
public bool IsIgnored {
get { return resultType == TestResultType.Ignored; }
}
public TestResultType ResultType {
get { return resultType; }
set { resultType = value; }
}
public string Message {
get { return message; }
set { message = value; }
}
public string StackTrace {
get { return stackTrace; }
set {
if (stackTrace != value) {
stackTrace = value;
OnStackTraceChanged();
}
}
}
protected virtual void OnStackTraceChanged()
{
}
public FilePosition StackTraceFilePosition {
get { return stackTraceFilePosition; }
set { stackTraceFilePosition = value; }
}
}
}

97
src/AddIns/Analysis/UnitTesting/Src/TestResultTask.cs

@ -1,97 +0,0 @@ @@ -1,97 +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.IO;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.UnitTesting
{
public class TestResultTask
{
TestResultTask()
{
}
public static Task Create(TestResult result, TestProject project)
{
TaskType taskType = TaskType.Warning;
FileLineReference lineRef = null;
string message = String.Empty;
if (result.IsFailure) {
taskType = TaskType.Error;
if (!result.StackTraceFilePosition.IsEmpty) {
lineRef = new FileLineReference(result.StackTraceFilePosition.FileName, result.StackTraceFilePosition.Line - 1, result.StackTraceFilePosition.Column - 1);
}
message = GetTestFailedMessage(result);
} else if (result.IsIgnored) {
message = GetTestIgnoredMessage(result);
}
if (lineRef == null) {
lineRef = FindTest(result.Name, project);
}
FileName fileName = null;
if (lineRef != null) {
fileName = new FileName(Path.GetFullPath(lineRef.FileName));
int line = lineRef.Line + 1;
return new Task(fileName, message, lineRef.Column, line, taskType);
}
return new Task(fileName, message, 0, 0, taskType);
}
static string GetTestFailedMessage(TestResult result)
{
string resource = "${res:NUnitPad.NUnitPadContent.TestTreeView.TestFailedMessage}";
return GetTestResultMessage(result, resource);
}
static string GetTestIgnoredMessage(TestResult result)
{
string resource = "${res:NUnitPad.NUnitPadContent.TestTreeView.TestNotExecutedMessage}";
return GetTestResultMessage(result, resource);
}
/// <summary>
/// Returns the test result message if there is on otherwise
/// uses the string resource to create a message.
/// </summary>
static string GetTestResultMessage(TestResult result, string stringResource)
{
if (result.Message.Length > 0) {
return result.Message;
}
return GetTestResultMessageFromResource(result, stringResource);
}
static string GetTestResultMessageFromResource(TestResult result, string stringResource)
{
return StringParser.Parse(stringResource, new StringTagPair("TestCase", result.Name));
}
/// <summary>
/// Returns the location of the specified test member in the
/// project being tested.
/// </summary>
static FileLineReference FindTest(string memberName, TestProject testProject)
{
if (testProject != null) {
TestMember testMember = testProject.TestClasses.GetTestMember(memberName);
if (testMember != null) {
return FindTest(testMember);
}
}
return null;
}
static FileLineReference FindTest(TestMember testMember)
{
MemberResolveResult resolveResult = new MemberResolveResult(null, null, testMember.Member);
FilePosition filePos = resolveResult.GetDefinitionPosition();
return new FileLineReference(filePos.FileName, filePos.Line - 1, filePos.Column - 1);
}
}
}

102
src/AddIns/Analysis/UnitTesting/Src/TestTreeNode.cs

@ -1,102 +0,0 @@ @@ -1,102 +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.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Base class for all test tree nodes.
/// </summary>
public abstract class TestTreeNode : ExtTreeNode
{
TestProject testProject;
public event EventHandler ImageIndexChanged;
public TestTreeNode(TestProject testProject, string text)
{
this.testProject = testProject;
this.Text = text;
ImageIndex = (int)TestTreeViewImageListIndex.TestNotRun;
}
public IProject Project {
get {
return testProject.Project;
}
}
public TestProject TestProject {
get {
return testProject;
}
}
/// <summary>
/// Changes the node's icon based on the specified test result.
/// </summary>
protected void UpdateImageListIndex(TestResultType result)
{
int previousImageIndex = ImageIndex;
switch (result) {
case TestResultType.Failure:
ImageIndex = (int)TestTreeViewImageListIndex.TestFailed;
break;
case TestResultType.Success:
ImageIndex = (int)TestTreeViewImageListIndex.TestPassed;
break;
case TestResultType.Ignored:
ImageIndex = (int)TestTreeViewImageListIndex.TestIgnored;
break;
case TestResultType.None:
ImageIndex = (int)TestTreeViewImageListIndex.TestNotRun;
break;
}
SelectedImageIndex = ImageIndex;
if (previousImageIndex != ImageIndex) {
OnImageIndexChanged();
}
}
/// <summary>
/// Raises the ImageIndexChanged event.
/// </summary>
protected void OnImageIndexChanged()
{
if (ImageIndexChanged != null) {
ImageIndexChanged(this, new EventArgs());
}
}
/// <summary>
/// Checks all the child nodes of this node to see
/// if the root namespace (i.e. the first part of the
/// namespace) exists in the tree.
/// </summary>
/// <param name="rootNamespace">The first dotted part
/// of the namespace.</param>
protected bool NamespaceNodeExists(string rootNamespace)
{
foreach (ExtTreeNode node in Nodes) {
TestNamespaceTreeNode namespaceNode = node as TestNamespaceTreeNode;
if (namespaceNode != null && namespaceNode.Text == rootNamespace) {
return true;
}
}
return false;
}
/// <summary>
/// Sorts the immediate child nodes of this node. The sort
/// is not done recursively.
/// </summary>
protected void SortChildNodes()
{
ExtTreeView treeView = (ExtTreeView)TreeView;
treeView.SortNodes(Nodes, false);
}
}
}

435
src/AddIns/Analysis/UnitTesting/Src/TestTreeView.cs

@ -1,435 +0,0 @@ @@ -1,435 +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.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Tree view that shows all the unit tests in a project.
/// </summary>
public class TestTreeView : ExtTreeView, ITestTreeView, IOwnerState
{
/// <summary>
/// The current state of the tree view.
/// </summary>
[Flags]
public enum TestTreeViewState {
None = 0,
SourceCodeItemSelected = 1
}
/// <summary>
/// The All Tests tree root node that is added if multiple
/// test projects exist in the solution. If the solution contains
/// only one test project then no such node will be added.
/// </summary>
AllTestsTreeNode allTestsNode;
IRegisteredTestFrameworks testFrameworks;
public TestTreeView(IRegisteredTestFrameworks testFrameworks)
{
this.testFrameworks = testFrameworks;
ImageList = TestTreeViewImageList.ImageList;
CanClearSelection = false;
}
/// <summary>
/// Gets the current state of the test tree view.
/// </summary>
public Enum InternalState {
get {
TestTreeNode selectedNode = SelectedNode as TestTreeNode;
if ((selectedNode is TestClassTreeNode) || (selectedNode is TestMemberTreeNode)) {
return TestTreeViewState.SourceCodeItemSelected;
}
return TestTreeViewState.None;
}
}
/// <summary>
/// Adds the solution's projects to the test tree view.
/// Only test projects are displayed.
/// </summary>
public void AddSolution(Solution solution)
{
Clear();
AddProjects(solution.Projects);
}
/// <summary>
/// Adds the projects to the test tree view. Only those projects
/// which are determined to have a reference to a supported
/// test framework will be added to the tree.
/// </summary>
public void AddProjects(IEnumerable<IProject> projects)
{
foreach (IProject project in projects) {
AddProject(project);
}
}
/// <summary>
/// Adds the project to the test tree view if the project
/// is a test project.
/// </summary>
/// <remarks>
/// If the project is already in the tree then it will
/// not be added again. If a project is already in the tree then
/// an All Tests root node will be added.
/// </remarks>
public void AddProject(IProject project)
{
if (IsTestProject(project)) {
if (GetProjectTreeNode(project) == null) {
AddProjectTreeNode(project);
}
}
}
bool IsTestProject(IProject project)
{
return testFrameworks.IsTestProject(project);
}
void AddProjectTreeNode(IProject project)
{
TestProjectTreeNode node = CreateProjectTreeNode(project);
if (node != null) {
AddProjectTreeNodeToTree(node);
SortNodes(Nodes, true);
}
}
TestProjectTreeNode CreateProjectTreeNode(IProject project)
{
IProjectContent projectContent = GetProjectContent(project);
if (projectContent != null) {
TestProject testProject = new TestProject(project, projectContent, testFrameworks);
return new TestProjectTreeNode(testProject);
}
return null;
}
void AddProjectTreeNodeToTree(TestProjectTreeNode node)
{
if (Nodes.Count == 0) {
node.AddTo(this);
} else {
AllTestsTreeNode allTestsNode = GetAllTestsNode();
allTestsNode.AddProjectNode(node);
}
}
public void RemoveSolutionFolder(ISolutionFolder solutionFolder)
{
IProject project = solutionFolder as IProject;
if (project != null) {
RemoveProject(project);
}
ISolutionFolderContainer solutionFolderContainer = solutionFolder as ISolutionFolderContainer;
if (solutionFolderContainer != null) {
foreach (ISolutionFolder subSolutionFolder in solutionFolderContainer.Folders) {
RemoveSolutionFolder(subSolutionFolder);
}
}
}
/// <summary>
/// Removes the specified project from the test tree view.
/// </summary>
public void RemoveProject(IProject project)
{
TestProjectTreeNode projectNode = GetProjectTreeNode(project);
RemoveProjectNode(projectNode);
RemoveAllTestsNodeIfOnlyOneProjectLeft();
}
void RemoveAllTestsNodeIfOnlyOneProjectLeft()
{
if (allTestsNode != null) {
if (GetProjectNodes().Count == 1) {
RemoveAllTestsNode();
}
}
}
/// <summary>
/// Gets the projects displayed in the tree.
/// </summary>
public IProject[] GetProjects()
{
List<IProject> projects = new List<IProject>();
foreach (TestProjectTreeNode projectNode in GetProjectNodes()) {
projects.Add(projectNode.Project);
}
return projects.ToArray();
}
/// <summary>
/// Returns the TestProject associated with the specified project.
/// </summary>
public TestProject GetTestProject(IProject project)
{
TestProjectTreeNode node = GetProjectTreeNode(project);
if (node != null) {
return node.TestProject;
}
return null;
}
/// <summary>
/// Gets the member of the currently selected tree node.
/// </summary>
public IMember SelectedMember {
get {
TestMemberTreeNode memberNode = SelectedNode as TestMemberTreeNode;
if (memberNode != null) {
return memberNode.Member;
}
return null;
}
}
/// <summary>
/// Gets the class of the currently selected tree node.
/// </summary>
public IClass SelectedClass {
get {
TestClassTreeNode classNode = SelectedNode as TestClassTreeNode;
if (classNode == null) {
classNode = GetClassNodeFromSelectedMemberNode();
}
if (classNode != null) {
return classNode.Class;
}
return null;
}
}
TestClassTreeNode GetClassNodeFromSelectedMemberNode()
{
TestMemberTreeNode memberNode = SelectedNode as TestMemberTreeNode;
if (memberNode != null) {
return memberNode.Parent as TestClassTreeNode;
}
return null;
}
/// <summary>
/// Gets the project associated with the currently selected
/// tree node.
/// </summary>
public IProject SelectedProject {
get {
TestProject testProject = SelectedTestProject;
if (testProject != null) {
return testProject.Project;
}
return null;
}
}
/// <summary>
/// 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.
/// </summary>
public string SelectedNamespace {
get {
TestNamespaceTreeNode selectedNode = SelectedNode as TestNamespaceTreeNode;
if (selectedNode != null) {
return selectedNode.FullNamespace;
}
return null;
}
}
/// <summary>
/// Gets the selected test project.
/// </summary>
public TestProject SelectedTestProject {
get {
TestTreeNode selectedNode = SelectedNode as TestTreeNode;
if (selectedNode != null) {
return selectedNode.TestProject;
}
return null;
}
}
/// <summary>
/// Updates the classes and members in the test tree view based on the
/// parse information.
/// </summary>
public void UpdateParseInfo(ICompilationUnit oldUnit, ICompilationUnit newUnit)
{
foreach (TestProjectTreeNode projectNode in GetProjectNodes()) {
TestProject testProject = projectNode.TestProject;
testProject.UpdateParseInfo(oldUnit, newUnit);
}
}
/// <summary>
/// Resets the test results for all the projects in the
/// test tree view.
/// </summary>
public void ResetTestResults()
{
foreach (TestProjectTreeNode projectNode in GetProjectNodes()) {
TestProject testProject = projectNode.TestProject;
testProject.ResetTestResults();
}
}
/// <summary>
/// Returns the project content for the specified project.
/// </summary>
public virtual IProjectContent GetProjectContent(IProject project)
{
return ParserService.GetProjectContent(project);
}
/// <summary>
/// A tree node has been selected. Here we make sure the tree node
/// uses the context menu strip that the tree view is using. This
/// ensures that if the user brings up the context menu using a keyboard
/// shortcut (Shift+F10) then it appears over the node rather than in
/// the middle of the Unit Tests window.
/// </summary>
protected override void OnBeforeSelect(TreeViewCancelEventArgs e)
{
TreeNode node = e.Node;
if (node.ContextMenuStrip == null) {
node.ContextMenuStrip = ContextMenuStrip;
}
}
/// <summary>
/// Returns the project tree node that is associated with the
/// specified project.
/// </summary>
TestProjectTreeNode GetProjectTreeNode(IProject project)
{
foreach (TestProjectTreeNode projectNode in GetProjectNodes()) {
if (Object.ReferenceEquals(projectNode.Project, project)) {
return projectNode;
}
}
return null;
}
/// <summary>
/// Returns the test project tree nodes taking into account
/// if the All Tests root node exists.
/// </summary>
TreeNodeCollection GetProjectNodes()
{
if (allTestsNode != null) {
return allTestsNode.Nodes;
}
return Nodes;
}
/// <summary>
/// Removes the project node from the tree.
/// </summary>
void RemoveProjectNode(TestProjectTreeNode projectNode)
{
if (projectNode != null) {
if (allTestsNode != null) {
allTestsNode.RemoveProjectNode(projectNode);
} else {
projectNode.Remove();
}
}
}
/// <summary>
/// Gets the All Tests root node which is added if the tree is
/// showing multiple test projects. The All Tests root node will
/// be added if it does not exist.
/// </summary>
AllTestsTreeNode GetAllTestsNode()
{
if (allTestsNode == null) {
AddAllTestsNode();
}
return allTestsNode;
}
/// <summary>
/// Adds a new All Tests root node.
/// </summary>
void AddAllTestsNode()
{
// Save existing nodes (should only be one) before
// clearing so we can add these to the new All Tests node.
TreeNode[] projectNodes = new TreeNode[Nodes.Count];
Nodes.CopyTo(projectNodes, 0);
Nodes.Clear();
allTestsNode = new AllTestsTreeNode();
allTestsNode.Disposed += AllTestsNodeDisposed;
Nodes.Add(allTestsNode);
// Add the original project nodes to the new
// All Tests node.
foreach (TestProjectTreeNode node in projectNodes) {
allTestsNode.AddProjectNode(node);
}
}
/// <summary>
/// Removes the all tests node.
/// </summary>
void RemoveAllTestsNode()
{
allTestsNode.Remove();
// Copy project nodes to the root.
foreach (TestTreeNode node in allTestsNode.Nodes) {
Nodes.Add(node);
}
AllTestsNodeDisposed(null, null);
}
/// <summary>
/// Ensures that if the TreeView's Clear member is called
/// directly the test tree does not think there is still
/// an All Tests node.
/// </summary>
void AllTestsNodeDisposed(object source, EventArgs e)
{
allTestsNode.Disposed -= AllTestsNodeDisposed;
allTestsNode = null;
}
/// <summary>
/// Adds the test project to the test tree view if it is now recognised as a
/// test project and is not already in the test tree.
/// </summary>
public void ProjectItemAdded(ProjectItem projectItem)
{
AddProject(projectItem.Project);
}
public void ProjectItemRemoved(ProjectItem projectItem)
{
if (!testFrameworks.IsTestProject(projectItem.Project)) {
RemoveProject(projectItem.Project);
}
}
}
}

55
src/AddIns/Analysis/UnitTesting/Src/TestTreeViewImageList.cs

@ -1,55 +0,0 @@ @@ -1,55 +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.Drawing;
using System.Reflection;
using System.Windows.Forms;
using ICSharpCode.Core;
namespace ICSharpCode.UnitTesting
{
public enum TestTreeViewImageListIndex
{
TestNotRun = 0,
TestPassed = 1,
TestFailed = 2,
TestIgnored = 3
}
public class TestTreeViewImageList
{
static ImageList imageList;
TestTreeViewImageList()
{
}
public static ImageList ImageList {
get {
if (imageList == null) {
GetImageList();
}
return imageList;
}
}
static void GetImageList()
{
imageList = new ImageList();
imageList.ColorDepth = ColorDepth.Depth32Bit;
AddBitmap("Grey.png");
AddBitmap("Green.png");
AddBitmap("Red.png");
AddBitmap("Yellow.png");
}
static void AddBitmap(string name)
{
string resourceName = String.Concat("ICSharpCode.UnitTesting.Resources.", name);
Assembly assembly = typeof(TestTreeViewImageList).Assembly;
imageList.Images.Add(new Bitmap(assembly.GetManifestResourceStream(resourceName)));
}
}
}

123
src/AddIns/Analysis/UnitTesting/Src/TestableCondition.cs

@ -1,123 +0,0 @@ @@ -1,123 +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.Bookmarks;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui.ClassBrowser;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Supplies a "Unit test" menu item if the class is a test fixture.
/// </summary>
public class TestableCondition : IConditionEvaluator
{
IRegisteredTestFrameworks testFrameworks;
public TestableCondition(IRegisteredTestFrameworks testFrameworks)
{
this.testFrameworks = testFrameworks;
}
public TestableCondition()
: this(TestService.RegisteredTestFrameworks)
{
}
public static IMember GetMember(object caller)
{
ITestTreeView testTreeView = caller as ITestTreeView;
if (testTreeView != null) {
return testTreeView.SelectedMember;
}
MemberNode memberNode = caller as MemberNode;
if (memberNode != null) {
return memberNode.Member;
} else {
ClassMemberBookmark mbookmark = caller as ClassMemberBookmark;
if (mbookmark != null) {
return mbookmark.Member;
}
}
return null;
}
public static IClass GetClass(object caller)
{
ITestTreeView testTreeView = caller as ITestTreeView;
if (testTreeView != null) {
return testTreeView.SelectedClass;
}
ClassNode classNode = caller as ClassNode;
if (classNode != null) {
return classNode.Class;
} else {
ClassBookmark bookmark = caller as ClassBookmark;
if (bookmark != null) {
return bookmark.Class;
}
}
return null;
}
public static IProject GetProject(object caller)
{
ITestTreeView testTreeView = caller as ITestTreeView;
if (testTreeView != null) {
return testTreeView.SelectedProject;
}
IClass c = GetClassFromMemberOrCaller(caller);
return GetProject(c);
}
static IClass GetClassFromMemberOrCaller(object caller)
{
IMember m = GetMember(caller);
if (m != null) {
return m.DeclaringType;
}
return GetClass(caller);
}
static IProject GetProject(IClass c)
{
if (c != null) {
return (IProject)c.ProjectContent.Project;
}
return null;
}
/// <summary>
/// Returns the namespace selected if any.
/// </summary>
public static string GetNamespace(object caller)
{
ITestTreeView testTreeView = caller as ITestTreeView;
if (testTreeView != null) {
return testTreeView.SelectedNamespace;
}
return null;
}
public bool IsValid(object caller, Condition condition)
{
IMember m = GetMember(caller);
if (m != null) {
return testFrameworks.IsTestMember(m);
}
IClass c = GetClass(caller);
if (ClassHasProject(c)) {
return testFrameworks.IsTestClass(c);
}
return false;
}
static bool ClassHasProject(IClass c)
{
return (c != null) && (c.ProjectContent.Project != null);
}
}
}

119
src/AddIns/Analysis/UnitTesting/Src/UnitTestCommands.cs

@ -1,119 +0,0 @@ @@ -1,119 +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.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
public class StopTestsCommand : AbstractMenuCommand
{
public override void Run()
{
AbstractRunTestCommand runTestCommand = AbstractRunTestCommand.RunningTestCommand;
if (runTestCommand != null) {
runTestCommand.Stop();
}
}
}
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
{
IUnitTestFileService fileService;
public GotoDefinitionCommand()
: this(new UnitTestFileService())
{
}
public GotoDefinitionCommand(IUnitTestFileService fileService)
{
this.fileService = fileService;
}
public override void Run()
{
ITestTreeView treeView = Owner as ITestTreeView;
if (treeView != null) {
IMember member = GetMember(treeView);
IClass c = treeView.SelectedClass;
if (member != null) {
GotoMember(member);
} else if (c != null) {
GotoClass(c);
}
}
}
IMember GetMember(ITestTreeView treeView)
{
IMember member = treeView.SelectedMember;
if (member != null) {
BaseTestMember baseTestMethod = member as BaseTestMember;
if (baseTestMethod != null) {
return baseTestMethod.Member;
}
}
return member;
}
void GotoMember(IMember member)
{
MemberResolveResult resolveResult = new MemberResolveResult(null, null, member);
GotoFilePosition(resolveResult.GetDefinitionPosition());
}
void GotoClass(IClass c)
{
TypeResolveResult resolveResult = new TypeResolveResult(null, null, c);
GotoFilePosition(resolveResult.GetDefinitionPosition());
}
void GotoFilePosition(FilePosition filePosition)
{
if (filePosition.Position.IsEmpty) {
fileService.OpenFile(filePosition.FileName);
} else {
fileService.JumpToFilePosition(filePosition.FileName, filePosition.Line - 1, filePosition.Column - 1);
}
}
}
public class CollapseAllTestsCommand : AbstractMenuCommand
{
public override void Run()
{
if (!(this.Owner is TreeView))
return;
var treeView = (TreeView)this.Owner;
treeView.CollapseAll();
if (treeView.Nodes.Count > 0) {
treeView.Nodes[0].Expand();
}
}
}
}

40
src/AddIns/Analysis/UnitTesting/Src/UnitTestTaskService.cs

@ -1,40 +0,0 @@ @@ -1,40 +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 UnitTestTaskService : IUnitTestTaskService
{
public void ClearExceptCommentTasks()
{
TaskService.ClearExceptCommentTasks();
}
public bool InUpdate {
get { return TaskService.InUpdate; }
set { TaskService.InUpdate = value; }
}
public MessageViewCategory BuildMessageViewCategory {
get { return TaskService.BuildMessageViewCategory; }
}
public void Add(Task task)
{
TaskService.Add(task);
}
public bool SomethingWentWrong {
get { return TaskService.SomethingWentWrong; }
}
public bool HasCriticalErrors(bool treatWarningsAsErrors)
{
return TaskService.HasCriticalErrors(treatWarningsAsErrors);
}
}
}

106
src/AddIns/Analysis/UnitTesting/Src/UnitTestingOptions.cs

@ -1,106 +0,0 @@ @@ -1,106 +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 UnitTestingOptions
{
/// <summary>
/// The name of the options as read from the PropertyService.
/// </summary>
public static readonly string AddInOptionsName = "UnitTesting.Options";
/// <summary>
/// The name of the noshadow property stored in SharpDevelop's options.
/// </summary>
public static readonly string NoShadowProperty = "NoShadow";
/// <summary>
/// The name of the nothread property stored in SharpDevelop's options.
/// </summary>
public static readonly string NoThreadProperty = "NoThread";
/// <summary>
/// The name of the nologo property stored in SharpDevelop's options.
/// </summary>
public static readonly string NoLogoProperty = "NoLogo";
/// <summary>
/// The name of the nodots property stored in SharpDevelop's options.
/// </summary>
public static readonly string NoDotsProperty = "NoDots";
/// <summary>
/// The name of the labels property stored in SharpDevelop's options.
/// </summary>
public static readonly string LabelsProperty = "Labels";
/// <summary>
/// The name of the create xml file property stored in SharpDevelop's options.
/// </summary>
public static readonly string CreateXmlOutputFileProperty = "CreateXmlOutputFile";
Properties properties;
public UnitTestingOptions()
: this(PropertyService.Get(AddInOptionsName, new Properties()))
{
}
public UnitTestingOptions(Properties properties)
{
this.properties = properties;
}
/// <summary>
/// Disables the use of a separate thread for running tests.
/// </summary>
public bool NoThread {
get { return properties.Get<bool>(NoThreadProperty, false); }
set { properties.Set<bool>(NoThreadProperty, value); }
}
/// <summary>
/// Disables shadow copying of the assemblies being tested.
/// </summary>
public bool NoShadow {
get { return properties.Get<bool>(NoShadowProperty, false); }
set { properties.Set<bool>(NoShadowProperty, value); }
}
/// <summary>
/// Disables the display of the NUnit logo when running NUnit-Console.
/// </summary>
public bool NoLogo {
get { return properties.Get<bool>(NoLogoProperty, false); }
set { properties.Set<bool>(NoLogoProperty, value); }
}
/// <summary>
/// Disables the display of progress when running the unit tests.
/// </summary>
public bool NoDots {
get { return properties.Get<bool>(NoDotsProperty, false); }
set { properties.Set<bool>(NoDotsProperty, value); }
}
/// <summary>
/// Labels each test in the console output.
/// </summary>
public bool Labels {
get { return properties.Get<bool>(LabelsProperty, false); }
set { properties.Set<bool>(LabelsProperty, value); }
}
/// <summary>
/// Creates an XML output file.
/// </summary>
public bool CreateXmlOutputFile {
get { return properties.Get<bool>(CreateXmlOutputFileProperty, false); }
set { properties.Set<bool>(CreateXmlOutputFileProperty, value); }
}
}
}

77
src/AddIns/Analysis/UnitTesting/Src/UnitTestingOptionsPanel.cs

@ -1,77 +0,0 @@ @@ -1,77 +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 ICSharpCode.SharpDevelop.Gui.OptionPanels;
using System;
using System.Drawing;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.UnitTesting
{
public class UnitTestingOptionsPanel : XmlFormsOptionPanel
{
UnitTestingOptions options;
CheckBox labelsCheckBox;
CheckBox showLogoCheckBox;
CheckBox showProgressCheckBox;
CheckBox threadCheckBox;
CheckBox shadowCopyCheckBox;
CheckBox createXmlOutputFileCheckBox;
public UnitTestingOptionsPanel() : this(new UnitTestingOptions())
{
}
public UnitTestingOptionsPanel(UnitTestingOptions options)
{
this.options = options;
}
public override void LoadPanelContents()
{
SetupFromManifestResource("ICSharpCode.UnitTesting.Resources.UnitTestingOptionsPanel.xfrm");
labelsCheckBox = (CheckBox)ControlDictionary["labelsCheckBox"];
labelsCheckBox.Checked = options.Labels;
showLogoCheckBox = (CheckBox)ControlDictionary["showLogoCheckBox"];
showLogoCheckBox.Checked = !options.NoLogo;
showProgressCheckBox = (CheckBox)ControlDictionary["showProgressCheckBox"];
showProgressCheckBox.Checked = !options.NoDots;
shadowCopyCheckBox = (CheckBox)ControlDictionary["shadowCopyCheckBox"];
shadowCopyCheckBox.Checked = !options.NoShadow;
threadCheckBox = (CheckBox)ControlDictionary["threadCheckBox"];
threadCheckBox.Checked = !options.NoThread;
createXmlOutputFileCheckBox = (CheckBox)ControlDictionary["createXmlOutputFileCheckBox"];
createXmlOutputFileCheckBox.Checked = options.CreateXmlOutputFile;
}
public override bool StorePanelContents()
{
options.Labels = labelsCheckBox.Checked;
options.NoLogo = !showLogoCheckBox.Checked;
options.NoDots = !showProgressCheckBox.Checked;
options.NoShadow = !shadowCopyCheckBox.Checked;
options.NoThread = !threadCheckBox.Checked;
options.CreateXmlOutputFile = createXmlOutputFileCheckBox.Checked;
return true;
}
/// <summary>
/// Calls SetupFromXmlStream after creating a stream from the current
/// assembly using the specified manifest resource name.
/// </summary>
/// <param name="resource">The manifest resource name used to create the stream.</param>
protected virtual void SetupFromManifestResource(string resource)
{
SetupFromXmlStream(typeof(UnitTestingOptionsPanel).Assembly.GetManifestResourceStream(resource));
}
}
}

332
src/AddIns/Analysis/UnitTesting/Src/UnitTestsPad.cs

@ -1,332 +0,0 @@ @@ -1,332 +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.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.UnitTesting
{
public class UnitTestsPad : AbstractPadContent, IUnitTestsPad
{
TestTreeView treeView;
bool disposed;
Panel panel;
ToolStrip toolStrip;
List<ICompilationUnit[]> pending = new List<ICompilationUnit[]>();
static UnitTestsPad instance;
public UnitTestsPad()
: this(TestService.RegisteredTestFrameworks)
{
}
public UnitTestsPad(IRegisteredTestFrameworks testFrameworks)
{
instance = this;
panel = new Panel();
treeView = CreateTestTreeView(testFrameworks);
treeView.Dock = DockStyle.Fill;
treeView.DoubleClick += TestTreeViewDoubleClick;
treeView.KeyPress += TestTreeViewKeyPress;
panel.Controls.Add(treeView);
toolStrip = CreateToolStrip("/SharpDevelop/Pads/UnitTestsPad/Toolbar");
toolStrip.GripStyle = ToolStripGripStyle.Hidden;
panel.Controls.Add(toolStrip);
// Add the load solution projects thread ended handler before
// we try to display the open solution so the event does not
// get missed.
ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEnded;
OnAddedLoadSolutionProjectsThreadEndedHandler();
// Display currently open solution.
if (!IsParserLoadingSolution) {
Solution openSolution = GetOpenSolution();
if (openSolution != null) {
SolutionLoaded(openSolution);
}
}
ParserService.ParseInformationUpdated += ParseInformationUpdated;
ProjectService.SolutionClosed += SolutionClosed;
ProjectService.SolutionFolderRemoved += SolutionFolderRemoved;
ProjectService.ProjectAdded += ProjectAdded;
ProjectService.ProjectItemAdded += ProjectItemAdded;
ProjectService.ProjectItemRemoved += ProjectItemRemoved;
treeView.ContextMenuStrip = CreateContextMenu("/SharpDevelop/Pads/UnitTestsPad/ContextMenu");
}
public static UnitTestsPad Instance {
get { return instance; }
}
public override object Control {
get { return panel; }
}
public override void Dispose()
{
if (!disposed) {
disposed = true;
treeView.Dispose();
treeView = null;
ProjectService.ProjectItemRemoved -= ProjectItemRemoved;
ProjectService.ProjectItemAdded -= ProjectItemAdded;
ProjectService.ProjectAdded -= ProjectAdded;
ProjectService.SolutionFolderRemoved -= SolutionFolderRemoved;
ProjectService.SolutionClosed -= SolutionClosed;
ParserService.ParseInformationUpdated -= ParseInformationUpdated;
ParserService.LoadSolutionProjectsThreadEnded -= LoadSolutionProjectsThreadEnded;
}
}
public TestTreeView TestTreeView {
get { return treeView; }
}
public void ResetTestResults()
{
treeView.ResetTestResults();
}
public IProject[] GetProjects()
{
return treeView.GetProjects();
}
public TestProject GetTestProject(IProject project)
{
return treeView.GetTestProject(project);
}
/// <summary>
/// Updates the state of the buttons on the Unit Tests pad's
/// toolbar.
/// </summary>
public void UpdateToolbar()
{
ToolbarService.UpdateToolbar(toolStrip);
}
/// <summary>
/// Collapses all nodes.
/// </summary>
public void CollapseAll()
{
if (treeView == null || treeView.Nodes == null || treeView.Nodes.Count == 0)
return;
treeView.CollapseAll();
}
/// <summary>
/// Called when a solution has been loaded.
/// </summary>
protected void SolutionLoaded(Solution solution)
{
// SolutionLoaded will be invoked from another thread.
// The UnitTestsPad might be disposed by the time the event is processed by the main thread.
if (treeView != null) {
if (solution != null) {
treeView.AddSolution(solution);
} else {
treeView.Clear();
}
}
}
/// <summary>
/// Called when a solution has been closed.
/// </summary>
protected void SolutionClosed()
{
treeView.Clear();
}
protected void SolutionFolderRemoved(ISolutionFolder solutionFolder)
{
treeView.RemoveSolutionFolder(solutionFolder);
}
/// <summary>
/// The project is added to the tree view only if it has a
/// reference to a unit testing framework.
/// </summary>
protected void ProjectAdded(IProject project)
{
treeView.AddProject(project);
}
/// <summary>
/// If the project item removed is a reference to a unit
/// test framework then the project will be removed from the
/// test tree.
/// </summary>
protected void ProjectItemRemoved(ProjectItem projectItem)
{
treeView.ProjectItemRemoved(projectItem);
}
protected void ProjectItemAdded(ProjectItem projectItem)
{
treeView.ProjectItemAdded(projectItem);
}
/// <summary>
/// Protected method so we can test this method.
/// </summary>
protected void UpdateParseInfo(ICompilationUnit oldUnit, ICompilationUnit newUnit)
{
treeView.UpdateParseInfo(oldUnit, newUnit);
}
/// <summary>
/// Virtual method so we can override this method and return
/// a dummy toolstrip when testing.
/// </summary>
protected virtual ToolStrip CreateToolStrip(string name)
{
return ToolbarService.CreateToolStrip(treeView, name);
}
/// <summary>
/// Virtual method so we can override this method and return
/// a dummy ContextMenuStrip when testing.
/// </summary>
protected virtual ContextMenuStrip CreateContextMenu(string name)
{
return MenuService.CreateContextMenu(treeView, name);
}
/// <summary>
/// Virtual method so we can override this method and return
/// a dummy TestTreeView when testing.
/// </summary>
protected virtual TestTreeView CreateTestTreeView(IRegisteredTestFrameworks testFrameworks)
{
return new TestTreeView(testFrameworks);
}
/// <summary>
/// Gets the currently open solution.
/// </summary>
protected virtual Solution GetOpenSolution()
{
return ProjectService.OpenSolution;
}
/// <summary>
/// Determines whether the parser is currently still loading the
/// solution.
/// </summary>
protected virtual bool IsParserLoadingSolution {
get { return ParserService.LoadSolutionProjectsThreadRunning; }
}
/// <summary>
/// Indicates that an event handler for the ParserService's
/// LoadSolutionProjectsThreadEnded event has been added
/// </summary>
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)
{
ProjectAdded(e.Project);
UpdateToolbar();
}
void LoadSolutionProjectsThreadEnded(object source, EventArgs e)
{
WorkbenchSingleton.SafeThreadAsyncCall(UpdateToolbar);
Solution solution = ProjectService.OpenSolution;
WorkbenchSingleton.SafeThreadAsyncCall(SolutionLoaded, solution);
}
void ParseInformationUpdated(object source, ParseInformationEventArgs e)
{
lock (pending) {
ICompilationUnit[] units = new ICompilationUnit[] {e.OldCompilationUnit, e.NewCompilationUnit};
pending.Add(units);
}
WorkbenchSingleton.SafeThreadAsyncCall(UpdateParseInfo);
}
void UpdateParseInfo()
{
lock (pending) {
foreach (ICompilationUnit[] units in pending) {
UpdateParseInfo(units[0], units[1]);
}
pending.Clear();
}
}
void TestTreeViewDoubleClick(object source, EventArgs e)
{
GotoDefinition();
}
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);
}
}
}

208
src/AddIns/Analysis/UnitTesting/UnitTesting.csproj

@ -36,12 +36,18 @@ @@ -36,12 +36,18 @@
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\..\..\bin\Tools\NUnit\nunit.framework.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="PresentationCore">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="nunit.util">
<HintPath>..\..\..\Tools\NUnit\lib\nunit.util.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
@ -57,113 +63,94 @@ @@ -57,113 +63,94 @@
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Src\IFileSystem.cs" />
<Compile Include="Src\InnerClassEnumerator.cs" />
<Compile Include="Src\IUnitTestMessageService.cs" />
<Compile Include="Src\MultipleProjectBuildable.cs" />
<Compile Include="Src\TestMemberEventArgs.cs" />
<Compile Include="Src\TestProcessRunnerBaseContext.cs" />
<Compile Include="Src\UnitTestAddInTree.cs" />
<Compile Include="Src\UnitTestBuildOptions.cs" />
<Compile Include="Src\UnitTestBuildProjectFactory.cs" />
<Compile Include="Src\UnitTestDebuggerService.cs" />
<Compile Include="Src\UnitTestFileService.cs" />
<Compile Include="Src\UnitTestMessageService.cs" />
<Compile Include="Src\UnitTestProcessRunner.cs" />
<Compile Include="Src\UnitTestSaveAllFilesCommand.cs" />
<Compile Include="Src\UnitTestTaskService.cs" />
<Compile Include="Src\UnitTestWorkbench.cs" />
<Compile Include="Commands\AbstractRunTestCommand.cs" />
<Compile Include="Gui\EmptyUnitTestsPad.cs" />
<Compile Include="Gui\UnitTestingOptionsPanel.xaml.cs">
<DependentUpon>UnitTestingOptionsPanel.xaml</DependentUpon>
</Compile>
<Compile Include="Gui\UnitTestsPad.cs" />
<Compile Include="Implementation\UnitTestAddInTree.cs" />
<Compile Include="Implementation\UnitTestBuildOptions.cs" />
<Compile Include="Implementation\UnitTestBuildProjectFactory.cs" />
<Compile Include="Implementation\UnitTestDebuggerService.cs" />
<Compile Include="Implementation\UnitTestFileService.cs" />
<Compile Include="Implementation\UnitTestSaveAllFilesCommand.cs" />
<Compile Include="Implementation\UnitTestTaskService.cs" />
<Compile Include="Implementation\UnitTestWorkbench.cs" />
<Compile Include="Interfaces\IAddInTree.cs" />
<Compile Include="Interfaces\IBuildOptions.cs" />
<Compile Include="Interfaces\IBuildProjectFactory.cs" />
<Compile Include="Interfaces\IFileSystem.cs" />
<Compile Include="Interfaces\IRegisteredTestFrameworks.cs" />
<Compile Include="Interfaces\IRunTestCommandContext.cs" />
<Compile Include="Interfaces\ITestFramework.cs" />
<Compile Include="Interfaces\ITestFrameworkFactory.cs" />
<Compile Include="Interfaces\ITestResultsMonitor.cs" />
<Compile Include="Interfaces\ITestRunner.cs" />
<Compile Include="Interfaces\ITestTreeView.cs" />
<Compile Include="Interfaces\IUnitTestDebuggerService.cs" />
<Compile Include="Interfaces\IUnitTestFileService.cs" />
<Compile Include="Interfaces\IUnitTestProcessRunner.cs" />
<Compile Include="Interfaces\IUnitTestSaveAllFilesCommand.cs" />
<Compile Include="Interfaces\IUnitTestsPad.cs" />
<Compile Include="Interfaces\IUnitTestTaskService.cs" />
<Compile Include="Interfaces\IUnitTestWorkbench.cs" />
<Compile Include="MultipleProjectBuildable.cs" />
<Compile Include="Nodes\ProjectUnitTestNode.cs" />
<Compile Include="Nodes\RootUnitTestNode.cs" />
<Compile Include="Nodes\UnitTestBaseNode.cs" />
<Compile Include="Resources\Images.cs" />
<Compile Include="RunTestCommandContext.cs" />
<Compile Include="Service\MessageReceivedEventArgs.cs" />
<Compile Include="Service\RegisteredTestFrameworks.cs" />
<Compile Include="Service\RunningTestsCondition.cs" />
<Compile Include="Service\SelectedTests.cs" />
<Compile Include="Service\TestClass.cs" />
<Compile Include="Service\TestFinishedEventArgs.cs" />
<Compile Include="Service\TestFrameworkDescriptor.cs" />
<Compile Include="Service\TestFrameworkDoozer.cs" />
<Compile Include="Service\TestFrameworkFactory.cs" />
<Compile Include="Service\TestProject.cs" />
<Compile Include="Service\TestResult.cs" />
<Compile Include="Service\TestRunnerBase.cs" />
<Compile Include="Service\TestService.cs" />
<Compile Include="TestResultTask.cs" />
<Compile Include="UnitTestingOptions.cs" />
<None Include="PostBuildEvent.proj" />
<EmbeddedResource Include="Resources\UnitTestingOptionsPanel.xfrm" />
<None Include="UnitTesting.addin">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<Compile Include="Src\AllTestsTreeNode.cs" />
<Compile Include="Src\BaseTestMember.cs" />
<Compile Include="Src\EmptyUnitTestsPad.cs" />
<Compile Include="Src\IAddInTree.cs" />
<Compile Include="Src\IBuildOptions.cs" />
<Compile Include="Src\IBuildProjectFactory.cs" />
<Compile Include="Src\IRegisteredTestFrameworks.cs" />
<Compile Include="Src\IRunTestCommandContext.cs" />
<Compile Include="Src\ITestFrameworkFactory.cs" />
<Compile Include="Src\ITestResultsMonitor.cs" />
<Compile Include="Src\ITestRunner.cs" />
<Compile Include="Src\IUnitTestDebuggerService.cs" />
<Compile Include="Src\IUnitTestFileService.cs" />
<Compile Include="Src\IUnitTestProcessRunner.cs" />
<Compile Include="Src\IUnitTestSaveAllFilesCommand.cs" />
<Compile Include="Src\IUnitTestsPad.cs" />
<Compile Include="Src\IUnitTestTaskService.cs" />
<Compile Include="Src\IUnitTestWorkbench.cs" />
<Compile Include="Src\MessageReceivedEventArgs.cs" />
<Compile Include="Src\NUnitTestDebugger.cs" />
<Compile Include="Src\NUnitTestFramework.cs" />
<Compile Include="Src\NUnitTestResult.cs" />
<Compile Include="Src\NUnitTestRunner.cs" />
<Compile Include="Src\RegisteredTestFrameworks.cs" />
<Compile Include="Src\RemovedClasses.cs" />
<Compile Include="Src\RunAllTestsInPadCommand.cs" />
<Compile Include="Src\RunProjectTestsInPadCommand.cs" />
<Compile Include="Src\RunTestCommandContext.cs" />
<Compile Include="Src\RunTestInPadCommand.cs" />
<Compile Include="Src\RunTestWithDebuggerCommand.cs" />
<Compile Include="Src\SelectedTests.cs" />
<Compile Include="Src\TestDebuggerBase.cs" />
<Compile Include="Src\TestFramework.cs" />
<Compile Include="Src\TestFrameworkDescriptor.cs" />
<Compile Include="Src\TestFrameworkDoozer.cs" />
<Compile Include="Src\TestFrameworkFactory.cs" />
<Compile Include="Src\TestProcessRunnerBase.cs" />
<Compile Include="Src\TestResultTask.cs" />
<Compile Include="Src\TestRunnerBase.cs" />
<Compile Include="Src\TestService.cs" />
<Compile Include="Src\UnitTestCommands.cs" />
<Compile Include="Src\TestableCondition.cs" />
<Compile Include="Src\RunningTestsCondition.cs" />
<Compile Include="Src\TestTreeView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Src\NUnitConsoleCommandLine.cs" />
<Compile Include="Src\AbstractRunTestCommand.cs" />
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Configuration\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Src\TestProject.cs" />
<Compile Include="Src\ITestTreeView.cs" />
<Compile Include="Src\TestClass.cs" />
<Compile Include="Src\TestMember.cs" />
<Compile Include="Src\TestAttributeName.cs" />
<Compile Include="Src\TestTreeNode.cs" />
<Compile Include="Src\TestTreeViewImageList.cs" />
<Compile Include="Src\TestProjectTreeNode.cs" />
<Compile Include="Src\TestNamespaceTreeNode.cs" />
<Compile Include="Src\TestClassTreeNode.cs" />
<Compile Include="Src\TestMemberTreeNode.cs" />
<Compile Include="Src\UnitTestingOptions.cs" />
<Compile Include="Src\UnitTestingOptionsPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Src\UnitTestsPad.cs" />
<EmbeddedResource Include="Resources\Red.png" />
<EmbeddedResource Include="Resources\Green.png" />
<EmbeddedResource Include="Resources\Yellow.png" />
<EmbeddedResource Include="Resources\Grey.png" />
<Compile Include="Src\TestResultsReader.cs" />
<Compile Include="Src\TestResult.cs" />
<Compile Include="Src\TestResultsMonitor.cs" />
<Compile Include="Src\TestFinishedEventArgs.cs" />
<Compile Include="Src\TestClassCollection.cs" />
<Compile Include="Src\TestMemberCollection.cs" />
<Compile Include="Src\TestClassEventArgs.cs" />
<Resource Include="Resources\Red.png" />
<Resource Include="Resources\Green.png" />
<Resource Include="Resources\Yellow.png" />
<Resource Include="Resources\Grey.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\NRefactory\Project\NRefactory.csproj">
<Project>{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}</Project>
<Name>NRefactory</Name>
<ProjectReference Include="..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Libraries\SharpTreeView\ICSharpCode.TreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Name>ICSharpCode.TreeView</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj">
@ -176,17 +163,28 @@ @@ -176,17 +163,28 @@
<Name>ICSharpCode.Core</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Main\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj">
<Project>{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}</Project>
<Name>ICSharpCode.Core.WinForms</Name>
<ProjectReference Include="..\..\..\Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj">
<Project>{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}</Project>
<Name>ICSharpCode.Core.Presentation</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Main\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj">
<Project>{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}</Project>
<Name>ICSharpCode.SharpDevelop.Dom</Name>
<ProjectReference Include="..\..\..\Main\ICSharpCode.SharpDevelop.Widgets\Project\ICSharpCode.SharpDevelop.Widgets.csproj">
<Project>{8035765F-D51F-4A0C-A746-2FD100E19419}</Project>
<Name>ICSharpCode.SharpDevelop.Widgets</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Commands" />
<Folder Include="Gui" />
<Folder Include="Implementation" />
<Folder Include="Interfaces" />
<Folder Include="Service" />
<Folder Include="Nodes" />
</ItemGroup>
<ItemGroup>
<Page Include="Gui\UnitTestingOptionsPanel.xaml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<Import Project="PostBuildEvent.proj" />
</Project>

18
src/Main/ICSharpCode.Core.Presentation/OptionBinding.cs

@ -3,9 +3,11 @@ @@ -3,9 +3,11 @@
using System;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace ICSharpCode.Core.Presentation
@ -15,7 +17,7 @@ namespace ICSharpCode.Core.Presentation @@ -15,7 +17,7 @@ namespace ICSharpCode.Core.Presentation
/// </summary>
/// <remarks>
/// Properties accessed by this binding have to be managed by a custom
/// settings class, which contains all settings as static properties or fields,
/// settings class, which contains all settings as static properties or fields,
/// or is a singleton class with the standard 'Instance' property.<br />
/// Do not use PropertyService directly!<br />
/// This markup extension can only be used in OptionPanels or other <br />containers implementing IOptionBindingContainer!
@ -42,6 +44,10 @@ namespace ICSharpCode.Core.Presentation @@ -42,6 +44,10 @@ namespace ICSharpCode.Core.Presentation
}
}
public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public CultureInfo ConverterCulture { get; set; }
static readonly Regex regex = new Regex("^.+\\:.+\\..+$", RegexOptions.Compiled);
DependencyObject target;
@ -137,8 +143,14 @@ namespace ICSharpCode.Core.Presentation @@ -137,8 +143,14 @@ namespace ICSharpCode.Core.Presentation
throw new ArgumentException("Type " + type.FullName + " has no 'Instance' property. Only singletons can be used with OptionBinding.");
}
object ConvertOnDemand(object result, Type returnType)
object ConvertOnDemand(object result, Type returnType, bool convertBack = false)
{
if (Converter != null) {
if (convertBack)
result = Converter.ConvertBack(result, returnType, ConverterParameter, ConverterCulture ?? CultureInfo.CurrentCulture);
else
result = Converter.Convert(result, returnType, ConverterParameter, ConverterCulture ?? CultureInfo.CurrentCulture);
}
if (returnType.IsInstanceOfType(result) || returnType == typeof(object))
return result;
@ -180,7 +192,7 @@ namespace ICSharpCode.Core.Presentation @@ -180,7 +192,7 @@ namespace ICSharpCode.Core.Presentation
if (returnType == null)
return false;
value = ConvertOnDemand(value, returnType);
value = ConvertOnDemand(value, returnType, true);
object instance = isStatic ? null : FetchInstance(propertyDeclaringType);
if (propertyInfo is PropertyInfo) {

Loading…
Cancel
Save