Browse Source

fix some bugs in test run handling and complete support for TestCase

newNRvisualizers
Siegfried Pammer 13 years ago
parent
commit
9a14ac1e52
  1. 2
      SharpDevelop.sln
  2. 0
      src/AddIns/Analysis/UnitTesting/Commands/RunProjectTestsInPadCommand.cs
  3. 2
      src/AddIns/Analysis/UnitTesting/Commands/RunTestCommands.cs
  4. 51
      src/AddIns/Analysis/UnitTesting/Commands/UnitTestCommands.cs
  5. 6
      src/AddIns/Analysis/UnitTesting/Extensions.cs
  6. 32
      src/AddIns/Analysis/UnitTesting/Gui/UnitTestsPad.cs
  7. 1
      src/AddIns/Analysis/UnitTesting/Interfaces/IRegisteredTestFrameworks.cs
  8. 1
      src/AddIns/Analysis/UnitTesting/Interfaces/ITestFramework.cs
  9. 2
      src/AddIns/Analysis/UnitTesting/Interfaces/ITestTreeView.cs
  10. 30
      src/AddIns/Analysis/UnitTesting/Model/TestClass.cs
  11. 23
      src/AddIns/Analysis/UnitTesting/Model/TestMember.cs
  12. 4
      src/AddIns/Analysis/UnitTesting/Model/TestProject.cs
  13. 9
      src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestFramework.cs
  14. 2
      src/AddIns/Analysis/UnitTesting/Nodes/ClassUnitTestNode.cs
  15. 1
      src/AddIns/Analysis/UnitTesting/Nodes/MemberUnitTestNode.cs
  16. 19
      src/AddIns/Analysis/UnitTesting/Nodes/NamespaceUnitTestNode.cs
  17. 4
      src/AddIns/Analysis/UnitTesting/Nodes/ProjectUnitTestNode.cs
  18. 9
      src/AddIns/Analysis/UnitTesting/Service/RegisteredTestFrameworks.cs
  19. 24
      src/AddIns/Analysis/UnitTesting/Service/TestResult.cs
  20. 5
      src/AddIns/Analysis/UnitTesting/Service/TestService.cs
  21. 4
      src/AddIns/Analysis/UnitTesting/Service/TestableCondition.cs
  22. 341
      src/AddIns/Analysis/UnitTesting/TestTreeView.cs
  23. 2
      src/AddIns/Analysis/UnitTesting/UnitTesting.csproj

2
SharpDevelop.sln

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
# SharpDevelop 4.2.0.8774-RC
# SharpDevelop 4.2.0.8783
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{256F5C28-532C-44C0-8AB8-D8EC5E492E01}"
ProjectSection(SolutionItems) = postProject
EndProjectSection

0
src/AddIns/Analysis/UnitTesting/RunProjectTestsInPadCommand.cs → src/AddIns/Analysis/UnitTesting/Commands/RunProjectTestsInPadCommand.cs

2
src/AddIns/Analysis/UnitTesting/Commands/RunTestCommands.cs

@ -527,7 +527,7 @@ namespace ICSharpCode.UnitTesting @@ -527,7 +527,7 @@ namespace ICSharpCode.UnitTesting
base.Run();
}
public IMethod SelectedMethod {
public TestMember SelectedMethod {
get { return null; }
}

51
src/AddIns/Analysis/UnitTesting/UnitTestCommands.cs → src/AddIns/Analysis/UnitTesting/Commands/UnitTestCommands.cs

@ -7,6 +7,7 @@ using ICSharpCode.NRefactory.TypeSystem; @@ -7,6 +7,7 @@ using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.TreeView;
namespace ICSharpCode.UnitTesting
{
@ -40,14 +41,14 @@ namespace ICSharpCode.UnitTesting @@ -40,14 +41,14 @@ namespace ICSharpCode.UnitTesting
public class GotoDefinitionCommand : AbstractMenuCommand
{
IUnitTestFileService fileService;
IFileService fileService;
public GotoDefinitionCommand()
: this(new UnitTestFileService())
: this(SD.FileService)
{
}
public GotoDefinitionCommand(IUnitTestFileService fileService)
public GotoDefinitionCommand(IFileService fileService)
{
this.fileService = fileService;
}
@ -56,46 +57,32 @@ namespace ICSharpCode.UnitTesting @@ -56,46 +57,32 @@ namespace ICSharpCode.UnitTesting
{
ITestTreeView treeView = Owner as ITestTreeView;
if (treeView != null) {
IMember member = GetMember(treeView);
IClass c = treeView.SelectedClass;
if (member != null) {
GotoMember(member);
IMethod method = treeView.SelectedMethod.Resolve();
ITypeDefinition c = treeView.SelectedClass;
if (method != null) {
GotoMember(method);
} 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());
GotoFilePosition(member.Region);
}
void GotoClass(IClass c)
void GotoClass(ITypeDefinition c)
{
TypeResolveResult resolveResult = new TypeResolveResult(null, null, c);
GotoFilePosition(resolveResult.GetDefinitionPosition());
GotoFilePosition(c.Region);
}
void GotoFilePosition(DomRegion filePosition)
{
if (filePosition.Position.IsEmpty) {
fileService.OpenFile(filePosition.FileName);
if (filePosition.IsEmpty) {
fileService.OpenFile(new FileName(filePosition.FileName));
} else {
fileService.JumpToFilePosition(filePosition.FileName, filePosition.Line - 1, filePosition.Column - 1);
fileService.JumpToFilePosition(new FileName(filePosition.FileName), filePosition.BeginLine, filePosition.BeginColumn);
}
}
}
@ -104,14 +91,14 @@ namespace ICSharpCode.UnitTesting @@ -104,14 +91,14 @@ namespace ICSharpCode.UnitTesting
{
public override void Run()
{
if (!(this.Owner is TreeView))
if (!(this.Owner is SharpTreeView))
return;
var treeView = (TreeView)this.Owner;
treeView.CollapseAll();
var treeView = (SharpTreeView)this.Owner;
NRefactory.Utils.TreeTraversal.PreOrder(treeView.Root, n => n.Children).ForEach(n => n.IsExpanded = false);
if (treeView.Nodes.Count > 0) {
treeView.Nodes[0].Expand();
if (treeView.Root.Children.Count > 0) {
treeView.Root.IsExpanded = true;
}
}
}

6
src/AddIns/Analysis/UnitTesting/Extensions.cs

@ -51,18 +51,18 @@ namespace ICSharpCode.UnitTesting @@ -51,18 +51,18 @@ namespace ICSharpCode.UnitTesting
list.Insert(index, item);
}
public static void UpdateTestClasses(this IList<TestClass> testClasses, IRegisteredTestFrameworks testFrameworks, IReadOnlyList<ITypeDefinition> oldTypes, IReadOnlyList<ITypeDefinition> newTypes, TestClass parent)
public static void UpdateTestClasses(this IList<TestClass> testClasses, IRegisteredTestFrameworks testFrameworks, IReadOnlyList<ITypeDefinition> oldTypes, IReadOnlyList<ITypeDefinition> newTypes, TestClass parent, TestProject project)
{
var mappings = oldTypes.FullOuterJoin(newTypes, t => t.ReflectionName, t => t.ReflectionName, Tuple.Create);
foreach (Tuple<ITypeDefinition, ITypeDefinition> mapping in mappings) {
if (mapping.Item2 == null)
testClasses.RemoveWhere(c => c.FullName == mapping.Item1.ReflectionName);
else if (mapping.Item1 == null)
testClasses.Add(new TestClass(testFrameworks, mapping.Item2.ReflectionName, mapping.Item2, parent));
testClasses.Add(new TestClass(project, testFrameworks, mapping.Item2.ReflectionName, mapping.Item2, parent));
else {
var testClass = testClasses.SingleOrDefault(c => c.FullName == mapping.Item1.ReflectionName);
if (testClass == null)
testClasses.Add(new TestClass(testFrameworks, mapping.Item2.ReflectionName, mapping.Item2, parent));
testClasses.Add(new TestClass(project, testFrameworks, mapping.Item2.ReflectionName, mapping.Item2, parent));
else
testClass.UpdateClass(mapping.Item2);
}

32
src/AddIns/Analysis/UnitTesting/Gui/UnitTestsPad.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.UnitTesting @@ -20,7 +20,7 @@ namespace ICSharpCode.UnitTesting
{
public class UnitTestsPad : AbstractPadContent
{
SharpTreeView treeView;
TestTreeView treeView;
bool disposed;
DockPanel panel;
ToolBar toolBar;
@ -42,9 +42,7 @@ namespace ICSharpCode.UnitTesting @@ -42,9 +42,7 @@ namespace ICSharpCode.UnitTesting
panel.Children.Add(toolBar);
DockPanel.SetDock(toolBar, Dock.Top);
treeView = new SharpTreeView();
treeView.MouseDoubleClick += TestTreeViewDoubleClick;
// treeView.KeyDown += TestTreeViewKeyPress;
treeView = new TestTreeView(testFrameworks);
panel.Children.Add(treeView);
// Add the load solution projects thread ended handler before
@ -55,7 +53,6 @@ namespace ICSharpCode.UnitTesting @@ -55,7 +53,6 @@ namespace ICSharpCode.UnitTesting
treeView.Root = new RootUnitTestNode();
SD.ParserService.ParseInformationUpdated += ParseInformationUpdated;
ProjectService.SolutionClosed += SolutionClosed;
ProjectService.SolutionFolderRemoved += SolutionFolderRemoved;
ProjectService.ProjectAdded += ProjectAdded;
@ -83,7 +80,6 @@ namespace ICSharpCode.UnitTesting @@ -83,7 +80,6 @@ namespace ICSharpCode.UnitTesting
ProjectService.ProjectAdded -= ProjectAdded;
ProjectService.SolutionFolderRemoved -= SolutionFolderRemoved;
ProjectService.SolutionClosed -= SolutionClosed;
SD.ParserService.ParseInformationUpdated -= ParseInformationUpdated;
SD.ParserService.LoadSolutionProjectsThread.Finished -= LoadSolutionProjectsThreadFinished;
}
}
@ -250,30 +246,6 @@ namespace ICSharpCode.UnitTesting @@ -250,30 +246,6 @@ namespace ICSharpCode.UnitTesting
// WorkbenchSingleton.SafeThreadAsyncCall(SolutionLoaded, solution);
}
void ParseInformationUpdated(object source, ParseInformationEventArgs e)
{
lock (pending) {
var files = Tuple.Create(e.OldParsedFile, e.NewParsedFile);
pending.Add(files);
}
WorkbenchSingleton.SafeThreadAsyncCall(UpdateParseInfo);
}
void UpdateParseInfo()
{
lock (pending) {
foreach (var files in pending) {
UpdateParseInfo(files.Item1, files.Item2);
}
pending.Clear();
}
}
void TestTreeViewDoubleClick(object source, EventArgs e)
{
GotoDefinition();
}
// void TestTreeViewKeyPress(object source, KeyPressEventArgs e)
// {
// if (e.KeyChar == '\r') {

1
src/AddIns/Analysis/UnitTesting/Interfaces/IRegisteredTestFrameworks.cs

@ -15,6 +15,7 @@ namespace ICSharpCode.UnitTesting @@ -15,6 +15,7 @@ namespace ICSharpCode.UnitTesting
ITestRunner CreateTestDebugger(IProject project);
bool IsTestMethod(IMethod method, ICompilation compilation);
bool IsTestCase(IMethod method, ICompilation compilation);
bool IsTestClass(ITypeDefinition typeDefinition, ICompilation compilation);
bool IsTestProject(IProject project);

1
src/AddIns/Analysis/UnitTesting/Interfaces/ITestFramework.cs

@ -11,6 +11,7 @@ namespace ICSharpCode.UnitTesting @@ -11,6 +11,7 @@ namespace ICSharpCode.UnitTesting
public interface ITestFramework
{
bool IsTestMethod(IMethod method, ICompilation compilation);
bool IsTestCase(IMethod method, ICompilation compilation);
bool IsTestClass(ITypeDefinition testClass, ICompilation compilation);
bool IsTestProject(IProject project);

2
src/AddIns/Analysis/UnitTesting/Interfaces/ITestTreeView.cs

@ -13,7 +13,7 @@ namespace ICSharpCode.UnitTesting @@ -13,7 +13,7 @@ namespace ICSharpCode.UnitTesting
/// <summary>
/// Gets the selected member in the test tree view.
/// </summary>
IMethod SelectedMethod {get;}
TestMember SelectedMethod {get;}
/// <summary>
/// Gets the selected class in the test tree view.

30
src/AddIns/Analysis/UnitTesting/Model/TestClass.cs

@ -26,19 +26,22 @@ namespace ICSharpCode.UnitTesting @@ -26,19 +26,22 @@ namespace ICSharpCode.UnitTesting
readonly ObservableCollection<TestClass> nestedClasses;
IRegisteredTestFrameworks testFrameworks;
public TestClass(IRegisteredTestFrameworks testFrameworks, string fullName, ITypeDefinition definition, TestClass parent = null)
public TestClass(TestProject project, IRegisteredTestFrameworks testFrameworks, string fullName, ITypeDefinition definition, TestClass parent = null)
{
this.parts = new ObservableCollection<IUnresolvedTypeDefinition>();
this.testMembers = new ObservableCollection<TestMember>();
this.nestedClasses = new ObservableCollection<TestClass>();
this.testFrameworks = testFrameworks;
this.fullName = fullName;
Project = project;
Parent = parent;
UpdateClass(definition);
}
public TestClass Parent { get; private set; }
public TestProject Project { get; private set; }
/// <summary>
/// Gets the underlying IClass for this test class.
/// </summary>
@ -126,7 +129,7 @@ namespace ICSharpCode.UnitTesting @@ -126,7 +129,7 @@ namespace ICSharpCode.UnitTesting
{
foreach (var testClass in TreeTraversal.PostOrder(this, c => c.NestedClasses)) {
foreach (var member in testClass.Members)
member.TestResult = TestResultType.None;
member.ResetTestResult();
testClass.TestResult = TestResultType.None;
}
var parent = this;
@ -156,10 +159,10 @@ namespace ICSharpCode.UnitTesting @@ -156,10 +159,10 @@ namespace ICSharpCode.UnitTesting
parts.Add(part);
}
testMembers.RemoveWhere(m => !definition.Methods.Any(dm => dm.ReflectionName == m.Method.ReflectionName && testFrameworks.IsTestMethod(dm, definition.Compilation)));
testMembers.AddRange(definition.Methods.Where(m => testFrameworks.IsTestMethod(m, definition.Compilation) && !testMembers.Any(dm => dm.Method.ReflectionName == m.ReflectionName)).Select(m => new TestMember((IUnresolvedMethod)m.UnresolvedMember)));
testMembers.AddRange(definition.Methods.Where(m => testFrameworks.IsTestMethod(m, definition.Compilation) && !testMembers.Any(dm => dm.Method.ReflectionName == m.ReflectionName)).Select(m => new TestMember(Project, (IUnresolvedMethod)m.UnresolvedMember, testFrameworks.IsTestCase(m, definition.Compilation))));
var context = new SimpleTypeResolveContext(definition);
nestedClasses.UpdateTestClasses(testFrameworks, nestedClasses.Select(tc => new DefaultResolvedTypeDefinition(context, tc.Parts.ToArray())).ToList(), definition.NestedTypes.Where(nt => testFrameworks.IsTestClass(nt, definition.Compilation)).ToList(), this);
nestedClasses.UpdateTestClasses(testFrameworks, nestedClasses.Select(tc => new DefaultResolvedTypeDefinition(context, tc.Parts.ToArray())).ToList(), definition.NestedTypes.Where(nt => testFrameworks.IsTestClass(nt, definition.Compilation)).ToList(), this, Project);
}
/// <summary>
@ -174,28 +177,15 @@ namespace ICSharpCode.UnitTesting @@ -174,28 +177,15 @@ namespace ICSharpCode.UnitTesting
return ns;
}
/// <summary>
/// Gets the test members for the class.
/// </summary>
void GetTestMembers()
public ITypeDefinition Resolve()
{
// testMembers = GetTestMembers(c);
// testMembers.ResultChanged += TestMembersResultChanged;
}
/// <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;
ICompilation compilation = SD.ParserService.GetCompilation(Project.Project);
return parts.First().Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition();
}
public override string ToString()
{
return string.Format("[TestClass TestResult={0}, FullName={1}]", testResult, fullName);
}
}
}

23
src/AddIns/Analysis/UnitTesting/Model/TestMember.cs

@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
using System;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Widgets;
namespace ICSharpCode.UnitTesting
@ -18,11 +20,17 @@ namespace ICSharpCode.UnitTesting @@ -18,11 +20,17 @@ namespace ICSharpCode.UnitTesting
get { return method; }
}
public TestMember(IUnresolvedMethod method)
public TestProject Project { get; private set; }
public bool IsTestCase { get; private set; }
public TestMember(TestProject project, IUnresolvedMethod method, bool isTestCase)
{
if (method == null)
throw new ArgumentNullException("method");
this.method = method;
this.Project = project;
this.IsTestCase = isTestCase;
}
TestResultType testResult;
@ -30,13 +38,24 @@ namespace ICSharpCode.UnitTesting @@ -30,13 +38,24 @@ namespace ICSharpCode.UnitTesting
public TestResultType TestResult {
get { return testResult; }
set {
if (testResult != value) {
if (testResult < value) {
testResult = value;
OnPropertyChanged();
}
}
}
public void ResetTestResult()
{
testResult = TestResultType.None;
}
public IMethod Resolve()
{
ICompilation compilation = SD.ParserService.GetCompilation(Project.Project);
return method.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly));
}
public override string ToString()
{
return string.Format("[TestMember Method={0}, TestResult={1}]", method, testResult);

4
src/AddIns/Analysis/UnitTesting/Model/TestProject.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.UnitTesting @@ -37,7 +37,7 @@ namespace ICSharpCode.UnitTesting
.Resolve(compilation.TypeResolveContext)
.TopLevelTypeDefinitions
.Where(td => testFrameworks.IsTestClass(td, compilation))
.Select(g => new TestClass(testFrameworks, g.ReflectionName, g));
.Select(g => new TestClass(this, testFrameworks, g.ReflectionName, g));
testClasses = new ObservableCollection<TestClass>(classes);
}
@ -49,7 +49,7 @@ namespace ICSharpCode.UnitTesting @@ -49,7 +49,7 @@ namespace ICSharpCode.UnitTesting
@new = e.NewParsedFile.TopLevelTypeDefinitions.Select(utd => utd.Resolve(context).GetDefinition()).Where(x => x != null && testFrameworks.IsTestClass(x, SD.ParserService.GetCompilation(project)));
else
@new = Enumerable.Empty<ITypeDefinition>();
testClasses.UpdateTestClasses(testFrameworks, testClasses.Where(tc => tc.Parts.Any(td => td.ParsedFile.FileName == e.OldParsedFile.FileName)).Select(tc => new DefaultResolvedTypeDefinition(context, tc.Parts.ToArray())).ToList(), @new.ToList(), null);
testClasses.UpdateTestClasses(testFrameworks, testClasses.Where(tc => tc.Parts.Any(td => td.ParsedFile.FileName == e.OldParsedFile.FileName)).Select(tc => new DefaultResolvedTypeDefinition(context, tc.Parts.ToArray())).ToList(), @new.ToList(), null, this);
}
public IProject Project {

9
src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestFramework.cs

@ -50,8 +50,15 @@ namespace ICSharpCode.UnitTesting @@ -50,8 +50,15 @@ namespace ICSharpCode.UnitTesting
if (method == null)
throw new ArgumentNullException("method");
var testAttribute = NUnitTestFramework.testAttribute.Resolve(compilation.TypeResolveContext);
return IsTestCase(method, compilation) || method.Attributes.Any(a => a.AttributeType.Equals(testAttribute));
}
public bool IsTestCase(IMethod method, ICompilation compilation)
{
if (method == null)
throw new ArgumentNullException("method");
var testCaseAttribute = NUnitTestFramework.testCaseAttribute.Resolve(compilation.TypeResolveContext);
return method.Attributes.Any(a => a.AttributeType.Equals(testAttribute) || a.AttributeType.Equals(testCaseAttribute));
return method.Attributes.Any(a => a.AttributeType.Equals(testCaseAttribute));
}
public bool IsTestClass(ITypeDefinition type, ICompilation compilation)

2
src/AddIns/Analysis/UnitTesting/Nodes/ClassUnitTestNode.cs

@ -24,9 +24,11 @@ namespace ICSharpCode.UnitTesting @@ -24,9 +24,11 @@ namespace ICSharpCode.UnitTesting
this.testClass.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "TestResult") {
RaisePropertyChanged("Icon");
RaisePropertyChanged("ExpandedIcon");
var parentNode = Parent;
while (parentNode is NamespaceUnitTestNode) {
parentNode.RaisePropertyChanged("Icon");
parentNode.RaisePropertyChanged("ExpandedIcon");
parentNode = parentNode.Parent;
}
}

1
src/AddIns/Analysis/UnitTesting/Nodes/MemberUnitTestNode.cs

@ -24,6 +24,7 @@ namespace ICSharpCode.UnitTesting @@ -24,6 +24,7 @@ namespace ICSharpCode.UnitTesting
this.testMember.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "TestResult") {
RaisePropertyChanged("Icon");
RaisePropertyChanged("ExpandedIcon");
}
};
}

19
src/AddIns/Analysis/UnitTesting/Nodes/NamespaceUnitTestNode.cs

@ -24,6 +24,15 @@ namespace ICSharpCode.UnitTesting @@ -24,6 +24,15 @@ namespace ICSharpCode.UnitTesting
get { return name; }
}
public string FullNamespace {
get {
TestProject p = GetProject();
if (p != null)
return p.Project.RootNamespace + "." + name;
return name;
}
}
public NamespaceUnitTestNode(string name)
{
if (string.IsNullOrEmpty(name))
@ -47,5 +56,15 @@ namespace ICSharpCode.UnitTesting @@ -47,5 +56,15 @@ namespace ICSharpCode.UnitTesting
return TestResultType.Success;
}
}
public TestProject GetProject()
{
UnitTestBaseNode parent = this;
while (parent is NamespaceUnitTestNode)
parent = (UnitTestBaseNode)parent.Parent;
if (parent is ProjectUnitTestNode)
return ((ProjectUnitTestNode)parent).Project;
return null;
}
}
}

4
src/AddIns/Analysis/UnitTesting/Nodes/ProjectUnitTestNode.cs

@ -35,8 +35,10 @@ namespace ICSharpCode.UnitTesting @@ -35,8 +35,10 @@ namespace ICSharpCode.UnitTesting
void ProjectPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "TestResult")
if (e.PropertyName == "TestResult") {
RaisePropertyChanged("Icon");
RaisePropertyChanged("ExpandedIcon");
}
}
void TestClassesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

9
src/AddIns/Analysis/UnitTesting/Service/RegisteredTestFrameworks.cs

@ -40,6 +40,15 @@ namespace ICSharpCode.UnitTesting @@ -40,6 +40,15 @@ namespace ICSharpCode.UnitTesting
return false;
}
public bool IsTestCase(IMethod method, ICompilation compilation)
{
ITestFramework testFramework = GetTestFramework(method, compilation);
if (testFramework != null) {
return testFramework.IsTestCase(method, compilation);
}
return false;
}
public IEnumerable<IMethod> GetTestMethodsFor(ITypeDefinition type, ICompilation compilation)
{
ITestFramework testFramework = GetTestFramework(type, compilation);

24
src/AddIns/Analysis/UnitTesting/Service/TestResult.cs

@ -20,12 +20,12 @@ namespace ICSharpCode.UnitTesting @@ -20,12 +20,12 @@ namespace ICSharpCode.UnitTesting
/// <summary>
/// The test failed.
/// </summary>
Failure = 2,
Failure = 3,
/// <summary>
/// The test was ignored.
/// </summary>
Ignored = 3
Ignored = 2
}
/// <summary>
@ -33,15 +33,27 @@ namespace ICSharpCode.UnitTesting @@ -33,15 +33,27 @@ namespace ICSharpCode.UnitTesting
/// </summary>
public class TestResult
{
string name = String.Empty;
string message = String.Empty;
string stackTrace = String.Empty;
string name = string.Empty;
string values = string.Empty;
string message = string.Empty;
string stackTrace = string.Empty;
TestResultType resultType = TestResultType.None;
DomRegion stackTraceFilePosition = DomRegion.Empty;
public TestResult(string name)
{
this.name = name;
this.name = ParseName(name, out values);
}
string ParseName(string name, out string values)
{
int i = name.IndexOf('(');
values = "";
if (i > -1) {
values = name.Substring(i);
return name.Substring(0, i);
} else
return name;
}
public string Name {

5
src/AddIns/Analysis/UnitTesting/Service/TestService.cs

@ -112,5 +112,10 @@ namespace ICSharpCode.UnitTesting @@ -112,5 +112,10 @@ namespace ICSharpCode.UnitTesting
return Enumerable.Empty<TestProject>();
return ProjectService.OpenSolution.Projects.Where(p => RegisteredTestFrameworks.IsTestProject(p)).Select(p => new TestProject(p));
}
public static TestProject GetTestProject(IProject currentProject)
{
return testableProjects.FirstOrDefault(p => p.Project == currentProject);
}
}
}

4
src/AddIns/Analysis/UnitTesting/Service/TestableCondition.cs

@ -31,8 +31,8 @@ namespace ICSharpCode.UnitTesting @@ -31,8 +31,8 @@ namespace ICSharpCode.UnitTesting
public static IMethod GetMethod(object caller)
{
ITestTreeView testTreeView = caller as ITestTreeView;
if (testTreeView != null) {
return testTreeView.SelectedMethod;
if (testTreeView != null && testTreeView.SelectedMethod != null) {
return testTreeView.SelectedMethod.Resolve();
}
// MemberNode memberNode = caller as MemberNode;
// if (memberNode != null)

341
src/AddIns/Analysis/UnitTesting/TestTreeView.cs

@ -3,19 +3,19 @@ @@ -3,19 +3,19 @@
using System;
using System.Collections.Generic;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.TreeView;
namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Tree view that shows all the unit tests in a project.
/// </summary>
public class TestTreeView : sharptr, ITestTreeView, IOwnerState
public class TestTreeView : SharpTreeView, ITestTreeView, IOwnerState
{
/// <summary>
/// The current state of the tree view.
@ -27,18 +27,16 @@ namespace ICSharpCode.UnitTesting @@ -27,18 +27,16 @@ namespace ICSharpCode.UnitTesting
}
/// <summary>
/// The All Tests tree root node that is added if multiple
/// 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;
TestService.TestableProjects.CollectionChanged += delegate { ShowRoot = TestService.TestableProjects.Count > 1; };
}
/// <summary>
@ -46,154 +44,25 @@ namespace ICSharpCode.UnitTesting @@ -46,154 +44,25 @@ namespace ICSharpCode.UnitTesting
/// </summary>
public Enum InternalState {
get {
TestTreeNode selectedNode = SelectedNode as TestTreeNode;
if ((selectedNode is TestClassTreeNode) || (selectedNode is TestMemberTreeNode)) {
if (SelectedItem is ClassUnitTestNode || SelectedItem is MemberUnitTestNode)
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 {
public TestMember SelectedMethod {
get {
TestMemberTreeNode memberNode = SelectedNode as TestMemberTreeNode;
MemberUnitTestNode memberNode = SelectedItem as MemberUnitTestNode;
if (memberNode != null) {
return memberNode.Member;
return memberNode.TestMember;
}
return null;
}
@ -202,25 +71,25 @@ namespace ICSharpCode.UnitTesting @@ -202,25 +71,25 @@ namespace ICSharpCode.UnitTesting
/// <summary>
/// Gets the class of the currently selected tree node.
/// </summary>
public IClass SelectedClass {
public ITypeDefinition SelectedClass {
get {
TestClassTreeNode classNode = SelectedNode as TestClassTreeNode;
ClassUnitTestNode classNode = SelectedItem as ClassUnitTestNode;
if (classNode == null) {
classNode = GetClassNodeFromSelectedMemberNode();
}
if (classNode != null) {
return classNode.Class;
return classNode.TestClass.Resolve();
}
return null;
}
}
TestClassTreeNode GetClassNodeFromSelectedMemberNode()
ClassUnitTestNode GetClassNodeFromSelectedMemberNode()
{
TestMemberTreeNode memberNode = SelectedNode as TestMemberTreeNode;
MemberUnitTestNode memberNode = SelectedItem as MemberUnitTestNode;
if (memberNode != null) {
return memberNode.Parent as TestClassTreeNode;
return memberNode.Parent as ClassUnitTestNode;
}
return null;
}
@ -240,13 +109,13 @@ namespace ICSharpCode.UnitTesting @@ -240,13 +109,13 @@ namespace ICSharpCode.UnitTesting
}
/// <summary>
/// If a namespace node is selected then the fully qualified namespace
/// 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;
NamespaceUnitTestNode selectedNode = SelectedItem as NamespaceUnitTestNode;
if (selectedNode != null) {
return selectedNode.FullNamespace;
}
@ -259,176 +128,16 @@ namespace ICSharpCode.UnitTesting @@ -259,176 +128,16 @@ namespace ICSharpCode.UnitTesting
/// </summary>
public TestProject SelectedTestProject {
get {
TestTreeNode selectedNode = SelectedNode as TestTreeNode;
if (selectedNode != null) {
return selectedNode.TestProject;
}
if (SelectedItem is MemberUnitTestNode)
return ((MemberUnitTestNode)SelectedItem).TestMember.Project;
if (SelectedItem is ClassUnitTestNode)
return ((ClassUnitTestNode)SelectedItem).TestClass.Project;
if (SelectedItem is NamespaceUnitTestNode)
return ((NamespaceUnitTestNode)SelectedItem).GetProject();
if (SelectedItem is ProjectUnitTestNode)
return ((ProjectUnitTestNode)SelectedItem).Project;
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);
}
}
}
}

2
src/AddIns/Analysis/UnitTesting/UnitTesting.csproj

@ -71,6 +71,7 @@ @@ -71,6 +71,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Commands\RunTestCommands.cs" />
<Compile Include="Commands\UnitTestCommands.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="Gui\EmptyUnitTestsPad.cs" />
<Compile Include="Gui\UnitTestingOptionsPanel.xaml.cs">
@ -138,6 +139,7 @@ @@ -138,6 +139,7 @@
<Compile Include="TestResultsMonitor.cs" />
<Compile Include="TestResultsReader.cs" />
<Compile Include="TestResultTask.cs" />
<Compile Include="TestTreeView.cs" />
<Compile Include="UnitTestApplicationStartHelper.cs" />
<Compile Include="UnitTestingOptions.cs" />
<Compile Include="UnitTestProcessRunner.cs" />

Loading…
Cancel
Save