Detect step definition regex from method name

441 views
Skip to first unread message

Gáspár Nagy

unread,
May 15, 2012, 10:04:53 AM5/15/12
to SpecFlow
Hi,

I'm sure many of you will like this.

https://github.com/techtalk/SpecFlow/blob/97a641aebcd7b465c0c4d0c4dc643e8bccdfb328/Tests/TechTalk.SpecFlow.Specs/Features/StepDefinitionsWithoutRegex.feature
(these tests are all green)

Near to the end, you can see some coolness with F# too.

I'm interested in any comments, suggestions.

Br,
Gaspar

Gáspár Nagy

unread,
Jul 13, 2012, 8:10:28 AM7/13/12
to SpecFlow
Thx for the feedback.

Here are my responses:

1. Yes, I agree. That will be the next step. We have to think over the
impact of this change on the VS integration tough. Also I was
considering to get rid of the [Binding] attribute, but obviously we
would need one of them.

2. Yes. I was quite unsure about the param handling and I'm also not
100% happy with the "WHO" syntax.

The problem with the "person" syntax is, that you can quickly run into
wrong matches. Consider the following:

You have a step like:

Given the room 101 is empty

That you want to match with "the room (.*) is empty":

Given_the_room_room_is_empty(int room)

Here the placeholder would be ambiguous...

We have the P0, P1, ... syntax, but I'm also not too sure. I was even
thinking about simply using an "X":

When_X_does_something(string person)
When_X_does_X_with(string who, string what)

I don't know. Any good idea?

3. The capitalization is not important as we are generating case-
insensitive method names. But I don't get the point how this would
help us in the parameter identification.

Br,
Gaspar


On Jul 13, 12:39 pm, Daniel Irvine <danielirv...@gmail.com> wrote:
> Hi Gaspar,
>
> Apologies if you've had this discussion countless times before, but I just
> started using SpecFlow yesterday and may have missed some related posts.
>
> My first thought on writing SpecFlow step definitions was "Why the
> duplication between method name and attribute regex? Can't this extra
> effort be factored out somehow?" So I went digging and found your work on
> step definitions without a supplied regex. It's pretty much what I'm
> looking for, and my team would like to follow this approach for writing our
> acceptance tests.
>
> I have a few comments.
>
>    1. Why not get rid of Given/When/Then attributes entirely? You could
>    continue to mark your class with the Binding attribute, but then
>    automatically assume any method named Given* is a given, When* is a when
>    and Then* is a then - if you see what I mean. In other words, move to a
>    convention-based model rather than an attribute-based model, which is
>    becoming more common in .NET projects (see, for example, MEF).
>    2. My prefered naming practice would be 'When_person_does_something
>    (string person)' rather than 'When_WHO_does_something (string who)'. It
>    wouldn't affect your implementation but the method name becomes more
>    readable/understandable - so may be important when you come to document
>    this feature.
>    3. Is the capitalization in the method names important? How about
>    matching on the parameter name itself so that any case can be used?
>
> Thanks
>
> Daniel
>
>
>
>
>
>
>
> On Tuesday, 15 May 2012 15:04:53 UTC+1, Gáspár Nagy wrote:
>
> > Hi,
>
> > I'm sure many of you will like this.
>
> >https://github.com/techtalk/SpecFlow/blob/97a641aebcd7b465c0c4d0c4dc6...

Darren Cauthon

unread,
Jul 13, 2012, 8:21:29 AM7/13/12
to spec...@googlegroups.com

Hi,

I just want to point out something with regards to supposed "duplication," which is:  

    The method name does not matter.

For example, this step definition is perfectly valid:

    [Given("I am writing a blog post")]
    public void x(){
        // step def here
    }

When I use SpecFlow, I replace all step definition method names with a, b, c, etc. because I want to squeeze everything that is irrelevant out of my code.  I'd love to get rid of the "public void x()" line and make the code look very similar to what it looks like in Cucumber or Spinach:

    Given /I am writing a blog post/ do
      # step def here
    end

... but C# is not quite as flexible as Ruby.  C# is not that bad, though, and when combined with the (awesome) fact that SpecFlow writes all of this step definition code, I think we have it pretty good.  

I'd also dispute that using the method name is "convention-based" any more than the attribute.  Compare this:

    [Given("I am writing a blog post")]
    public void x(){
        // step def here
    }

with this:

    public void Given_I_am_writing_a_blog_post(){
        // step def here
    }

They are practically the same.  Grading the latter as better or "convention-based" just because the system matches a static method name versus a string seems a little off.  If anything, the latter seems more painful because a.) I'm now writing code to REPLACE the code that SpecFlow has already written for me, b.) I'm now creating a mismatch where I have strings in my features that have to be matched to static method names, and c.) I'm deviating from the Cucumber way.  Strings are how they do it with Cucumber and Ruby, and I'd want to stay as close to the native tongue as possible.

I like how Gaspar has added this feature, as I know using the methods this way is a popular idea and has been requested before.  Even in my own personal SpecFlow tutorials with other devs, they've said they thought it would be neat if SpecFlow worked that way.  Personally, I feel that this is not a pain point, the attributes work, and this is a proper point for developers to "get out of the code."  My first forays into SpecFlow were absolute failures because I started using it with my own short-sighted views of how it "should" work (especially my pref of "code over strings").  It wasn't until I gave myself over to the ideas from those that created these tools that I saw how they *really* should be used and how powerful they could be.  I'm afraid that this could give some devs an outlet to stay in their own ways instead of doing it like shown in the books.


Darren

P.S.  The suggestion that the Given/When/Then attributes should be "dropped entirely" blows my mind.  I'm going to be shaking my head to that one all day.



On Friday, July 13, 2012 5:39:57 AM UTC-5, Daniel Irvine wrote:
Hi Gaspar,

Apologies if you've had this discussion countless times before, but I just started using SpecFlow yesterday and may have missed some related posts.

My first thought on writing SpecFlow step definitions was "Why the duplication between method name and attribute regex? Can't this extra effort be factored out somehow?" So I went digging and found your work on step definitions without a supplied regex. It's pretty much what I'm looking for, and my team would like to follow this approach for writing our acceptance tests.

I have a few comments.

  1. Why not get rid of Given/When/Then attributes entirely? You could continue to mark your class with the Binding attribute, but then automatically assume any method named Given* is a given, When* is a when and Then* is a then - if you see what I mean. In other words, move to a convention-based model rather than an attribute-based model, which is becoming more common in .NET projects (see, for example, MEF).
  1. My prefered naming practice would be 'When_person_does_something (string person)' rather than 'When_WHO_does_something (string who)'. It wouldn't affect your implementation but the method name becomes more readable/understandable - so may be important when you come to document this feature.
  1. Is the capitalization in the method names important? How about matching on the parameter name itself so that any case can be used?

Thanks

Daniel



On Tuesday, 15 May 2012 15:04:53 UTC+1, Gáspár Nagy wrote:

On Friday, July 13, 2012 5:39:57 AM UTC-5, Daniel Irvine wrote:
Hi Gaspar,

Apologies if you've had this discussion countless times before, but I just started using SpecFlow yesterday and may have missed some related posts.

My first thought on writing SpecFlow step definitions was "Why the duplication between method name and attribute regex? Can't this extra effort be factored out somehow?" So I went digging and found your work on step definitions without a supplied regex. It's pretty much what I'm looking for, and my team would like to follow this approach for writing our acceptance tests.

I have a few comments.

  1. Why not get rid of Given/When/Then attributes entirely? You could continue to mark your class with the Binding attribute, but then automatically assume any method named Given* is a given, When* is a when and Then* is a then - if you see what I mean. In other words, move to a convention-based model rather than an attribute-based model, which is becoming more common in .NET projects (see, for example, MEF).
  1. My prefered naming practice would be 'When_person_does_something (string person)' rather than 'When_WHO_does_something (string who)'. It wouldn't affect your implementation but the method name becomes more readable/understandable - so may be important when you come to document this feature.
  1. Is the capitalization in the method names important? How about matching on the parameter name itself so that any case can be used?

Thanks

Daniel



On Tuesday, 15 May 2012 15:04:53 UTC+1, Gáspár Nagy wrote:

Kenneth LeFebvre

unread,
Jul 13, 2012, 8:36:11 AM7/13/12
to spec...@googlegroups.com
For what it's worth, I totally agree with Darren.

The method name is irrelevant, and using a string in the attribute is so
much more flexible, when the goal is to match natural language as much
as possible.

Now, if the VS integration included a little utility for scanning all
the methods in my class and renaming them to match the string in the
attribute (taking into account identifier rules and uniqueness), that
would be helpful. I don't go as far as Darren does, naming my methods
with single letters, simply because I tend to use the member drop-down
at the top of the code editor quite a lot, and you can't see the
attributes' constructors in that view (so names that are similar are
helpful in that case).

But, I can live without the member drop-down for the sake of the
flexibility of strings versus identifiers.

Daniel Irvine

unread,
Jul 14, 2012, 3:34:29 PM7/14/12
to spec...@googlegroups.com
Seems like there may be a variety of different useful syntaxes, each with a particular use. I don't feel qualified enough to come up with any further suggestions without having a better understanding of how I'd use it, so I'll spend some time with the implemented solution and then send feedback soon.

Thanks
Daniel

Gáspár Nagy

unread,
Jul 17, 2012, 10:49:02 AM7/17/12
to SpecFlow
That's fine. I anyway decided to announce this feature as "beta".
Let's test and taste this new feature and reconsider the alternatives
afterwards.

Darren & Kenneth: I was on the same opinion as you were. Maybe I'm
still.

It's a fact that many people complaining about the the "redundancy"
and this seem to be a decision making criteria for them (there are
people who start to explain me the DRY principle after seeing SpecFlow
- and it is hard to escape). But I haven't decided to add this feature
because of this.

I had the following reasons:

- As far as I see it today: regex is not the right tool for the
purpose. It's far too technical and can be far too complex. I
personally (almost) never use a SpecFlow regex that is more complex
than (.*). On CukeUp this year, Aslak was showing some examples with a
datetime parameter in the step. He was using a (for me) very complex
regex to catch the right date format. I was discussing afterwards what
is the benefit of using the complex regex instead of (.*). Nothing.
The "worst" thing can happen that you get a conversion error instead
of a "no step definition found". People do not even realize that they
are lead by the possibilities of the tool and not the real purpose.
And in some cases (like this), this can be even contra-productive.

- I have seen how Twist works - using the method names only in a very
liberal way (even too much for my taste). And surprisingly it was
"good enough". And finally I have realized, that similarly to the
exact date format, you can also ignore the differences in the detail
whitespaces, casing and punctuation. The words are much more
important.

- It does not disturbs the regex-style declaration and it is quite
clear for the reader if he sees this or that syntax. (This is not true
for omitting the G/W/T attributes, BTW.)

- We have F#, where the method names can be much more flexible. Why
not use this power?


The strength of SpecFlow is to "translate" Cucumber to a style that is
more fitting to the .NET ecosystem. From the feedback I've got my
feeling is that for _finding the matching step definition for a step_,
the regex-based binding was not the perfect match. (Although as
the .NET counterpart of the ruby-regex-methods, this was the best
match!)

I think for ones who have used the regex step definitions, it change
is not relevant - it's quite easy to get used to the regex bindings,
and they are not disturbing at all. And they will never disappear.

Br,
Gaspar

Pedro G. Dias

unread,
Aug 13, 2012, 1:43:59 AM8/13/12
to spec...@googlegroups.com
Daniel. 

In BDD, the natural domain language is everything. I'm Norwegian, so I write all my specs in Norwegian, the domain language of my client. Were I to be working in Portugal, I would be writing them in that language.

The reason why we need the attributes is because of that. Even though the Domain language is non-english, one normally writes code in English (common practice in Norway at the least), so method names may look like this: 

Scenario: Noe må alltid skje
Gitt at jeg har gjort noe spennende
Når jeg utfører en handling
kommer en konsekvens

[Given("jeg har gjort noe spennende")]
GivenIDidSomethingExciting(){
   // code
}



On Friday, July 13, 2012 12:39:57 PM UTC+2, Daniel Irvine wrote:

I have a few comments.

Vagif Abilov

unread,
Aug 23, 2012, 4:13:13 AM8/23/12
to spec...@googlegroups.com
You have a point here Pedro. I didn't think about it although I am also in Norway and even in the same buidling :-)

But I share more and more Darren's view on this even though I wrote a blog post explaining how to get rid of attribute properties. But if I rename methods to A,B,C to detach them completely from step semantics, it makes more sense.

Vagif
Reply all
Reply to author
Forward
0 new messages