~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to src/AddIns/Analysis/UnitTesting/Src/TestProject.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
3
 
 
4
using System;
 
5
using System.Collections.Generic;
 
6
using ICSharpCode.Core;
 
7
using ICSharpCode.SharpDevelop.Dom;
 
8
using ICSharpCode.SharpDevelop.Project;
 
9
 
 
10
namespace ICSharpCode.UnitTesting
 
11
{
 
12
        /// <summary>
 
13
        /// Represents a project that has a reference to a unit testing
 
14
        /// framework assembly. Currently only NUnit is supported.
 
15
        /// </summary>
 
16
        public class TestProject
 
17
        {
 
18
                IProject project;
 
19
                IProjectContent projectContent;
 
20
                TestClassCollection testClasses;
 
21
                List<string> rootNamespaces;
 
22
                IRegisteredTestFrameworks testFrameworks;
 
23
                
 
24
                public TestProject(IProject project, IProjectContent projectContent, IRegisteredTestFrameworks testFrameworks)
 
25
                {
 
26
                        this.project = project;
 
27
                        this.projectContent = projectContent;
 
28
                        this.testFrameworks = testFrameworks;
 
29
                }
 
30
                
 
31
                public IProject Project {
 
32
                        get { return project; }
 
33
                }
 
34
                
 
35
                /// <summary>
 
36
                /// Gets the test classes in this project.
 
37
                /// </summary>
 
38
                public TestClassCollection TestClasses {
 
39
                        get {
 
40
                                if (testClasses == null) {
 
41
                                        GetTestClasses();
 
42
                                }
 
43
                                return testClasses;
 
44
                        }
 
45
                }
 
46
                
 
47
                /// <summary>
 
48
                /// Gets the test classes that exist in the specified namespace.
 
49
                /// </summary>
 
50
                public TestClass[] GetTestClasses(string ns)
 
51
                {
 
52
                        return TestClass.GetTestClasses(TestClasses, ns);
 
53
                }
 
54
                
 
55
                /// <summary>
 
56
                /// Gets the test classes whose namespaces start with the specified string.
 
57
                /// </summary>
 
58
                public TestClass[] GetAllTestClasses(string namespaceStartsWith)
 
59
                {
 
60
                        return TestClass.GetAllTestClasses(TestClasses, namespaceStartsWith);
 
61
                }
 
62
                
 
63
                /// <summary>
 
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.
 
67
                /// </summary>
 
68
                public string[] GetChildNamespaces(string parentNamespace)
 
69
                {
 
70
                        return TestClass.GetChildNamespaces(TestClasses, parentNamespace);
 
71
                }
 
72
                
 
73
                /// <summary>
 
74
                /// Gets the project's name.
 
75
                /// </summary>
 
76
                public string Name {
 
77
                        get { return project.Name; }
 
78
                }
 
79
                
 
80
                /// <summary>
 
81
                /// Gets the distinct root namespaces for all this project.
 
82
                /// </summary>
 
83
                /// <remarks>
 
84
                /// If one of the namespaces is 'ICSharpCode.XmlEditor' then this
 
85
                /// method will return 'ICSharpCode' as one of the root namespaces.
 
86
                /// </remarks>
 
87
                public IList<string> RootNamespaces {
 
88
                        get {
 
89
                                if (rootNamespaces == null) {
 
90
                                        GetRootNamespaces();
 
91
                                }
 
92
                                return rootNamespaces;
 
93
                        }
 
94
                }
 
95
                
 
96
                /// <summary>
 
97
                /// Updates the test method based on the test result.
 
98
                /// </summary>
 
99
                public void UpdateTestResult(TestResult testResult)
 
100
                {
 
101
                        TestClasses.UpdateTestResult(testResult);
 
102
                }
 
103
                
 
104
                /// <summary>
 
105
                /// Sets all the test results back to none.
 
106
                /// </summary>
 
107
                public void ResetTestResults()
 
108
                {
 
109
                        TestClasses.ResetTestResults();
 
110
                }
 
111
                
 
112
                /// <summary>
 
113
                /// Updates the classes and methods based on the new parse information.
 
114
                /// </summary>
 
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)
 
120
                {
 
121
                        if (!IsParseInfoForThisProject(oldUnit, newUnit)) {
 
122
                                return;
 
123
                        }
 
124
                        
 
125
                        RemovedClasses removedClasses = new RemovedClasses();
 
126
                        
 
127
                        if (oldUnit != null) {
 
128
                                removedClasses.Add(oldUnit.Classes);
 
129
                        }
 
130
                        if (newUnit != null) {
 
131
                                foreach (IClass c in newUnit.Classes) {
 
132
                                        UpdateTestClass(c);
 
133
                                        foreach (IClass innerClass in c.InnerClasses) {
 
134
                                                UpdateTestClass(innerClass);
 
135
                                                removedClasses.Remove(innerClass);
 
136
                                        }
 
137
                                        removedClasses.Remove(c);
 
138
                                }
 
139
                        }
 
140
                        
 
141
                        // Remove missing classes.
 
142
                        foreach (IClass c in removedClasses.GetMissingClasses()) {
 
143
                                IClass existingClass = GetExistingTestClassInProject(c);
 
144
                                if (existingClass != null) {
 
145
                                        UpdateTestClass(existingClass);
 
146
                                } else {
 
147
                                        TestClasses.Remove(c.DotNetName);
 
148
                                }
 
149
                        }
 
150
                }
 
151
                
 
152
                /// <summary>
 
153
                /// Determines whether the new parse information is for this test
 
154
                /// project.
 
155
                /// </summary>
 
156
                public bool IsParseInfoForThisProject(ICompilationUnit oldUnit, ICompilationUnit newUnit)
 
157
                {
 
158
                        ICompilationUnit unit = oldUnit;
 
159
                        if (unit == null) {
 
160
                                unit = newUnit;
 
161
                        }
 
162
                        if (unit != null) {
 
163
                                return Object.ReferenceEquals(unit.ProjectContent, this.projectContent);
 
164
                        }
 
165
                        return false;
 
166
                }
 
167
                
 
168
                /// <summary>
 
169
                /// Adds a new class to the test project's classes only if
 
170
                /// the class is a test class.
 
171
                /// </summary>
 
172
                void AddNewTestClass(IClass c)
 
173
                {
 
174
                        if (IsTestClass(c)) {
 
175
                                TestClass testClass = CreateTestClass(c);
 
176
                                TestClasses.Add(testClass);
 
177
                        }
 
178
                }
 
179
                
 
180
                TestClass CreateTestClass(IClass c)
 
181
                {
 
182
                        return new TestClass(c, testFrameworks);
 
183
                }
 
184
                
 
185
                /// <summary>
 
186
                /// Updates the test class methods based on the newly parsed class
 
187
                /// information.
 
188
                /// </summary>
 
189
                void UpdateTestClass(IClass c)
 
190
                {
 
191
                        if (TestClasses.Contains(c.DotNetName)) {
 
192
                                if (IsTestClass(c)) {
 
193
                                        TestClass testClass = TestClasses[c.DotNetName];
 
194
                                        testClass.UpdateClass(c);
 
195
                                } else {
 
196
                                        // TestFixture attribute has been removed so
 
197
                                        // remove the class from the set of TestClasses.
 
198
                                        TestClasses.Remove(c.DotNetName);
 
199
                                }
 
200
                        } else {
 
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.
 
205
                                AddNewTestClass(c);
 
206
                        }
 
207
                }
 
208
                
 
209
                void GetTestClasses()
 
210
                {
 
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));
 
216
                                        }
 
217
                                }
 
218
                                foreach (IClass innerClass in c.InnerClasses) {
 
219
                                        if (IsTestClass(innerClass)) {
 
220
                                                if (!testClasses.Contains(innerClass.DotNetName)) {
 
221
                                                        testClasses.Add(CreateTestClass(innerClass));
 
222
                                                }
 
223
                                        }
 
224
                                }
 
225
                        }
 
226
                }
 
227
                
 
228
                bool IsTestClass(IClass c)
 
229
                {
 
230
                        return testFrameworks.IsTestClass(c);
 
231
                }
 
232
                
 
233
                void GetRootNamespaces()
 
234
                {
 
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);
 
240
                                }
 
241
                        }
 
242
                }
 
243
                
 
244
                /// <summary>
 
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
 
247
                /// is changed.
 
248
                /// </summary>
 
249
                IClass GetExistingTestClassInProject(IClass c)
 
250
                {
 
251
                        foreach (IClass existingClass in projectContent.Classes) {
 
252
                                if (IsTestClass(existingClass)) {
 
253
                                        if (existingClass.DotNetName == c.DotNetName) {
 
254
                                                return existingClass;
 
255
                                        }
 
256
                                }
 
257
                        }
 
258
                        return null;
 
259
                }
 
260
        }
 
261
}