2 using System
.Reflection
;
3 using System
.Collections
;
9 /// Helper methods for inspecting a type by reflection.
11 /// Many of these methods take a MemberInfo as an argument to avoid
12 /// duplication, even though certain attributes can only appear on
13 /// specific types of members, like MethodInfo or Type.
15 /// Generally, these methods perform simple utility functions like
16 /// checking for a given attribute. However, some of the methdods
17 /// actually implement policies, which might change at some later
18 /// time. The intent is that policies that may vary among different
19 /// types of test cases or suites should be handled by those types,
20 /// while common decisions are handled here.
24 #region Attribute types used by reflect
26 public static readonly Type TestFixtureType
= typeof( TestFixtureAttribute
);
27 public static readonly Type TestType
= typeof( TestAttribute
);
28 public static readonly Type SetUpType
= typeof( SetUpAttribute
);
29 public static readonly Type TearDownType
= typeof( TearDownAttribute
);
30 public static readonly Type FixtureSetUpType
= typeof( TestFixtureSetUpAttribute
);
31 public static readonly Type FixtureTearDownType
= typeof( TestFixtureTearDownAttribute
);
32 public static readonly Type ExplicitType
= typeof( ExplicitAttribute
);
33 public static readonly Type CategoryType
= typeof( CategoryAttribute
);
34 public static readonly Type IgnoreType
= typeof( IgnoreAttribute
);
35 public static readonly Type ExpectedExceptionType
= typeof( ExpectedExceptionAttribute
);
36 public static readonly Type SuiteType
= typeof( SuiteAttribute
);
40 #region Binding flags used by reflect
42 private static readonly BindingFlags InstanceMethods
=
43 BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.Instance
;
45 private static readonly BindingFlags StaticMethods
=
46 BindingFlags
.Static
| BindingFlags
.Public
| BindingFlags
.DeclaredOnly
;
48 private static readonly BindingFlags AllMethods
=
49 BindingFlags
.Public
| BindingFlags
.NonPublic
|
50 BindingFlags
.Instance
| BindingFlags
.Static
;
52 private static readonly BindingFlags AllDeclaredMethods
=
53 AllMethods
| BindingFlags
.DeclaredOnly
;
57 #region Check for presence of an attribute
59 public static bool HasTestFixtureAttribute(Type type
)
61 return type
.IsDefined( TestFixtureType
, true ); // Inheritable
64 public static bool HasTestAttribute(MethodInfo method
)
66 return method
.IsDefined( TestType
, false );
69 public static bool HasExplicitAttribute(MemberInfo member
)
71 return member
.IsDefined( ExplicitType
, false );
74 public static bool HasCategoryAttribute(MemberInfo member
)
76 return member
.IsDefined( CategoryType
, false );
79 public static bool HasExpectedExceptionAttribute(MethodInfo method
)
81 return method
.IsDefined( ExpectedExceptionType
, false );
84 public static bool HasIgnoreAttribute( MemberInfo member
)
86 return member
.IsDefined( IgnoreType
, false );
89 public static bool HasSuiteAttribute( PropertyInfo property
)
91 return property
.IsDefined( SuiteType
, false );
96 #region Legacy Checks on Names
98 public static bool IsObsoleteTestMethod(MethodInfo methodToCheck
)
100 if ( methodToCheck
.Name
.ToLower().StartsWith("test") )
102 object[] attributes
= methodToCheck
.GetCustomAttributes( false );
104 foreach( Attribute attribute
in attributes
)
105 if( attribute
is SetUpAttribute
||
106 attribute
is TestFixtureSetUpAttribute
||
107 attribute
is TearDownAttribute
||
108 attribute
is TestFixtureTearDownAttribute
)
121 #region Get Attributes
123 public static TestFixtureAttribute
GetTestFixtureAttribute( Type type
)
125 object[] attributes
= type
.GetCustomAttributes( TestFixtureType
, true );
126 return attributes
.Length
> 0 ? (TestFixtureAttribute
) attributes
[0] : null;
129 public static TestAttribute
GetTestAttribute( MemberInfo member
)
131 object[] attributes
= member
.GetCustomAttributes( TestType
, false );
132 return attributes
.Length
> 0 ? (TestAttribute
)attributes
[0] : null;
135 public static IgnoreAttribute
GetIgnoreAttribute( MemberInfo member
)
137 object[] attributes
= member
.GetCustomAttributes( IgnoreType
, false );
138 return attributes
.Length
> 0 ? (IgnoreAttribute
) attributes
[0] : null;
141 public static ExpectedExceptionAttribute
GetExpectedExceptionAttribute( MethodInfo method
)
143 object[] attributes
= method
.GetCustomAttributes( ExpectedExceptionType
, false);
144 return attributes
.Length
> 0 ? (ExpectedExceptionAttribute
) attributes
[0] : null;
149 #region Get Properties of Attributes
151 public static string GetIgnoreReason( MemberInfo member
)
153 IgnoreAttribute attribute
= GetIgnoreAttribute( member
);
154 return attribute
== null ? "no reason" : attribute
.Reason
;
157 public static string GetDescription( MethodInfo method
)
159 TestAttribute attribute
= GetTestAttribute( method
);
160 return attribute
== null ? null : attribute
.Description
;
163 public static string GetDescription( Type fixtureType
)
165 TestFixtureAttribute attribute
= GetTestFixtureAttribute( fixtureType
);
166 return attribute
== null ? null : attribute
.Description
;
171 #region Methods to check validity of a type and its members
174 /// Method to validate that a type is a valid test fixture
176 /// <param name="fixtureType">The type to be checked</param>
177 public static void CheckFixtureType( Type fixtureType
)
179 if ( fixtureType
.GetConstructor( Type
.EmptyTypes
) == null )
180 throw new InvalidTestFixtureException(fixtureType
.FullName
+ " does not have a valid constructor");
182 CheckSetUpTearDownMethod( fixtureType
, SetUpType
);
183 CheckSetUpTearDownMethod( fixtureType
, TearDownType
);
184 CheckSetUpTearDownMethod( fixtureType
, FixtureSetUpType
);
185 CheckSetUpTearDownMethod( fixtureType
, FixtureTearDownType
);
189 /// This method verifies that a type has no more than one method of a particular
190 /// SetUp or TearDown type and that the method has a correct signature.
192 /// <param name="fixtureType">The type to be checked</param>
193 /// <param name="attributeType">The attribute to check for</param>
194 private static void CheckSetUpTearDownMethod( Type fixtureType
, Type attributeType
)
197 MethodInfo theMethod
= null;
199 foreach(MethodInfo method
in fixtureType
.GetMethods( AllDeclaredMethods
))
201 if( method
.IsDefined( attributeType
, false ) )
210 string attributeName
= attributeType
.Name
;
211 if ( attributeName
.EndsWith( "Attribute" ) )
212 attributeName
= attributeName
.Substring(
213 0, attributeName
.Length
- 9 );
215 throw new InvalidTestFixtureException(
216 string.Format( "{0} has multiple {1} methods",
217 fixtureType
.Name
, attributeName
) );
220 CheckSetUpTearDownSignature( theMethod
);
223 private static void CheckSetUpTearDownSignature( MethodInfo method
)
225 if ( method
!= null )
227 if ( !method
.IsPublic
&& !method
.IsFamily
|| method
.IsStatic
|| method
.ReturnType
!= typeof(void) || method
.GetParameters().Length
> 0 )
228 throw new InvalidTestFixtureException("Invalid SetUp or TearDown method signature");
233 /// Check the signature of a test method
235 /// <param name="methodToCheck">The method signature to check</param>
236 /// <returns>True if the signature is correct, otherwise false</returns>
237 public static bool IsTestMethodSignatureCorrect(MethodInfo methodToCheck
)
240 !methodToCheck
.IsStatic
241 && !methodToCheck
.IsAbstract
242 && methodToCheck
.IsPublic
243 && methodToCheck
.GetParameters().Length
== 0
244 && methodToCheck
.ReturnType
.Equals(typeof(void));
249 #region Get Methods of a type
251 // These methods all take an object and assume that the type of the
252 // object was pre-checked so that there are no duplicate methods,
253 // statics, private methods, etc.
255 public static ConstructorInfo
GetConstructor( Type fixtureType
)
257 return fixtureType
.GetConstructor( Type
.EmptyTypes
);
260 public static MethodInfo
GetSetUpMethod( Type fixtureType
)
262 return GetMethod( fixtureType
, SetUpType
);
265 public static MethodInfo
GetTearDownMethod(Type fixtureType
)
267 return GetMethod(fixtureType
, TearDownType
);
270 public static MethodInfo
GetFixtureSetUpMethod( Type fixtureType
)
272 return GetMethod( fixtureType
, FixtureSetUpType
);
275 public static MethodInfo
GetFixtureTearDownMethod( Type fixtureType
)
277 return GetMethod( fixtureType
, FixtureTearDownType
);
280 public static MethodInfo
GetMethod( Type fixtureType
, Type attributeType
)
282 foreach(MethodInfo method
in fixtureType
.GetMethods( InstanceMethods
) )
284 if( method
.IsDefined( attributeType
, true ) )
291 public static MethodInfo
GetMethod( Type fixtureType
, string methodName
)
293 foreach(MethodInfo method
in fixtureType
.GetMethods( InstanceMethods
) )
295 if( method
.Name
== methodName
)
304 #region Get Suite Property
306 public static PropertyInfo
GetSuiteProperty( Type testClass
)
308 if( testClass
!= null )
310 PropertyInfo
[] properties
= testClass
.GetProperties( StaticMethods
);
311 foreach( PropertyInfo property
in properties
)
313 if( Reflect
.HasSuiteAttribute( property
) )
317 CheckSuiteProperty(property
);
319 catch( InvalidSuiteException
)
330 private static void CheckSuiteProperty(PropertyInfo property
)
332 MethodInfo method
= property
.GetGetMethod(true);
333 if(method
.ReturnType
!=typeof(NUnit
.Core
.TestSuite
))
334 throw new InvalidSuiteException("Invalid suite property method signature");
335 if(method
.GetParameters().Length
>0)
336 throw new InvalidSuiteException("Invalid suite property method signature");
343 public static IList
GetCategories( MemberInfo member
)
345 object[] attributes
= member
.GetCustomAttributes( CategoryType
, false );
346 IList names
= new ArrayList();
348 foreach(CategoryAttribute attribute
in attributes
)
349 names
.Add(attribute
.Name
);
356 #region Invoke Methods
358 public static object Construct( Type type
)
360 ConstructorInfo ctor
= GetConstructor( type
);
362 throw new InvalidTestFixtureException(type
.FullName
+ " does not have a valid constructor");
364 return ctor
.Invoke( Type
.EmptyTypes
);
367 public static void InvokeMethod( MethodInfo method
, object fixture
)
373 method
.Invoke( fixture
, null );
375 catch(TargetInvocationException e
)
377 Exception inner
= e
.InnerException
;
378 throw new NunitException("Rethrown",inner
);
383 public static void InvokeSetUp( object fixture
)
385 MethodInfo method
= GetSetUpMethod( fixture
.GetType() );
388 InvokeMethod(method
, fixture
);
392 public static void InvokeTearDown( object fixture
)
394 MethodInfo method
= GetTearDownMethod( fixture
.GetType() );
397 InvokeMethod(method
, fixture
);
403 #region Private Constructor for static-only class
405 private Reflect() { }