PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NUnit/core/NUnitFramework.cs

#
C# | 437 lines | 322 code | 46 blank | 69 comment | 62 complexity | 60add14917d41755daf5fd107b307bbc MD5 | raw file
Possible License(s): GPL-2.0
  1. // ****************************************************************
  2. // Copyright 2007, Charlie Poole
  3. // This is free software licensed under the NUnit license. You may
  4. // obtain a copy of the license at http://nunit.org.
  5. // ****************************************************************
  6. using System;
  7. using System.Reflection;
  8. using System.Collections;
  9. using System.Collections.Specialized;
  10. using System.Diagnostics;
  11. using NUnit.Core.Extensibility;
  12. namespace NUnit.Core
  13. {
  14. /// <summary>
  15. /// Static methods that implement aspects of the NUnit framework that cut
  16. /// across individual test types, extensions, etc. Some of these use the
  17. /// methods of the Reflect class to implement operations specific to the
  18. /// NUnit Framework.
  19. /// </summary>
  20. public class NUnitFramework
  21. {
  22. #region Constants
  23. #region Attribute Names
  24. // NOTE: Attributes used in switch statements must be const
  25. // Attributes that apply to Assemblies, Classes and Methods
  26. public const string IgnoreAttribute = "NUnit.Framework.IgnoreAttribute";
  27. public const string PlatformAttribute = "NUnit.Framework.PlatformAttribute";
  28. public const string CultureAttribute = "NUnit.Framework.CultureAttribute";
  29. public const string ExplicitAttribute = "NUnit.Framework.ExplicitAttribute";
  30. public const string CategoryAttribute = "NUnit.Framework.CategoryAttribute";
  31. public const string PropertyAttribute = "NUnit.Framework.PropertyAttribute";
  32. public const string DescriptionAttribute = "NUnit.Framework.DescriptionAttribute";
  33. public const string RequiredAddinAttribute = "NUnit.Framework.RequiredAddinAttribute";
  34. // Attributes that apply only to Classes
  35. public const string TestFixtureAttribute = "NUnit.Framework.TestFixtureAttribute";
  36. public const string SetUpFixtureAttribute = "NUnit.Framework.SetUpFixtureAttribute";
  37. // Attributes that apply only to Methods
  38. public const string TestAttribute = "NUnit.Framework.TestAttribute";
  39. public const string TestCaseAttribute = "NUnit.Framework.TestCaseAttribute";
  40. public const string TestCaseSourceAttribute = "NUnit.Framework.TestCaseSourceAttribute";
  41. public const string TheoryAttribute = "NUnit.Framework.TheoryAttribute";
  42. public static readonly string SetUpAttribute = "NUnit.Framework.SetUpAttribute";
  43. public static readonly string TearDownAttribute = "NUnit.Framework.TearDownAttribute";
  44. public static readonly string FixtureSetUpAttribute = "NUnit.Framework.TestFixtureSetUpAttribute";
  45. public static readonly string FixtureTearDownAttribute = "NUnit.Framework.TestFixtureTearDownAttribute";
  46. public static readonly string ExpectedExceptionAttribute = "NUnit.Framework.ExpectedExceptionAttribute";
  47. // Attributes that apply only to Properties
  48. public static readonly string SuiteAttribute = "NUnit.Framework.SuiteAttribute";
  49. #endregion
  50. #region Other Framework Types
  51. public static readonly string AssertException = "NUnit.Framework.AssertionException";
  52. public static readonly string IgnoreException = "NUnit.Framework.IgnoreException";
  53. public static readonly string InconclusiveException = "NUnit.Framework.InconclusiveException";
  54. public static readonly string SuccessException = "NUnit.Framework.SuccessException";
  55. public static readonly string AssertType = "NUnit.Framework.Assert";
  56. public static readonly string ExpectExceptionInterface = "NUnit.Framework.IExpectException";
  57. #endregion
  58. #region Core Types
  59. public static readonly string SuiteBuilderAttribute = typeof(SuiteBuilderAttribute).FullName;
  60. public static readonly string SuiteBuilderInterface = typeof(ISuiteBuilder).FullName;
  61. public static readonly string TestCaseBuilderAttributeName = typeof(TestCaseBuilderAttribute).FullName;
  62. public static readonly string TestCaseBuilderInterfaceName = typeof(ITestCaseBuilder).FullName;
  63. public static readonly string TestDecoratorAttributeName = typeof(TestDecoratorAttribute).FullName;
  64. public static readonly string TestDecoratorInterfaceName = typeof(ITestDecorator).FullName;
  65. #endregion
  66. #endregion
  67. #region Properties
  68. private static Assembly frameworkAssembly;
  69. private static bool frameworkAssemblyInitialized;
  70. private static Assembly FrameworkAssembly
  71. {
  72. get
  73. {
  74. if (!frameworkAssemblyInitialized)
  75. foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
  76. if (assembly.GetName().Name == "nunit.framework" ||
  77. assembly.GetName().Name == "NUnitLite")
  78. {
  79. frameworkAssembly = assembly;
  80. break;
  81. }
  82. frameworkAssemblyInitialized = true;
  83. return frameworkAssembly;
  84. }
  85. }
  86. #endregion
  87. #region Check SetUp and TearDown methods
  88. public static bool CheckSetUpTearDownMethods(Type fixtureType, string attributeName, ref string reason)
  89. {
  90. foreach( MethodInfo theMethod in Reflect.GetMethodsWithAttribute(fixtureType, attributeName, true ))
  91. if ( theMethod.IsAbstract ||
  92. !theMethod.IsPublic && !theMethod.IsFamily ||
  93. theMethod.GetParameters().Length > 0 ||
  94. !theMethod.ReturnType.Equals(typeof(void)))
  95. {
  96. reason = string.Format( "Invalid signature for SetUp or TearDown method: {0}", theMethod.Name );
  97. return false;
  98. }
  99. return true;
  100. }
  101. #endregion
  102. #region Get Special Properties of Attributes
  103. #region IgnoreReason
  104. public static string GetIgnoreReason( System.Attribute attribute )
  105. {
  106. return Reflect.GetPropertyValue(attribute, PropertyNames.Reason) as string;
  107. }
  108. #endregion
  109. #region Description
  110. /// <summary>
  111. /// Method to return the description from an source
  112. /// </summary>
  113. /// <param name="source">The source to check</param>
  114. /// <returns>The description, if any, or null</returns>
  115. public static string GetDescription(System.Attribute attribute)
  116. {
  117. return Reflect.GetPropertyValue(attribute, PropertyNames.Description) as string;
  118. }
  119. #endregion
  120. #endregion
  121. #region ApplyCommonAttributes
  122. /// <summary>
  123. /// Modify a newly constructed test based on a type or method by
  124. /// applying any of NUnit's common attributes.
  125. /// </summary>
  126. /// <param name="member">The type or method from which the test was constructed</param>
  127. /// <param name="test">The test to which the attributes apply</param>
  128. public static void ApplyCommonAttributes(MemberInfo member, Test test)
  129. {
  130. ApplyCommonAttributes( Reflect.GetAttributes( member, true ), test );
  131. }
  132. /// <summary>
  133. /// Modify a newly constructed test based on an assembly by applying
  134. /// any of NUnit's common attributes.
  135. /// </summary>
  136. /// <param name="assembly">The assembly from which the test was constructed</param>
  137. /// <param name="test">The test to which the attributes apply</param>
  138. public static void ApplyCommonAttributes(Assembly assembly, Test test)
  139. {
  140. ApplyCommonAttributes( Reflect.GetAttributes( assembly, false ), test );
  141. }
  142. /// <summary>
  143. /// Modify a newly constructed test by applying any of NUnit's common
  144. /// attributes, based on an input array of attributes. This method checks
  145. /// for all attributes, relying on the fact that specific attributes can only
  146. /// occur on those constructs on which they are allowed.
  147. /// </summary>
  148. /// <param name="attributes">An array of attributes possibly including NUnit attributes
  149. /// <param name="test">The test to which the attributes apply</param>
  150. public static void ApplyCommonAttributes(Attribute[] attributes, Test test)
  151. {
  152. foreach (Attribute attribute in attributes)
  153. {
  154. Type attributeType = attribute.GetType();
  155. string attributeName = attributeType.FullName;
  156. bool isValid = test.RunState != RunState.NotRunnable;
  157. switch (attributeName)
  158. {
  159. case TestFixtureAttribute:
  160. case TestAttribute:
  161. if ( test.Description == null )
  162. test.Description = GetDescription( attribute );
  163. break;
  164. case DescriptionAttribute:
  165. test.Description = GetDescription( attribute );
  166. break;
  167. case PlatformAttribute:
  168. PlatformHelper pHelper = new PlatformHelper();
  169. if (isValid && !pHelper.IsPlatformSupported(attribute))
  170. {
  171. test.RunState = RunState.Skipped;
  172. test.IgnoreReason = GetIgnoreReason(attribute);
  173. if ( test.IgnoreReason == null )
  174. test.IgnoreReason = pHelper.Reason;
  175. }
  176. break;
  177. case CultureAttribute:
  178. CultureDetector cultureDetector = new CultureDetector();
  179. if (isValid && !cultureDetector.IsCultureSupported(attribute))
  180. {
  181. test.RunState = RunState.Skipped;
  182. test.IgnoreReason = cultureDetector.Reason;
  183. }
  184. break;
  185. case RequiredAddinAttribute:
  186. string required = (string)Reflect.GetPropertyValue(attribute, PropertyNames.RequiredAddin);
  187. if (!IsAddinAvailable(required))
  188. {
  189. test.RunState = RunState.NotRunnable;
  190. test.IgnoreReason = string.Format("Required addin {0} not available", required);
  191. }
  192. break;
  193. case "System.STAThreadAttribute":
  194. test.Properties.Add("APARTMENT_STATE", System.Threading.ApartmentState.STA);
  195. break;
  196. case "System.MTAThreadAttribute":
  197. test.Properties.Add("APARTMENT_STATE", System.Threading.ApartmentState.MTA);
  198. break;
  199. default:
  200. if ( Reflect.InheritsFrom( attributeType, CategoryAttribute ) )
  201. {
  202. string categoryName = (string)Reflect.GetPropertyValue(attribute, PropertyNames.CategoryName);
  203. test.Categories.Add(categoryName);
  204. if (categoryName.IndexOfAny(new char[] { ',', '!', '+', '-' }) >= 0)
  205. {
  206. test.RunState = RunState.NotRunnable;
  207. test.IgnoreReason = "Category name must not contain ',', '!', '+' or '-'";
  208. }
  209. }
  210. else if ( Reflect.InheritsFrom( attributeType, PropertyAttribute ) )
  211. {
  212. IDictionary props = (IDictionary)Reflect.GetPropertyValue( attribute, PropertyNames.Properties );
  213. if ( props != null )
  214. foreach( DictionaryEntry entry in props )
  215. test.Properties.Add(entry.Key, entry.Value);
  216. }
  217. else if ( Reflect.InheritsFrom( attributeType, ExplicitAttribute ) )
  218. {
  219. if (isValid)
  220. {
  221. test.RunState = RunState.Explicit;
  222. test.IgnoreReason = GetIgnoreReason(attribute);
  223. }
  224. }
  225. else if ( Reflect.InheritsFrom( attributeType, IgnoreAttribute ) )
  226. {
  227. if (isValid)
  228. {
  229. test.RunState = RunState.Ignored;
  230. test.IgnoreReason = GetIgnoreReason(attribute);
  231. }
  232. }
  233. break;
  234. }
  235. }
  236. }
  237. #endregion
  238. #region ApplyExpectedExceptionAttribute
  239. /// <summary>
  240. /// Modify a newly constructed test by checking for ExpectedExceptionAttribute
  241. /// and setting properties on the test accordingly.
  242. /// </summary>
  243. /// <param name="attributes">An array of attributes possibly including NUnit attributes
  244. /// <param name="test">The test to which the attributes apply</param>
  245. public static void ApplyExpectedExceptionAttribute(MethodInfo method, TestMethod testMethod)
  246. {
  247. Attribute attribute = Reflect.GetAttribute(
  248. method, NUnitFramework.ExpectedExceptionAttribute, false);
  249. if (attribute != null)
  250. testMethod.ExceptionProcessor = new ExpectedExceptionProcessor(testMethod, attribute);
  251. }
  252. #endregion
  253. #region IsSuiteBuilder
  254. public static bool IsSuiteBuilder( Type type )
  255. {
  256. return Reflect.HasAttribute( type, SuiteBuilderAttribute, false )
  257. && Reflect.HasInterface( type, SuiteBuilderInterface );
  258. }
  259. #endregion
  260. #region IsTestCaseBuilder
  261. public static bool IsTestCaseBuilder( Type type )
  262. {
  263. return Reflect.HasAttribute( type, TestCaseBuilderAttributeName, false )
  264. && Reflect.HasInterface( type, TestCaseBuilderInterfaceName );
  265. }
  266. #endregion
  267. #region IsTestDecorator
  268. public static bool IsTestDecorator( Type type )
  269. {
  270. return Reflect.HasAttribute( type, TestDecoratorAttributeName, false )
  271. && Reflect.HasInterface( type, TestDecoratorInterfaceName );
  272. }
  273. #endregion
  274. #region IsAddinAvailable
  275. public static bool IsAddinAvailable(string name)
  276. {
  277. foreach (Addin addin in CoreExtensions.Host.AddinRegistry.Addins)
  278. if (addin.Name == name && addin.Status == AddinStatus.Loaded)
  279. return true;
  280. return false;
  281. }
  282. #endregion
  283. #region Framework Assert Access
  284. /// <summary>
  285. /// NUnitFramework.Assert is a nested class that implements
  286. /// a few of the framework operations by reflection,
  287. /// using whatever framework version is available.
  288. /// </summary>
  289. public class Assert
  290. {
  291. #region Properties
  292. private static Type assertType;
  293. private static Type AssertType
  294. {
  295. get
  296. {
  297. if (assertType == null && FrameworkAssembly != null)
  298. assertType = FrameworkAssembly.GetType(NUnitFramework.AssertType);
  299. return assertType;
  300. }
  301. }
  302. private static MethodInfo areEqualMethod;
  303. private static MethodInfo AreEqualMethod
  304. {
  305. get
  306. {
  307. if (areEqualMethod == null && AssertType != null)
  308. areEqualMethod = AssertType.GetMethod(
  309. "AreEqual",
  310. BindingFlags.Static | BindingFlags.Public,
  311. null,
  312. new Type[] { typeof(object), typeof(object) },
  313. null );
  314. return areEqualMethod;
  315. }
  316. }
  317. private static PropertyInfo counterProperty;
  318. private static PropertyInfo CounterProperty
  319. {
  320. get
  321. {
  322. if (counterProperty == null && AssertType != null)
  323. counterProperty = Reflect.GetNamedProperty(
  324. AssertType,
  325. "Counter",
  326. BindingFlags.Public | BindingFlags.Static);
  327. return counterProperty;
  328. }
  329. }
  330. #endregion
  331. /// <summary>
  332. /// Invoke Assert.AreEqual by reflection
  333. /// </summary>
  334. /// <param name="expected">The expected value</param>
  335. /// <param name="actual">The actual value</param>
  336. public static void AreEqual(object expected, object actual)
  337. {
  338. if (AreEqualMethod != null)
  339. try
  340. {
  341. AreEqualMethod.Invoke(null, new object[] { expected, actual });
  342. }
  343. catch (TargetInvocationException e)
  344. {
  345. Exception inner = e.InnerException;
  346. throw new NUnitException("Rethrown", inner);
  347. }
  348. }
  349. /// <summary>
  350. /// Get the assertion counter. It clears itself automatically
  351. /// on each call.
  352. /// </summary>
  353. /// <returns>Count of number of asserts since last call</returns>
  354. public static int GetAssertCount()
  355. {
  356. return CounterProperty == null
  357. ? 0
  358. : (int)CounterProperty.GetValue(null, new object[0]);
  359. }
  360. }
  361. #endregion
  362. #region GetResultState
  363. /// <summary>
  364. /// Returns a result state for a special exception.
  365. /// If the exception is not handled specially, returns
  366. /// ResultState.Error.
  367. /// </summary>
  368. /// <param name="ex">The exception to be examined</param>
  369. /// <returns>A ResultState</returns>
  370. public static ResultState GetResultState(Exception ex)
  371. {
  372. if (ex is System.Threading.ThreadAbortException)
  373. return ResultState.Cancelled;
  374. string name = ex.GetType().FullName;
  375. if (name == NUnitFramework.AssertException)
  376. return ResultState.Failure;
  377. else
  378. if (name == NUnitFramework.IgnoreException)
  379. return ResultState.Ignored;
  380. else
  381. if (name == NUnitFramework.InconclusiveException)
  382. return ResultState.Inconclusive;
  383. else
  384. if (name == NUnitFramework.SuccessException)
  385. return ResultState.Success;
  386. else
  387. return ResultState.Error;
  388. }
  389. #endregion
  390. }
  391. }