20 changed files with 373 additions and 934 deletions
@ -1,198 +0,0 @@
@@ -1,198 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.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; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a class that can be tested.
|
||||
/// </summary>
|
||||
public class TestClass |
||||
{ |
||||
readonly ITestFramework testFramework; |
||||
readonly ObservableCollection<TestMember> testMembers; |
||||
readonly ObservableCollection<TestClass> nestedClasses; |
||||
IList<IUnresolvedTypeDefinition> parts; |
||||
|
||||
public TestClass(ITypeDefinition definition, ITestFramework testFramework) |
||||
{ |
||||
if (definition == null) |
||||
throw new ArgumentNullException("definition"); |
||||
if (testFramework == null) |
||||
throw new ArgumentNullException("testFramework"); |
||||
this.testFramework = testFramework; |
||||
this.parts = new ObservableCollection<IUnresolvedTypeDefinition>(); |
||||
this.testMembers = new ObservableCollection<TestMember>(); |
||||
this.nestedClasses = new ObservableCollection<TestClass>(); |
||||
UpdateClass(definition); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying IUnresolvedTypeDefinitions for this test class.
|
||||
/// </summary>
|
||||
public IList<IUnresolvedTypeDefinition> Parts { |
||||
get { return parts; } |
||||
} |
||||
|
||||
public ObservableCollection<TestMember> Members { |
||||
get { return testMembers; } |
||||
} |
||||
|
||||
public ObservableCollection<TestClass> NestedClasses { |
||||
get { return nestedClasses; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the class.
|
||||
/// </summary>
|
||||
public string Name { |
||||
get { return parts[0].Name; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the fully qualified name of the class.
|
||||
/// </summary>
|
||||
public string QualifiedName { |
||||
get { return parts[0].ReflectionName; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the namespace of this class.
|
||||
/// </summary>
|
||||
public string Namespace { |
||||
get { return parts[0].Namespace; } |
||||
} |
||||
|
||||
TestResultType testResult; |
||||
|
||||
public event EventHandler TestResultChanged; |
||||
|
||||
/// <summary>
|
||||
/// Gets the test result for this class.
|
||||
/// </summary>
|
||||
public TestResultType TestResult { |
||||
get { return testResult; } |
||||
set { |
||||
if (testResult != value) { |
||||
testResult = value; |
||||
if (TestResultChanged != null) |
||||
TestResultChanged(this, EventArgs.Empty); |
||||
} |
||||
} |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Updates the test member with the specified test result.
|
||||
/// </summary>
|
||||
public void UpdateTestResult(TestResult testResult) |
||||
{ |
||||
var member = testMembers.SingleOrDefault(m => m.Member.ReflectionName == testResult.Name); |
||||
member.TestResult = testResult.ResultType; |
||||
this.TestResult = GetTestResult(this); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Resets all the test results back to none.
|
||||
/// </summary>
|
||||
public void ResetTestResults() |
||||
{ |
||||
foreach (var testClass in this.NestedClasses) { |
||||
testClass.ResetTestResults(); |
||||
} |
||||
foreach (var member in this.Members) { |
||||
member.ResetTestResults(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Updates the members and class based on the new class
|
||||
/// information that has been parsed.
|
||||
/// </summary>
|
||||
public void UpdateClass(ITypeDefinition typeDefinition) |
||||
{ |
||||
this.parts = typeDefinition.Parts; |
||||
|
||||
testMembers.Clear(); |
||||
testMembers.AddRange(testFramework.GetTestMembersFor(typeDefinition)); |
||||
|
||||
|
||||
/*var oldParts = this.parts; |
||||
nestedClasses.UpdateTestClasses(testFrameworks, |
||||
|
||||
int i = 0; |
||||
while (i < parts.Count) { |
||||
var part = parts[i]; |
||||
if (!definition.Parts.Any(p => p.UnresolvedFile.FileName == part.UnresolvedFile.FileName && p.Region == part.Region)) |
||||
parts.RemoveAt(i); |
||||
else |
||||
i++; |
||||
} |
||||
|
||||
foreach (var part in definition.Parts) { |
||||
if (!parts.Any(p => p.UnresolvedFile.FileName == part.UnresolvedFile.FileName && p.Region == part.Region)) |
||||
parts.Add(part); |
||||
} |
||||
testMembers.RemoveWhere(m => !definition.Methods.Any(dm => dm.ReflectionName == m.Member.ReflectionName && testFrameworks.IsTestMethod(dm))); |
||||
testMembers.AddRange( |
||||
definition.Methods.Where(m => testFrameworks.IsTestMethod(m, definition.Compilation) |
||||
&& !testMembers.Any(dm => dm.Member.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, Project); |
||||
*/ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the first dotted part of the namespace.
|
||||
/// </summary>
|
||||
static string GetRootNamespace(string ns) |
||||
{ |
||||
int index = ns.IndexOf('.'); |
||||
if (index > 0) { |
||||
return ns.Substring(0, index); |
||||
} |
||||
return ns; |
||||
} |
||||
|
||||
public ITypeDefinition Resolve(TestProject project) |
||||
{ |
||||
if (project == null) |
||||
return null; |
||||
ICompilation compilation = SD.ParserService.GetCompilation(project.Project); |
||||
return parts[0].Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition(); |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return string.Format("[TestClass TestResult={0}, Name={1}]", testResult, this.QualifiedName); |
||||
} |
||||
} |
||||
} |
@ -1,67 +0,0 @@
@@ -1,67 +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; |
||||
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Widgets; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a member that can be tested.
|
||||
/// </summary>
|
||||
public class TestMember |
||||
{ |
||||
readonly IUnresolvedMember member; |
||||
|
||||
public IUnresolvedMember Member { |
||||
get { return member; } |
||||
} |
||||
|
||||
public TestMember(IUnresolvedMember member) |
||||
{ |
||||
if (member == null) |
||||
throw new ArgumentNullException("member"); |
||||
this.member = member; |
||||
} |
||||
|
||||
public string Name { |
||||
get { return member.Name; } |
||||
} |
||||
|
||||
public event EventHandler TestResultChanged; |
||||
|
||||
TestResultType testResult; |
||||
|
||||
public TestResultType TestResult { |
||||
get { return testResult; } |
||||
set { |
||||
if (testResult != value) { |
||||
testResult = value; |
||||
if (TestResultChanged != null) |
||||
TestResultChanged(this, EventArgs.Empty); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public virtual void ResetTestResults() |
||||
{ |
||||
testResult = TestResultType.None; |
||||
} |
||||
|
||||
public IMember Resolve(TestProject project) |
||||
{ |
||||
if (project == null) |
||||
return null; |
||||
ICompilation compilation = SD.ParserService.GetCompilation(project.Project); |
||||
return member.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)); |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return string.Format("[TestMember Method={0}, TestResult={1}]", member, testResult); |
||||
} |
||||
} |
||||
} |
@ -1,196 +0,0 @@
@@ -1,196 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using System.Diagnostics; |
||||
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.Parser; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Widgets; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a project that has a reference to a unit testing
|
||||
/// framework assembly. Currently only NUnit is supported.
|
||||
/// </summary>
|
||||
public class TestProject : ViewModelBase |
||||
{ |
||||
readonly IProject project; |
||||
readonly ITestFramework testFramework; |
||||
readonly ObservableCollection<TestClass> testClasses; |
||||
|
||||
public TestProject(IProject project, ITestFramework testFramework) |
||||
{ |
||||
this.testFramework = testFramework; |
||||
this.project = project; |
||||
var compilation = SD.ParserService.GetCompilation(project); |
||||
testClasses = new ObservableCollection<TestClass>( |
||||
from td in compilation.MainAssembly.TopLevelTypeDefinitions |
||||
where this.testFramework.IsTestClass(td) |
||||
select new TestClass(td, this.testFramework) |
||||
); |
||||
} |
||||
|
||||
HashSet<FullNameAndTypeParameterCount> dirtyTypeDefinitions = new HashSet<FullNameAndTypeParameterCount>(); |
||||
|
||||
public void NotifyParseInformationChanged(IUnresolvedFile oldUnresolvedFile, IUnresolvedFile newUnresolvedFile) |
||||
{ |
||||
AddToDirtyList(oldUnresolvedFile); |
||||
AddToDirtyList(newUnresolvedFile); |
||||
ProcessUpdates(); |
||||
} |
||||
|
||||
void AddToDirtyList(IUnresolvedFile unresolvedFile) |
||||
{ |
||||
if (unresolvedFile != null) { |
||||
foreach (var td in unresolvedFile.TopLevelTypeDefinitions) { |
||||
dirtyTypeDefinitions.Add(new FullNameAndTypeParameterCount(td.Namespace, td.Name, td.TypeParameters.Count)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ProcessUpdates() |
||||
{ |
||||
var compilation = SD.ParserService.GetCompilation(project); |
||||
var context = new SimpleTypeResolveContext(compilation.MainAssembly); |
||||
|
||||
var testClassNameToIndex = new Dictionary<FullNameAndTypeParameterCount, int>(); |
||||
for (int i = 0; i < testClasses.Count; i++) { |
||||
var primaryPart = testClasses[i].Parts[0]; |
||||
testClassNameToIndex[new FullNameAndTypeParameterCount(primaryPart.Namespace, primaryPart.Name, primaryPart.TypeParameters.Count)] = i; |
||||
} |
||||
|
||||
List<int> testClassesToRemove = new List<int>(); |
||||
foreach (var dirtyTypeDef in dirtyTypeDefinitions) { |
||||
ITypeDefinition typeDef = compilation.MainAssembly.GetTypeDefinition(dirtyTypeDef.Namespace, dirtyTypeDef.Name, dirtyTypeDef.TypeParameterCount); |
||||
int pos; |
||||
if (testClassNameToIndex.TryGetValue(dirtyTypeDef, out pos)) { |
||||
if (typeDef == null) { |
||||
// Test class was removed completely (no parts left)
|
||||
|
||||
// Removing the class messes up the indices stored in the dictionary,
|
||||
// so we'll just remember that we need to remove the class
|
||||
testClassesToRemove.Add(pos); |
||||
} else { |
||||
// Test class was modified
|
||||
// Check if it's still a test class:
|
||||
if (testFramework.IsTestClass(typeDef)) |
||||
testClasses[pos].UpdateClass(typeDef); |
||||
else |
||||
testClassesToRemove.Add(pos); |
||||
} |
||||
} else if (typeDef != null && testFramework.IsTestClass(typeDef)) { |
||||
// Test class was added
|
||||
testClasses.Add(new TestClass(typeDef, testFramework)); |
||||
} |
||||
} |
||||
dirtyTypeDefinitions.Clear(); |
||||
// Now remove the outdated test classes
|
||||
testClassesToRemove.Sort(); |
||||
foreach (int index in testClassesToRemove) { |
||||
testClasses.RemoveAt(index); |
||||
} |
||||
} |
||||
|
||||
public ITestFramework TestFramework { |
||||
get { return testFramework; } |
||||
} |
||||
|
||||
public IProject Project { |
||||
get { return project; } |
||||
} |
||||
|
||||
public ObservableCollection<TestClass> TestClasses { |
||||
get { return testClasses; } |
||||
} |
||||
|
||||
public TestMember GetTestMember(IMember member) |
||||
{ |
||||
if (member != null) |
||||
return GetTestMember(member.ReflectionName); |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
public TestMember GetTestMember(string reflectionName) |
||||
{ |
||||
return TreeTraversal.PostOrder(testClasses, c => c.NestedClasses) |
||||
.SelectMany(c => c.Members) |
||||
.FirstOrDefault(m => reflectionName.Equals(m.Member.ReflectionName, StringComparison.Ordinal)); |
||||
} |
||||
|
||||
public TestClass GetTestClass(ITypeDefinition typeDefinition) |
||||
{ |
||||
if (typeDefinition != null) |
||||
return GetTestClass(typeDefinition.ReflectionName); |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
public TestClass GetTestClass(string reflectionName) |
||||
{ |
||||
int pos = reflectionName.LastIndexOf('+'); |
||||
if (pos < 0) { |
||||
// top-level class
|
||||
foreach (var tc in testClasses) { |
||||
if (tc.QualifiedName == reflectionName) |
||||
return tc; |
||||
} |
||||
} else { |
||||
// nested class
|
||||
TestClass declaringClass = GetTestClass(reflectionName.Substring(0, pos)); |
||||
if (declaringClass != null) { |
||||
return declaringClass.NestedClasses.FirstOrDefault(t => t.QualifiedName == reflectionName); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public void UpdateTestResult(TestResult result) |
||||
{ |
||||
TestClass testClass = GetTestClass(result.Name); |
||||
if (testClass != null) { |
||||
testClass.UpdateTestResult(result); |
||||
TestResult = GetTestResult(testClasses); |
||||
} |
||||
} |
||||
|
||||
public void ResetTestResults() |
||||
{ |
||||
foreach (var testClass in testClasses) |
||||
testClass.ResetTestResults(); |
||||
TestResult = TestResultType.None; |
||||
} |
||||
|
||||
TestResultType testResult; |
||||
|
||||
/// <summary>
|
||||
/// Gets the test result for this project.
|
||||
/// </summary>
|
||||
public TestResultType TestResult { |
||||
get { return testResult; } |
||||
set { SetAndNotifyPropertyChanged(ref testResult, value); } |
||||
} |
||||
|
||||
static TestResultType GetTestResult(IList<TestClass> 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; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// NUnit test fixture.
|
||||
/// </summary>
|
||||
public class NUnitTestClass : TestBase |
||||
{ |
||||
ITestProject parentProject; |
||||
IUnresolvedTypeDefinition primaryPart; |
||||
|
||||
public NUnitTestClass(ITestProject parentProject, ITypeDefinition typeDefinition) |
||||
{ |
||||
this.parentProject = parentProject; |
||||
UpdateTestClass(typeDefinition); |
||||
BindResultToCompositeResultOfNestedTests(); |
||||
} |
||||
|
||||
public override ITestProject ParentProject { |
||||
get { return parentProject; } |
||||
} |
||||
|
||||
public override string DisplayName { |
||||
get { return primaryPart.Name; } |
||||
} |
||||
|
||||
public string ReflectionName { |
||||
get { return primaryPart.ReflectionName; } |
||||
} |
||||
|
||||
public override bool SupportsGoToDefinition { |
||||
get { return true; } |
||||
} |
||||
|
||||
ITypeDefinition Resolve() |
||||
{ |
||||
ICompilation compilation = SD.ParserService.GetCompilation(parentProject.Project); |
||||
IType type = primaryPart.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)); |
||||
return type.GetDefinition(); |
||||
} |
||||
|
||||
public override void GoToDefinition() |
||||
{ |
||||
ITypeDefinition typeDefinition = Resolve(); |
||||
if (typeDefinition != null) |
||||
NavigationService.NavigateTo(typeDefinition); |
||||
} |
||||
|
||||
public void UpdateTestClass(ITypeDefinition typeDefinition) |
||||
{ |
||||
primaryPart = typeDefinition.Parts[0]; |
||||
if (this.NestedTestsInitialized) { |
||||
this.NestedTests.Clear(); |
||||
this.NestedTests.AddRange(from nt in typeDefinition.NestedTypes |
||||
where NUnitTestFramework.IsTestClass(nt) |
||||
select new NUnitTestClass(parentProject, nt)); |
||||
this.NestedTests.AddRange(from m in typeDefinition.Methods |
||||
where NUnitTestFramework.IsTestMember(m) |
||||
select new NUnitTestMethod(parentProject, (IUnresolvedMethod)m.UnresolvedMember)); |
||||
} |
||||
} |
||||
|
||||
public override bool CanExpandNestedTests { |
||||
get { return true; } |
||||
} |
||||
|
||||
protected override void OnNestedTestsInitialized() |
||||
{ |
||||
ITypeDefinition typeDefinition = Resolve(); |
||||
if (typeDefinition != null) { |
||||
UpdateTestClass(typeDefinition); |
||||
} |
||||
base.OnNestedTestsInitialized(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
// 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 |
||||
{ |
||||
/// <summary>
|
||||
/// NUnit test method.
|
||||
/// </summary>
|
||||
public class NUnitTestMethod : TestBase |
||||
{ |
||||
ITestProject parentProject; |
||||
IUnresolvedMethod method; |
||||
|
||||
public NUnitTestMethod(ITestProject parentProject, IUnresolvedMethod method) |
||||
{ |
||||
if (parentProject == null) |
||||
throw new ArgumentNullException("parentProject"); |
||||
if (method == null) |
||||
throw new ArgumentNullException("method"); |
||||
this.parentProject = parentProject; |
||||
this.method = method; |
||||
} |
||||
|
||||
public override ITestProject ParentProject { |
||||
get { return parentProject; } |
||||
} |
||||
|
||||
public override string DisplayName { |
||||
get { return method.Name; } |
||||
} |
||||
} |
||||
} |
@ -1,100 +0,0 @@
@@ -1,100 +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.Specialized; |
||||
using System.ComponentModel; |
||||
|
||||
using ICSharpCode.SharpDevelop; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
/// <summary>
|
||||
/// Represents a TestClass in the tree view.
|
||||
/// </summary>
|
||||
public class ClassUnitTestNode : UnitTestNode |
||||
{ |
||||
TestClass testClass; |
||||
|
||||
public TestClass TestClass { |
||||
get { return testClass; } |
||||
} |
||||
|
||||
public ClassUnitTestNode(TestClass testClass) |
||||
{ |
||||
this.testClass = testClass; |
||||
this.testClass.TestResultChanged += delegate { |
||||
RaisePropertyChanged("Icon"); |
||||
RaisePropertyChanged("ExpandedIcon"); |
||||
var parentNode = Parent; |
||||
while (parentNode is NamespaceUnitTestNode) { |
||||
parentNode.RaisePropertyChanged("Icon"); |
||||
parentNode.RaisePropertyChanged("ExpandedIcon"); |
||||
parentNode = parentNode.Parent; |
||||
} |
||||
}; |
||||
testClass.Members.CollectionChanged += TestMembersCollectionChanged; |
||||
testClass.NestedClasses.CollectionChanged += NestedClassesCollectionChanged; |
||||
LazyLoading = true; |
||||
} |
||||
|
||||
void NestedClassesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
switch (e.Action) { |
||||
case NotifyCollectionChangedAction.Add: |
||||
foreach (TestClass c in e.NewItems) { |
||||
Children.OrderedInsert(new ClassUnitTestNode(c), NodeTextComparer); |
||||
} |
||||
break; |
||||
case NotifyCollectionChangedAction.Remove: |
||||
foreach (TestClass c in e.OldItems) { |
||||
Children.RemoveAll(n => n is ClassUnitTestNode && ((ClassUnitTestNode)n).TestClass == c); |
||||
} |
||||
break; |
||||
case NotifyCollectionChangedAction.Reset: |
||||
LoadChildren(); |
||||
break; |
||||
default: |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
|
||||
void TestMembersCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
switch (e.Action) { |
||||
case NotifyCollectionChangedAction.Add: |
||||
foreach (TestMember m in e.NewItems) { |
||||
Children.OrderedInsert(new MemberUnitTestNode(m), NodeTextComparer); |
||||
} |
||||
break; |
||||
case NotifyCollectionChangedAction.Remove: |
||||
foreach (TestMember m in e.OldItems) { |
||||
Children.RemoveAll(n => n is MemberUnitTestNode && ((MemberUnitTestNode)n).TestMember == m); |
||||
} |
||||
break; |
||||
case NotifyCollectionChangedAction.Reset: |
||||
LoadChildren(); |
||||
break; |
||||
default: |
||||
throw new NotSupportedException(); |
||||
} |
||||
} |
||||
|
||||
protected override void LoadChildren() |
||||
{ |
||||
Children.Clear(); |
||||
foreach (TestClass c in testClass.NestedClasses) |
||||
Children.Add(new ClassUnitTestNode(c)); |
||||
foreach (TestMember m in testClass.Members) |
||||
Children.Add(new MemberUnitTestNode(m)); |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return testClass.Name; } |
||||
} |
||||
|
||||
internal override TestResultType TestResultType { |
||||
get { return testClass.TestResult; } |
||||
} |
||||
} |
||||
} |
@ -1,44 +0,0 @@
@@ -1,44 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Specialized; |
||||
using System.ComponentModel; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.TreeView; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class MemberUnitTestNode : UnitTestNode |
||||
{ |
||||
TestMember testMember; |
||||
|
||||
public TestMember TestMember { |
||||
get { return testMember; } |
||||
} |
||||
|
||||
public MemberUnitTestNode(TestMember testMember) |
||||
{ |
||||
this.testMember = testMember; |
||||
this.testMember.TestResultChanged += delegate { |
||||
RaisePropertyChanged("Icon"); |
||||
RaisePropertyChanged("ExpandedIcon"); |
||||
}; |
||||
} |
||||
|
||||
internal override TestResultType TestResultType { |
||||
get { return this.testMember.TestResult; } |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return testMember.Member.Name; } |
||||
} |
||||
|
||||
public override void ActivateItem(System.Windows.RoutedEventArgs e) |
||||
{ |
||||
var region = testMember.Member.Region; |
||||
SD.FileService.JumpToFilePosition(new FileName(region.FileName), region.BeginLine, region.BeginColumn); |
||||
} |
||||
} |
||||
} |
@ -1,63 +0,0 @@
@@ -1,63 +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.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 : UnitTestNode |
||||
{ |
||||
readonly string shortName; |
||||
readonly string namespaceName; |
||||
|
||||
/// <summary>
|
||||
/// Gets the namespace suffix (namespace portion after the root namespace)
|
||||
/// </summary>
|
||||
public string ShortName { |
||||
get { return shortName; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the full namespace
|
||||
/// </summary>
|
||||
public string NamespaceName { |
||||
get { return namespaceName; } |
||||
} |
||||
|
||||
public NamespaceUnitTestNode(string namespaceName) |
||||
{ |
||||
if (namespaceName == null) |
||||
throw new ArgumentNullException("namespaceName"); |
||||
this.namespaceName = namespaceName; |
||||
this.shortName = namespaceName.Substring(namespaceName.IndexOf('.') + 1); |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return shortName; } |
||||
} |
||||
|
||||
internal override TestResultType TestResultType { |
||||
get { |
||||
if (Children.Count == 0) return TestResultType.None; |
||||
if (Children.OfType<UnitTestNode>().Any(node => node.TestResultType == TestResultType.Failure)) |
||||
return TestResultType.Failure; |
||||
if (Children.OfType<UnitTestNode>().Any(node => node.TestResultType == TestResultType.None)) |
||||
return TestResultType.None; |
||||
if (Children.OfType<UnitTestNode>().Any(node => node.TestResultType == TestResultType.Ignored)) |
||||
return TestResultType.Ignored; |
||||
return TestResultType.Success; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,136 +0,0 @@
@@ -1,136 +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.Specialized; |
||||
using System.ComponentModel; |
||||
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 ProjectUnitTestNode : UnitTestNode |
||||
{ |
||||
TestProject project; |
||||
|
||||
public TestProject Project { |
||||
get { return project; } |
||||
} |
||||
|
||||
public ProjectUnitTestNode(TestProject project) |
||||
{ |
||||
this.project = project; |
||||
project.TestClasses.CollectionChanged += TestClassesCollectionChanged; |
||||
project.PropertyChanged += ProjectPropertyChanged; |
||||
LazyLoading = true; |
||||
} |
||||
|
||||
void ProjectPropertyChanged(object sender, PropertyChangedEventArgs e) |
||||
{ |
||||
if (e.PropertyName == "TestResult") { |
||||
RaisePropertyChanged("Icon"); |
||||
RaisePropertyChanged("ExpandedIcon"); |
||||
} |
||||
} |
||||
|
||||
void TestClassesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
switch (e.Action) { |
||||
case NotifyCollectionChangedAction.Add: |
||||
foreach (TestClass c in e.NewItems) { |
||||
if (c.Namespace == "<invalid>") continue; |
||||
UnitTestNode node = FindOrCreateNamespace(this, project.Project.RootNamespace, c.Namespace); |
||||
node.Children.OrderedInsert(new ClassUnitTestNode(c), NodeTextComparer); |
||||
} |
||||
break; |
||||
case NotifyCollectionChangedAction.Remove: |
||||
foreach (TestClass c in e.OldItems) { |
||||
if (c.Namespace == "<invalid>") continue; |
||||
SharpTreeNode node = FindNamespace(this, project.Project.RootNamespace, c.Namespace); |
||||
node.Children.RemoveAll(n => n is ClassUnitTestNode && ((ClassUnitTestNode)n).TestClass == c); |
||||
while (node is NamespaceUnitTestNode && node.Children.Count == 0) { |
||||
var parent = node.Parent; |
||||
if (parent == null) break; |
||||
parent.Children.Remove(node); |
||||
node = parent; |
||||
} |
||||
} |
||||
break; |
||||
case NotifyCollectionChangedAction.Reset: |
||||
LoadChildren(); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static UnitTestNode FindOrCreateNamespace(UnitTestNode parent, string parentNamespace, string @namespace) |
||||
{ |
||||
if (parentNamespace == @namespace) |
||||
return parent; |
||||
foreach (var node in parent.Children.OfType<NamespaceUnitTestNode>()) { |
||||
if (@namespace == node.NamespaceName) |
||||
return node; |
||||
if (@namespace.StartsWith(node.NamespaceName + ".", StringComparison.Ordinal)) { |
||||
return FindOrCreateNamespace(node, node.NamespaceName, @namespace); |
||||
} |
||||
} |
||||
// Create missing namespace node:
|
||||
|
||||
// Figure out which part of the namespace we can remove due to the parent namespace:
|
||||
int startPos = 0; |
||||
if (@namespace.StartsWith(parentNamespace + ".", StringComparison.Ordinal)) { |
||||
startPos = parentNamespace.Length + 1; |
||||
} |
||||
// Get the next dot
|
||||
int dotPos = @namespace.IndexOf('.', startPos); |
||||
if (dotPos < 0) { |
||||
var newNode = new NamespaceUnitTestNode(@namespace); |
||||
parent.Children.OrderedInsert(newNode, NodeTextComparer); |
||||
return newNode; |
||||
} else { |
||||
var newNode = new NamespaceUnitTestNode(@namespace.Substring(0, dotPos)); |
||||
parent.Children.OrderedInsert(newNode, NodeTextComparer); |
||||
return FindOrCreateNamespace(newNode, newNode.NamespaceName, @namespace); |
||||
} |
||||
} |
||||
|
||||
static UnitTestNode FindNamespace(UnitTestNode parent, string parentNamespace, string @namespace) |
||||
{ |
||||
if (parentNamespace == @namespace) |
||||
return parent; |
||||
foreach (var node in parent.Children.OfType<NamespaceUnitTestNode>()) { |
||||
if (@namespace == node.NamespaceName) |
||||
return node; |
||||
if (@namespace.StartsWith(node.NamespaceName + ".", StringComparison.Ordinal)) { |
||||
return FindNamespace(node, node.NamespaceName, @namespace); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
protected override void LoadChildren() |
||||
{ |
||||
Children.Clear(); |
||||
foreach (var g in project.TestClasses.Select(c => new ClassUnitTestNode(c)).GroupBy(tc => tc.TestClass.Namespace)) { |
||||
if (g.Key == "<invalid>") continue; |
||||
UnitTestNode node = FindOrCreateNamespace(this, project.Project.RootNamespace, g.Key); |
||||
node.Children.AddRange(g.OrderBy(NodeTextComparer)); |
||||
} |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return project.Project.Name; } |
||||
} |
||||
|
||||
internal override TestResultType TestResultType { |
||||
get { return project.TestResult; } |
||||
} |
||||
} |
||||
} |
@ -1,76 +0,0 @@
@@ -1,76 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.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 |
||||
{ |
||||
/// <summary>
|
||||
/// Description of RootUnitTestNode.
|
||||
/// </summary>
|
||||
public class RootUnitTestNode : UnitTestNode |
||||
{ |
||||
readonly TestSolution testSolution; |
||||
|
||||
public RootUnitTestNode(TestSolution testSolution) |
||||
{ |
||||
this.testSolution = testSolution; |
||||
testSolution.TestableProjects.CollectionChanged += TestSolution_TestableProjects_CollectionChanged; |
||||
LazyLoading = true; |
||||
} |
||||
|
||||
void TestSolution_TestableProjects_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
switch (e.Action) { |
||||
case NotifyCollectionChangedAction.Add: |
||||
Children.AddRange(e.NewItems.OfType<TestProject>().Select(p => new ProjectUnitTestNode(p))); |
||||
break; |
||||
case NotifyCollectionChangedAction.Remove: |
||||
Children.RemoveAll(node => node is ProjectUnitTestNode && e.OldItems.OfType<TestProject>().Any(p => p.Project == ((ProjectUnitTestNode)node).Project)); |
||||
break; |
||||
case NotifyCollectionChangedAction.Reset: |
||||
LoadChildren(); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
protected override void LoadChildren() |
||||
{ |
||||
Children.Clear(); |
||||
Children.AddRange(testSolution.TestableProjects.Select(p => new ProjectUnitTestNode(p))); |
||||
} |
||||
|
||||
public override object Text { |
||||
get { return ResourceService.GetString("ICSharpCode.UnitTesting.AllTestsTreeNode.Text"); } |
||||
} |
||||
|
||||
internal override TestResultType TestResultType { |
||||
get { |
||||
if (Children.Count == 0) return TestResultType.None; |
||||
if (Children.OfType<UnitTestNode>().Any(node => node.TestResultType == TestResultType.Failure)) |
||||
return TestResultType.Failure; |
||||
if (Children.OfType<UnitTestNode>().Any(node => node.TestResultType == TestResultType.None)) |
||||
return TestResultType.None; |
||||
if (Children.OfType<UnitTestNode>().Any(node => node.TestResultType == TestResultType.Ignored)) |
||||
return TestResultType.Ignored; |
||||
return TestResultType.Success; |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue