Merge pull request #3040 from xmcclure/debugger-step-recursive
[mono.git] / mcs / nunit24 / NUnitCore / interfaces / TestResult.cs
1 // ****************************************************************\r
2 // This is free software licensed under the NUnit license. You\r
3 // may obtain a copy of the license as well as information regarding\r
4 // copyright ownership at http://nunit.org/?p=license&r=2.4.\r
5 // ****************************************************************\r
6 \r
7 namespace NUnit.Core\r
8 {\r
9         using System;\r
10         using System.Text;\r
11 \r
12         /// <summary>\r
13         /// The TestResult abstract class represents\r
14         /// the result of a test and is used to\r
15         /// communicate results across AppDomains.\r
16         /// </summary>\r
17         /// \r
18         [Serializable]\r
19         public abstract class TestResult\r
20         {\r
21                 #region Fields\r
22                 /// <summary>\r
23                 /// Indicates whether the test was executed or not\r
24                 /// </summary>\r
25                 private RunState runState;\r
26 \r
27                 /// <summary>\r
28                 /// Indicates the result of the test\r
29                 /// </summary>\r
30                 private ResultState resultState;\r
31 \r
32                 /// <summary>\r
33                 /// Indicates the location of a failure\r
34                 /// </summary>\r
35         private FailureSite failureSite;\r
36 \r
37                 /// <summary>\r
38                 /// The elapsed time for executing this test\r
39                 /// </summary>\r
40                 private double time = 0.0;\r
41 \r
42                 /// <summary>\r
43                 /// The name of the test\r
44                 /// </summary>\r
45                 private string name;\r
46 \r
47                 /// <summary>\r
48                 /// The test that this result pertains to\r
49                 /// </summary>\r
50                 private TestInfo test;\r
51 \r
52                 /// <summary>\r
53                 /// The stacktrace at the point of failure\r
54                 /// </summary>\r
55                 private string stackTrace;\r
56 \r
57                 /// <summary>\r
58                 /// Description of this test\r
59                 /// </summary>\r
60                 private string description;\r
61 \r
62                 /// <summary>\r
63                 /// Message giving the reason for failure\r
64                 /// </summary>\r
65                 protected string messageString;\r
66 \r
67                 /// <summary>\r
68                 /// Number of asserts executed by this test\r
69                 /// </summary>\r
70                 private int assertCount = 0;\r
71 \r
72                 #endregion\r
73 \r
74                 #region Protected Constructor\r
75                 /// <summary>\r
76                 /// Protected constructor constructs a test result given\r
77                 /// a test and a name.\r
78                 /// </summary>\r
79                 /// <param name="test">The test to be used</param>\r
80                 /// <param name="name">Name for this result</param>\r
81                 protected TestResult(TestInfo test, string name)\r
82                 {\r
83                         this.name = name;\r
84                         this.test = test;\r
85             this.RunState = RunState.Runnable;\r
86             if (test != null)\r
87             {\r
88                 this.description = test.Description;\r
89                 this.runState = test.RunState;\r
90                 this.messageString = test.IgnoreReason;\r
91             }\r
92         }\r
93                 #endregion\r
94 \r
95         #region Properties\r
96 \r
97                 /// <summary>\r
98                 /// Gets the RunState of the result, which indicates\r
99                 /// whether or not it has executed and why.\r
100                 /// </summary>\r
101         public RunState RunState\r
102         {\r
103             get { return runState; }\r
104             set { runState = value; }\r
105         }\r
106 \r
107                 /// <summary>\r
108                 /// Gets the ResultState of the test result, which \r
109                 /// indicates the success or failure of the test.\r
110                 /// </summary>\r
111         public ResultState ResultState\r
112         {\r
113             get { return resultState; }\r
114         }\r
115 \r
116                 /// <summary>\r
117                 /// Gets the stage of the test in which a failure\r
118                 /// or error occured.\r
119                 /// </summary>\r
120         public FailureSite FailureSite\r
121         {\r
122             get { return failureSite; }\r
123         }\r
124 \r
125                 /// <summary>\r
126                 /// Indicates whether the test executed\r
127                 /// </summary>\r
128         public bool Executed\r
129         {\r
130             get { return runState == RunState.Executed; }\r
131         }\r
132 \r
133                 /// <summary>\r
134                 /// Gets the name of the test result\r
135                 /// </summary>\r
136         public virtual string Name\r
137         {\r
138             get { return name; }\r
139         }\r
140 \r
141                 /// <summary>\r
142                 /// Gets the test associated with this result\r
143                 /// </summary>\r
144         public ITest Test\r
145         {\r
146             get { return test; }\r
147         }\r
148 \r
149                 /// <summary>\r
150                 /// Indicates whether the test ran successfully\r
151                 /// </summary>\r
152         public virtual bool IsSuccess\r
153         {\r
154             // TODO: Redefine this more precisely\r
155             get { return !IsFailure; }\r
156             //get { return resultState == ResultState.Success; }\r
157         }\r
158 \r
159         /// <summary>\r
160         /// Indicates whether the test failed\r
161         /// </summary>\r
162                 // TODO: Distinguish errors from failures\r
163         public virtual bool IsFailure\r
164         {\r
165             get { return resultState == ResultState.Failure || resultState == ResultState.Error; }\r
166         }\r
167 \r
168                 /// <summary>\r
169                 /// Gets a description associated with the test\r
170                 /// </summary>\r
171         public virtual string Description\r
172         {\r
173             get { return description; }\r
174             set { description = value; }\r
175         }\r
176 \r
177                 /// <summary>\r
178                 /// Gets the elapsed time for running the test\r
179                 /// </summary>\r
180         public double Time\r
181         {\r
182             get { return time; }\r
183             set { time = value; }\r
184         }\r
185 \r
186                 /// <summary>\r
187                 /// Gets the message associated with a test\r
188                 /// failure or with not running the test\r
189                 /// </summary>\r
190         public string Message\r
191         {\r
192             get { return messageString; }\r
193         }\r
194 \r
195                 /// <summary>\r
196                 /// Gets any stacktrace associated with an\r
197                 /// error or failure.\r
198                 /// </summary>\r
199         public virtual string StackTrace\r
200         {\r
201             get\r
202             {\r
203                 return stackTrace;\r
204             }\r
205             set\r
206             {\r
207                 stackTrace = value;\r
208             }\r
209         }\r
210 \r
211                 /// <summary>\r
212                 /// Gets or sets the count of asserts executed\r
213                 /// when running the test.\r
214                 /// </summary>\r
215         public int AssertCount\r
216         {\r
217             get { return assertCount; }\r
218             set { assertCount = value; }\r
219         }\r
220 \r
221         #endregion\r
222 \r
223         #region Public Methods\r
224         /// <summary>\r
225                 /// Mark the test as succeeding\r
226                 /// </summary>\r
227                 public void Success() \r
228                 { \r
229                         this.runState = RunState.Executed;\r
230                         this.resultState = ResultState.Success; \r
231                 }\r
232 \r
233                 /// <summary>\r
234                 /// Mark the test as ignored.\r
235                 /// </summary>\r
236                 /// <param name="reason">The reason the test was not run</param>\r
237                 public void Ignore(string reason)\r
238                 {\r
239                         Ignore( reason, null );\r
240                 }\r
241 \r
242                 /// <summary>\r
243                 /// Mark the test as ignored.\r
244                 /// </summary>\r
245                 /// <param name="ex">The ignore exception that was thrown</param>\r
246                 public void Ignore( Exception ex )\r
247                 {\r
248                         Ignore( ex.Message, BuildStackTrace( ex ) );\r
249                 }\r
250 \r
251                 /// <summary>\r
252                 /// Mark the test as ignored.\r
253                 /// </summary>\r
254                 /// <param name="reason">The reason the test was not run</param>\r
255                 /// <param name="stackTrace">Stack trace giving the location of the command</param>\r
256                 public void Ignore(string reason, string stackTrace)\r
257                 {\r
258                         NotRun( RunState.Ignored, reason, stackTrace );\r
259                 }\r
260 \r
261                 /// <summary>\r
262                 /// Mark the test as skipped.\r
263                 /// </summary>\r
264                 /// <param name="reason">The reason the test was not run</param>\r
265                 public void Skip(string reason)\r
266                 {\r
267                         Skip( reason, null );\r
268                 }\r
269 \r
270                 /// <summary>\r
271                 /// Mark the test as ignored.\r
272                 /// </summary>\r
273                 /// <param name="ex">The ignore exception that was thrown</param>\r
274                 public void Skip( Exception ex )\r
275                 {\r
276                         Skip( ex.Message, BuildStackTrace( ex ) );\r
277                 }\r
278 \r
279                 /// <summary>\r
280                 /// Mark the test as skipped.\r
281                 /// </summary>\r
282                 /// <param name="reason">The reason the test was not run</param>\r
283                 /// <param name="stackTrace">Stack trace giving the location of the command</param>\r
284                 public void Skip(string reason, string stackTrace)\r
285                 {\r
286                         NotRun( RunState.Skipped, reason, stackTrace );\r
287                 }\r
288 \r
289                 /// <summary>\r
290                 /// Mark the test as Not Run - either skipped or ignored\r
291                 /// </summary>\r
292                 /// <param name="runState">The RunState to use in the result</param>\r
293                 /// <param name="reason">The reason the test was not run</param>\r
294                 /// <param name="stackTrace">Stack trace giving the location of the command</param>\r
295                 public void NotRun(RunState runState, string reason, string stackTrace)\r
296                 {\r
297                         this.runState = runState;\r
298                         this.messageString = reason;\r
299                         this.stackTrace = stackTrace;\r
300                 }\r
301 \r
302 \r
303                 /// <summary>\r
304                 /// Mark the test as a failure due to an\r
305                 /// assertion having failed.\r
306                 /// </summary>\r
307                 /// <param name="message">Message to display</param>\r
308                 /// <param name="stackTrace">Stack trace giving the location of the failure</param>\r
309                 public void Failure(string message, string stackTrace)\r
310         {\r
311             Failure(message, stackTrace, FailureSite.Test);\r
312         }\r
313 \r
314                 /// <summary>\r
315                 /// Mark the test as a failure due to an\r
316                 /// assertion having failed.\r
317                 /// </summary>\r
318                 /// <param name="message">Message to display</param>\r
319                 /// <param name="stackTrace">Stack trace giving the location of the failure</param>\r
320                 /// <param name="failureSite">The site of the failure</param>\r
321                 public void Failure(string message, string stackTrace, FailureSite failureSite )\r
322                 {\r
323                         this.runState = RunState.Executed;\r
324                         this.resultState = ResultState.Failure;\r
325             this.failureSite = failureSite;\r
326                         this.messageString = message;\r
327                         this.stackTrace = stackTrace;\r
328                 }\r
329 \r
330                 /// <summary>\r
331                 /// Marks the result as an error due to an exception thrown\r
332                 /// by the test.\r
333                 /// </summary>\r
334                 /// <param name="exception">The exception that was caught</param>\r
335         public void Error(Exception exception)\r
336         {\r
337             Error(exception, FailureSite.Test);\r
338         }\r
339 \r
340                 /// <summary>\r
341                 /// Marks the result as an error due to an exception thrown\r
342                 /// from the indicated FailureSite.\r
343                 /// </summary>\r
344                 /// <param name="exception">The exception that was caught</param>\r
345                 /// <param name="failureSite">The site from which it was thrown</param>\r
346                 public void Error( Exception exception, FailureSite failureSite )\r
347                 {\r
348                         this.runState = RunState.Executed;\r
349                         this.resultState = ResultState.Error;\r
350             this.failureSite = failureSite;\r
351 \r
352             string message = BuildMessage(exception);\r
353             string stackTrace = BuildStackTrace(exception);\r
354 \r
355             if (failureSite == FailureSite.TearDown)\r
356             {\r
357                 message = "TearDown : " + message;\r
358                 stackTrace = "--TearDown" + Environment.NewLine + stackTrace;\r
359 \r
360                 if (this.messageString != null)\r
361                     message = this.messageString + Environment.NewLine + message;\r
362                 if (this.stackTrace != null)\r
363                     stackTrace = this.stackTrace + Environment.NewLine + stackTrace;\r
364             }\r
365 \r
366             this.messageString = message;\r
367             this.stackTrace = stackTrace;\r
368                 }\r
369                 #endregion\r
370 \r
371                 #region Exception Helpers\r
372 \r
373                 private string BuildMessage(Exception exception)\r
374                 {\r
375                         StringBuilder sb = new StringBuilder();\r
376                         sb.AppendFormat( "{0} : {1}", exception.GetType().ToString(), exception.Message );\r
377 \r
378                         Exception inner = exception.InnerException;\r
379                         while( inner != null )\r
380                         {\r
381                                 sb.Append( Environment.NewLine );\r
382                                 sb.AppendFormat( "  ----> {0} : {1}", inner.GetType().ToString(), inner.Message );\r
383                                 inner = inner.InnerException;\r
384                         }\r
385 \r
386                         return sb.ToString();\r
387                 }\r
388                 \r
389                 private string BuildStackTrace(Exception exception)\r
390                 {\r
391             StringBuilder sb = new StringBuilder( GetStackTrace( exception ) );\r
392 \r
393             Exception inner = exception.InnerException;\r
394             while( inner != null )\r
395             {\r
396                 sb.Append( Environment.NewLine );\r
397                 sb.Append( "--" );\r
398                 sb.Append( inner.GetType().Name );\r
399                 sb.Append( Environment.NewLine );\r
400                 sb.Append( GetStackTrace( inner ) );\r
401 \r
402                 inner = inner.InnerException;\r
403             }\r
404 \r
405             return sb.ToString();\r
406                 }\r
407 \r
408                 private string GetStackTrace(Exception exception)\r
409                 {\r
410                         try\r
411                         {\r
412                                 return exception.StackTrace;\r
413                         }\r
414                         catch( Exception )\r
415                         {\r
416                                 return "No stack trace available";\r
417                         }\r
418                 }\r
419 \r
420                 #endregion\r
421 \r
422                 /// <summary>\r
423                 /// Abstract method that accepts a ResultVisitor\r
424                 /// </summary>\r
425                 /// <param name="visitor">The visitor</param>\r
426                 public abstract void Accept(ResultVisitor visitor);\r
427         }\r
428 }\r