diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs index e86d3ee0e2..519e764eb5 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs @@ -34,6 +34,9 @@ namespace ICSharpCode.CodeCoverage CodeCoverageMethodTreeNode node = new CodeCoverageMethodTreeNode(method); node.AddTo(this); } + + // Sort nodes. + SortChildNodes(); } } } diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethod.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethod.cs index ba04e5f943..86e65dd0bc 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethod.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethod.cs @@ -190,20 +190,6 @@ namespace ICSharpCode.CodeCoverage return matchedMethods; } - /// - /// Gets only those methods whose namespaces exactly match the specified string. - /// - public static List GetMethods(List methods, string ns) - { - List matchedMethods = new List(); - foreach (CodeCoverageMethod method in methods) { - if (method.ClassNamespace == ns) { - matchedMethods.Add(method); - } - } - return matchedMethods; - } - /// /// Gets only those methods for the specified class. /// diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethodTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethodTreeNode.cs index 042787d2d4..4c5e7aa001 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethodTreeNode.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageMethodTreeNode.cs @@ -48,5 +48,32 @@ namespace ICSharpCode.CodeCoverage } } + /// + /// Gets the string to be used when comparing method tree nodes + /// on sorting. + /// + /// + /// Until we group the getter and setter into its own + /// property tree node we return a compare string of the + /// form "PropertyName set" so sorting is acceptable. + /// + public override string CompareString { + get { + if (IsGetterOrSetter(Name)) { + string getterSetterPart = Name.Substring(0, 3); + string property = Name.Substring(4); + return String.Concat(property, ' ', getterSetterPart); + } + return base.CompareString; + } + } + + /// + /// Determines if the name refers to a getter or setter method. + /// + static bool IsGetterOrSetter(string name) + { + return name.StartsWith("get_") || name.StartsWith("set_"); + } } } diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModuleTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModuleTreeNode.cs index 2fe776a9aa..b23a3c5171 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModuleTreeNode.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageModuleTreeNode.cs @@ -10,6 +10,10 @@ using ICSharpCode.SharpDevelop.Gui; namespace ICSharpCode.CodeCoverage { + /// + /// Represents an assembly in the code coverage tree view. NCover + /// refers to it as a module. + /// public class CodeCoverageModuleTreeNode : CodeCoverageTreeNode { CodeCoverageModule module; @@ -36,7 +40,9 @@ namespace ICSharpCode.CodeCoverage CodeCoverageClassTreeNode classNode = new CodeCoverageClassTreeNode(className, CodeCoverageMethod.GetMethods(module.Methods, String.Empty, className)); classNode.AddTo(this); } - + + // Sort these nodes. + SortChildNodes(); } } } diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageNamespaceTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageNamespaceTreeNode.cs index 6917532301..274c69886d 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageNamespaceTreeNode.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageNamespaceTreeNode.cs @@ -20,6 +20,7 @@ namespace ICSharpCode.CodeCoverage public CodeCoverageNamespaceTreeNode(string namespacePrefix, string name, List methods) : base(name, methods, CodeCoverageImageListIndex.Namespace) { + sortOrder = 1; this.namespacePrefix = namespacePrefix; } @@ -40,6 +41,9 @@ namespace ICSharpCode.CodeCoverage CodeCoverageClassTreeNode classNode = new CodeCoverageClassTreeNode(className, CodeCoverageMethod.GetMethods(Methods, fullNamespace, className)); classNode.AddTo(this); } + + // Sort nodes added. + SortChildNodes(); } } } diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeNode.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeNode.cs index dc69d41668..6598c51a0f 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeNode.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeNode.cs @@ -33,6 +33,7 @@ namespace ICSharpCode.CodeCoverage public CodeCoverageTreeNode(string name, CodeCoverageImageListIndex index, int visitedCount, int notVisitedCount) { + sortOrder = 10; this.visitedCount = visitedCount; this.notVisitedCount = notVisitedCount; @@ -64,6 +65,25 @@ namespace ICSharpCode.CodeCoverage } } + /// + /// Gets the string to use when sorting the code coverage tree node. + /// + public override string CompareString { + get { + return Name; + } + } + + /// + /// Sorts the child nodes of this node. This sort is not + /// recursive so it only sorts the immediate children. + /// + protected void SortChildNodes() + { + ExtTreeView treeView = (ExtTreeView)TreeView; + treeView.SortNodes(Nodes, false); + } + static string GetPercentage(int visitedCount, int totalCount) { int percentage = (visitedCount * 100) / totalCount; diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeView.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeView.cs index 388b6465d6..2ab573cc57 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeView.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageTreeView.cs @@ -40,6 +40,5 @@ namespace ICSharpCode.CodeCoverage } base.OnAfterSelect(e); } - } } diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj index 42514e96c3..ed5cabe9c5 100644 --- a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj @@ -51,6 +51,7 @@ + @@ -64,6 +65,8 @@ + + diff --git a/src/AddIns/Misc/CodeCoverage/Test/DerivedCodeCoverageTreeView.cs b/src/AddIns/Misc/CodeCoverage/Test/DerivedCodeCoverageTreeView.cs new file mode 100644 index 0000000000..b306ca3520 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/DerivedCodeCoverageTreeView.cs @@ -0,0 +1,57 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Windows.Forms; +using ICSharpCode.CodeCoverage; +using ICSharpCode.SharpDevelop.Gui; + +namespace ICSharpCode.CodeCoverage.Tests +{ + /// + /// Derived code coverage tree view that gives us access to the + /// AfterSelect method. + /// + public class DerivedCodeCoverageTreeView : CodeCoverageTreeView + { + public void CallOnAfterSelect(TreeNode node) + { + base.OnAfterSelect(new TreeViewEventArgs(node)); + } + } + + /// + /// Derived ExtTreeNode class so we can check the IsInitialized + /// property. + /// + public class DerivedExtTreeNode : ExtTreeNode + { + public bool IsInitialized { + get { + return base.isInitialized; + } + } + } + + /// + /// Derived CodeCoverageTreeNode class so we can check the IsInitialized + /// property. + /// + public class DerivedCodeCoverageTreeNode : CodeCoverageTreeNode + { + public DerivedCodeCoverageTreeNode(string name, CodeCoverageImageListIndex index) + : base(name, index) + { + } + + public bool IsInitialized { + get { + return base.isInitialized; + } + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/TreeViewAfterSelectTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/TreeViewAfterSelectTestFixture.cs new file mode 100644 index 0000000000..3b6577ea90 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/TreeViewAfterSelectTestFixture.cs @@ -0,0 +1,54 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Gui; +using NUnit.Framework; + +namespace ICSharpCode.CodeCoverage.Tests +{ + /// + /// Tests the CodeCoverageResultsTreeView AfterSelect method. + /// + [TestFixture] + public class TreeViewAfterSelectTestFixture + { + /// + /// Code coverage tree node should be initialised in OnAfterSelect method. + /// + [Test] + public void NodeInitialised() + { + DerivedCodeCoverageTreeView treeView = new DerivedCodeCoverageTreeView(); + DerivedCodeCoverageTreeNode node = new DerivedCodeCoverageTreeNode("Test", CodeCoverageImageListIndex.Class); + treeView.CallOnAfterSelect(node); + Assert.IsTrue(node.IsInitialized); + } + + /// + /// Non code coverage tree node should not initialised in OnAfterSelect method. + /// + [Test] + public void NonCodeCoverageNodeNotInitialised() + { + DerivedCodeCoverageTreeView treeView = new DerivedCodeCoverageTreeView(); + DerivedExtTreeNode node = new DerivedExtTreeNode(); + treeView.CallOnAfterSelect(node); + Assert.IsFalse(node.IsInitialized); + } + + /// + /// Check that the OnAfterSelect method handles a null node. + /// + [Test] + public void NullNode() + { + DerivedCodeCoverageTreeView treeView = new DerivedCodeCoverageTreeView(); + treeView.CallOnAfterSelect(null); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/TreeViewSortingTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/TreeViewSortingTestFixture.cs new file mode 100644 index 0000000000..8e6c5311d1 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/TreeViewSortingTestFixture.cs @@ -0,0 +1,253 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using ICSharpCode.CodeCoverage; +using ICSharpCode.SharpDevelop.Gui; +using NUnit.Framework; + +namespace ICSharpCode.CodeCoverage.Tests +{ + /// + /// Tests that the code coverage tree view is sorted correctly for + /// all node types. + /// + [TestFixture] + public class TreeViewSortingTestFixture + { + IComparer nodeSorter; + CodeCoverageTreeView treeView; + CodeCoverageModuleTreeNode codeCoverageModuleTreeNode; + CodeCoverageModuleTreeNode zModuleTreeNode; + CodeCoverageTreeNode betaNamespaceTreeNode; + CodeCoverageTreeNode testFixtureClassTreeNode; + CodeCoverageTreeNode aardvarkNamespaceTreeNode; + CodeCoverageTreeNode anotherTestFixtureTreeNode; + CodeCoverageTreeNode testFixtureTreeNode; + CodeCoverageTreeNode addNodeTestTreeNode; + CodeCoverageTreeNode removeMarkersTestTreeNode; + + [TestFixtureSetUp] + public void SetUpFixture() + { + treeView = new CodeCoverageTreeView(); + nodeSorter = treeView.NodeSorter; + + List modules = new List(); + + // Create a module called Z. + CodeCoverageModule zModule = new CodeCoverageModule("Z"); + modules.Add(zModule); + + // Create a module called CodeCoverage. + CodeCoverageModule codeCoverageModule = new CodeCoverageModule("CodeCoverage"); + modules.Add(codeCoverageModule); + + // Add a method that lives in a class without any namespace. + CodeCoverageMethod testMethod = new CodeCoverageMethod("Test", "TestFixture"); + codeCoverageModule.Methods.Add(testMethod); + + // Add a method which produces a namespace that alphabetically + // occurs after the class already added. + CodeCoverageMethod removeCodeMarkersMethod = new CodeCoverageMethod("RemoveCodeMarkersMethod", "Beta.TestFixture"); + codeCoverageModule.Methods.Add(removeCodeMarkersMethod); + + // Add a method that lives in a namespace that + // occurs before the removeCodeMarkersMethod. We want to + // make sure that this namespace node gets added before the Beta one. + CodeCoverageMethod zebraMethod = new CodeCoverageMethod("Zebra", "Aardvark.TestFixture"); + codeCoverageModule.Methods.Add(zebraMethod); + + // Add a second class in the beta namespace so we check the + // sorting of classes. + CodeCoverageMethod addCodeMarkersMethod = new CodeCoverageMethod("AddCodeMarkersMethod", "Beta.AnotherTestFixture"); + codeCoverageModule.Methods.Add(addCodeMarkersMethod); + + // Add a method which produces occurs before the remove code markers method. + CodeCoverageMethod addNodeMethod = new CodeCoverageMethod("AddNode", "Beta.TestFixture"); + codeCoverageModule.Methods.Add(addNodeMethod); + + // Add two get and set properties. + CodeCoverageMethod method = new CodeCoverageMethod("get_Zebra", "Beta.AnotherTestFixture"); + codeCoverageModule.Methods.Add(method); + method = new CodeCoverageMethod("set_Zebra", "Beta.AnotherTestFixture"); + codeCoverageModule.Methods.Add(method); + + method = new CodeCoverageMethod("set_Aardvark", "Beta.AnotherTestFixture"); + codeCoverageModule.Methods.Add(method); + method = new CodeCoverageMethod("get_Aardvark", "Beta.AnotherTestFixture"); + codeCoverageModule.Methods.Add(method); + + // Add a method which should appear between the two properties. + method = new CodeCoverageMethod("Chimp", "Beta.AnotherTestFixture"); + codeCoverageModule.Methods.Add(method); + + + // Add the modules to the tree. + treeView.AddModules(modules); + + codeCoverageModuleTreeNode = (CodeCoverageModuleTreeNode)treeView.Nodes[0]; + zModuleTreeNode = (CodeCoverageModuleTreeNode)treeView.Nodes[1]; + + // Initialise the code coverage module tree node. + codeCoverageModuleTreeNode.PerformInitialization(); + aardvarkNamespaceTreeNode = (CodeCoverageTreeNode)codeCoverageModuleTreeNode.Nodes[0]; + betaNamespaceTreeNode = (CodeCoverageTreeNode)codeCoverageModuleTreeNode.Nodes[1]; + testFixtureClassTreeNode = (CodeCoverageTreeNode)codeCoverageModuleTreeNode.Nodes[2]; + + // Initialise the beta namespace tree node. + betaNamespaceTreeNode.PerformInitialization(); + anotherTestFixtureTreeNode = (CodeCoverageTreeNode)betaNamespaceTreeNode.Nodes[0]; + testFixtureTreeNode = (CodeCoverageTreeNode)betaNamespaceTreeNode.Nodes[1]; + + // Initialise the test fixture class tree node + testFixtureTreeNode.PerformInitialization(); + addNodeTestTreeNode = (CodeCoverageTreeNode)testFixtureTreeNode.Nodes[0]; + removeMarkersTestTreeNode = (CodeCoverageTreeNode)testFixtureTreeNode.Nodes[1]; + + // Initialise the anotherTestFixtureTreeNode + anotherTestFixtureTreeNode.PerformInitialization(); + } + + [TestFixtureTearDown] + public void TearDownFixture() + { + treeView.Dispose(); + } + + [Test] + public void FirstModuleTreeNode() + { + Assert.AreEqual("CodeCoverage", codeCoverageModuleTreeNode.Name); + } + + [Test] + public void SecondModuleTreeNode() + { + Assert.AreEqual("Z", zModuleTreeNode.Name); + } + + /// + /// Makes sure this is the second child node of the code coverage module + /// parent tree node. + /// + [Test] + public void BetaNamespaceTreeNodeName() + { + Assert.AreEqual("Beta", betaNamespaceTreeNode.Name); + } + + [Test] + public void AardvarkNamespaceTreeNodeName() + { + Assert.AreEqual("Aardvark", aardvarkNamespaceTreeNode.Name); + } + + /// + /// Test the code coverage tree view's node sorted correctly + /// orders the namespace tree nodes. + /// + [Test] + public void SameNamespaceTreeNodeCompared() + { + Assert.AreEqual(0, nodeSorter.Compare(aardvarkNamespaceTreeNode, aardvarkNamespaceTreeNode)); + } + + [Test] + public void FirstNamespaceTreeNodeLessThan() + { + int expectedResult = aardvarkNamespaceTreeNode.CompareString.CompareTo(betaNamespaceTreeNode.CompareString); + Assert.AreEqual(aardvarkNamespaceTreeNode.Name, aardvarkNamespaceTreeNode.CompareString); + Assert.AreEqual(betaNamespaceTreeNode.Name, betaNamespaceTreeNode.CompareString); + Assert.AreEqual(expectedResult, nodeSorter.Compare(aardvarkNamespaceTreeNode, betaNamespaceTreeNode)); + } + + [Test] + public void FirstNamespaceTreeNodeMoreThan() + { + int expectedResult = betaNamespaceTreeNode.CompareString.CompareTo(aardvarkNamespaceTreeNode.CompareString); + Assert.AreEqual(expectedResult, nodeSorter.Compare(betaNamespaceTreeNode, aardvarkNamespaceTreeNode)); + } + + /// + /// The namespace node should always be ordered before any class node. + /// + [Test] + public void ClassAndNamespaceTreeNodeCompared() + { + List methods = new List(); + CodeCoverageNamespaceTreeNode namespaceTreeNode = new CodeCoverageNamespaceTreeNode("Z", methods); + CodeCoverageClassTreeNode classTreeNode = new CodeCoverageClassTreeNode("A", methods); + Assert.AreEqual(-1, nodeSorter.Compare(namespaceTreeNode, classTreeNode)); + Assert.Greater(classTreeNode.SortOrder, namespaceTreeNode.SortOrder); + } + + /// + /// The compare string should be the name of the node not including + /// any percentages. + /// + [Test] + public void CodeCoverageTreeNodeCompareString() + { + CodeCoverageTreeNode node = new CodeCoverageTreeNode("A", CodeCoverageImageListIndex.Class, 1, 2); + Assert.AreEqual("A", node.CompareString); + } + + [Test] + public void TestFixtureTreeNodeName() + { + Assert.AreEqual("TestFixture", testFixtureTreeNode.Name); + } + + [Test] + public void AnotherTestFixtureTreeNodeName() + { + Assert.AreEqual("AnotherTestFixture", anotherTestFixtureTreeNode.Name); + } + + [Test] + public void RemoveMarkersTestTreeNodeName() + { + Assert.AreEqual("RemoveCodeMarkersMethod", removeMarkersTestTreeNode.Name); + } + + [Test] + public void AddNodeTestTreeNodeName() + { + Assert.AreEqual("AddNode", addNodeTestTreeNode.Name); + } + + [Test] + public void PropertyMethodsSorted() + { + Assert.AreEqual("get_Aardvark", anotherTestFixtureTreeNode.Nodes[0].Name); + Assert.AreEqual("set_Aardvark", anotherTestFixtureTreeNode.Nodes[1].Name); + Assert.AreEqual("AddCodeMarkersMethod", anotherTestFixtureTreeNode.Nodes[2].Name); + Assert.AreEqual("Chimp", anotherTestFixtureTreeNode.Nodes[3].Name); + Assert.AreEqual("get_Zebra", anotherTestFixtureTreeNode.Nodes[4].Name); + Assert.AreEqual("set_Zebra", anotherTestFixtureTreeNode.Nodes[5].Name); + } + + [Test] + public void GetterPropertyCompareString() + { + CodeCoverageMethod getterMethod = new CodeCoverageMethod("get_Aardvark", "Animal"); + CodeCoverageMethodTreeNode getterNode = new CodeCoverageMethodTreeNode(getterMethod); + Assert.AreEqual("Aardvark get", getterNode.CompareString); + } + + [Test] + public void SetterPropertyCompareString() + { + CodeCoverageMethod setterMethod = new CodeCoverageMethod("set_Aardvark", "Animal"); + CodeCoverageMethodTreeNode setterNode = new CodeCoverageMethodTreeNode(setterMethod); + Assert.AreEqual("Aardvark set", setterNode.CompareString); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/ZeroCodeCoverageTreeViewTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/ZeroCodeCoverageTreeViewTestFixture.cs index eb23d1d67f..925d15a208 100644 --- a/src/AddIns/Misc/CodeCoverage/Test/ZeroCodeCoverageTreeViewTestFixture.cs +++ b/src/AddIns/Misc/CodeCoverage/Test/ZeroCodeCoverageTreeViewTestFixture.cs @@ -99,6 +99,7 @@ namespace ICSharpCode.CodeCoverage.Tests { fooTestMethodTreeNode.VisitedCount = 1; Assert.AreEqual(CodeCoverageImageListIndex.Method, (CodeCoverageImageListIndex)(fooTestMethodTreeNode.ImageIndex)); + Assert.AreEqual(1, fooTestMethodTreeNode.VisitedCount); } [Test] @@ -107,6 +108,7 @@ namespace ICSharpCode.CodeCoverage.Tests fooTestMethodTreeNode.NotVisitedCount = 0; fooTestMethodTreeNode.VisitedCount = 2; Assert.AreEqual(Color.Empty, fooTestMethodTreeNode.ForeColor); + Assert.AreEqual(0, fooTestMethodTreeNode.NotVisitedCount); } } }