2004-05-25 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / nunit20 / core / TestCaseBuilder.cs
1 #region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
2 /************************************************************************************
3 '
4 ' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
5 ' Copyright © 2000-2003 Philip A. Craig
6 '
7 ' This software is provided 'as-is', without any express or implied warranty. In no 
8 ' event will the authors be held liable for any damages arising from the use of this 
9 ' software.
10
11 ' Permission is granted to anyone to use this software for any purpose, including 
12 ' commercial applications, and to alter it and redistribute it freely, subject to the 
13 ' following restrictions:
14 '
15 ' 1. The origin of this software must not be misrepresented; you must not claim that 
16 ' you wrote the original software. If you use this software in a product, an 
17 ' acknowledgment (see the following) in the product documentation is required.
18 '
19 ' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
20 ' or Copyright © 2000-2003 Philip A. Craig
21 '
22 ' 2. Altered source versions must be plainly marked as such, and must not be 
23 ' misrepresented as being the original software.
24 '
25 ' 3. This notice may not be removed or altered from any source distribution.
26 '
27 '***********************************************************************************/
28 #endregion
29
30 namespace NUnit.Core
31 {
32         using System;
33         using System.Reflection;
34         using System.Collections;
35
36         /// <summary>
37         /// Summary description for TestCaseBuilder.
38         /// </summary>
39         public class TestCaseBuilder
40         {
41                 private static Hashtable builders;
42                 private static ITestBuilder normalBuilder = new NormalBuilder();
43
44                 private static void InitBuilders() 
45                 {
46                         builders = new Hashtable();
47                         builders[typeof(NUnit.Framework.ExpectedExceptionAttribute)] = new ExpectedExceptionBuilder();
48                 }
49
50                 private static ITestBuilder GetBuilder(MethodInfo method) 
51                 {
52                         if (builders == null)
53                                 InitBuilders();
54
55                         object[] attributes = method.GetCustomAttributes(false);
56                         
57                         foreach (object attribute in attributes) 
58                         {
59                                 ITestBuilder builder = (ITestBuilder) builders[attribute.GetType()];
60                                 if (builder != null)
61                                         return builder;
62                         }
63
64                         return normalBuilder;
65                 }
66
67                 public static TestCase Make(object fixture, MethodInfo method)
68                 {
69                         TestCase testCase = null;
70
71                         if(HasTestAttribute(method) || HasObsoleteTestName(method) && !HasAnySetUpOrTearDownAttribute(method) )
72                         {
73                                 if(IsTestMethodSignatureCorrect(method))
74                                 {
75                                         ITestBuilder builder = GetBuilder(method);
76                                         testCase = builder.Make(fixture, method);
77
78                                         if(HasIgnoreAttribute(method))
79                                         {
80                                                 testCase.ShouldRun = false;
81                                                 testCase.IgnoreReason = GetIgnoreReason(method);
82                                         }
83
84                                         if (HasCategoryAttribute(method)) 
85                                         {
86                                                 IList categories = GetCategories(method);
87                                                 CategoryManager.Add(categories);
88                                                 testCase.Categories = categories;
89                                         }
90
91                                         testCase.IsExplicit = HasExplicitAttribute(method);
92
93                                         testCase.Description = GetDescription(method);
94                                 }
95                                 else
96                                 {
97                                         testCase = new NotRunnableTestCase(method);
98                                 }
99                         }
100
101                         return testCase;
102                 }
103
104                 public static TestCase Make(object fixture, string methodName)
105                 {
106                         MethodInfo [] methods = fixture.GetType().GetMethods(BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance);
107                         foreach(MethodInfo method in methods)
108                         {
109                                 if(method.Name.Equals(methodName))
110                                         return Make(fixture, method);
111                         }
112
113                         return null;
114                 }
115
116                 private static bool IsExpectedException(MethodInfo method)
117                 {
118                         Type exceptionAttr = typeof(NUnit.Framework.ExpectedExceptionAttribute);
119                         object[] attributes = method.GetCustomAttributes(exceptionAttr, false);
120                         return attributes.Length == 1;
121                 }
122
123                 private static NUnit.Framework.ExpectedExceptionAttribute GetExpectedExceptions(MethodInfo method)
124                 {
125                         Type exceptionAttr = typeof(NUnit.Framework.ExpectedExceptionAttribute);
126                         object[] attributes = method.GetCustomAttributes(exceptionAttr, false);
127
128                         NUnit.Framework.ExpectedExceptionAttribute expectedAttr = null;
129
130                         if(attributes.Length == 1)
131                         {
132                                 expectedAttr = (NUnit.Framework.ExpectedExceptionAttribute)attributes[0];
133                         }
134
135                         return expectedAttr;
136                 }
137
138                 private static string GetDescription(MethodInfo method)
139                 {
140                         Type testAttr = typeof(NUnit.Framework.TestAttribute);
141                         object[] attributes = method.GetCustomAttributes(testAttr, false);
142
143                         string description = null;
144
145                         if(attributes.Length == 1)
146                         {
147                                 NUnit.Framework.TestAttribute attribute = 
148                                         (NUnit.Framework.TestAttribute)attributes[0];
149                                 description = attribute.Description;
150                         }
151
152                         return description;
153                 }
154
155
156                 public static int CountTestCases(object fixture) 
157                 {
158                         int testCases = 0;
159
160                         MethodInfo [] methods = fixture.GetType().GetMethods();
161                         foreach(MethodInfo method in methods)
162                         {
163                                 if(IsTestMethod(method))
164                                         testCases++;
165                         }
166
167                         return testCases;
168                 }
169
170
171                 public static bool IsTestMethod(MethodInfo methodToCheck) 
172                 {
173                         return
174                                 (HasTestAttribute(methodToCheck) || HasObsoleteTestName(methodToCheck))
175                                 && IsTestMethodSignatureCorrect(methodToCheck);
176                 }
177
178                 private static bool IsTestMethodSignatureCorrect(MethodInfo methodToCheck)
179                 {
180                         return 
181                                 !methodToCheck.IsStatic
182                                 && !methodToCheck.IsAbstract
183                                 && methodToCheck.IsPublic
184                                 && methodToCheck.GetParameters().Length == 0
185                                 && methodToCheck.ReturnType.Equals(typeof(void));
186                 }
187
188                 private static bool HasTestAttribute(MethodInfo methodToCheck)
189                 {
190                         return methodToCheck.IsDefined(typeof(NUnit.Framework.TestAttribute),false);
191                 }
192                 
193                 private static bool HasObsoleteTestName(MethodInfo methodToCheck)
194                 {
195                         return methodToCheck.Name.ToLower().StartsWith("test");
196                 }
197
198                 private static bool HasAnySetUpOrTearDownAttribute( MethodInfo methodToCheck )
199                 {
200                         object[] attributes = methodToCheck.GetCustomAttributes( false );
201                         foreach( Attribute attribute in attributes )
202                                 if ( attribute is NUnit.Framework.SetUpAttribute ||
203                                          attribute is NUnit.Framework.TestFixtureSetUpAttribute ||
204                                          attribute is NUnit.Framework.TearDownAttribute || 
205                                          attribute is NUnit.Framework.TestFixtureTearDownAttribute )
206                                         return true;
207
208                         return false;   
209                 }
210
211                 private static bool HasIgnoreAttribute(MethodInfo methodToCheck)
212                 {
213                         Type ignoreMethodAttribute = typeof(NUnit.Framework.IgnoreAttribute);
214                         object[] attributes = methodToCheck.GetCustomAttributes(ignoreMethodAttribute, false);
215                         return attributes.Length == 1;
216                 }
217
218                 private static string GetIgnoreReason(MethodInfo methodToCheck)
219                 {
220                         Type ignoreMethodAttribute = typeof(NUnit.Framework.IgnoreAttribute);
221                         NUnit.Framework.IgnoreAttribute[] attributes = (NUnit.Framework.IgnoreAttribute[])methodToCheck.GetCustomAttributes(ignoreMethodAttribute, false);
222                         string result = "no reason";
223                         if(attributes.Length > 0)
224                                 result = attributes[0].Reason;
225
226                         return result;
227                 }
228
229                 private static bool HasCategoryAttribute(MethodInfo methodToCheck) 
230                 {
231                         object[] attributes = methodToCheck.GetCustomAttributes(typeof(NUnit.Framework.CategoryAttribute), false);
232                         return attributes.Length > 0;
233                 }
234
235                 private static bool HasExplicitAttribute(MethodInfo methodToCheck)
236                 {
237                         object[] attributes = methodToCheck.GetCustomAttributes(typeof(NUnit.Framework.ExplicitAttribute), false);
238                         return attributes.Length > 0;
239                 }
240
241                 private static IList GetCategories(MethodInfo methodToCheck) 
242                 {
243                         object[] attributes = methodToCheck.GetCustomAttributes(typeof(NUnit.Framework.CategoryAttribute), false);
244                         ArrayList list = new ArrayList();
245                         foreach (NUnit.Framework.CategoryAttribute attrib in attributes) 
246                         {
247                                 list.Add(attrib.Name);
248                         }
249
250                         return list;
251                 }
252         }
253
254         internal interface ITestBuilder 
255         {
256                 TestCase Make(object fixture, MethodInfo method);
257         }
258
259         internal class ExpectedExceptionBuilder : ITestBuilder
260         {
261                 #region ITestBuilder Members
262
263                 public TestCase Make(object fixture, MethodInfo method)
264                 {
265                         NUnit.Framework.ExpectedExceptionAttribute expectedException = GetExpectedExceptions(method);
266                         TestCase testCase = new ExpectedExceptionTestCase(fixture, method, expectedException.ExceptionType, expectedException.ExpectedMessage);
267
268                         return testCase;
269                 }
270
271                 #endregion
272
273                 private static NUnit.Framework.ExpectedExceptionAttribute GetExpectedExceptions(MethodInfo method)
274                 {
275                         Type exceptionAttr = typeof(NUnit.Framework.ExpectedExceptionAttribute);
276                         object[] attributes = method.GetCustomAttributes(exceptionAttr, false);
277
278                         NUnit.Framework.ExpectedExceptionAttribute expectedAttr = null;
279
280                         if(attributes.Length == 1)
281                         {
282                                 expectedAttr = (NUnit.Framework.ExpectedExceptionAttribute)attributes[0];
283                         }
284
285                         return expectedAttr;
286                 }
287
288         }
289
290         internal class NormalBuilder : ITestBuilder
291         {
292                 #region ITestBuilder Members
293
294                 public TestCase Make(object fixture, MethodInfo method)
295                 {
296                         return new NormalTestCase(fixture, method);
297                 }
298
299                 #endregion
300
301         }
302
303
304 }
305