async Task Run(ITestRunner runner, TestResultCollection result, IEnumerable <TestCase> selected, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); if (Attribute.Timeout > 0) { cts.CancelAfter(Attribute.Timeout); } var context = runner.CreateContext(this); context.Configuration = Configuration; try { SetUp(context); } catch (Exception ex) { Log("{0}.SetUp failed: {1}", result.Name, ex); result.AddChild(new TestError(result.Name, "SetUp failed", ex)); return; } foreach (var test in selected) { if (cts.Token.IsCancellationRequested) { break; } bool reuseContext = GetReuseContext(test); int repeat = reuseContext ? GetRepeat(test) : 1; string iteration; if (Suite.MaxIterations == 1) { iteration = string.Empty; } else { iteration = string.Format( " (iteration {0}/{1})", Suite.CurrentIteration + 1, Suite.MaxIterations); } string name = Name; if (runner.Name != null) { name = string.Format( "{0}.{1} ({2}){3}", Name, test.Name, runner.Name, iteration); } else { name = string.Format( "{0}.{1} ({2}", Name, test.Name, iteration); } for (int i = 0; i < repeat; i++) { string thisIter; if (repeat == 1) { thisIter = string.Empty; } else { thisIter = string.Format(" (iteration {0}/{1})", i + 1, repeat); } Suite.OnStatusMessageEvent("Running {0}{1}", name, thisIter); try { var retval = await Run(test, context, cts.Token); result.AddChild(retval); } catch (Exception ex) { Log("{0} failed: {1}", test.Name, ex); result.AddChild(new TestError(result.Name, null, ex)); } } } try { TearDown(context); } catch (Exception ex) { Log("{0}.TearDown failed: {1}", result.Name, ex); result.AddChild(new TestError(result.Name, "TearDown failed", ex)); } cts.Token.ThrowIfCancellationRequested(); }