19 changed files with 299 additions and 1153 deletions
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Specialized; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Media; |
||||
using System.Windows.Media.Imaging; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Parser; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.TreeView; |
||||
using NUnit.Framework; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public static class Extensions |
||||
{ |
||||
static readonly ITypeReference testAttribute = new GetClassTypeReference("NUnit.Framework", "TestAttribute", 0); |
||||
|
||||
public static bool IsTestProject(this IProject project) |
||||
{ |
||||
if (project == null) |
||||
throw new ArgumentNullException("project"); |
||||
if (project.ProjectContent == null) |
||||
return false; |
||||
return testAttribute.Resolve(SD.ParserService.GetCompilation(project).TypeResolveContext).Kind != TypeKind.Unknown; |
||||
} |
||||
|
||||
public static bool IsTestMethod(this IMethod method, ICompilation compilation) |
||||
{ |
||||
if (method == null) |
||||
throw new ArgumentNullException("method"); |
||||
var testAttribute = Extensions.testAttribute.Resolve(compilation.TypeResolveContext); |
||||
return method.Attributes.Any(a => a.AttributeType.Equals(testAttribute)); |
||||
} |
||||
|
||||
public static bool HasTests(this ITypeDefinition type, ICompilation compilation) |
||||
{ |
||||
if (type == null) |
||||
throw new ArgumentNullException("type"); |
||||
var testAttribute = Extensions.testAttribute.Resolve(compilation.TypeResolveContext); |
||||
return type.Methods.Any(m => m.Attributes.Any(a => a.AttributeType.Equals(testAttribute))); |
||||
} |
||||
|
||||
public static IEnumerable<TResult> FullOuterJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter,TKey> outerKeySelector, Func<TInner,TKey> innerKeySelector, Func<TOuter,TInner,TResult> resultSelector) |
||||
where TInner : class |
||||
where TOuter : class |
||||
{ |
||||
var innerLookup = inner.ToLookup(innerKeySelector); |
||||
var outerLookup = outer.ToLookup(outerKeySelector); |
||||
|
||||
var innerJoinItems = inner |
||||
.Where(innerItem => !outerLookup.Contains(innerKeySelector(innerItem))) |
||||
.Select(innerItem => resultSelector(null, innerItem)); |
||||
|
||||
return outer |
||||
.SelectMany(outerItem => { |
||||
var innerItems = innerLookup[outerKeySelector(outerItem)]; |
||||
|
||||
return innerItems.Any() ? innerItems : new TInner[] { null }; |
||||
}, resultSelector) |
||||
.Concat(innerJoinItems); |
||||
} |
||||
|
||||
public static void OrderedInsert<T>(this IList<T> list, T item, Func<T, T, int> comparer) |
||||
{ |
||||
int index = 0; |
||||
while (index < list.Count && comparer(list[index], item) < 0) |
||||
index++; |
||||
list.Insert(index, item); |
||||
} |
||||
} |
||||
} |
@ -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.Core; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// All Tests root tree node that is added to the test tree when the
|
||||
/// solution has multiple test projects.
|
||||
/// </summary>
|
||||
public class AllTestsTreeNode : TestTreeNode |
||||
{ |
||||
public AllTestsTreeNode() |
||||
: base(null, StringParser.Parse("${res:ICSharpCode.UnitTesting.AllTestsTreeNode.Text}")) |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Raised when the all tests tree node is disposed.
|
||||
/// </summary>
|
||||
public event EventHandler Disposed; |
||||
|
||||
/// <summary>
|
||||
/// Disposes this tree node.
|
||||
/// </summary>
|
||||
public override void Dispose() |
||||
{ |
||||
base.Dispose(); |
||||
if (Disposed != null) { |
||||
Disposed(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Adds a new project node as a child of the All Tests node.
|
||||
/// </summary>
|
||||
public void AddProjectNode(TestProjectTreeNode node) |
||||
{ |
||||
node.AddTo(this); |
||||
node.ImageIndexChanged += TestProjectTreeNodeImageIndexChanged; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Removes the project node.
|
||||
/// </summary>
|
||||
public void RemoveProjectNode(TestProjectTreeNode node) |
||||
{ |
||||
if (Nodes.Contains(node)) { |
||||
node.ImageIndexChanged -= TestProjectTreeNodeImageIndexChanged; |
||||
node.Remove(); |
||||
} |
||||
} |
||||
|
||||
void TestProjectTreeNodeImageIndexChanged(object source, EventArgs e) |
||||
{ |
||||
UpdateImageListIndex(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sets the All Tests image index based on the current image
|
||||
/// indexes of the child project tree nodes.
|
||||
/// </summary>
|
||||
void UpdateImageListIndex() |
||||
{ |
||||
int ignored = 0; |
||||
int failed = 0; |
||||
int passed = 0; |
||||
int notRun = 0; |
||||
int total = Nodes.Count; |
||||
|
||||
foreach (TestProjectTreeNode projectNode in Nodes) { |
||||
switch (projectNode.ImageIndex) { |
||||
case (int)TestTreeViewImageListIndex.TestFailed: |
||||
failed++; |
||||
break; |
||||
case (int)TestTreeViewImageListIndex.TestPassed: |
||||
passed++; |
||||
break; |
||||
case (int)TestTreeViewImageListIndex.TestIgnored: |
||||
ignored++; |
||||
break; |
||||
default: // Not run.
|
||||
notRun++; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
// Update the image index based on the test project results.
|
||||
if (failed > 0) { |
||||
UpdateImageListIndex(TestResultType.Failure); |
||||
} else if (ignored > 0) { |
||||
UpdateImageListIndex(TestResultType.Ignored); |
||||
} else if (passed > 0 && notRun == 0) { |
||||
UpdateImageListIndex(TestResultType.Success); |
||||
} else { |
||||
UpdateImageListIndex(TestResultType.None); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Specialized; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class MemberUnitTestNode : UnitTestBaseNode |
||||
{ |
||||
TestMember testMember; |
||||
|
||||
public TestMember TestMember { |
||||
get { return testMember; } |
||||
} |
||||
|
||||
public MemberUnitTestNode(TestMember testMember) |
||||
{ |
||||
this.testMember = testMember; |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return testMember.Method.Name; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
// 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.Specialized; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Media; |
||||
using System.Windows.Media.Imaging; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.TreeView; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class NamespaceUnitTestNode : UnitTestBaseNode |
||||
{ |
||||
string name; |
||||
|
||||
public string Namespace { |
||||
get { return name; } |
||||
} |
||||
|
||||
public NamespaceUnitTestNode(string name) |
||||
{ |
||||
if (string.IsNullOrEmpty(name)) |
||||
throw new ArgumentException("name"); |
||||
this.name = name; |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return name.Substring(name.LastIndexOf('.') + 1); } |
||||
} |
||||
} |
||||
} |
@ -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.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 itd 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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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.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); |
||||
} |
||||
} |
||||
} |
@ -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 ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a method that has the [Test] attribute associated with it.
|
||||
/// </summary>
|
||||
public class TestMethodTreeNode : TestTreeNode |
||||
{ |
||||
TestMethod testMethod; |
||||
|
||||
public TestMethodTreeNode(TestProject project, TestMethod testMethod) |
||||
: base(project, testMethod.Name) |
||||
{ |
||||
this.testMethod = testMethod; |
||||
testMethod.ResultChanged += TestMethodResultChanged; |
||||
UpdateImageListIndex(testMethod.Result); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying IMethod for this test method.
|
||||
/// </summary>
|
||||
public IMember Method { |
||||
get { |
||||
return testMethod.Method; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Removes the TestMethod.ResultChanged event handler.
|
||||
/// </summary>
|
||||
public override void Dispose() |
||||
{ |
||||
if (!IsDisposed) { |
||||
testMethod.ResultChanged -= TestMethodResultChanged; |
||||
} |
||||
base.Dispose(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Updates the node's icon after the test method result
|
||||
/// has changed.
|
||||
/// </summary>
|
||||
void TestMethodResultChanged(object source, EventArgs e) |
||||
{ |
||||
UpdateImageListIndex(testMethod.Result); |
||||
} |
||||
} |
||||
} |
@ -1,336 +0,0 @@
@@ -1,336 +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.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(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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.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); |
||||
} |
||||
} |
||||
} |
@ -1,103 +0,0 @@
@@ -1,103 +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; |
||||
using ICSharpCode.TreeView; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Base class for all test tree nodes.
|
||||
/// </summary>
|
||||
public abstract class TestTreeNode : SharpTreeNode |
||||
{ |
||||
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); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue