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