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/?p=license&r=2.4
5 // ****************************************************************
8 using System
.Threading
;
9 using System
.Collections
;
10 using System
.Collections
.Specialized
;
11 using NUnit
.Core
.Filters
;
12 using System
.Reflection
;
17 /// SimpleTestRunner is the simplest direct-running TestRunner. It
18 /// passes the event listener interface that is provided on to the tests
19 /// to use directly and does nothing to redirect text output. Both
20 /// Run and BeginRun are actually synchronous, although the client
21 /// can usually ignore this. BeginRun + EndRun operates as expected.
23 public class SimpleTestRunner
: MarshalByRefObject
, TestRunner
25 #region Instance Variables
28 /// Identifier for this runner. Must be unique among all
29 /// active runners in order to locate tests. Default
30 /// value of 0 is adequate in applications with a single
31 /// runner or a non-branching chain of runners.
33 private int runnerID
= 0;
36 /// The loaded test suite
41 /// The builder we use to load tests, created for each load
43 private TestSuiteBuilder builder
;
46 /// Results from the last test run
48 private TestResult testResult
;
51 /// The thread on which Run was called. Set to the
52 /// current thread while a run is in process.
54 private Thread runThread
;
59 public SimpleTestRunner() : this( 0 ) { }
61 public SimpleTestRunner( int runnerID
)
63 this.runnerID
= runnerID
;
70 get { return runnerID; }
73 public IList AssemblyInfo
75 get { return builder.AssemblyInfo; }
80 get { return test == null ? null : new TestNode( test ); }
84 /// Results from the last test run
86 public TestResult TestResult
88 get { return testResult; }
91 public virtual bool Running
93 get { return runThread != null && runThread.IsAlive; }
97 #region Methods for Loading Tests
99 /// Load a TestPackage
101 /// <param name="package">The package to be loaded</param>
102 /// <returns>True on success, false on failure</returns>
103 public bool Load( TestPackage package
)
105 this.builder
= new TestSuiteBuilder();
107 this.test
= builder
.Build( package
);
108 if ( test
== null ) return false;
110 test
.SetRunnerID( this.runnerID
, true );
115 /// Unload all tests previously loaded
119 this.test
= null; // All for now
123 #region CountTestCases
124 public int CountTestCases( ITestFilter filter
)
126 return test
.CountTestCases( filter
);
130 #region Methods for Running Tests
131 public virtual TestResult
Run( EventListener listener
)
133 return Run( listener
, TestFilter
.Empty
);
136 public virtual TestResult
Run( EventListener listener
, ITestFilter filter
)
140 // Take note of the fact that we are running
141 this.runThread
= Thread
.CurrentThread
;
143 listener
.RunStarted( this.Test
.TestName
.FullName
, test
.CountTestCases( filter
) );
145 testResult
= test
.Run( listener
, filter
);
147 // Signal that we are done
148 listener
.RunFinished( testResult
);
150 // Return result array
153 catch( Exception exception
)
155 // Signal that we finished with an exception
156 listener
.RunFinished( exception
);
157 // Rethrow - should we do this?
166 public void BeginRun( EventListener listener
)
168 testResult
= this.Run( listener
);
171 public void BeginRun( EventListener listener
, ITestFilter filter
)
173 testResult
= this.Run( listener
, filter
);
176 public virtual TestResult
EndRun()
182 /// Wait is a NOP for SimpleTestRunner
184 public virtual void Wait()
188 public virtual void CancelRun()
190 if (this.runThread
!= null)
192 // Cancel Synchronous run only if on another thread
193 if ( runThread
== Thread
.CurrentThread
)
194 throw new InvalidOperationException( "May not CancelRun on same thread that is running the test" );
196 // Make a copy of runThread, which will be set to
197 // null when the thread terminates.
198 Thread cancelThread
= this.runThread
;
200 // Tell the thread to abort
201 this.runThread
.Abort();
203 // Wake up the thread if necessary
204 // Figure out if we need to do an interupt
205 if ( (cancelThread
.ThreadState
& ThreadState
.WaitSleepJoin
) != 0 )
206 cancelThread
.Interrupt();
211 #region InitializeLifetimeService Override
212 public override object InitializeLifetimeService()