From f2cdbee3b04cae3a3c6a7f03f938aa26c1709838 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 4 May 2012 18:43:52 +0200 Subject: [PATCH] implement test result update logic --- src/AddIns/Analysis/UnitTesting/Extensions.cs | 6 +- .../Analysis/UnitTesting/Model/TestClass.cs | 58 +++++++++++++++---- .../Analysis/UnitTesting/Model/TestMember.cs | 5 ++ .../Analysis/UnitTesting/Model/TestProject.cs | 47 ++++++++------- .../UnitTesting/Nodes/ClassUnitTestNode.cs | 11 ++++ .../UnitTesting/Nodes/MemberUnitTestNode.cs | 14 +++-- .../Nodes/NamespaceUnitTestNode.cs | 11 +++- .../Analysis/UnitTesting/TestAttributeName.cs | 50 ---------------- 8 files changed, 111 insertions(+), 91 deletions(-) delete mode 100644 src/AddIns/Analysis/UnitTesting/TestAttributeName.cs diff --git a/src/AddIns/Analysis/UnitTesting/Extensions.cs b/src/AddIns/Analysis/UnitTesting/Extensions.cs index ae24f3c252..3726c562c0 100644 --- a/src/AddIns/Analysis/UnitTesting/Extensions.cs +++ b/src/AddIns/Analysis/UnitTesting/Extensions.cs @@ -51,18 +51,18 @@ namespace ICSharpCode.UnitTesting list.Insert(index, item); } - public static void UpdateTestClasses(this IList testClasses, IRegisteredTestFrameworks testFrameworks, IReadOnlyList oldTypes, IReadOnlyList newTypes) + public static void UpdateTestClasses(this IList testClasses, IRegisteredTestFrameworks testFrameworks, IReadOnlyList oldTypes, IReadOnlyList newTypes, TestClass parent) { var mappings = oldTypes.FullOuterJoin(newTypes, t => t.ReflectionName, t => t.ReflectionName, Tuple.Create); foreach (Tuple 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)); + testClasses.Add(new TestClass(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)); + testClasses.Add(new TestClass(testFrameworks, mapping.Item2.ReflectionName, mapping.Item2, parent)); else testClass.UpdateClass(mapping.Item2); } diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestClass.cs b/src/AddIns/Analysis/UnitTesting/Model/TestClass.cs index a387740161..e5d26dbaea 100644 --- a/src/AddIns/Analysis/UnitTesting/Model/TestClass.cs +++ b/src/AddIns/Analysis/UnitTesting/Model/TestClass.cs @@ -5,9 +5,11 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; + using ICSharpCode.Core; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Widgets; @@ -24,16 +26,19 @@ namespace ICSharpCode.UnitTesting readonly ObservableCollection nestedClasses; IRegisteredTestFrameworks testFrameworks; - public TestClass(IRegisteredTestFrameworks testFrameworks, string fullName, ITypeDefinition definition) + public TestClass(IRegisteredTestFrameworks testFrameworks, string fullName, ITypeDefinition definition, TestClass parent = null) { this.parts = new ObservableCollection(); this.testMembers = new ObservableCollection(); this.nestedClasses = new ObservableCollection(); this.testFrameworks = testFrameworks; this.fullName = fullName; + Parent = parent; UpdateClass(definition); } + public TestClass Parent { get; private set; } + /// /// Gets the underlying IClass for this test class. /// @@ -81,12 +86,23 @@ namespace ICSharpCode.UnitTesting /// public TestResultType TestResult { get { return testResult; } - set { - if (testResult != value) { - testResult = value; - OnPropertyChanged(); - } - } + set { SetAndNotifyPropertyChanged(ref testResult, value); } + } + + static TestResultType GetTestResult(TestClass testClass) + { + if (testClass.nestedClasses.Count == 0 && testClass.testMembers.Count == 0) + return TestResultType.None; + if (testClass.nestedClasses.Any(c => c.TestResult == TestResultType.Failure) + || testClass.testMembers.Any(m => m.TestResult == TestResultType.Failure)) + return TestResultType.Failure; + if (testClass.nestedClasses.Any(c => c.TestResult == TestResultType.None) + || testClass.testMembers.Any(m => m.TestResult == TestResultType.None)) + return TestResultType.None; + if (testClass.nestedClasses.Any(c => c.TestResult == TestResultType.Ignored) + || testClass.testMembers.Any(m => m.TestResult == TestResultType.Ignored)) + return TestResultType.Ignored; + return TestResultType.Success; } /// @@ -94,7 +110,13 @@ namespace ICSharpCode.UnitTesting /// public void UpdateTestResult(TestResult testResult) { - + var member = testMembers.SingleOrDefault(m => m.Method.ReflectionName == testResult.Name); + member.TestResult = testResult.ResultType; + var parent = this; + while (parent != null) { + parent.TestResult = GetTestResult(parent); + parent = parent.Parent; + } } /// @@ -102,8 +124,16 @@ namespace ICSharpCode.UnitTesting /// public void ResetTestResults() { - TestResult = TestResultType.None; -// TestMembers.ResetTestResults(); + foreach (var testClass in TreeTraversal.PostOrder(this, c => c.NestedClasses)) { + foreach (var member in testClass.Members) + member.TestResult = TestResultType.None; + testClass.TestResult = TestResultType.None; + } + var parent = this; + while (parent != null) { + parent.TestResult = TestResultType.None; + parent = parent.Parent; + } } /// @@ -129,7 +159,7 @@ namespace ICSharpCode.UnitTesting 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))); 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()); + nestedClasses.UpdateTestClasses(testFrameworks, nestedClasses.Select(tc => new DefaultResolvedTypeDefinition(context, tc.Parts.ToArray())).ToList(), definition.NestedTypes.Where(nt => testFrameworks.IsTestClass(nt, definition.Compilation)).ToList(), this); } /// @@ -161,5 +191,11 @@ namespace ICSharpCode.UnitTesting { // Result = testMembers.Result; } + + public override string ToString() + { + return string.Format("[TestClass TestResult={0}, FullName={1}]", testResult, fullName); + } + } } \ No newline at end of file diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestMember.cs b/src/AddIns/Analysis/UnitTesting/Model/TestMember.cs index 60a4d24103..ab114c9300 100644 --- a/src/AddIns/Analysis/UnitTesting/Model/TestMember.cs +++ b/src/AddIns/Analysis/UnitTesting/Model/TestMember.cs @@ -36,5 +36,10 @@ namespace ICSharpCode.UnitTesting } } } + + public override string ToString() + { + return string.Format("[TestMember Method={0}, TestResult={1}]", method, testResult); + } } } diff --git a/src/AddIns/Analysis/UnitTesting/Model/TestProject.cs b/src/AddIns/Analysis/UnitTesting/Model/TestProject.cs index 9f1df2769f..a07c35b414 100644 --- a/src/AddIns/Analysis/UnitTesting/Model/TestProject.cs +++ b/src/AddIns/Analysis/UnitTesting/Model/TestProject.cs @@ -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(); - 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()); + 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); } public IProject Project { @@ -72,35 +72,32 @@ namespace ICSharpCode.UnitTesting return null; } - public bool FindTestInfo(string fullName, out TestClass testClass, out TestMember method) + public TestClass FindTestClass(string fullName) { - testClass = null; - method = null; foreach (var tc in testClasses) { foreach (var c in TreeTraversal.PostOrder(tc, c => c.NestedClasses)) { - testClass = c; - method = c.SingleOrDefault(m => fullName.Equals(m.Method.ReflectionName, StringComparison.Ordinal)); + var method = c.Members.SingleOrDefault(m => fullName.Equals(m.Method.ReflectionName, StringComparison.Ordinal)); if (method != null) - return true; + return c; } } - return false; + return null; } public void UpdateTestResult(TestResult result) { - TestMember member; - TestClass testClass; - if (FindTestInfo(result.Name, out testClass, out member)) { - member.TestResult = result.ResultType; - testClass.TestResult = r + TestClass testClass = FindTestClass(result.Name); + if (testClass != null) { + testClass.UpdateTestResult(result); + TestResult = GetTestResult(testClasses); } } public void ResetTestResults() { - foreach (var member in testClasses.SelectMany(tc => TreeTraversal.PostOrder(tc, c => c.NestedClasses)).SelectMany(c => c.Members)) - member.TestResult = TestResultType.None; + foreach (var testClass in testClasses) + testClass.ResetTestResults(); + TestResult = TestResultType.None; } TestResultType testResult; @@ -110,12 +107,20 @@ namespace ICSharpCode.UnitTesting /// public TestResultType TestResult { get { return testResult; } - set { - if (testResult != value) { - testResult = value; - OnPropertyChanged(); - } - } + set { SetAndNotifyPropertyChanged(ref testResult, value); } + } + + static TestResultType GetTestResult(IList testClasses) + { + if (testClasses.Count == 0) + return TestResultType.None; + if (testClasses.Any(c => c.TestResult == TestResultType.Failure)) + return TestResultType.Failure; + if (testClasses.Any(c => c.TestResult == TestResultType.None)) + return TestResultType.None; + if (testClasses.Any(c => c.TestResult == TestResultType.Ignored)) + return TestResultType.Ignored; + return TestResultType.Success; } } } diff --git a/src/AddIns/Analysis/UnitTesting/Nodes/ClassUnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/Nodes/ClassUnitTestNode.cs index fa4b7edb01..98d857ca1f 100644 --- a/src/AddIns/Analysis/UnitTesting/Nodes/ClassUnitTestNode.cs +++ b/src/AddIns/Analysis/UnitTesting/Nodes/ClassUnitTestNode.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Specialized; +using System.ComponentModel; namespace ICSharpCode.UnitTesting { @@ -20,6 +21,16 @@ namespace ICSharpCode.UnitTesting public ClassUnitTestNode(TestClass testClass) { this.testClass = testClass; + this.testClass.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) { + if (e.PropertyName == "TestResult") { + RaisePropertyChanged("Icon"); + var parentNode = Parent; + while (parentNode is NamespaceUnitTestNode) { + parentNode.RaisePropertyChanged("Icon"); + parentNode = parentNode.Parent; + } + } + }; testClass.Members.CollectionChanged += TestMembersCollectionChanged; testClass.NestedClasses.CollectionChanged += NestedClassesCollectionChanged; LazyLoading = true; diff --git a/src/AddIns/Analysis/UnitTesting/Nodes/MemberUnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/Nodes/MemberUnitTestNode.cs index 2b2e09a83c..408abeb53d 100644 --- a/src/AddIns/Analysis/UnitTesting/Nodes/MemberUnitTestNode.cs +++ b/src/AddIns/Analysis/UnitTesting/Nodes/MemberUnitTestNode.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Specialized; using System.ComponentModel; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; using ICSharpCode.TreeView; namespace ICSharpCode.UnitTesting @@ -21,11 +23,7 @@ namespace ICSharpCode.UnitTesting this.testMember = testMember; this.testMember.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "TestResult") { - SharpTreeNode p = this; - while (p != null) { - p.RaisePropertyChanged("Icon"); - p = p.Parent; - } + RaisePropertyChanged("Icon"); } }; } @@ -37,5 +35,11 @@ namespace ICSharpCode.UnitTesting public override object Text { get { return testMember.Method.Name; } } + + public override void ActivateItem(System.Windows.RoutedEventArgs e) + { + var region = testMember.Method.Region; + SD.FileService.JumpToFilePosition(new FileName(region.FileName), region.BeginLine, region.BeginColumn); + } } } diff --git a/src/AddIns/Analysis/UnitTesting/Nodes/NamespaceUnitTestNode.cs b/src/AddIns/Analysis/UnitTesting/Nodes/NamespaceUnitTestNode.cs index c0e34325e0..67fd3cf031 100644 --- a/src/AddIns/Analysis/UnitTesting/Nodes/NamespaceUnitTestNode.cs +++ b/src/AddIns/Analysis/UnitTesting/Nodes/NamespaceUnitTestNode.cs @@ -36,7 +36,16 @@ namespace ICSharpCode.UnitTesting } internal override TestResultType TestResultType { - get { return TestResultType.None; } + get { + if (Children.Count == 0) return TestResultType.None; + if (Children.OfType().Any(node => node.TestResultType == TestResultType.Failure)) + return TestResultType.Failure; + if (Children.OfType().Any(node => node.TestResultType == TestResultType.None)) + return TestResultType.None; + if (Children.OfType().Any(node => node.TestResultType == TestResultType.Ignored)) + return TestResultType.Ignored; + return TestResultType.Success; + } } } } diff --git a/src/AddIns/Analysis/UnitTesting/TestAttributeName.cs b/src/AddIns/Analysis/UnitTesting/TestAttributeName.cs deleted file mode 100644 index e769e64640..0000000000 --- a/src/AddIns/Analysis/UnitTesting/TestAttributeName.cs +++ /dev/null @@ -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.NRefactory.TypeSystem; - -namespace ICSharpCode.UnitTesting -{ - public class NUnitTestAttributeName - { - string name = String.Empty; - string qualifiedName = String.Empty; - string fullName = String.Empty; - StringComparer nameComparer; - - /// - /// Creates a new instance of the NUnit Test Attribute class. - /// - /// The name of the attribute (e.g. Test) not - /// the full name of the attribute (e.g. TestAttribute). - /// The string comparer to use - /// when comparing attribute names. - public NUnitTestAttributeName(string name, StringComparer nameComparer) - { - this.name = name; - this.nameComparer = nameComparer; - qualifiedName = String.Concat(name, "Attribute"); - fullName = String.Concat("NUnit.Framework.", name, "Attribute"); - } - - /// - /// Determines whether the specified attribute name is a - /// match to this attribute. - /// - public bool IsEqual(string attributeName) - { - if (nameComparer.Equals(attributeName, name) || - nameComparer.Equals(attributeName, qualifiedName) || - nameComparer.Equals(attributeName, fullName)) { - return true; - } - return false; - } - - public bool IsEqual(IAttribute attribute) - { - return IsEqual(attribute.AttributeType.FullName); - } - } -}