PageRenderTime 73ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/NUnit/core/TestSuite.cs

#
C# | 530 lines | 404 code | 81 blank | 45 comment | 66 complexity | abf93391fb30da74a673ae2cd6991875 MD5 | raw file
Possible License(s): GPL-2.0
  1. // ****************************************************************
  2. // This is free software licensed under the NUnit license. You
  3. // may obtain a copy of the license as well as information regarding
  4. // copyright ownership at http://nunit.org.
  5. // ****************************************************************
  6. namespace NUnit.Core
  7. {
  8. using System;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Collections;
  12. using System.Reflection;
  13. using NUnit.Core.Filters;
  14. /// <summary>
  15. /// Summary description for TestSuite.
  16. /// </summary>
  17. ///
  18. [Serializable]
  19. public class TestSuite : Test
  20. {
  21. #region Fields
  22. static Logger log = InternalTrace.GetLogger(typeof(TestSuite));
  23. /// <summary>
  24. /// Our collection of child tests
  25. /// </summary>
  26. private ArrayList tests = new ArrayList();
  27. /// <summary>
  28. /// The fixture setup methods for this suite
  29. /// </summary>
  30. protected MethodInfo[] fixtureSetUpMethods;
  31. /// <summary>
  32. /// The fixture teardown methods for this suite
  33. /// </summary>
  34. protected MethodInfo[] fixtureTearDownMethods;
  35. /// <summary>
  36. /// The setup methods for this suite
  37. /// </summary>
  38. protected MethodInfo[] setUpMethods;
  39. /// <summary>
  40. /// The teardown methods for this suite
  41. /// </summary>
  42. protected MethodInfo[] tearDownMethods;
  43. /// <summary>
  44. /// Set to true to suppress sorting this suite's contents
  45. /// </summary>
  46. protected bool maintainTestOrder;
  47. /// <summary>
  48. /// Arguments for use in creating a parameterized fixture
  49. /// </summary>
  50. internal object[] arguments;
  51. /// <summary>
  52. /// The System.Type of the fixture for this test suite, if there is one
  53. /// </summary>
  54. private Type fixtureType;
  55. /// <summary>
  56. /// The fixture object, if it has been created
  57. /// </summary>
  58. private object fixture;
  59. #endregion
  60. #region Constructors
  61. public TestSuite( string name )
  62. : base( name ) { }
  63. public TestSuite( string parentSuiteName, string name )
  64. : base( parentSuiteName, name ) { }
  65. public TestSuite(Type fixtureType)
  66. : this(fixtureType, null) { }
  67. public TestSuite(Type fixtureType, object[] arguments)
  68. : base(fixtureType.FullName)
  69. {
  70. string name = TypeHelper.GetDisplayName(fixtureType, arguments);
  71. this.TestName.Name = name;
  72. this.TestName.FullName = name;
  73. string nspace = fixtureType.Namespace;
  74. if (nspace != null && nspace != "")
  75. this.TestName.FullName = nspace + "." + name;
  76. this.fixtureType = fixtureType;
  77. this.arguments = arguments;
  78. }
  79. #endregion
  80. #region Public Methods
  81. public void Sort()
  82. {
  83. if (!maintainTestOrder)
  84. {
  85. this.tests.Sort();
  86. foreach (Test test in Tests)
  87. {
  88. TestSuite suite = test as TestSuite;
  89. if (suite != null)
  90. suite.Sort();
  91. }
  92. }
  93. }
  94. public void Sort(IComparer comparer)
  95. {
  96. this.tests.Sort(comparer);
  97. foreach( Test test in Tests )
  98. {
  99. TestSuite suite = test as TestSuite;
  100. if ( suite != null )
  101. suite.Sort(comparer);
  102. }
  103. }
  104. public void Add( Test test )
  105. {
  106. // if( test.RunState == RunState.Runnable )
  107. // {
  108. // test.RunState = this.RunState;
  109. // test.IgnoreReason = this.IgnoreReason;
  110. // }
  111. test.Parent = this;
  112. tests.Add(test);
  113. }
  114. public void Add( object fixture )
  115. {
  116. Test test = TestFixtureBuilder.BuildFrom( fixture );
  117. if ( test != null )
  118. Add( test );
  119. }
  120. #endregion
  121. #region Properties
  122. public override IList Tests
  123. {
  124. get { return tests; }
  125. }
  126. public override bool IsSuite
  127. {
  128. get { return true; }
  129. }
  130. public override int TestCount
  131. {
  132. get
  133. {
  134. int count = 0;
  135. foreach(Test test in Tests)
  136. {
  137. count += test.TestCount;
  138. }
  139. return count;
  140. }
  141. }
  142. public override Type FixtureType
  143. {
  144. get { return fixtureType; }
  145. }
  146. public override object Fixture
  147. {
  148. get { return fixture; }
  149. set { fixture = value; }
  150. }
  151. public MethodInfo[] GetSetUpMethods()
  152. {
  153. return setUpMethods;
  154. }
  155. public MethodInfo[] GetTearDownMethods()
  156. {
  157. return tearDownMethods;
  158. }
  159. #endregion
  160. #region Test Overrides
  161. public override string TestType
  162. {
  163. get { return "TestSuite"; }
  164. }
  165. public override int CountTestCases(ITestFilter filter)
  166. {
  167. int count = 0;
  168. if(filter.Pass(this))
  169. {
  170. foreach(Test test in Tests)
  171. {
  172. count += test.CountTestCases(filter);
  173. }
  174. }
  175. return count;
  176. }
  177. public override TestResult Run(EventListener listener, ITestFilter filter)
  178. {
  179. listener.SuiteStarted(this.TestName);
  180. long startTime = DateTime.Now.Ticks;
  181. TestResult suiteResult = this.RunState == RunState.Runnable || this.RunState == RunState.Explicit
  182. ? RunSuiteInContext(listener, filter)
  183. : SkipSuite(listener, filter);
  184. long stopTime = DateTime.Now.Ticks;
  185. double time = ((double)(stopTime - startTime)) / (double)TimeSpan.TicksPerSecond;
  186. suiteResult.Time = time;
  187. listener.SuiteFinished(suiteResult);
  188. return suiteResult;
  189. }
  190. private TestResult SkipSuite(EventListener listener, ITestFilter filter)
  191. {
  192. TestResult suiteResult = new TestResult(this);
  193. switch (this.RunState)
  194. {
  195. default:
  196. case RunState.Skipped:
  197. SkipAllTests(suiteResult, listener, filter);
  198. break;
  199. case RunState.NotRunnable:
  200. MarkAllTestsInvalid(suiteResult, listener, filter);
  201. break;
  202. case RunState.Ignored:
  203. IgnoreAllTests(suiteResult, listener, filter);
  204. break;
  205. }
  206. return suiteResult;
  207. }
  208. private TestResult RunSuiteInContext(EventListener listener, ITestFilter filter)
  209. {
  210. TestExecutionContext.Save();
  211. try
  212. {
  213. return ShouldRunOnOwnThread
  214. ? new TestSuiteThread(this).Run(listener, filter)
  215. : RunSuite(listener, filter);
  216. }
  217. finally
  218. {
  219. TestExecutionContext.Restore();
  220. }
  221. }
  222. public TestResult RunSuite(EventListener listener, ITestFilter filter)
  223. {
  224. TestResult suiteResult = new TestResult(this);
  225. DoOneTimeSetUp(suiteResult);
  226. if (this.Properties["_SETCULTURE"] != null)
  227. TestExecutionContext.CurrentContext.CurrentCulture =
  228. new System.Globalization.CultureInfo((string)Properties["_SETCULTURE"]);
  229. if (this.Properties["_SETUICULTURE"] != null)
  230. TestExecutionContext.CurrentContext.CurrentUICulture =
  231. new System.Globalization.CultureInfo((string)Properties["_SETUICULTURE"]);
  232. switch (suiteResult.ResultState)
  233. {
  234. case ResultState.Failure:
  235. case ResultState.Error:
  236. MarkTestsFailed(Tests, suiteResult, listener, filter);
  237. break;
  238. case ResultState.NotRunnable:
  239. MarkTestsNotRun(this.Tests, ResultState.NotRunnable, suiteResult.Message, suiteResult, listener, filter);
  240. break;
  241. default:
  242. try
  243. {
  244. RunAllTests(suiteResult, listener, filter);
  245. }
  246. finally
  247. {
  248. DoOneTimeTearDown(suiteResult);
  249. }
  250. break;
  251. }
  252. return suiteResult;
  253. }
  254. #endregion
  255. #region Virtual Methods
  256. protected virtual void DoOneTimeSetUp(TestResult suiteResult)
  257. {
  258. if (FixtureType != null)
  259. {
  260. try
  261. {
  262. // In case TestFixture was created with fixture object
  263. if (Fixture == null && !IsStaticClass( FixtureType ) )
  264. CreateUserFixture();
  265. if (this.fixtureSetUpMethods != null)
  266. foreach( MethodInfo fixtureSetUp in fixtureSetUpMethods )
  267. Reflect.InvokeMethod(fixtureSetUp, fixtureSetUp.IsStatic ? null : Fixture);
  268. TestExecutionContext.CurrentContext.Update();
  269. }
  270. catch (Exception ex)
  271. {
  272. if (ex is NUnitException || ex is System.Reflection.TargetInvocationException)
  273. ex = ex.InnerException;
  274. if (ex is InvalidTestFixtureException)
  275. suiteResult.Invalid(ex.Message);
  276. else if (IsIgnoreException(ex))
  277. {
  278. this.RunState = RunState.Ignored;
  279. suiteResult.Ignore(ex.Message);
  280. suiteResult.StackTrace = ex.StackTrace;
  281. this.IgnoreReason = ex.Message;
  282. }
  283. else if (IsAssertException(ex))
  284. suiteResult.Failure(ex.Message, ex.StackTrace, FailureSite.SetUp);
  285. else
  286. suiteResult.Error(ex, FailureSite.SetUp);
  287. }
  288. }
  289. }
  290. protected virtual void CreateUserFixture()
  291. {
  292. if (arguments != null && arguments.Length > 0)
  293. Fixture = Reflect.Construct(FixtureType, arguments);
  294. else
  295. Fixture = Reflect.Construct(FixtureType);
  296. }
  297. protected virtual void DoOneTimeTearDown(TestResult suiteResult)
  298. {
  299. if ( this.FixtureType != null)
  300. {
  301. try
  302. {
  303. if (this.fixtureTearDownMethods != null)
  304. {
  305. int index = fixtureTearDownMethods.Length;
  306. while (--index >= 0 )
  307. {
  308. MethodInfo fixtureTearDown = fixtureTearDownMethods[index];
  309. Reflect.InvokeMethod(fixtureTearDown, fixtureTearDown.IsStatic ? null : Fixture);
  310. }
  311. }
  312. IDisposable disposable = Fixture as IDisposable;
  313. if (disposable != null)
  314. disposable.Dispose();
  315. }
  316. catch (Exception ex)
  317. {
  318. // Error in TestFixtureTearDown or Dispose causes the
  319. // suite to be marked as a failure, even if
  320. // all the contained tests passed.
  321. NUnitException nex = ex as NUnitException;
  322. if (nex != null)
  323. ex = nex.InnerException;
  324. suiteResult.Failure(ex.Message, ex.StackTrace, FailureSite.TearDown);
  325. }
  326. this.Fixture = null;
  327. }
  328. }
  329. protected virtual bool IsAssertException(Exception ex)
  330. {
  331. return ex.GetType().FullName == NUnitFramework.AssertException;
  332. }
  333. protected virtual bool IsIgnoreException(Exception ex)
  334. {
  335. return ex.GetType().FullName == NUnitFramework.IgnoreException;
  336. }
  337. #endregion
  338. #region Helper Methods
  339. private bool IsStaticClass(Type type)
  340. {
  341. return type.IsAbstract && type.IsSealed;
  342. }
  343. private void RunAllTests(
  344. TestResult suiteResult, EventListener listener, ITestFilter filter )
  345. {
  346. if (Properties.Contains("Timeout"))
  347. TestExecutionContext.CurrentContext.TestCaseTimeout = (int)Properties["Timeout"];
  348. foreach (Test test in ArrayList.Synchronized(Tests))
  349. {
  350. if (filter.Pass(test))
  351. {
  352. RunState saveRunState = test.RunState;
  353. if (test.RunState == RunState.Runnable && this.RunState != RunState.Runnable && this.RunState != RunState.Explicit )
  354. {
  355. test.RunState = this.RunState;
  356. test.IgnoreReason = this.IgnoreReason;
  357. }
  358. TestResult result = test.Run(listener, filter);
  359. log.Debug("Test result = " + result.ResultState);
  360. suiteResult.AddResult(result);
  361. log.Debug("Suite result = " + suiteResult.ResultState);
  362. if (saveRunState != test.RunState)
  363. {
  364. test.RunState = saveRunState;
  365. test.IgnoreReason = null;
  366. }
  367. if (result.ResultState == ResultState.Cancelled)
  368. break;
  369. }
  370. }
  371. }
  372. private void SkipAllTests(TestResult suiteResult, EventListener listener, ITestFilter filter)
  373. {
  374. suiteResult.Skip(this.IgnoreReason);
  375. MarkTestsNotRun(this.Tests, ResultState.Skipped, this.IgnoreReason, suiteResult, listener, filter);
  376. }
  377. private void IgnoreAllTests(TestResult suiteResult, EventListener listener, ITestFilter filter)
  378. {
  379. suiteResult.Ignore(this.IgnoreReason);
  380. MarkTestsNotRun(this.Tests, ResultState.Ignored, this.IgnoreReason, suiteResult, listener, filter);
  381. }
  382. private void MarkAllTestsInvalid(TestResult suiteResult, EventListener listener, ITestFilter filter)
  383. {
  384. suiteResult.Invalid(this.IgnoreReason);
  385. MarkTestsNotRun(this.Tests, ResultState.NotRunnable, this.IgnoreReason, suiteResult, listener, filter);
  386. }
  387. private void MarkTestsNotRun(
  388. IList tests, ResultState resultState, string ignoreReason, TestResult suiteResult, EventListener listener, ITestFilter filter)
  389. {
  390. foreach (Test test in ArrayList.Synchronized(tests))
  391. {
  392. if (filter.Pass(test))
  393. MarkTestNotRun(test, resultState, ignoreReason, suiteResult, listener, filter);
  394. }
  395. }
  396. private void MarkTestNotRun(
  397. Test test, ResultState resultState, string ignoreReason, TestResult suiteResult, EventListener listener, ITestFilter filter)
  398. {
  399. if (test is TestSuite)
  400. {
  401. listener.SuiteStarted(test.TestName);
  402. TestResult result = new TestResult( new TestInfo(test) );
  403. result.SetResult( resultState, ignoreReason, null );
  404. MarkTestsNotRun(test.Tests, resultState, ignoreReason, suiteResult, listener, filter);
  405. suiteResult.AddResult(result);
  406. listener.SuiteFinished(result);
  407. }
  408. else
  409. {
  410. listener.TestStarted(test.TestName);
  411. TestResult result = new TestResult( new TestInfo(test) );
  412. result.SetResult( resultState, ignoreReason, null );
  413. suiteResult.AddResult(result);
  414. listener.TestFinished(result);
  415. }
  416. }
  417. private void MarkTestsFailed(
  418. IList tests, TestResult suiteResult, EventListener listener, ITestFilter filter)
  419. {
  420. foreach (Test test in ArrayList.Synchronized(tests))
  421. if (filter.Pass(test))
  422. MarkTestFailed(test, suiteResult, listener, filter);
  423. }
  424. private void MarkTestFailed(
  425. Test test, TestResult suiteResult, EventListener listener, ITestFilter filter)
  426. {
  427. if (test is TestSuite)
  428. {
  429. listener.SuiteStarted(test.TestName);
  430. TestResult result = new TestResult( new TestInfo(test) );
  431. string msg = string.Format( "Parent SetUp failed in {0}", this.FixtureType.Name );
  432. result.Failure(msg, null, FailureSite.Parent);
  433. MarkTestsFailed(test.Tests, suiteResult, listener, filter);
  434. suiteResult.AddResult(result);
  435. listener.SuiteFinished(result);
  436. }
  437. else
  438. {
  439. listener.TestStarted(test.TestName);
  440. TestResult result = new TestResult( new TestInfo(test) );
  441. string msg = string.Format( "TestFixtureSetUp failed in {0}", this.FixtureType.Name );
  442. result.Failure(msg, null, FailureSite.Parent);
  443. suiteResult.AddResult(result);
  444. listener.TestFinished(result);
  445. }
  446. }
  447. #endregion
  448. }
  449. }