Browse Source

Show classes and methods in the unit test treeview.

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
cc8ce304a3
  1. 11
      src/AddIns/Analysis/UnitTesting/Frameworks/ITestFramework.cs
  2. 8
      src/AddIns/Analysis/UnitTesting/Model/ITest.cs
  3. 5
      src/AddIns/Analysis/UnitTesting/Model/ITestSolution.cs
  4. 22
      src/AddIns/Analysis/UnitTesting/Model/TestBase.cs
  5. 198
      src/AddIns/Analysis/UnitTesting/Model/TestClass.cs
  6. 67
      src/AddIns/Analysis/UnitTesting/Model/TestMember.cs
  7. 196
      src/AddIns/Analysis/UnitTesting/Model/TestProject.cs
  8. 183
      src/AddIns/Analysis/UnitTesting/Model/TestProjectBase.cs
  9. 83
      src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestClass.cs
  10. 35
      src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestFramework.cs
  11. 35
      src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestMethod.cs
  12. 34
      src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestProject.cs
  13. 100
      src/AddIns/Analysis/UnitTesting/TreeView/ClassUnitTestNode.cs
  14. 44
      src/AddIns/Analysis/UnitTesting/TreeView/MemberUnitTestNode.cs
  15. 63
      src/AddIns/Analysis/UnitTesting/TreeView/NamespaceUnitTestNode.cs
  16. 136
      src/AddIns/Analysis/UnitTesting/TreeView/ProjectUnitTestNode.cs
  17. 76
      src/AddIns/Analysis/UnitTesting/TreeView/RootUnitTestNode.cs
  18. 5
      src/AddIns/Analysis/UnitTesting/TreeView/UnitTestNode.cs
  19. 2
      src/AddIns/Analysis/UnitTesting/UnitTesting.csproj
  20. 2
      src/Main/Base/Project/Src/Util/AtomicBoolean.cs

11
src/AddIns/Analysis/UnitTesting/Frameworks/ITestFramework.cs

@ -19,16 +19,5 @@ namespace ICSharpCode.UnitTesting @@ -19,16 +19,5 @@ namespace ICSharpCode.UnitTesting
/// Creates a new test project based on the specified project.
/// </summary>
ITestProject CreateTestProject(ITestSolution parentSolution, IProject project);
/*
bool IsTestMember(IMember member);
bool IsTestClass(ITypeDefinition testClass);
IEnumerable<TestMember> GetTestMembersFor(ITypeDefinition typeDefinition);
ITestRunner CreateTestRunner();
ITestRunner CreateTestDebugger();
bool IsBuildNeededBeforeTestRun { get; }*/
}
}

8
src/AddIns/Analysis/UnitTesting/Model/ITest.cs

@ -16,6 +16,14 @@ namespace ICSharpCode.UnitTesting @@ -16,6 +16,14 @@ namespace ICSharpCode.UnitTesting
/// </summary>
TestCollection NestedTests { get; }
/// <summary>
/// Gets whether this test allows expanding the list of nested tests.
/// If possible, this property should return the same value as NestedTests.Count.
/// However, when doing so is expensive (e.g. due to lazy initialization), this
/// property may return true even if there are no nested tests.
/// </summary>
bool CanExpandNestedTests { get; }
/// <summary>
/// Gets the parent project that owns this test.
/// </summary>

5
src/AddIns/Analysis/UnitTesting/Model/ITestSolution.cs

@ -13,11 +13,6 @@ namespace ICSharpCode.UnitTesting @@ -13,11 +13,6 @@ namespace ICSharpCode.UnitTesting
/// </summary>
public interface ITestSolution : ITest
{
// /// <summary>
// /// Gets the list of all test projects.
// /// </summary>
// ObservableCollection<ITestProject> TestableProjects { get; }
/// <summary>
/// Gets the test project for the specified project.
/// Returns null if the project is not a test project.

22
src/AddIns/Analysis/UnitTesting/Model/TestBase.cs

@ -86,18 +86,30 @@ namespace ICSharpCode.UnitTesting @@ -86,18 +86,30 @@ namespace ICSharpCode.UnitTesting
public TestCollection NestedTests {
get {
if (nestedTests == null) {
nestedTests = InitializeNestedTests();
OnNestedTestsInitialized();
}
EnsureNestedTestsInitialized();
return nestedTests;
}
}
public virtual bool CanExpandNestedTests {
get {
EnsureNestedTestsInitialized();
return nestedTests.Count != 0;
}
}
protected bool NestedTestsInitialized {
get { return nestedTests != null; }
}
protected void EnsureNestedTestsInitialized()
{
if (nestedTests == null) {
nestedTests = InitializeNestedTests();
OnNestedTestsInitialized();
}
}
protected virtual TestCollection InitializeNestedTests()
{
return new TestCollection();
@ -130,7 +142,7 @@ namespace ICSharpCode.UnitTesting @@ -130,7 +142,7 @@ namespace ICSharpCode.UnitTesting
get { return false; }
}
public void GoToDefinition()
public virtual void GoToDefinition()
{
throw new NotSupportedException();
}

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

@ -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);
}
}
}

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

@ -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);
}
}
}

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

@ -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;
}
}
}

183
src/AddIns/Analysis/UnitTesting/Model/TestProjectBase.cs

@ -3,8 +3,12 @@ @@ -3,8 +3,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
@ -12,10 +16,14 @@ namespace ICSharpCode.UnitTesting @@ -12,10 +16,14 @@ namespace ICSharpCode.UnitTesting
{
/// <summary>
/// Base class for <see cref="ITestProject"/> implementations.
///
/// This implementation will show a tree of namespaces, with each namespace
/// containing a list of test fixtures (ITests created from type definitions).
/// </summary>
public abstract class TestProjectBase : TestBase, ITestProject
{
IProject project;
Dictionary<FullNameAndTypeParameterCount, ITest> topLevelTestClasses = new Dictionary<FullNameAndTypeParameterCount, ITest>();
public TestProjectBase(IProject project)
{
@ -25,6 +33,14 @@ namespace ICSharpCode.UnitTesting @@ -25,6 +33,14 @@ namespace ICSharpCode.UnitTesting
BindResultToCompositeResultOfNestedTests();
}
public abstract Task RunTestsAsync(IEnumerable<ITest> tests, TestExecutionOptions options, IProgressMonitor progressMonitor);
public abstract ITest GetTestForEntity(IEntity entity);
// Test class management methods
public abstract bool IsTestClass(ITypeDefinition typeDefinition);
public abstract ITest CreateTestClass(ITypeDefinition typeDefinition);
public abstract void UpdateTestClass(ITest test, ITypeDefinition typeDefinition);
public IProject Project {
get { return project; }
}
@ -37,22 +53,177 @@ namespace ICSharpCode.UnitTesting @@ -37,22 +53,177 @@ namespace ICSharpCode.UnitTesting
get { return project.Name; }
}
public virtual ITest GetTestForEntity(IEntity entity)
{
return null;
}
public virtual IBuildable GetBuildableForTesting()
{
return project;
}
#region NotifyParseInformationChanged
public void NotifyParseInformationChanged(IUnresolvedFile oldUnresolvedFile, IUnresolvedFile newUnresolvedFile)
{
// We use delay-loading: the nested tests of a project are
// initializedhmm
if (!NestedTestsInitialized)
return;
var dirtyTypeDefinitions = new HashSet<FullNameAndTypeParameterCount>();
AddToDirtyList(oldUnresolvedFile, dirtyTypeDefinitions);
AddToDirtyList(newUnresolvedFile, dirtyTypeDefinitions);
ProcessUpdates(dirtyTypeDefinitions);
}
public abstract Task RunTestsAsync(IEnumerable<ITest> tests, TestExecutionOptions options, IProgressMonitor progressMonitor);
public override bool CanExpandNestedTests {
get { return true; }
}
protected override void OnNestedTestsInitialized()
{
var compilation = SD.ParserService.GetCompilation(project);
foreach (var typeDef in compilation.MainAssembly.TopLevelTypeDefinitions) {
UpdateType(new FullNameAndTypeParameterCount(typeDef.Namespace, typeDef.Name, typeDef.TypeParameterCount), typeDef);
}
base.OnNestedTestsInitialized();
}
void AddToDirtyList(IUnresolvedFile unresolvedFile, HashSet<FullNameAndTypeParameterCount> dirtyTypeDefinitions)
{
if (unresolvedFile != null) {
foreach (var td in unresolvedFile.TopLevelTypeDefinitions) {
dirtyTypeDefinitions.Add(new FullNameAndTypeParameterCount(td.Namespace, td.Name, td.TypeParameters.Count));
}
}
}
void ProcessUpdates(HashSet<FullNameAndTypeParameterCount> dirtyTypeDefinitions)
{
var compilation = SD.ParserService.GetCompilation(project);
var context = new SimpleTypeResolveContext(compilation.MainAssembly);
foreach (var dirtyTypeDef in dirtyTypeDefinitions) {
ITypeDefinition typeDef = compilation.MainAssembly.GetTypeDefinition(dirtyTypeDef.Namespace, dirtyTypeDef.Name, dirtyTypeDef.TypeParameterCount);
UpdateType(dirtyTypeDef, typeDef);
}
}
/// <summary>
/// Adds/Updates/Removes the test class for the type definition.
/// </summary>
void UpdateType(FullNameAndTypeParameterCount dirtyTypeDef, ITypeDefinition typeDef)
{
ITest test;
if (topLevelTestClasses.TryGetValue(dirtyTypeDef, out test)) {
if (typeDef == null) {
// Test class was removed completely (no parts left)
RemoveTestClass(dirtyTypeDef, test);
} else {
// Test class was modified
// Check if it's still a test class:
if (IsTestClass(typeDef))
UpdateTestClass(test, typeDef);
else
RemoveTestClass(dirtyTypeDef, test);
}
} else if (typeDef != null) {
// Test class was added
var testClass = CreateTestClass(typeDef);
if (testClass != null)
AddTestClass(dirtyTypeDef, testClass);
}
}
#endregion
#region Namespace Management
protected ITest GetTestClass(FullNameAndTypeParameterCount fullName)
{
EnsureNestedTestsInitialized();
return topLevelTestClasses.GetOrDefault(fullName);
}
void AddTestClass(FullNameAndTypeParameterCount fullName, ITest test)
{
topLevelTestClasses.Add(fullName, test);
ITest testNamespace = FindOrCreateNamespace(this, project.RootNamespace, fullName.Namespace);
testNamespace.NestedTests.Add(test);
}
void RemoveTestClass(FullNameAndTypeParameterCount fullName, ITest test)
{
topLevelTestClasses.Remove(fullName);
ITest testNamespace = FindNamespace(this, project.RootNamespace, fullName.Namespace);
if (testNamespace != null) {
testNamespace.NestedTests.Remove(test);
if (testNamespace.NestedTests.Count == 0) {
// Remove the namespace
RemoveTestNamespace(this, project.RootNamespace, fullName.Namespace);
}
}
}
ITest FindOrCreateNamespace(ITest parent, string parentNamespace, string @namespace)
{
if (parentNamespace == @namespace)
return parent;
foreach (var node in parent.NestedTests.OfType<TestNamespace>()) {
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 TestNamespace(this, @namespace);
parent.NestedTests.Add(newNode);
return newNode;
} else {
var newNode = new TestNamespace(this, @namespace.Substring(0, dotPos));
parent.NestedTests.Add(newNode);
return FindOrCreateNamespace(newNode, newNode.NamespaceName, @namespace);
}
}
static ITest FindNamespace(ITest parent, string parentNamespace, string @namespace)
{
if (parentNamespace == @namespace)
return parent;
foreach (var node in parent.NestedTests.OfType<TestNamespace>()) {
if (@namespace == node.NamespaceName)
return node;
if (@namespace.StartsWith(node.NamespaceName + ".", StringComparison.Ordinal)) {
return FindNamespace(node, node.NamespaceName, @namespace);
}
}
return null;
}
/// <summary>
/// Removes the target namespace and all parent namespaces that are empty after the removal.
/// </summary>
static void RemoveTestNamespace(ITest parent, string parentNamespace, string @namespace)
{
if (parentNamespace == @namespace)
return;
foreach (var node in parent.NestedTests.OfType<TestNamespace>()) {
if (@namespace == node.NamespaceName) {
parent.NestedTests.Remove(node);
return;
}
if (@namespace.StartsWith(node.NamespaceName + ".", StringComparison.Ordinal)) {
RemoveTestNamespace(node, node.NamespaceName, @namespace);
if (node.NestedTests.Count == 0) {
parent.NestedTests.Remove(node);
}
return;
}
}
}
#endregion
}
}

83
src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestClass.cs

@ -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();
}
}
}

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

@ -14,9 +14,9 @@ namespace ICSharpCode.UnitTesting @@ -14,9 +14,9 @@ namespace ICSharpCode.UnitTesting
{
public class NUnitTestFramework : ITestFramework
{
readonly ITypeReference testAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestAttribute", 0);
readonly ITypeReference testCaseAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestCaseAttribute", 0);
readonly ITypeReference testFixtureAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestFixtureAttribute", 0);
static readonly ITypeReference testAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestAttribute", 0);
static readonly ITypeReference testCaseAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestCaseAttribute", 0);
static readonly ITypeReference testFixtureAttributeRef = new GetClassTypeReference("NUnit.Framework", "TestFixtureAttribute", 0);
/// <summary>
/// Determines whether the project is a test project. A project
@ -35,19 +35,7 @@ namespace ICSharpCode.UnitTesting @@ -35,19 +35,7 @@ namespace ICSharpCode.UnitTesting
return new NUnitTestProject(project);
}
/*
public ITestRunner CreateTestRunner()
{
return new NUnitTestRunner();
}
public ITestRunner CreateTestDebugger()
{
return new NUnitTestDebugger();
}
public bool IsTestMember(IMember member)
public static bool IsTestMember(IMember member)
{
if (member == null || member.EntityType != EntityType.Method)
return false;
@ -60,21 +48,18 @@ namespace ICSharpCode.UnitTesting @@ -60,21 +48,18 @@ namespace ICSharpCode.UnitTesting
return false;
}
public bool IsTestClass(ITypeDefinition type)
public static bool IsTestClass(ITypeDefinition type)
{
if (type == null || type.IsAbstract)
if (type == null)
return false;
if (type.NestedTypes.Any(IsTestClass))
return true;
if (type.IsAbstract)
return false;
var testFixtureAttribute = testFixtureAttributeRef.Resolve(type.Compilation);
if (type.Attributes.Any(attr => attr.AttributeType.Equals(testFixtureAttributeRef)))
return true;
else
return type.Methods.Any(IsTestMember);
}
public IEnumerable<TestMember> GetTestMembersFor(ITypeDefinition typeDefinition)
{
var project = typeDefinition.ParentAssembly.GetProject();
return typeDefinition.Methods.Where(IsTestMember).Select(m => new TestMember(m.UnresolvedMember));
}*/
}
}

35
src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestMethod.cs

@ -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; }
}
}
}

34
src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestProject.cs

@ -4,6 +4,8 @@ @@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
@ -22,5 +24,37 @@ namespace ICSharpCode.UnitTesting @@ -22,5 +24,37 @@ namespace ICSharpCode.UnitTesting
{
throw new NotImplementedException();
}
public override void UpdateTestClass(ITest test, ITypeDefinition typeDefinition)
{
((NUnitTestClass)test).UpdateTestClass(typeDefinition);
}
public override bool IsTestClass(ITypeDefinition typeDefinition)
{
return NUnitTestFramework.IsTestClass(typeDefinition);
}
public override ITest GetTestForEntity(IEntity entity)
{
if (entity.DeclaringTypeDefinition != null) {
ITest testClass = GetTestForEntity(entity.DeclaringTypeDefinition);
throw new NotImplementedException();
} else if (entity is ITypeDefinition) {
// top-level type definition
ITypeDefinition typeDef = (ITypeDefinition)entity;
return GetTestClass(new FullNameAndTypeParameterCount(typeDef.Namespace, typeDef.Name, typeDef.TypeParameterCount));
} else {
return null;
}
}
public override ITest CreateTestClass(ITypeDefinition typeDefinition)
{
if (NUnitTestFramework.IsTestClass(typeDefinition))
return new NUnitTestClass(this, typeDefinition);
else
return null;
}
}
}

100
src/AddIns/Analysis/UnitTesting/TreeView/ClassUnitTestNode.cs

@ -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; }
}
}
}

44
src/AddIns/Analysis/UnitTesting/TreeView/MemberUnitTestNode.cs

@ -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);
}
}
}

63
src/AddIns/Analysis/UnitTesting/TreeView/NamespaceUnitTestNode.cs

@ -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;
}
}
}
}

136
src/AddIns/Analysis/UnitTesting/TreeView/ProjectUnitTestNode.cs

@ -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; }
}
}
}

76
src/AddIns/Analysis/UnitTesting/TreeView/RootUnitTestNode.cs

@ -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;
}
}
}
}

5
src/AddIns/Analysis/UnitTesting/TreeView/UnitTestNode.cs

@ -30,6 +30,7 @@ namespace ICSharpCode.UnitTesting @@ -30,6 +30,7 @@ namespace ICSharpCode.UnitTesting
void DetachEventHandlers()
{
// TODO: figure out when we can call this method
test.DisplayNameChanged -= test_NameChanged;
test.ResultChanged -= test_ResultChanged;
// If children loaded, also detach the collection change event handler
@ -43,6 +44,10 @@ namespace ICSharpCode.UnitTesting @@ -43,6 +44,10 @@ namespace ICSharpCode.UnitTesting
}
#region Manage Children
public override bool ShowExpander {
get { return test.CanExpandNestedTests && base.ShowExpander; }
}
protected override void LoadChildren()
{
Children.Clear();

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

@ -92,6 +92,8 @@ @@ -92,6 +92,8 @@
<Compile Include="Model\TestProjectBase.cs" />
<Compile Include="Model\TestResult.cs" />
<Compile Include="Model\TestResultTypeChangedEventArgs.cs" />
<Compile Include="NUnit\NUnitTestClass.cs" />
<Compile Include="NUnit\NUnitTestMethod.cs" />
<Compile Include="NUnit\NUnitTestProject.cs" />
<Compile Include="Pad\UnitTestsPad.cs" />
<Compile Include="Interfaces\UnitTestBuildProjectFactory.cs" />

2
src/Main/Base/Project/Src/Util/AtomicBoolean.cs

@ -54,7 +54,7 @@ namespace ICSharpCode.SharpDevelop @@ -54,7 +54,7 @@ namespace ICSharpCode.SharpDevelop
/// <inheritdoc/>
public override bool Equals(object obj)
{
return (obj is AtomicBoolean) && val == ((AtomicBoolean)obj).val;
return (obj is AtomicBoolean) && this.Value == ((AtomicBoolean)obj).Value;
}
}
}

Loading…
Cancel
Save