2 using System
.Reflection
;
3 using System
.Collections
;
4 using System
.Collections
.Generic
;
5 using System
.Runtime
.InteropServices
;
6 using System
.Runtime
.CompilerServices
;
7 using System
.Diagnostics
;
10 using NUnit
.Framework
;
11 using NUnit
.Framework
.Internal
;
12 using NUnit
.Framework
.Api
;
13 using NUnit
.Framework
.Internal
.Filters
;
14 using NUnitLite
.Runner
;
17 public class MyListener
: ITestListener
20 public void TestStarted(ITest test
)
27 Console
.WriteLine ("{0} {1}/{2}", test
.FullName
, scount
, count
);
30 public void TestFinished(ITestResult result
)
34 public void TestOutput(TestOutput testOutput
)
39 class AbstractAction
{
40 internal TestExecutionContext context
, initialCtx
;
41 internal TestResult testResult
;
42 internal IncrementalTestRunner runner
;
44 AbstractAction parent
;
46 internal AbstractAction (Test test
, AbstractAction parent
, IncrementalTestRunner runner
)
51 this.initialCtx
= parent
.context
;
52 this.testResult
= test
.MakeTestResult ();
55 internal AbstractAction (Test test
, TestExecutionContext initialCtx
, IncrementalTestRunner runner
)
59 this.initialCtx
= initialCtx
;
60 this.testResult
= test
.MakeTestResult ();
63 protected void SetupContext () {
64 this.context
= new TestExecutionContext (this.initialCtx
);
65 this.context
.CurrentTest
= this.test
;
66 this.context
.CurrentResult
= this.testResult
;
67 ((ITestListener
)IncrementalTestRunner
.listener
.GetValue (this.context
)).TestStarted (this.test
);
68 this.context
.StartTime
= DateTime
.Now
;
70 IncrementalTestRunner
.setCurrentContext
.Invoke (null, new object[] { this.context }
);
72 long startTicks
= Stopwatch
.GetTimestamp();
73 runner
.finallyDelegate
.Set (context
, startTicks
, testResult
);
76 protected void WorkItemComplete ()
78 if (this.parent
!= null)
79 this.parent
.testResult
.AddResult (testResult
);
81 runner
.finallyDelegate
.Complete ();
82 // _state = WorkItemState.Complete;
83 // if (Completed != null)
84 // Completed(this, EventArgs.Empty);
88 class TestAction
: AbstractAction
{
91 public TestAction (TestMethod test
, AbstractAction parent
, IncrementalTestRunner runner
) : base (test
, parent
, runner
)
96 public void PerformWork () {
100 if (IncrementalTestRunner
.testSkipCount
> 0) {
101 --IncrementalTestRunner
.testSkipCount
;
102 testResult
= ((Test
)test
).MakeTestResult ();
103 testResult
.SetResult (ResultState
.Success
);
105 testResult
= test
.MakeTestCommand ().Execute(this.context
);
115 class TestSuiteAction
: AbstractAction
{
117 List
<ITest
> children
;
119 public TestSuiteAction (TestSuite test
, AbstractAction parent
, IncrementalTestRunner runner
) : base (test
, parent
, runner
)
121 this.testSuite
= test
;
124 public TestSuiteAction (TestSuite test
, TestExecutionContext initialCtx
, IncrementalTestRunner runner
) : base (test
, initialCtx
, runner
)
126 this.testSuite
= test
;
129 void EnqueueChildren () {
130 foreach (var t
in children
) {
131 if (t
is TestSuite
) {
132 var a
= new TestSuiteAction ((TestSuite
)t
, this, runner
);
133 runner
.actions
.Enqueue (a
.PerformWork
);
135 var a
= new TestAction ((TestMethod
)t
, this, runner
);
136 runner
.actions
.Enqueue (a
.PerformWork
);
141 private void SkipChildren ()
143 foreach (var t
in children
) {
144 TestResult result
= ((Test
)t
).MakeTestResult ();
145 if (testResult
.ResultState
.Status
== TestStatus
.Failed
)
146 result
.SetResult (ResultState
.Failure
, "TestFixtureSetUp Failed");
148 result
.SetResult (testResult
.ResultState
, testResult
.Message
);
149 testResult
.AddResult (result
);
153 void SkipFixture (ResultState resultState
, string message
, string stackTrace
)
155 testResult
.SetResult (resultState
, message
, stackTrace
);
159 private string GetSkipReason()
161 return (string)testSuite
.Properties
.Get(PropertyNames
.SkipReason
);
164 private string GetProviderStackTrace()
166 return (string)testSuite
.Properties
.Get(PropertyNames
.ProviderStackTrace
);
169 public void PerformWork () {
172 children
= new List
<ITest
> ();
174 if (testSuite
.HasChildren
) {
175 foreach (Test test
in testSuite
.Tests
) {
176 if (runner
.filter
.Pass(test
))
181 switch (testSuite
.RunState
) {
183 case RunState
.Runnable
:
184 case RunState
.Explicit
:
185 testResult
.SetResult (ResultState
.Success
);
186 PerformOneTimeSetUp ();
188 if (children
.Count
> 0) {
189 switch (testResult
.ResultState
.Status
)
191 case TestStatus
.Passed
:
195 case TestStatus
.Skipped
:
196 case TestStatus
.Inconclusive
:
197 case TestStatus
.Failed
:
203 //all action enqueuing actions have already run, now it's ok to enqueue this.
204 runner
.actions
.Enqueue (() => runner
.actions
.Enqueue (this.PerformOneTimeTearDown
));
207 case RunState
.Skipped
:
208 SkipFixture (ResultState
.Skipped
, GetSkipReason(), null);
211 case RunState
.Ignored
:
212 SkipFixture (ResultState
.Ignored
, GetSkipReason(), null);
215 case RunState
.NotRunnable
:
216 SkipFixture (ResultState
.NotRunnable
, GetSkipReason(), GetProviderStackTrace());
220 //all action enqueuing actions have already run, now it's ok to enqueue this.
221 runner
.actions
.Enqueue (() => runner
.actions
.Enqueue (this.WorkItemComplete
));
224 private void PerformOneTimeTearDown ()
226 IncrementalTestRunner
.setCurrentContext
.Invoke (null, new object[] { this.context }
);
227 testSuite
.GetOneTimeTearDownCommand ().Execute(this.context
);
230 private void PerformOneTimeSetUp ()
234 testSuite
.GetOneTimeSetUpCommand().Execute(this.context
);
236 // SetUp may have changed some things
237 this.context
.UpdateContext();
241 if (ex
is NUnitException
|| ex
is System
.Reflection
.TargetInvocationException
)
242 ex
= ex
.InnerException
;
244 testResult
.RecordException (ex
);
249 public class IncrementalTestRunner
{
250 internal static PropertyInfo listener
= typeof (TestExecutionContext
).GetProperty ("Listener", BindingFlags
.Instance
| BindingFlags
.NonPublic
);
251 internal static MethodInfo setCurrentContext
= typeof (TestExecutionContext
).GetMethod ("SetCurrentContext", BindingFlags
.Static
| BindingFlags
.NonPublic
);
253 IDictionary loadOptions
;
254 internal ITestFilter filter
= TestFilter
.Empty
;
255 UnhandledExceptionEventHandler crashHandler
;
257 internal FinallyDelegate finallyDelegate
;
258 ITestAssemblyBuilder builder
;
259 // ITestAssemblyRunner runner;
261 public IncrementalTestRunner () {
262 this.finallyDelegate
= new FinallyDelegate();
263 this.builder
= new NUnitLiteTestAssemblyBuilder();
264 // this.runner = new NUnitLiteTestAssemblyRunner(new NUnitLiteTestAssemblyBuilder(), finallyDelegate);
266 this.loadOptions
= new Hashtable ();
272 public void Add (Assembly assembly
) {
273 testSuite
= builder
.Build (assembly
, loadOptions
);
274 if (testSuite
== null)
275 throw new Exception ("Could not load " + assembly
);
276 // if (!runner.Load (assembly, loadOptions))
277 // throw new Exception ("Could not load " + assembly);
280 public void Exclude (string categories
) {
281 var excludeFilter
= new NotFilter (new SimpleCategoryExpression(categories
).Filter
);
282 filter
= And (filter
, excludeFilter
);
285 public void RunOnly (string testName
) {
286 var nameFilter
= new SimpleNameFilter (testName
);
287 filter
= And (filter
, nameFilter
);
290 internal Queue
<Action
> actions
= new Queue
<Action
> ();
293 internal static int testSkipCount
;
295 public string Status
{
296 get { return test_status; }
299 TestSuiteAction rootAction
;
300 void QueueActions (TestSuite suite
) {
301 TestExecutionContext context
= new TestExecutionContext ();
302 if (this.loadOptions
.Contains ("WorkDirectory"))
303 context
.WorkDirectory
= (string)this.loadOptions
["WorkDirectory"];
305 context
.WorkDirectory
= Environment
.CurrentDirectory
;
307 listener
.SetValue (context
, new MyListener ());
308 rootAction
= new TestSuiteAction (suite
, context
, this);
309 actions
.Enqueue (rootAction
.PerformWork
);
312 public void SkipFirst (int tsc
) {
316 public void Start (int step
) {
317 if (actions
.Count
> 0)
318 throw new Exception ("Test already started");
320 crashHandler
= new UnhandledExceptionEventHandler(TopLevelHandler
);
321 AppDomain
.CurrentDomain
.UnhandledException
+= crashHandler
;
323 this.test_step_count
= step
;
324 QueueActions (testSuite
);
327 public bool Step () {
328 int remaining
= test_step_count
;
330 while (actions
.Count
> 0 && remaining
> 0) {
331 var a
= actions
.Dequeue ();
336 if (actions
.Count
== 0) {
337 var res
= new ResultReporter (rootAction
.testResult
, Console
.Out
);
338 if ((res
.Summary
.FailureCount
+ res
.Summary
.ErrorCount
) > 0)
339 test_status
= "FAIL";
341 test_status
= "PASS";
343 res
.ReportResults ();
350 void TopLevelHandler(object sender
, UnhandledExceptionEventArgs e
)
352 // Make sure that the test harness knows this exception was thrown
353 if (finallyDelegate
!= null)
354 finallyDelegate
.HandleUnhandledExc(e
.ExceptionObject
as Exception
);
357 static ITestFilter
And (ITestFilter filter
, ITestFilter other
) {
360 else if (filter
is AndFilter
)
361 ((AndFilter
)filter
).Add(other
);
363 filter
= new AndFilter(filter
, other
);