private TestCommand MakeOneTimeTearDownCommand(List <SetUpTearDownItem> setUpTearDownItems, List <TestActionItem> actions)
        {
            TestCommand command = new EmptyTestCommand(Test);

            // For Theories, follow with TheoryResultCommand to adjust result as needed
            if (Test.TestType == "Theory")
            {
                command = new TheoryResultCommand(command);
            }

            // Create the AfterTestAction commands
            int index = actions.Count;

            while (--index >= 0)
            {
                command = new AfterTestActionCommand(command, actions[index]);
            }

            // Create the OneTimeTearDown commands
            foreach (SetUpTearDownItem item in setUpTearDownItems)
            {
                command = new OneTimeTearDownCommand(command, item);
            }

            // Dispose of fixture if necessary
            if (Test is IDisposableFixture && typeof(IDisposable).IsAssignableFrom(Test.TypeInfo.Type))
            {
                command = new DisposeFixtureCommand(command);
            }

            return(command);
        }
示例#2
0
        /// <summary>
        /// Creates a test command for use in running this test.
        /// </summary>
        /// <returns>A TestCommand</returns>
        private TestCommand MakeTestCommand()
        {
            if (Test.RunState == RunState.Runnable ||
                Test.RunState == RunState.Explicit && Filter.IsExplicitMatch(Test))
            {
                // Command to execute test
                TestCommand command = new TestMethodCommand(_testMethod);

                var method = _testMethod.Method;

                // Add any wrappers to the TestMethodCommand
                foreach (IWrapTestMethod wrapper in method.GetCustomAttributes <IWrapTestMethod>(true))
                {
                    command = wrapper.Wrap(command);
                }

                // Create TestActionCommands using attributes of the method
                foreach (ITestAction action in Test.Actions)
                {
                    if (action.Targets == ActionTargets.Default || action.Targets.HasFlag(ActionTargets.Test))
                    {
                        command = new TestActionCommand(command, action);
                    }
                }
                ;

                // Try to locate the parent fixture. In current implementations, the test method
                // is either one or two levels below the TestFixture - if this changes,
                // so should the following code.
                TestFixture parentFixture = Test.Parent as TestFixture ?? Test.Parent?.Parent as TestFixture;

                // In normal operation we should always get the methods from the parent fixture.
                // However, some of NUnit's own tests can create a TestMethod without a parent
                // fixture. Most likely, we should stop doing this, but it affects 100s of cases.
                var setUpMethods    = parentFixture?.SetUpMethods ?? Test.TypeInfo.GetMethodsWithAttribute <SetUpAttribute>(true);
                var tearDownMethods = parentFixture?.TearDownMethods ?? Test.TypeInfo.GetMethodsWithAttribute <TearDownAttribute>(true);

                // Wrap in SetUpTearDownCommands
                var setUpTearDownList = BuildSetUpTearDownList(setUpMethods, tearDownMethods);
                foreach (var item in setUpTearDownList)
                {
                    command = new SetUpTearDownCommand(command, item);
                }

                // Dispose of fixture if necessary
                var isInstancePerTestCase = Test.HasLifeCycle(LifeCycle.InstancePerTestCase);
                if (isInstancePerTestCase && parentFixture is IDisposableFixture && typeof(IDisposable).IsAssignableFrom(parentFixture.TypeInfo.Type))
                {
                    command = new DisposeFixtureCommand(command);
                }

                // In the current implementation, upstream actions only apply to tests. If that should change in the future,
                // then actions would have to be tested for here. For now we simply assert it in Debug. We allow
                // ActionTargets.Default, because it is passed down by ParameterizedMethodSuite.
                int index = Context.UpstreamActions.Count;
                while (--index >= 0)
                {
                    ITestAction action = Context.UpstreamActions[index];
                    System.Diagnostics.Debug.Assert(
                        action.Targets == ActionTargets.Default || action.Targets.HasFlag(ActionTargets.Test),
                        "Invalid target on upstream action: " + action.Targets.ToString());

                    command = new TestActionCommand(command, action);
                }

                // Add wrappers that apply before setup and after teardown
                foreach (ICommandWrapper decorator in method.GetCustomAttributes <IWrapSetUpTearDown>(true))
                {
                    command = decorator.Wrap(command);
                }

                // Add command to set up context using attributes that implement IApplyToContext
                foreach (var attr in method.GetCustomAttributes <IApplyToContext>(true))
                {
                    command = new ApplyChangesToContextCommand(command, attr);
                }

                // Add a construct command and optionally a dispose command in case of instance per test case.
                if (isInstancePerTestCase)
                {
                    command = new FixturePerTestCaseCommand(command);
                }
                // If a timeout is specified, create a TimeoutCommand
                // Timeout set at a higher level
                int timeout = Context.TestCaseTimeout;

                // Timeout set on this test
                if (Test.Properties.ContainsKey(PropertyNames.Timeout))
                {
                    timeout = (int)Test.Properties.Get(PropertyNames.Timeout);
                }

                if (timeout > 0)
                {
                    command = new TimeoutCommand(command, timeout, _debugger);
                }

                // Add wrappers for repeatable tests after timeout so the timeout is reset on each repeat
                foreach (var repeatableAttribute in method.GetCustomAttributes <IRepeatTest>(true))
                {
                    command = repeatableAttribute.Wrap(command);
                }

                return(command);
            }
            else
            {
                return(new SkipCommand(_testMethod));
            }
        }