/// <summary>
        /// Create a fail-fast step definition, meaning a failure in this step will immediately fail the entire test.
        /// </summary>
        /// <param name="stepDescription">The plain-english description of this step</param>
        /// <param name="action">The action to perform</param>
        public static void x(this string stepDescription, Action action, TimeSpan maxDuration)
        {
            if (TestStepContext.Current == null)
                throw new InvalidOperationException(NoContextMessage);

            var step = new TestStep(stepDescription, action, TestStepContext.CurrentStep, maxDuration, true);
            TestStepContext.Current.AddAndExecute(step);
        }
示例#2
0
 public TestStep(string description, Action action, TestStep parentStep, TimeSpan maxDuration, bool failFast = true) : this()
 {
     this.Description = description;
     this.Action = action;
     this.Parent = parentStep;
     this.MaxDuration = maxDuration;
     this.FailFast = failFast;
 }
        /// <summary>
        /// Create a step definition that, if it fails, will still allow the next defined step to execute.
        /// </summary>
        /// <param name="stepDescription">The plain-english description of this step</param>
        /// <param name="action">The action to perform</param>
        public static void continueOnFail(this string stepDescription, Action action, TimeSpan maxDuration)
        {
            // If there is no current BddTestContext, just create one that will never be disposed.
            // This allows code to use step definitions even if there is no active test running with a BddTestContext at that time.
            // NOTE: the BddTestContext constructor will register the object with CallContext so it will not be garbage collected
            // unless Dispose() is explicitly called.
            if (TestStepContext.Current == null)
                new TestStepContext();

            var step = new TestStep(stepDescription, action, TestStepContext.CurrentStep, maxDuration, false);
            TestStepContext.Current.AddAndExecute(step);
        }
        /// <inheritdoc/>
        public void AddAndExecute(TestStep step)
        {
            TestStep parentStep = TestStepContext.CurrentStep;

            List<TestStep> stepList = parentStep == null ? this.topSteps : parentStep.Children;
            lock (stepList)
                stepList.Add(step);

            TimeSpan duration = TimeSpan.Zero;
            try
            {
                TestStepContext.CurrentStep = step;
                Collect.TimeOf(step.Action, out duration);
                step.Duration = duration;
                step.FunctionalPassed = true;
            }
            catch (Exception ex)
            {
                step.FunctionalPassed = false;
                step.Exception = ex;
                step.Duration = duration;
                if (step.FailFast)
                {
                    // If we are in a continue on fail context on an *ancestor* BDD step, we do NOT want to 
                    // render the BDD steps at this time - just throw the exception
                    // Also true if there are any parent steps
                    if (step.InContinueOnFailContext || step.Parent != null)
                        throw;
                    else
                        this.RenderStepResultsAndFail();
                }
            }
            finally
            {
                TestStepContext.CurrentStep = parentStep;
            }
        }