This repository has been archived by the owner on Aug 2, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 26
/
SimpleTestRunner.cs
217 lines (180 loc) · 5.18 KB
/
SimpleTestRunner.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// ****************************************************************
// Copyright 2007, Charlie Poole
// This is free software licensed under the NUnit license. You may
// obtain a copy of the license at http://nunit.org.
// ****************************************************************
using System;
using System.IO;
using System.Threading;
using System.Collections;
using System.Collections.Specialized;
using NUnit.Core.Filters;
using System.Reflection;
namespace NUnit.Core
{
/// <summary>
/// SimpleTestRunner is the simplest direct-running TestRunner. It
/// passes the event listener interface that is provided on to the tests
/// to use directly and does nothing to redirect text output. Both
/// Run and BeginRun are actually synchronous, although the client
/// can usually ignore this. BeginRun + EndRun operates as expected.
/// </summary>
public class SimpleTestRunner : MarshalByRefObject, TestRunner
{
static Logger log = InternalTrace.GetLogger(typeof(SimpleTestRunner));
#region Instance Variables
/// <summary>
/// Identifier for this runner. Must be unique among all
/// active runners in order to locate tests. Default
/// value of 0 is adequate in applications with a single
/// runner or a non-branching chain of runners.
/// </summary>
private int runnerID = 0;
/// <summary>
/// The loaded test suite
/// </summary>
private Test test;
/// <summary>
/// The builder we use to load tests, created for each load
/// </summary>
private TestSuiteBuilder builder;
/// <summary>
/// Results from the last test run
/// </summary>
private TestResult testResult;
/// <summary>
/// The thread on which Run was called. Set to the
/// current thread while a run is in process.
/// </summary>
private Thread runThread;
#endregion
#region Constructor
public SimpleTestRunner() : this( 0 ) { }
public SimpleTestRunner( int runnerID )
{
this.runnerID = runnerID;
}
#endregion
#region Properties
public virtual int ID
{
get { return runnerID; }
}
public IList AssemblyInfo
{
get { return builder.AssemblyInfo; }
}
public ITest Test
{
get { return test == null ? null : new TestNode( test ); }
}
/// <summary>
/// Results from the last test run
/// </summary>
public TestResult TestResult
{
get { return testResult; }
}
public virtual bool Running
{
get { return runThread != null && runThread.IsAlive; }
}
#endregion
#region Methods for Loading Tests
/// <summary>
/// Load a TestPackage
/// </summary>
/// <param name="package">The package to be loaded</param>
/// <returns>True on success, false on failure</returns>
public bool Load( TestPackage package )
{
log.Debug("Loading package " + package.Name);
this.builder = new TestSuiteBuilder();
this.test = builder.Build( package );
if ( test == null ) return false;
test.SetRunnerID( this.runnerID, true );
TestExecutionContext.CurrentContext.TestPackage = package;
return true;
}
/// <summary>
/// Unload all tests previously loaded
/// </summary>
public void Unload()
{
log.Debug("Unloading");
this.test = null; // All for now
}
#endregion
#region CountTestCases
public int CountTestCases( ITestFilter filter )
{
return test.CountTestCases( filter );
}
#endregion
#region Methods for Running Tests
public virtual TestResult Run( EventListener listener, ITestFilter filter, bool tracing, LoggingThreshold logLevel )
{
try
{
log.Debug("Starting test run");
// Take note of the fact that we are running
this.runThread = Thread.CurrentThread;
listener.RunStarted( this.Test.TestName.FullName, test.CountTestCases( filter ) );
testResult = test.Run( listener, filter );
// Signal that we are done
listener.RunFinished( testResult );
log.Debug("Test run complete");
// Return result array
return testResult;
}
catch( Exception exception )
{
// Signal that we finished with an exception
listener.RunFinished( exception );
// Rethrow - should we do this?
throw;
}
finally
{
runThread = null;
}
}
public void BeginRun(EventListener listener, ITestFilter filter, bool tracing, LoggingThreshold logLevel)
{
testResult = this.Run(listener, filter, tracing, logLevel);
}
public virtual TestResult EndRun()
{
return TestResult;
}
/// <summary>
/// Wait is a NOP for SimpleTestRunner
/// </summary>
public virtual void Wait()
{
}
public virtual void CancelRun()
{
if (this.runThread != null)
{
// Cancel Synchronous run only if on another thread
if ( this.runThread == Thread.CurrentThread )
throw new InvalidOperationException( "May not CancelRun on same thread that is running the test" );
ThreadUtility.Kill(this.runThread);
}
}
#endregion
#region InitializeLifetimeService Override
public override object InitializeLifetimeService()
{
return null;
}
#endregion
#region IDisposable Members
public void Dispose()
{
Unload();
}
#endregion
}
}