<PackageReference Include="NUnit" Version="3.0.0-beta-2" />

CompositeWorkItem

public class CompositeWorkItem : WorkItem
A CompositeWorkItem represents a test suite and encapsulates the execution of the suite as well as all its child tests.
using NUnit.Framework.Interfaces; using NUnit.Framework.Internal.Commands; using System; using System.Collections.Generic; using System.Reflection; using System.Threading; namespace NUnit.Framework.Internal.Execution { public class CompositeWorkItem : WorkItem { private TestSuite _suite; private ITestFilter _childFilter; private TestCommand _setupCommand; private TestCommand _teardownCommand; private List<WorkItem> _children; private CountdownEvent _childTestCountdown; private object _completionLock = new object(); public CompositeWorkItem(TestSuite suite, ITestFilter childFilter) : base(suite) { _suite = suite; _childFilter = childFilter; } protected override void PerformWork() { InitializeSetUpAndTearDownCommands(); if (!CheckForCancellation()) { switch (base.Test.RunState) { default: base.Result.SetResult(ResultState.Success); CreateChildWorkItems(); if (_children.Count > 0) { PerformOneTimeSetUp(); if (!CheckForCancellation()) { switch (base.Result.ResultState.Status) { case TestStatus.Passed: RunChildren(); return; case TestStatus.Inconclusive: case TestStatus.Skipped: case TestStatus.Failed: SkipChildren(_suite, base.Result.ResultState.WithSite(FailureSite.Parent), "OneTimeSetUp: " + base.Result.Message); break; } } if (base.Context.ExecutionStatus != TestExecutionStatus.AbortRequested) PerformOneTimeTearDown(); } break; case RunState.Skipped: SkipFixture(ResultState.Skipped, GetSkipReason(), null); break; case RunState.Ignored: SkipFixture(ResultState.Ignored, GetSkipReason(), null); break; case RunState.NotRunnable: SkipFixture(ResultState.NotRunnable, GetSkipReason(), GetProviderStackTrace()); break; } } WorkItemComplete(); } private bool CheckForCancellation() { if (base.Context.ExecutionStatus != 0) { base.Result.SetResult(ResultState.Cancelled, "Test cancelled by user"); return true; } return false; } private void InitializeSetUpAndTearDownCommands() { List<SetUpTearDownItem> list = (_suite.FixtureType != (Type)null) ? CommandBuilder.BuildSetUpTearDownList(_suite.FixtureType, typeof(OneTimeSetUpAttribute), typeof(OneTimeTearDownAttribute)) : new List<SetUpTearDownItem>(); List<TestActionItem> list2 = new List<TestActionItem>(); foreach (ITestAction action in base.Actions) { bool flag = (action.Targets & ActionTargets.Suite) == ActionTargets.Suite || (action.Targets == ActionTargets.Default && !(base.Test is ParameterizedMethodSuite)); bool num = (action.Targets & ActionTargets.Test) == ActionTargets.Test && !(base.Test is ParameterizedMethodSuite); if (flag) list2.Add(new TestActionItem(action)); if (num) base.Context.UpstreamActions.Add(action); } _setupCommand = CommandBuilder.MakeOneTimeSetUpCommand(_suite, list, list2); _teardownCommand = CommandBuilder.MakeOneTimeTearDownCommand(_suite, list, list2); } private void PerformOneTimeSetUp() { try { _setupCommand.Execute(base.Context); base.Context.UpdateContextFromEnvironment(); } catch (Exception ex) { Exception ex2 = ex; if (ex2 is NUnitException || ex2 is TargetInvocationException) ex2 = ex2.InnerException; base.Result.RecordException(ex2, FailureSite.SetUp); } } private void RunChildren() { int num = _children.Count; if (num == 0) throw new InvalidOperationException("RunChildren called but item has no children"); _childTestCountdown = new CountdownEvent(num); foreach (WorkItem child in _children) { if (CheckForCancellation()) break; child.Completed += OnChildCompleted; child.InitializeContext(new TestExecutionContext(base.Context)); base.Context.Dispatcher.Dispatch(child); num--; } if (num > 0) { while (num-- > 0) { CountDownChildTest(); } } } private void CreateChildWorkItems() { _children = new List<WorkItem>(); foreach (Test test in _suite.Tests) { if (_childFilter.Pass(test)) _children.Add(WorkItem.CreateWorkItem(test, _childFilter)); } } private void SkipFixture(ResultState resultState, string message, string stackTrace) { base.Result.SetResult(resultState.WithSite(FailureSite.SetUp), message, StackFilter.Filter(stackTrace)); SkipChildren(_suite, resultState.WithSite(FailureSite.Parent), "OneTimeSetUp: " + message); } private void SkipChildren(TestSuite suite, ResultState resultState, string message) { foreach (Test test in suite.Tests) { if (_childFilter.Pass(test)) { TestResult testResult = test.MakeTestResult(); testResult.SetResult(resultState, message); base.Result.AddResult(testResult); if (test.IsSuite) SkipChildren((TestSuite)test, resultState, message); } } } private void PerformOneTimeTearDown() { base.Context.EstablishExecutionEnvironment(); _teardownCommand.Execute(base.Context); } private string GetSkipReason() { return (string)base.Test.Properties.Get("_SKIPREASON"); } private string GetProviderStackTrace() { return (string)base.Test.Properties.Get("_PROVIDERSTACKTRACE"); } private void OnChildCompleted(object sender, EventArgs e) { lock (_completionLock) { WorkItem workItem = sender as WorkItem; if (workItem != null) { workItem.Completed -= OnChildCompleted; base.Result.AddResult(workItem.Result); if (base.Context.StopOnError && workItem.Result.ResultState.Status == TestStatus.Failed) base.Context.ExecutionStatus = TestExecutionStatus.StopRequested; CountDownChildTest(); } } } private void CountDownChildTest() { _childTestCountdown.Signal(); if (_childTestCountdown.CurrentCount == 0) { if (base.Context.ExecutionStatus != TestExecutionStatus.AbortRequested) PerformOneTimeTearDown(); foreach (ITestResult child in base.Result.Children) { if (child.ResultState == ResultState.Cancelled) { base.Result.SetResult(ResultState.Cancelled, "Cancelled by user"); break; } } WorkItemComplete(); } } private static bool IsStaticClass(Type type) { if (type.IsAbstract) return type.IsSealed; return false; } } }