1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.Collections.Generic;
6
using ICSharpCode.Core;
7
using ICSharpCode.SharpDevelop.Dom;
8
using ICSharpCode.SharpDevelop.Project;
10
namespace ICSharpCode.UnitTesting
13
/// Represents a project that has a reference to a unit testing
14
/// framework assembly. Currently only NUnit is supported.
16
public class TestProject
19
IProjectContent projectContent;
20
TestClassCollection testClasses;
21
List<string> rootNamespaces;
22
IRegisteredTestFrameworks testFrameworks;
24
public TestProject(IProject project, IProjectContent projectContent, IRegisteredTestFrameworks testFrameworks)
26
this.project = project;
27
this.projectContent = projectContent;
28
this.testFrameworks = testFrameworks;
31
public IProject Project {
32
get { return project; }
36
/// Gets the test classes in this project.
38
public TestClassCollection TestClasses {
40
if (testClasses == null) {
48
/// Gets the test classes that exist in the specified namespace.
50
public TestClass[] GetTestClasses(string ns)
52
return TestClass.GetTestClasses(TestClasses, ns);
56
/// Gets the test classes whose namespaces start with the specified string.
58
public TestClass[] GetAllTestClasses(string namespaceStartsWith)
60
return TestClass.GetAllTestClasses(TestClasses, namespaceStartsWith);
64
/// Gets all the child namespaces with the specified parent
65
/// namespace. The parent namespace can be one or more
66
/// namespaces separated with a period.
68
public string[] GetChildNamespaces(string parentNamespace)
70
return TestClass.GetChildNamespaces(TestClasses, parentNamespace);
74
/// Gets the project's name.
77
get { return project.Name; }
81
/// Gets the distinct root namespaces for all this project.
84
/// If one of the namespaces is 'ICSharpCode.XmlEditor' then this
85
/// method will return 'ICSharpCode' as one of the root namespaces.
87
public IList<string> RootNamespaces {
89
if (rootNamespaces == null) {
92
return rootNamespaces;
97
/// Updates the test method based on the test result.
99
public void UpdateTestResult(TestResult testResult)
101
TestClasses.UpdateTestResult(testResult);
105
/// Sets all the test results back to none.
107
public void ResetTestResults()
109
TestClasses.ResetTestResults();
113
/// Updates the classes and methods based on the new parse information.
115
/// <param name="oldUnit">The old compiliation unit
116
/// (ParseInformationEventArgs.ParseInformation.BestCompilationUnit as ICompilationUnit)</param>
117
/// <param name="newUnit">The new compilation unit
118
/// (ParseInformationEventArgs.CompilationUnit).</param>
119
public void UpdateParseInfo(ICompilationUnit oldUnit, ICompilationUnit newUnit)
121
if (!IsParseInfoForThisProject(oldUnit, newUnit)) {
125
RemovedClasses removedClasses = new RemovedClasses();
127
if (oldUnit != null) {
128
removedClasses.Add(oldUnit.Classes);
130
if (newUnit != null) {
131
foreach (IClass c in newUnit.Classes) {
133
foreach (IClass innerClass in c.InnerClasses) {
134
UpdateTestClass(innerClass);
135
removedClasses.Remove(innerClass);
137
removedClasses.Remove(c);
141
// Remove missing classes.
142
foreach (IClass c in removedClasses.GetMissingClasses()) {
143
IClass existingClass = GetExistingTestClassInProject(c);
144
if (existingClass != null) {
145
UpdateTestClass(existingClass);
147
TestClasses.Remove(c.DotNetName);
153
/// Determines whether the new parse information is for this test
156
public bool IsParseInfoForThisProject(ICompilationUnit oldUnit, ICompilationUnit newUnit)
158
ICompilationUnit unit = oldUnit;
163
return Object.ReferenceEquals(unit.ProjectContent, this.projectContent);
169
/// Adds a new class to the test project's classes only if
170
/// the class is a test class.
172
void AddNewTestClass(IClass c)
174
if (IsTestClass(c)) {
175
TestClass testClass = CreateTestClass(c);
176
TestClasses.Add(testClass);
180
TestClass CreateTestClass(IClass c)
182
return new TestClass(c, testFrameworks);
186
/// Updates the test class methods based on the newly parsed class
189
void UpdateTestClass(IClass c)
191
if (TestClasses.Contains(c.DotNetName)) {
192
if (IsTestClass(c)) {
193
TestClass testClass = TestClasses[c.DotNetName];
194
testClass.UpdateClass(c);
196
// TestFixture attribute has been removed so
197
// remove the class from the set of TestClasses.
198
TestClasses.Remove(c.DotNetName);
201
// TestFixture attribute may have been recently added to
202
// this class so call AddNewTestClass. No need to
203
// check if the class is actually a test class since
204
// AddNewTestClass does this anyway.
209
void GetTestClasses()
211
testClasses = new TestClassCollection();
212
foreach (IClass c in projectContent.Classes) {
213
if (IsTestClass(c)) {
214
if (!testClasses.Contains(c.FullyQualifiedName)) {
215
testClasses.Add(CreateTestClass(c));
218
foreach (IClass innerClass in c.InnerClasses) {
219
if (IsTestClass(innerClass)) {
220
if (!testClasses.Contains(innerClass.DotNetName)) {
221
testClasses.Add(CreateTestClass(innerClass));
228
bool IsTestClass(IClass c)
230
return testFrameworks.IsTestClass(c);
233
void GetRootNamespaces()
235
rootNamespaces = new List<string>();
236
foreach (TestClass c in TestClasses) {
237
string rootNamespace = c.RootNamespace;
238
if ((rootNamespace.Length > 0) && !rootNamespaces.Contains(rootNamespace)) {
239
rootNamespaces.Add(rootNamespace);
245
/// Gets an existing test class with the same name in the project. This
246
/// method is used to check that we do not remove a class after an existing duplicate class name
249
IClass GetExistingTestClassInProject(IClass c)
251
foreach (IClass existingClass in projectContent.Classes) {
252
if (IsTestClass(existingClass)) {
253
if (existingClass.DotNetName == c.DotNetName) {
254
return existingClass;