/// <summary>
/// Runs specified test class as coroutine.
/// </summary>
/// <param name="testClass">The test class.</param>
/// <param name="summaryReporter">The reporter object to report test class execution summary.</param>
/// <param name="resultPrefab">The prefab for test result indicators.</param>
/// <param name="resultVertical">The vertical area which test result indicators to be belonging.</param>
/// <returns><see cref="IEnumerator"/> for coroutine.</returns>
private static IEnumerator RuntTestCoroutineCore( TestClass testClass, TestSummaryReporter summaryReporter, Result resultPrefab, GameObject resultVertical )
{
bool isCrashed = false;
try
{
InitializeTestEngine();
}
catch ( Exception ex )
{
summaryReporter.HandleFatalException( "InitializeTestEngine", ex, resultPrefab, resultVertical );
summaryReporter.RecordError( testClass.MethodCount );
isCrashed = true;
}
if ( isCrashed )
{
yield break;
}
yield return null;
try
{
testClass.FixtureSetup();
}
catch ( Exception ex )
{
summaryReporter.HandleFatalException( "FixtureSetup", ex, resultPrefab, resultVertical );
summaryReporter.RecordError( testClass.MethodCount );
isCrashed = true;
}
if ( isCrashed )
{
yield break;
}
yield return null;
TestClassInstance instance = null;
try
{
instance = testClass.NewTest();
}
catch ( Exception ex )
{
summaryReporter.HandleFatalException( "Instantiation", ex, resultPrefab, resultVertical );
summaryReporter.RecordError( testClass.MethodCount );
isCrashed = true;
}
if ( isCrashed )
{
yield break;
}
yield return null;
int remains = testClass.MethodCount;
foreach ( var method in instance.TestMethods )
{
try
{
instance.TestSetup();
}
catch ( Exception ex )
{
summaryReporter.HandleFatalException( "TestSetup", ex, resultPrefab, resultVertical );
summaryReporter.RecordError( remains );
isCrashed = true;
}
if ( isCrashed )
{
yield break;
}
yield return null;
var fullMethodName = testClass.Name + "." + method.Name;
try
{
method.Method();
summaryReporter.RecordSuccess();
// Omit test result to reduce memory usage and avoid cluttered screen.
}
catch ( Exception ex )
{
if ( IsTestSkipping( ex ) )
{
summaryReporter.RecordSkip();
}
else
{
bool isFailure = IsTestFailure( ex );
var messageHeader = summaryReporter.FormatMethodName( method.Name ) + ( isFailure ? " NG" : " Error" ) + Environment.NewLine;
UnityEngine.Debug.LogError( messageHeader + ex );
var r = CreateResult( fullMethodName, resultPrefab, resultVertical );
var baseException = ex.GetBaseException();
if ( isFailure || baseException == ex )
{
r.Message.Value = messageHeader + ex.Message;
}
else
{
// Record BaseException to help investigation.
r.Message.Value = messageHeader + ex.Message + "-->" + Environment.NewLine + baseException.Message;
}
r.Color.Value = UnityEngine.Color.red;
if ( isFailure )
{
summaryReporter.RecordFailure();
}
else
{
summaryReporter.RecordError();
}
}
}
remains--;
yield return null;
try
{
instance.TestCleanup();
}
catch ( Exception ex )
{
summaryReporter.HandleFatalException( "TestCleanup", ex, resultPrefab, resultVertical );
summaryReporter.RecordError( remains );
isCrashed = true;
}
if ( isCrashed )
{
yield break;
}
yield return null;
} // foreach method
try
{
testClass.FixtureCleanup();
}
catch ( Exception ex )
{
summaryReporter.HandleFatalException( "FixtureCleanup", ex, resultPrefab, resultVertical );
isCrashed = true;
}
if ( isCrashed )
{
yield break;
}
yield return null;
try
{
CleanUpTestEngine();
}
catch ( Exception ex )
{
summaryReporter.HandleFatalException( "CleanupTestEngine", ex, resultPrefab, resultVertical );
}
yield return null;
}