Skip to content
This repository has been archived by the owner on Jun 12, 2021. It is now read-only.

StepDefinition filter attributes #254

Closed
adamralph opened this issue May 5, 2015 · 8 comments
Closed

StepDefinition filter attributes #254

adamralph opened this issue May 5, 2015 · 8 comments
Labels
enhancement New feature or request
Milestone

Comments

@adamralph
Copy link
Owner

An extensibility point to allow the filtering of step definitions in a scenario before execution.

E.g. emulation of the undocumented 1.x ContinueOnFailureAfterAttribute:

[Scenario]
[ContinueAfterThen]
public void Something()
{
    "Given something"
        .f(() => ...);

    "When something"
        .f(() => ...);

    "Then something"
        .f(() => ...);

    "And something else"
        .f(() => ...);

    "And something else again"
        .f(() => ...);
}

// your own custom extension
public class ContinueAfterThenAttribute : Attribute, IFilter<IStepDefinition>
{
    public IEnumerable<IStepDefinition> Filter(IEnumerable<IStepDefinition> steps)
    {
        var then = false;
        return steps.Select(step => step.OnFailure(
            then || (then = step.Text.StartsWith("Then ", StringComparison.OrdinalIgnoreCase))
            ? RemainingSteps.Run
            : RemainingSteps.Skip));
    }
}
@adamralph adamralph added enhancement New feature or request 0 - Backlog labels May 5, 2015
@adamralph adamralph added this to the 2.0 milestone May 5, 2015
@adamralph adamralph mentioned this issue May 6, 2015
35 tasks
@adamralph
Copy link
Owner Author

@ursenzler any thoughts on the base attribute name?

@ursenzler
Copy link
Contributor

Depends on what else is possible with this attribute.
In this scenario it is not filtering.

Maybe StepConfigurationAttribute? -> method Configure(steps)
Or StepDefinitionAttribute? -> method Define(steps)
Or TweakStepAttribute? -> method Tweak(steps)

@adamralph
Copy link
Owner Author

Thanks for the suggestions. 'configuration' may be appropriate. I'm not sure about 'definition' since the steps are already defined, the attribute just adds some extra mutation to them. I think 'tweak' doesn't really convey enough. I also thought about 'customize' but that doesn't really fit. There are no 'standard' steps so every step or list of steps is custom.

I think the reason I initially proposed 'filter' was from the 'pipes and filters' pattern. I.e. in a pipe, a stream is passed into a filter and different stream comes out. I admit that the analogy to physical filters is very loose since a physical filter just removes some constituents from the stream, but it is a recognised term in software, e.g. http://en.wikipedia.org/wiki/Filter_(software) and http://www.eaipatterns.com/PipesAndFilters.html

To fit that pattern properly, the type would look like this:

public abstract class StepDefinitionFilterAttribute : Attribute
{
    public abstract IEnumerable<IStepDefinition> Filter(IEnumerable<IStepDefinition> steps);
}

Moreover, we could also have an int Priority property which allows xbehave to order multiple filters into a pipe.

I guess your custom attribute would look something like:

private class ContinueOnFailureAfterIt : StepDefinitionFilterAttribute
{
    public override IEnumerable<IStepDefinition> Filter(IEnumerable<IStepDefinition> steps)
    {
        var it = false;
        return steps.Select(step =>
        {
            if (it ? it : it = step.Text.StartsWith("It "))
            {
                step.ContinueOnFailure = true;
            }

            return step;
        });
    }
}

It might be possible to improve the API to provide a builder method on IStepDefinition:

private class ContinueOnFailureAfterIt : StepDefinitionFilterAttribute
{
    public override IEnumerable<IStepDefinition> Filter(IEnumerable<IStepDefinition> steps)
    {
        var it = false;
        return steps.Select(step =>
            step.ContinueOnFailure(it ? it : it = step.Text.StartsWith("It ")));
    }
}

I guess some further functional wizardry (using .Aggregate()?) could even remove the local it variable.

@ursenzler
Copy link
Contributor

I like this idea.

@adamralph
Copy link
Owner Author

then it shall be done 😃

@adamralph adamralph self-assigned this May 7, 2015
@adamralph adamralph changed the title StepDefinitionsFilterAttribute StepDefinition filter attributes May 17, 2015
@adamralph
Copy link
Owner Author

@ursenzler I came up with a slightly different way of doing it (I've updated the example in the description).

The step builder method is now OnFailure(RemainingSteps) where the RemainingSteps enum has values Skip (default) and Run.

Your custom attribute does not have to inherit from any base attribute. All it has to do is implement IFilter<IStepDefinition>. xBehave will search the assembly, class and method for attributes which implement this interface and will execute them in that order.

The work is done, but not set in stone, so it would be great to hear your thoughts on this before I push out RC3.

@adamralph
Copy link
Owner Author

FWIW, RC3 is out - https://www.nuget.org/packages/Xbehave/2.0.0-rc003-build581

There's still time to change things if required.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants