/// <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); }
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; } }