/src/NUnit/interfaces/TestResult.cs
C# | 503 lines | 248 code | 64 blank | 191 comment | 32 complexity | 911b29b5604dc6a6f6a054c2a236ab6d 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.Collections; 12 13 /// <summary> 14 /// The TestResult class represents 15 /// the result of a test and is used to 16 /// communicate results across AppDomains. 17 /// </summary> 18 /// 19 [Serializable] 20 public class TestResult 21 { 22 #region Fields 23 /// <summary> 24 /// Indicates the result of the test 25 /// </summary> 26 private ResultState resultState; 27 28 /// <summary> 29 /// Indicates the location of a failure 30 /// </summary> 31 private FailureSite failureSite; 32 33 /// <summary> 34 /// The elapsed time for executing this test 35 /// </summary> 36 private double time = 0.0; 37 38 /// <summary> 39 /// The test that this result pertains to 40 /// </summary> 41 private readonly TestInfo test; 42 43 /// <summary> 44 /// The stacktrace at the point of failure 45 /// </summary> 46 private string stackTrace; 47 48 /// <summary> 49 /// Message giving the reason for failure 50 /// </summary> 51 private string message; 52 53 /// <summary> 54 /// List of child results 55 /// </summary> 56 private IList results; 57 58 /// <summary> 59 /// Number of asserts executed by this test 60 /// </summary> 61 private int assertCount = 0; 62 63 #endregion 64 65 #region Constructor 66 /// <summary> 67 /// Construct a test result given a TestInfo 68 /// </summary> 69 /// <param name="test">The test to be used</param> 70 public TestResult(TestInfo test) 71 { 72 this.test = test; 73 this.message = test.IgnoreReason; 74 } 75 76 /// <summary> 77 /// Construct a TestResult given an ITest 78 /// </summary> 79 /// <param name="test"></param> 80 public TestResult(ITest test) : this( new TestInfo(test) ) { } 81 82 /// <summary> 83 /// Construct a TestResult given a TestName 84 /// </summary> 85 /// <param name="testName">A TestName</param> 86 public TestResult(TestName testName) : this( new TestInfo( testName ) ) { } 87 #endregion 88 89 #region Properties 90 91 /// <summary> 92 /// Gets the ResultState of the test result, which 93 /// indicates the success or failure of the test. 94 /// </summary> 95 public ResultState ResultState 96 { 97 get { return resultState; } 98 } 99 100 /// <summary> 101 /// Gets the stage of the test in which a failure 102 /// or error occured. 103 /// </summary> 104 public FailureSite FailureSite 105 { 106 get { return failureSite; } 107 } 108 109 /// <summary> 110 /// Indicates whether the test executed 111 /// </summary> 112 public bool Executed 113 { 114 get 115 { 116 return resultState == ResultState.Success || 117 resultState == ResultState.Failure || 118 resultState == ResultState.Error || 119 resultState == ResultState.Inconclusive; 120 } 121 } 122 123 /// <summary> 124 /// Gets the name of the test result 125 /// </summary> 126 public virtual string Name 127 { 128 get { return test.TestName.Name; } 129 } 130 131 /// <summary> 132 /// Gets the full name of the test result 133 /// </summary> 134 public virtual string FullName 135 { 136 get { return test.TestName.FullName; } 137 } 138 139 /// <summary> 140 /// Gets the test associated with this result 141 /// </summary> 142 public ITest Test 143 { 144 get { return test; } 145 } 146 147 /// <summary> 148 /// Indicates whether the test ran successfully 149 /// </summary> 150 public virtual bool IsSuccess 151 { 152 get { return resultState == ResultState.Success; } 153 } 154 155 /// <summary> 156 /// Indicates whether the test failed 157 /// </summary> 158 public virtual bool IsFailure 159 { 160 get { return resultState == ResultState.Failure; } 161 } 162 163 /// <summary> 164 /// Indicates whether the test had an error (as opposed to a failure) 165 /// </summary> 166 public virtual bool IsError 167 { 168 get { return resultState == ResultState.Error; } 169 } 170 171 /// <summary> 172 /// Gets a description associated with the test 173 /// </summary> 174 public string Description 175 { 176 get { return test.Description; } 177 } 178 179 /// <summary> 180 /// Gets the elapsed time for running the test 181 /// </summary> 182 public double Time 183 { 184 get { return time; } 185 set { time = value; } 186 } 187 188 /// <summary> 189 /// Gets the message associated with a test 190 /// failure or with not running the test 191 /// </summary> 192 public string Message 193 { 194 get { return message; } 195 } 196 197 /// <summary> 198 /// Gets any stacktrace associated with an 199 /// error or failure. 200 /// </summary> 201 public virtual string StackTrace 202 { 203 get { return stackTrace; } 204 set { stackTrace = value; } 205 } 206 207 /// <summary> 208 /// Gets or sets the count of asserts executed 209 /// when running the test. 210 /// </summary> 211 public int AssertCount 212 { 213 get { return assertCount; } 214 set { assertCount = value; } 215 } 216 217 /// <summary> 218 /// Return true if this result has any child results 219 /// </summary> 220 public bool HasResults 221 { 222 get { return results != null && results.Count > 0; } 223 } 224 225 /// <summary> 226 /// Gets a list of the child results of this TestResult 227 /// </summary> 228 public IList Results 229 { 230 get { return results; } 231 } 232 233 #endregion 234 235 #region Public Methods 236 /// <summary> 237 /// Mark the test as succeeding 238 /// </summary> 239 public void Success() 240 { 241 SetResult( ResultState.Success, null, null ); 242 } 243 244 /// <summary> 245 /// Mark the test as succeeding and set a message 246 /// </summary> 247 public void Success( string message ) 248 { 249 SetResult( ResultState.Success, message, null ); 250 } 251 252 /// <summary> 253 /// Mark the test as ignored. 254 /// </summary> 255 /// <param name="reason">The reason the test was not run</param> 256 public void Ignore(string reason) 257 { 258 Ignore( reason, null ); 259 } 260 261 /// <summary> 262 /// Mark the test as ignored. 263 /// </summary> 264 /// <param name="ex">The ignore exception that was thrown</param> 265 public void Ignore( Exception ex ) 266 { 267 Ignore( ex.Message, BuildStackTrace( ex ) ); 268 } 269 270 /// <summary> 271 /// Mark the test as ignored. 272 /// </summary> 273 /// <param name="reason">The reason the test was not run</param> 274 /// <param name="stackTrace">Stack trace giving the location of the command</param> 275 public void Ignore(string reason, string stackTrace) 276 { 277 SetResult( ResultState.Ignored, reason, stackTrace ); 278 } 279 280 /// <summary> 281 /// Mark the test as skipped. 282 /// </summary> 283 /// <param name="reason">The reason the test was not run</param> 284 public void Skip(string reason) 285 { 286 SetResult(ResultState.Skipped, reason, null); 287 } 288 289 /// <summary> 290 /// Mark the test a not runnable with a reason 291 /// </summary> 292 /// <param name="reason">The reason the test is invalid</param> 293 public void Invalid( string reason ) 294 { 295 SetResult( ResultState.NotRunnable, reason, null ); 296 } 297 298 /// <summary> 299 /// Mark the test as not runnable due to a builder exception 300 /// </summary> 301 /// <param name="ex">The exception thrown by the builder or an addin</param> 302 public void Invalid(Exception ex) 303 { 304 SetResult(ResultState.NotRunnable, BuildMessage( ex ), BuildStackTrace(ex)); 305 } 306 307 /// <summary> 308 /// Set the result of the test 309 /// </summary> 310 /// <param name="resultState">The ResultState to use in the result</param> 311 /// <param name="reason">The reason the test was not run</param> 312 /// <param name="stackTrace">Stack trace giving the location of the command</param> 313 /// <param name="failureSite">The location of the failure, if any</param> 314 public void SetResult(ResultState resultState, string reason, string stackTrace, FailureSite failureSite) 315 { 316 if (failureSite == FailureSite.SetUp) 317 reason = "SetUp : " + reason; 318 else if (failureSite == FailureSite.TearDown) 319 { 320 reason = "TearDown : " + reason; 321 stackTrace = "--TearDown" + Environment.NewLine + stackTrace; 322 323 if (this.message != null) 324 reason = this.message + Environment.NewLine + reason; 325 if (this.stackTrace != null) 326 stackTrace = this.stackTrace + Environment.NewLine + stackTrace; 327 } 328 329 this.resultState = resultState; 330 this.message = reason; 331 this.stackTrace = stackTrace; 332 this.failureSite = failureSite; 333 } 334 335 /// <summary> 336 /// Set the result of the test 337 /// </summary> 338 /// <param name="resultState">The ResultState to use in the result</param> 339 /// <param name="reason">The reason the test was not run</param> 340 /// <param name="stackTrace">Stack trace giving the location of the command</param> 341 public void SetResult(ResultState resultState, string reason, string stackTrace) 342 { 343 SetResult(resultState, reason, stackTrace, FailureSite.Test); 344 } 345 346 /// <summary> 347 /// Set the result of the test. 348 /// </summary> 349 /// <param name="resultState">The ResultState to use in the result</param> 350 /// <param name="ex">The exception that caused this result</param> 351 /// <param name="failureSite">The site at which an error or failure occured</param> 352 public void SetResult(ResultState resultState, Exception ex, FailureSite failureSite) 353 { 354 if (resultState == ResultState.Cancelled) 355 SetResult(resultState, "Test cancelled by user", BuildStackTrace(ex)); 356 else if (resultState == ResultState.Error) 357 SetResult( resultState, BuildMessage(ex), BuildStackTrace(ex), failureSite); 358 else 359 SetResult(resultState, ex.Message, ex.StackTrace, failureSite); 360 } 361 362 /// <summary> 363 /// Mark the test as a failure due to an 364 /// assertion having failed. 365 /// </summary> 366 /// <param name="message">Message to display</param> 367 /// <param name="stackTrace">Stack trace giving the location of the failure</param> 368 public void Failure(string message, string stackTrace) 369 { 370 Failure(message, stackTrace, FailureSite.Test); 371 } 372 373 /// <summary> 374 /// Mark the test as a failure due to an 375 /// assertion having failed. 376 /// </summary> 377 /// <param name="message">Message to display</param> 378 /// <param name="stackTrace">Stack trace giving the location of the failure</param> 379 /// <param name="failureSite">The site of the failure</param> 380 public void Failure(string message, string stackTrace, FailureSite failureSite ) 381 { 382 SetResult( Core.ResultState.Failure, message, stackTrace ); 383 this.failureSite = failureSite; 384 } 385 386 /// <summary> 387 /// Marks the result as an error due to an exception thrown 388 /// by the test. 389 /// </summary> 390 /// <param name="exception">The exception that was caught</param> 391 public void Error(Exception exception) 392 { 393 Error(exception, FailureSite.Test); 394 } 395 396 /// <summary> 397 /// Marks the result as an error due to an exception thrown 398 /// from the indicated FailureSite. 399 /// </summary> 400 /// <param name="exception">The exception that was caught</param> 401 /// <param name="failureSite">The site from which it was thrown</param> 402 public void Error(Exception exception, FailureSite failureSite) 403 { 404 SetResult(ResultState.Error, exception, failureSite); 405 //string message = BuildMessage(exception); 406 //string stackTrace = BuildStackTrace(exception); 407 408 //if (failureSite == FailureSite.TearDown) 409 //{ 410 // message = "TearDown : " + message; 411 // stackTrace = "--TearDown" + Environment.NewLine + stackTrace; 412 413 // if (this.message != null) 414 // message = this.message + Environment.NewLine + message; 415 // if (this.stackTrace != null) 416 // stackTrace = this.stackTrace + Environment.NewLine + stackTrace; 417 //} 418 419 //SetResult( ResultState.Error, message, stackTrace ); 420 //this.failureSite = failureSite; 421 } 422 423 /// <summary> 424 /// Add a child result 425 /// </summary> 426 /// <param name="result">The child result to be added</param> 427 public void AddResult(TestResult result) 428 { 429 if ( results == null ) 430 results = new ArrayList(); 431 432 this.results.Add(result); 433 434 switch (result.ResultState) 435 { 436 case ResultState.Failure: 437 case ResultState.Error: 438 if (!this.IsFailure && !this.IsError) 439 this.Failure("Child test failed", null, FailureSite.Child); 440 break; 441 case ResultState.Success: 442 if (this.ResultState == ResultState.Inconclusive) 443 this.Success(); 444 break; 445 case ResultState.Cancelled: 446 this.SetResult(ResultState.Cancelled, result.Message, null, FailureSite.Child); 447 break; 448 } 449 } 450 #endregion 451 452 #region Exception Helpers 453 454 private static string BuildMessage(Exception exception) 455 { 456 StringBuilder sb = new StringBuilder(); 457 sb.AppendFormat( "{0} : {1}", exception.GetType().ToString(), exception.Message ); 458 459 Exception inner = exception.InnerException; 460 while( inner != null ) 461 { 462 sb.Append( Environment.NewLine ); 463 sb.AppendFormat( " ----> {0} : {1}", inner.GetType().ToString(), inner.Message ); 464 inner = inner.InnerException; 465 } 466 467 return sb.ToString(); 468 } 469 470 private static string BuildStackTrace(Exception exception) 471 { 472 StringBuilder sb = new StringBuilder( GetStackTrace( exception ) ); 473 474 Exception inner = exception.InnerException; 475 while( inner != null ) 476 { 477 sb.Append( Environment.NewLine ); 478 sb.Append( "--" ); 479 sb.Append( inner.GetType().Name ); 480 sb.Append( Environment.NewLine ); 481 sb.Append( GetStackTrace( inner ) ); 482 483 inner = inner.InnerException; 484 } 485 486 return sb.ToString(); 487 } 488 489 private static string GetStackTrace(Exception exception) 490 { 491 try 492 { 493 return exception.StackTrace; 494 } 495 catch( Exception ) 496 { 497 return "No stack trace available"; 498 } 499 } 500 501 #endregion 502 } 503}