9

In SpecFlow, I want to check for the presence of a string in a step definition and at the moment I am doing clunky things like this contrived example:

[Given(@"Foo ( bar)?")]
public void GivenFoo(string bar)
{
    if (bar == " bar")
    {
        // do bar
    }
}

However, I'd like to do something like this:

[Given(@"Foo ( bar)?")]
public void GivenFoo(bool bar)
{
    if (bar)
    {
        // do bar
    }
}

But I can't find out how, so is this possible and if so how?

4
  • What is a meaning of the boolean flag in this case? What does it mean to do something twice when twice == false? Commented Apr 24, 2013 at 14:54
  • It's a made-up example, so probably not the best. I just want a nice way to find if a string is present or not in the step in the feature file. Commented Apr 24, 2013 at 14:57
  • 1
    It would be good to see the real example... Seems to me your problem could be with the way you write the scenario. Commented Apr 24, 2013 at 14:59
  • Is a boolean still valid in the following example? Then the total amount should be displayed OR Then the total amount should not displayed Commented Jul 25, 2013 at 13:33

3 Answers 3

8

You definitely can do that sort of thing, using a StepArgumentTransformation method. You still have to write the parser logic, but you can sequester it into a method who's only purpose is to perform that parsing.

Example feature file:

Feature: I win if I am Batman

Scenario: Happy
    Given I am the Batman
    Then I defeat the Joker

Scenario: Sad
    Given I am not the Batman
    Then I am defeated by the Joker

Specflow Bindings (C#):

[Binding]
public class IWinIfIAmBatmanFeature
{
    private bool iAmBatman;

    [StepArgumentTransformation(@"(am ?.*)")]
    public bool AmToBool(string value)
    {
        return value == "am";
    }

    [Given(@"I (.*) the Batman")]
    public void WhoAmI(bool amIBatman)
    {
        iAmBatman = amIBatman;
    }

    [StepArgumentTransformation(@"(defeat|am defeated by)")]
    public bool WinLoseToBool(string value)
    {
        return value == "defeat";
    }

    [Then(@"I (.*) the Joker")]
    public void SuccessCondition(bool value)
    {
        Assert.AreEqual(iAmBatman, value);
    }
}

The key factor is that the regex match in your Given clause is matched by the step argument transformation. So in I (.*) the Batman, if the capture matches the regex in the argument for the StepArgumentTransformation, as it does in the attribute for AmToBool then that is the transformation that gets used.

Sign up to request clarification or add additional context in comments.

Comments

1

Based on your question and the comments to Jakub's answer, it looks like you are trying to write a single Step that can cover multiple user journeys through your site. SpecFlow isn't really designed for this, and it's probably an indication that you should try and improve the structure of your scenarios/features.

To answer your question directly, I don't believe there is a way to deduce boolean values based on the existence of certain strings in your step definition.

If you want to persist down this route, then your original example is probably your best bet.

I would recommend that you don't take this approach, however, and instead look at restructuring your step definitions so that you can chain them together, and re-use them across scenarios. I'm actually struggling to think of an example step definition that would fit your solution.

An example of a multi-step approach might look like this:

Given I have logged in as an existing user //1
And I have started my 6-step registration process //2
And I have filled in valid address values on step 1 //3
And I have left the fields blank on step 2 //4
... etc
When I save my registration

And your steps would be:

  1. navigate to login page, log in as valid user
  2. navigate to step 1
  3. fill in fields with valid input, click 'next'
  4. click 'next'

You just need to ensure that each step is as independent of the others as possible, so you could replace one step with a subtly different one (for a new scenario) without affecting the others.

With this approach you can still end up with complex (and potentially quite verbose) scenarios, but I think that's a better solution than trying to be clever and pack as much into a single step definition. You'll probably end up with scenarios that are unreadable, and the code will probably be a pain to read/maintain as well.

1 Comment

> "... trying to write a single Step that can cover multiple user journeys through your site. SpecFlow isn't really designed for this" It seems that SpecFlow is designed exactly for that as they make their steps global and even say "Be careful! Coupling your step definitions to the features is an anti-pattern". They even link to the Cucumber docs that say to not reuse steps is "evil because it may lead to an explosion of step definitions, code duplication and high maintenance costs."
0

Are you looking for:

[Given(@"I do something (times) times")]
public void GivenIDoSomething(int times)
{
}

Otherwise this seems to suffice

[Given(@"I do something twice")]
public void GivenIDoSomethingTwice()
{
}

EDIT

I think that instead of if statement in the step you actually want to separate steps.

5 Comments

Ignore the twice bit; I've edited the question to make it clear that the example is completely made-up, and not actual code.
Originally I did, but that resulted in having steps with minor differences that were hard to extract. Without upsetting clients I can't post examples of what we have.
Your steps should be implemented in a 'reusable' way so you should be able to use GivenFoo step twice in the scenario: Given IDoFoo And IDoFoo When xxxx Then yyyy. There is nothing in SpecFlow to check for existence of string and turn it into boolean. Your if (bar == " bar") is the only way I can think of without restructuring your steps.
Ideally we would do this, but there's one in particular that has 6 optional parts in the step and if we did one for each combination that's 64.
For me it looks like you have 6 steps and want to reuse them in multiple scenarios - in some scenarios you will use all 6, in some you will only use the subset. The idea of the SpecFlow is that you (or domain expert) can write new scenarios without having to write new code for steps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.