Cucumber Preprocessor

133 views
Skip to first unread message

kpughc...@gmail.com

unread,
Jun 12, 2018, 10:28:08 AM6/12/18
to Cukes
Here's a pre-processor for Cucumber   An explanation of its purpose is here: 

https://github.com/atdd-bdd/preprocessor/blob/master/Cucumber%20Preprocessor%20Introduction.pdf

It uses #define and #include directives to transform feature files in one directory into processed files in another directory.    It stands separate from Cucumber and is executed prior in the build to running cucumber.    I'm trying it out as an experiment.    One feature is the ability to include csv files as tables.   Someone had mentioned that a few years ago in a separate thread.    

The code is at:

https://github.com/atdd-bdd/preprocessor/

and further documentation is at:

https://github.com/atdd-bdd/preprocessor/blob/master/CucumberPreprocessorExplanation.pdf


Ken

Roberto Lo Giacco

unread,
Jun 13, 2018, 5:25:14 PM6/13/18
to Cukes


Il giorno martedì 12 giugno 2018 16:28:08 UTC+2, kpughc...@gmail.com ha scritto:
Here's a pre-processor for Cucumber   An explanation of its purpose is here: 

https://github.com/atdd-bdd/preprocessor/blob/master/Cucumber%20Preprocessor%20Introduction.pdf

It uses #define and #include directives to transform feature files in one directory into processed files in another directory.    It stands separate from Cucumber and is executed prior in the build to running cucumber.    I'm trying it out as an experiment.    One feature is the ability to include csv files as tables.   Someone had mentioned that a few years ago in a separate thread.    

My personal opinion is this pre-processor is actually against BDD and ATDD concepts and brings test features into a non-test context: it turns a feature file, which should be focused on project documentation, into a test, which also depends on another file.

Following BDD and ATDD principles the #define could be simply avoided with proper description:

When value is over the 200 maximum
Then report error

I could argue that 200 should be just a system parameter, so having it inside the feature file makes the feature file more brittle and increases maintenance costs, but that is another story. Honestly, while I can see a value in the #define directive I believe it's implemented the wrong way, from the perspective of a developer.

From a business point of view it should look something like

Given a maximum of 200 
When the value is over the maximum 
Then report error

Better, giving a little personalization and readability, IMHO it should be

Given maximum value is set to 200 
When the user sets a value above the maximum
Then an error is reported

With regards to the #include directive, I believe it simply breaks the feature file "contract" of being a self-contained system documentation, other than making the file not self-explanatory, not counting the thing could just be implemented as

When the dataset matches the expected content

With a step definition which simply reads the appropriate file in CSV format. If I have a number of files and I really want to make those explicit, I would go for something like

When the dataset matches the list of "banned users"

With a step definition that converts "banned users" in "banend-users.csv" (or whatever convention you like) and the calls a helper function with the converted value...

What benefit do you see in having the table being put into the feature file? Are you aware that your Cucumber output will report the whole content of the CSV? Don't you think that your business partner will feel overwhelmed by a report containing a table with hundreds of data he doesn't understand?

Sorry if I came across like I'm attacking your solution, that's not my intention: in the end, I can simply not use your pre-processor. 
My intention is to discuss the reasons behind your project, as I believe you too should not be using it if you want to take the benefits Cucumber can provide.

Regards,
    Roberto

Tim Walker

unread,
Jun 14, 2018, 8:38:28 AM6/14/18
to cu...@googlegroups.com
Quick question while I am thinking on this.

Is there anything besides data in rows and columns in those csv files? That is, anything "spreadsheety" (functions, charts, etc)? Or is this so POs can edit that data more easily? Would an IDE that had better table support solve your problem too? 

Thanks,

Tim

--
Posting rules: http://cukes.info/posting-rules.html
---
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cukes+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

kpughc...@gmail.com

unread,
Jun 14, 2018, 9:27:04 AM6/14/18
to Cukes
Tim,

My thought behind the CSV files is that anyone can manipulate a spreadsheet to create variations of a business rule or data and then save it as a CSV file.      If there were an IDE that supported tables and some Excel functions, that be basically have the same effect.  If it not, then there probably be a separate cut-and-paste operation from Excel to the IDE.  

Ken

kpughc...@gmail.com

unread,
Jun 14, 2018, 10:22:23 AM6/14/18
to Cukes
Roberto,

Thanks for your reply.   We have different approaches to what a feature file represents and how it is used.   If a feature file does not contain any data, then there is no need for this preprocessor, as you illustrated.  The more data one places in a feature file, then the possibility of values that represent one domain term can be duplicated.   Having #defines for those terms can make for easier maintenance.    In addition, giving names to values helps create ubiquitous terms for understanding for the entire team (e.g. MAXIMUM_VALUE).    

I've found that having specific values in a scenario really helps in discussion between the business and development.  Using tables to contain these values reduces the number of step definitions that need to be created.  

As far as CSV files, see my response to Halfordian Golfer.  
Ken





Ken

George Dinwiddie

unread,
Jun 14, 2018, 10:38:26 AM6/14/18
to cu...@googlegroups.com
Ken,

On 6/14/18 10:22 AM, kpughc...@gmail.com wrote:
> Roberto,
>
> Thanks for your reply.   We have different approaches to what a feature
> file represents and how it is used.   If a feature file does not contain
> any data, then there is no need for this preprocessor, as you
> illustrated.  The more data one places in a feature file, then the
> possibility of values that represent one domain term can be
> duplicated.   Having #defines for those terms can make for easier
> maintenance.    In addition, giving names to values helps create
> ubiquitous terms for understanding for the entire team (e.g.
> MAXIMUM_VALUE).

As Brian Marick says, "An example would be handy right now."

Have you used this and found patterns that have worked well, or are you
still exploring and looking for those patterns? If you have found
patterns, would you share examples of them with this list?

- George

>
> I've found that having specific values in a scenario really helps in
> discussion between the business and development.  Using tables to
> contain these values reduces the number of step definitions that need to
> be created.
>
> As far as CSV files, see my response to Halfordian Golfer.
> Ken
>
--
----------------------------------------------------------------------
* George Dinwiddie * http://blog.gdinwiddie.com
Software Development http://www.idiacomputing.com
Consultant and Coach http://www.agilemaryland.org
----------------------------------------------------------------------

kpughc...@gmail.com

unread,
Jun 14, 2018, 2:00:30 PM6/14/18
to Cukes
George,

I'm still exploring potential patterns.   However some of the things I have seen in the past are:

Business Rule Pattern

Business person creates a spreadsheet that contains a table representing a requirement (a business rule or tests for that business rule).   Developers copy and paste that table into a feature file as a table (typically an example table).   Now the business person updates the values.   The developers need to update the feature file manually.   

One alternative used was to read the spreadsheet into the test via an Excel library.  Changes to the spreadsheet would be then incorporated into the test.    The code to read the Excel spreadsheet was a bit of work.

So here's an alternative using the proposed #include.  

    Business person updates the spreadsheet and saves it as a CSV file in a shared location.   
    Build script copies the CSV file and checks it into source repository.    (If business person could easily update source repository, this could be combined with previous step)
    Preprocessor run, inserts the file, then Cucumber runs.   
    Output shows results. 

Domain Term Pattern

I've also seen a lot of duplication with values in tests, such as:

When value is greater than 200
....
When value is equal to 200

Here's the alternative with #define:

#define MAXIMUM_VALUE 200

When value is greater than MAXIMUM_VALUE
...
When value is equal to MAXIMUM_VALUE

This is equivalent to using named constants in code, which makes code much easier to maintain.  In addition, it creates a domain term - MAXIMUM_VALUE that is shared among the team and appears in the feature file for documentation.   


Let me know if these examples resonant with you.   Every context is different.   

Ken

Roberto Lo Giacco

unread,
Jun 15, 2018, 5:20:49 AM6/15/18
to Cukes
Il giorno giovedì 14 giugno 2018 16:22:23 UTC+2, kpughc...@gmail.com ha scritto:
Roberto,

Thanks for your reply.   We have different approaches to what a feature file represents and how it is used.   If a feature file does not contain any data, then there is no need for this preprocessor, as you illustrated.  The more data one places in a feature file, then the possibility of values that represent one domain term can be duplicated.   Having #defines for those terms can make for easier maintenance.    In addition, giving names to values helps create ubiquitous terms for understanding for the entire team (e.g. MAXIMUM_VALUE).    

I've found that having specific values in a scenario really helps in discussion between the business and development.  Using tables to contain these values reduces the number of step definitions that need to be created.  

True, but that could be achieved in a non programmer way:

Background
Given the system is set up for with
    | param        | value     |
    | maximum  | 200        |
    | minimum   | 50          |
    | min length | 6            |
 

When the user inputs a value above the maximum allowed value
Then an error is shown


You should now question yourself: is what is written above a functional requirement or a test? If your answer is the former within your context, than you are ok. If it's the latter than why bother use Gherkin?


As far as CSV files, see my response to Halfordian Golfer.  

My take on that is if I need a CSV to describe a business rule then that business rule doesn't require Gherkin. I would also question myself why I call "business rule" a CSV file and if I'm misinterpreting the concept of business rule if I am thinking as a developer, trying to squeeze business rules in a tabular format rather than trying to describe the business rule for what it is... Does a table communicate better than natural language? We, as software developers, are used to communicating in ways our business partners do not understand, but if we don't treat Gherkin as a tool for bridging communication between those two parties, why should we bother?


Regards,
   Roberto

kpughc...@gmail.com

unread,
Jun 15, 2018, 11:02:54 AM6/15/18
to Cukes
Roberto,

This is an experiment.  I've introduced #defines to a select audience and gotten positive feedback.   However it appears they don't resonate with you. 

See my answer to George regarding CSV files.   Tables are a natural form of communication.    I've seen them used in lots of places.   

        | Value      | Result       |   Notes       |     
    | 200        | Accepted     |               |
    | 201        | Error        | Above Maximum |
    | 50         | Accepted     |               |
    | 49         | Error        | Below Minimum |

 

Ken

kpughc...@gmail.com

unread,
Jun 15, 2018, 11:17:35 AM6/15/18
to Cukes
Roberto,

I think I see where a misunderstanding lies. 

I am experimenting with Gherkin to become a more useful tool for testing as well as communication.     One of the original purposes of  Gherkin was as an alternative to JUnit.
   
See https://dannorth.net/introducing-bdd/

Take a look at my Deliver Agile Session (you need to login as an agile alliance member)  https://lnkd.in/enCkUVf

There are two advantages:of using Gherkin

1.) The test is independent of the implementation.   It specifies the behavior of a unit.  

2.) The test is readable by all members of the triad (customer, developer, tester).   


Ken

Roberto Lo Giacco

unread,
Jun 15, 2018, 1:39:23 PM6/15/18
to cu...@googlegroups.com
Il giorno ven 15 giu 2018 alle 17:17 <kpughc...@gmail.com> ha scritto:
Roberto,

I think I see where a misunderstanding lies. 

I am experimenting with Gherkin to become a more useful tool for testing as well as communication.     One of the original purposes of  Gherkin was as an alternative to JUnit.
   
See https://dannorth.net/introducing-bdd/

​Ken, did you notice the whole article written by Dan doesn't mention Gherkin at all? Actually Gherkin was an addition to JBehave, it didn't support Gherkin at the beginning... Nonetheless, if you look at JBehave syntax, you'll find very quickly it does in fact have some common grounds with JUnit (one above all, the After element), which is the main reason why I'm not a fan of JBehave Story syntax... but that's more a personal taste than anything.

Back on track, sorry for the diversion., I'll try to put two different hats on my little head, just to word what I think are the two perspectives here.

As an experienced developer ​I wouldn't pick Gherkin (or Cucumber) over JUnit for testing not even if my only option would be JUnit version 1.0.0: Gherkin is not a testing framework, nor is Cucumber, and if they were, they would have been a very very poor one.​

​As a business representative/product owner I couldn't care less if you have tests behind a Gherkin file: all I would care is if the feature described in the file accurately matches with what I need the software to do. As a PO I've probably done that for years using Use Case Scenarios and MS Word, but I would probably accept a different format if it can provide the same or a better result​.

My opinion is Gherkin + Cucumber represent a decent bridge between these two worlds, but it does provide the most of its value only if you walk this bridge in one direction: from the specification to the tests.

What I am trying to say is that if your focus is on specifications and requirements, than Gherkin can help you a lot in defining those in a manner you can then decide what needs to be automatically tested, resolving the need for validating the acceptance tests before the software gets into the hands of the PO, who can get really frustrated by a failing software.
But if you are focused on testing than why use a language/framework which doesn't even have an assertion structure? I mean, Cucumber by itself doesn't even allow you to check if two strings are equal each other... And I believe there is a good reason for the lack of those tools. 
If my focus is on testing I would pick a testing framework and use it, like JUnit, TestNG, etc... Something that helps me execute the checks I need to perform to verify my assertions.

I perfectly understand the reasoning of Dan in his article and I've personally partially experienced his very same frustrations during my professional life, but I don't agree with you in summarizing it in "Gherking (or JBehave, it doesn't really matter) was an alternative to JUnit". My take from that article is the tool was intended to help you move from TDD to BDD or, in other words, move from testing for the purpose of verifying the code to checking the behaviour correctness. 

It's a not a slight difference, but rather a huge leap: when we switch the point of view, we also need to switch the language, stepping away from computer programming and get our feet in the business language, the language spoken by those who don't develop software.

Hence the natural language approach, hence the localization support and the file format, hence the HTML reports: it must be readable and accessible to people who don't have much of computer science in their DNA.

When we introduce pre-processor macros (#define and #include) we are bringing this back into our programmer's lingo: sure, we can teach to our business partners and product owners what #define and #include are and they surely already understand tables, but is this what we should be doing? Teaching them our geeky vocabulary? 

I believe Gherkin and Cucumber aim at inverting this approach, letting the business express their intentions using their own vocabulary, a vocabulary that is finally shared between the parties.

Given I've signed up
I can log in
But only after I've confirmed my email address

Rather than

assertNotNull(username)
assertNotNull(password)
assertTrue(emailConfirmed)
assertEquals(username, storedUsername)
assertEquals(hash(password), storedPassword)


True, the above example is comparing potatoes and apples, I'm only trying to express how distinct I see the world of testing from the world of requirement specifications.




Take a look at my Deliver Agile Session (you need to login as an agile alliance member)  https://lnkd.in/enCkUVf


​Sorry, I'm not a member of such alliance, can't access it, but this article on my blog is freely accessible.

There are two advantages:of using Gherkin

1.) The test is independent of the implementation.   It specifies the behavior of a unit.   

2.) The test is readable by all members of the triad (customer, developer, tester).   


​I see... Your focus is on the tests. My take is different​:

1) the triad shares the same ubiquitous language

2) the specification is described in terms of what is needed, not on how it has to be implemented (this is a very good match with Agile practices, where you don't think on how things are going to be implemented beforehand, but rather decide it when you start implementing)

3) The requirements are live and maintainable by all members of the triad

As I'm a plain user of Cucumber and not an agile guru or something, I can't say my take is better than yours, but it's definitely very different: to me, tests are far away from being the driver for Cucumber adoption.

Apologies for the length of my reply, I didn't realize it was so long winded until I re-read it.

Thanks for the time,
    Roberto
 

Ken

On Friday, June 15, 2018 at 5:20:49 AM UTC-4, Roberto Lo Giacco wrote:
Il giorno giovedì 14 giugno 2018 16:22:23 UTC+2, kpughc...@gmail.com ha scritto:
Roberto,

Thanks for your reply.   We have different approaches to what a feature file represents and how it is used.   If a feature file does not contain any data, then there is no need for this preprocessor, as you illustrated.  The more data one places in a feature file, then the possibility of values that represent one domain term can be duplicated.   Having #defines for those terms can make for easier maintenance.    In addition, giving names to values helps create ubiquitous terms for understanding for the entire team (e.g. MAXIMUM_VALUE).    

I've found that having specific values in a scenario really helps in discussion between the business and development.  Using tables to contain these values reduces the number of step definitions that need to be created.  

True, but that could be achieved in a non programmer way:

Background
Given the system is set up for with
    | param        | value     |
    | maximum  | 200        |
    | minimum   | 50          |
    | min length | 6            |
 

When the user inputs a value above the maximum allowed value
Then an error is shown


You should now question yourself: is what is written above a functional requirement or a test? If your answer is the former within your context, than you are ok. If it's the latter than why bother use Gherkin?


As far as CSV files, see my response to Halfordian Golfer.  

My take on that is if I need a CSV to describe a business rule then that business rule doesn't require Gherkin. I would also question myself why I call "business rule" a CSV file and if I'm misinterpreting the concept of business rule if I am thinking as a developer, trying to squeeze business rules in a tabular format rather than trying to describe the business rule for what it is... Does a table communicate better than natural language? We, as software developers, are used to communicating in ways our business partners do not understand, but if we don't treat Gherkin as a tool for bridging communication between those two parties, why should we bother?


Regards,
   Roberto

--
You received this message because you are subscribed to a topic in the Google Groups "Cukes" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cukes/F0AQ0DpVoZU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cukes+un...@googlegroups.com.

George Dinwiddie

unread,
Jun 15, 2018, 3:46:27 PM6/15/18
to cu...@googlegroups.com
Ken,

On 6/14/18 2:00 PM, kpughc...@gmail.com wrote:
> George,
>
> I'm still exploring potential patterns.   However some of the things I
> have seen in the past are:
>
> *Business Rule Pattern*
>
> Business person creates a spreadsheet that contains a table representing
> a requirement (a business rule or tests for that business rule).
> Developers copy and paste that table into a feature file as a table
> (typically an example table).   Now the business person updates the
> values.   The developers need to update the feature file manually.

I feel the pain of working with business people who would rather work
with Microsoft Office than text files. I've known BAs who would write
gherkin in Word.

How often do these spreadsheets change? I might be inclined to stick
with copying the data in to have one file that clearly describes that
business rule, rather than having it spread between files that can get
out of sync.

>
> One alternative used was to read the spreadsheet into the test via an
> Excel library.  Changes to the spreadsheet would be then incorporated
> into the test.    The code to read the Excel spreadsheet was a bit of work.

Not a terrible amount of work. I wrote
https://github.com/gdinwiddie/Spreadsheet when working with a client
some years back. The idea (which never came to fruition while I was
there) was to be able to specify "a customer with only one policy" in
the test, and have the step definitions map that to a user ID behind the
scenes. This would allow the Data Group to maintain the test data (which
development wasn't allowed to change) and provide the appropriate IDs in
the spreadsheet. Given that they were looking for data that matched
conditions rather than creating it to match the conditions, it was
likely to change frequently. The QA Department was using the same
database for their manual testing. The data was populated with a
sanitized extract from production. Not ideal, but it seemed like a good
compromise for the context.

>
> So here's an alternative using the proposed #include.
>
>     Business person updates the spreadsheet and saves it as a CSV file
> in a shared location.
>     Build script copies the CSV file and checks it into source
> repository.    (If business person could easily update source
> repository, this could be combined with previous step)
>     Preprocessor run, inserts the file, then Cucumber runs.
>     Output shows results.

After running the preprocessor, do you end up with a normal gherkin
feature file? If so, that seems like an easy way to let the business
people edit the part of the gherkin they want to edit in a tool that is
familiar to them. I suggest versioning the processed file as the
canonical description of the functionality.

>
> *Domain Term Pattern*
>
> I've also seen a lot of duplication with values in tests, such as:
>
> When value is greater than 200
> ....
> When value is equal to 200
>
> Here's the alternative with #define:
>
> #define MAXIMUM_VALUE 200
>
> When value is greater than MAXIMUM_VALUE
> ...
> When value is equal to MAXIMUM_VALUE
>
> This is equivalent to using named constants in code, which makes code
> much easier to maintain.  In addition, it creates a domain term -
> MAXIMUM_VALUE that is shared among the team and appears in the feature
> file for documentation.

This I don't like so much. I'd rather put this in the Background if the
steps need it.

Background:
Given the maximum value is 200

Scenario: Greater than maximum
When the value is greater than the maximum value

Scenario: Equal to maximum
When the value is equal to the maximum value

Using a #define construct is too much like C programming for my taste.
Not that I dislike C programming, but that I think it's inappropriate to
share with the business. And I think it puts me into a programmers
mindset when reading it, rather than thinking about the
business/customer/user POV.

For one thing, it leads to terms like MAXIMUM_VALUE when, as I reword
it, is clearly the wrong name. The computer doesn't care, but value can
obviously be greater than the maximum value, which means it's something
else than a maximum value. Perhaps maximum allowed value?

Keeping things in English helps my brain notice such things.

> Let me know if these examples resonant with you.   Every context is
> different.

Yes, and experimentation is how we learn. Not every experiment is
something we want to continue doing, however. And I try to be very
careful to look for the limitations of new approaches.

- George

Roberto Lo Giacco

unread,
Jun 18, 2018, 5:39:58 AM6/18/18
to Cukes
Il giorno venerdì 15 giugno 2018 21:46:27 UTC+2, George Dinwiddie ha scritto:
Ken,

On 6/14/18 2:00 PM, kpughc...@gmail.com wrote:
> George,
>
> So here's an alternative using the proposed #include.
>
>      Business person updates the spreadsheet and saves it as a CSV file
> in a shared location.
>      Build script copies the CSV file and checks it into source
> repository.    (If business person could easily update source
> repository, this could be combined with previous step)
>      Preprocessor run, inserts the file, then Cucumber runs.
>      Output shows results.

After running the preprocessor, do you end up with a normal gherkin
feature file? If so, that seems like an easy way to let the business
people edit the part of the gherkin they want to edit in a tool that is
familiar to them. I suggest versioning the processed file as the
canonical description of the functionality.

I would be greatly concerned about what would be the report content of such execution: tons of data describing the test details transforming the report into a something nobody will take the time to look at....


Matt Wynne

unread,
Jun 19, 2018, 1:53:18 AM6/19/18
to Cukes
On Thursday, June 14, 2018 at 7:00:30 PM UTC+1, kpughc...@gmail.com wrote:
George,

I'm still exploring potential patterns.   However some of the things I have seen in the past are:

Business Rule Pattern

Business person creates a spreadsheet that contains a table representing a requirement (a business rule or tests for that business rule).   Developers copy and paste that table into a feature file as a table (typically an example table).   Now the business person updates the values.   The developers need to update the feature file manually.   

One alternative used was to read the spreadsheet into the test via an Excel library.  Changes to the spreadsheet would be then incorporated into the test.    The code to read the Excel spreadsheet was a bit of work.

So here's an alternative using the proposed #include.  

    Business person updates the spreadsheet and saves it as a CSV file in a shared location.   
    Build script copies the CSV file and checks it into source repository.    (If business person could easily update source repository, this could be combined with previous step)
    Preprocessor run, inserts the file, then Cucumber runs.   
    Output shows results. 

I'm wondering: if we had a native way to pull table content into Gherkin from a CSV file, would that solve this problem for you?

e.g.

Given the maximum values are:
  |<< maximum_values.csv >>|
When I ...

 
Domain Term Pattern

I've also seen a lot of duplication with values in tests, such as:

When value is greater than 200
....
When value is equal to 200

Here's the alternative with #define:

#define MAXIMUM_VALUE 200

When value is greater than MAXIMUM_VALUE
...
When value is equal to MAXIMUM_VALUE

This is equivalent to using named constants in code, which makes code much easier to maintain.  In addition, it creates a domain term - MAXIMUM_VALUE that is shared among the team and appears in the feature file for documentation.   

I like the solution George suggests (which in fact he taught me) of writing these in Gherkin steps, often in a Background.

Does that not work for you because you want these terms to be global?

kpughc...@gmail.com

unread,
Jun 19, 2018, 9:29:56 AM6/19/18
to Cukes
One of the reasons for using #defines is to clearly indicate domain terms (as in Domain Driven Design) which should be global as you mentioned.   As George suggested, he didn't like the term MAXIMUM_VALUE,  he would rather have it be MAXIMUM_ALLOWED_VALUE.    By agreeing on the term and using it everywhere, then misunderstanding decreases.     


For example, one might write two scenarios containing:   

When value is less than maximum value 

When values is greater than maximum allowed value 

Then one might ask whether these are referring to the same domain term and simply expressed with different text.     

With #defines, scenarios would look like:

When value is less than MAXIMUM_VALUE 

When values is greater than MAXIMUM_ALLOWED_VALUE

The terms stand out.   


With free text, it's less easy to spot domain terms unless they are denoted somehow.   If the triad did not like all caps, they could use MaximumValue or some other convention to designate the terms.   

kpughc...@gmail.com

unread,
Jun 19, 2018, 7:32:52 PM6/19/18
to Cukes
Roberto, 

We do have different perspectives.      

I've found Given/When/Then (similar to Arrange/Act/Assert,  PreConditions/Action/PostConditions, etc.) to be extremely useful in expressing requirements/tests.   In one sense, the only difference between a requirement and a test is that the Then part checks the actual result to the expected result.   

Given/When/Then can have varying levels of expression: 

Here's an generic one.  It really doesn't have enough in it to be a test.   

Given a calculator 
When I add two numbers 
The sum is correct 

Here's a specific example, which is found during discovery phase   This could  be used as a test.   

Given a calculator 
When I add 2 and 2 
The sum is 4 

Here's a specific example, which also documents domain terms (e.g. addend)   
 
Given a calculator 
When I add <addend1> and <addend2> 
Then the sum is <sum> 
Examples:
|addend1 |addend2 |sum| 
|2       | 2      | 4 |

If the Given/When/Then is in this form, then it's ready for step defs to turn in into an automated test.  But it's also in the language of the customer.   So it has a dual purpose.   Expressing the requirement and being the test for the requirement.   And a tester can easily add additional examples to check on boundary conditions or edge cases without having to do any copy and paste.  

kpughc...@gmail.com

unread,
Jun 19, 2018, 7:40:38 PM6/19/18
to Cukes
Roberto,

As you suggest, having a table rather than #defines would be less programmer-like.  So instead of #defines, one might use syntax like:

#DefinedValues
 | Maximum            | 200        |
 | Minimum             | 50          |
 | MinimumLength  | 6            |

The preprocessor would read these lines and do the same substitutions.        

Ken .     

kpughc...@gmail.com

unread,
Jun 19, 2018, 7:46:53 PM6/19/18
to Cukes
Here's a link to the PDF of the presentation:   :


Ken 

Roberto Lo Giacco

unread,
Jun 19, 2018, 8:09:19 PM6/19/18
to cu...@googlegroups.com
On Wed, Jun 20, 2018 at 1:32 AM <kpughc...@gmail.com> wrote:
Roberto, 

We do have different perspectives.

​We do, indeed​

I've found Given/When/Then (similar to Arrange/Act/Assert,  PreConditions/Action/PostConditions, etc.) to be extremely useful in expressing requirements/tests.   In one sense, the only difference between a requirement and a test is that the Then part checks the actual result to the expected result.   

​The difference I see is a test aims at verifying a requirement is implemented as expected, so a test follows a requirement. If you follow me on this thinking, then a feature file, expressed in Gherkin aims at describing the requirement, the stepdefs, defined implementing the Cucumber framework, help you realize the associated test which is implemented with whatever testing framework of your choice.
If you keep along with me along this path it should be clear why I'm against having #includes and #defines in the Gherkin while I have absolutely no problem in having those included in the stepdefs: the former describes the requirement, the latter is closer to the test.
 
Given/When/Then can have varying levels of expression: 

Here's an generic one.  It really doesn't have enough in it to be a test.   

Given a calculator 
When I add two numbers 
The sum is correct 

Here's a specific example, which is found during discovery phase   This could  be used as a test.   

Given a calculator 
When I add 2 and 2 
The sum is 4 

Here's a specific example, which also documents domain terms (e.g. addend)   
 
Given a calculator 
When I add <addend1> and <addend2> 
Then the sum is <sum> 
Examples:
|addend1 |addend2 |sum| 
|2       | 2      | 4 |

If the Given/When/Then is in this form, then it's ready for step defs to turn in into an automated test.  But it's also in the language of the customer.   So it has a dual purpose.   Expressing the requirement and being the test for the requirement.   And a tester can easily add additional examples to check on boundary conditions or edge cases without having to do any copy and paste.  

​While I agree with you the above examples are increments in describing the feature, they still don't represent a test: you are moving toward what is commonly described as Specification By Example: the feature, initially described in a generic form is refactored to use examples to increase it's clearness. I feel that very different from a test and I truly believe you too should: if we don't do that distinction it's a small step to mevo into something like

Given the calculator has been started
When I set the addend 1 to <addend1>
And I set the addend 2 to <addend2>
Then the sum ​is <sum>
Examples:
 #here all possible edge cases the QA might identify valid for testing

This last example is how a requirement can be easily torn into a test, destroying its value of clearly communicating the requirement to the occasional reader.

This gets even worse when the above is turned into

Given the calculator has been started
When I set the addend 1 to <addend1>
And I set the addend 2 to <addend2>
Then the sum ​is <sum>
Examples:
 #include <edge-cases.csv>

This is the final step toward misuse: now not only it has been turned into a test, but all the edge cases have been separated somewhere for the sake of ease manipulation... But if they need to be changed, why are those in there at all? If they can change then they are not part of the requirement...

Now, if I want to create a test for the above feature I would simply go for:

open the CSV
for each row in the CSV
Calculator calc = new Calculator();
assertEquals(3, calc.sum(1,2) );

What is the difference between those two approaches? Why spend your time in writing a test in natural language when you can code it straight away? The communication? But aren't you progressively subtracting communication value when you move important bits away from where the communication occurs? Or may be those are not so important bits... then don't clutter the communication channel with unecessary information...

Well, I guess you got my point already, it's simply a matter of opposite point of views.



Ken 
  

​BTW, I suggest you have a look at the posting rules ;-)

Roberto Lo Giacco

unread,
Jun 19, 2018, 8:25:23 PM6/19/18
to cu...@googlegroups.com
On Wed, Jun 20, 2018 at 1:46 AM <kpughc...@gmail.com> wrote:
Here's a link to the PDF of the presentation:   :



​Thanks a million for sharing Ken. 
Sorry, but I once again have to disagree: using Cucumber for unit testing is a certain path toward failure... I say that for personal experience.

The developers will hate you because ​you are forcing them to write and maintain doubled files (one for the feature, one for the stepdef)
The QAs will hate you because they will have to maintain a lot of files (that explains your #include and #define to me now)
The Project Manager will hate you because you are spending a lot more effort in testing
The Product Owner will hate you because you will be forcing him to read and validate tons of files he doesn't really care of (or he will just nod at you while you go through all of them)

Did you really manage to have "los tres amigos" work on those together? Sorry buddy, I can't believe that...
Trust me, you'll do yourself a favour if you don't use Cucumber for unit testing: it is truly not meant for that.

Another certain path toward failure is trying to generalize stepdefs: that's another error I've made and paid on my own skin.... Don't try to reduce the number of stepdefs so to have "only one stepdef to click a button": you'll end up having very complex and costly to maintain stepdefs. But that's another story, may be worth another blog post :-D Please note that post has been there since January 2014...

Roberto

 
Ken 

kpughc...@gmail.com

unread,
Jun 19, 2018, 10:57:58 PM6/19/18
to Cukes
Roberto,

As I mentioned, we differ on perspectives.   

Here are an article on  writing tests for business rules using an ATDD/BDD framework:   


Here's another article:


My approach is that if business rules are important, then having business readable tests for those rules is also important.    Using developer-centric tools like JUnit does not make those tests business readable.  

Now our views are shaped by our context and experience.   We have different contexts and experiences.    So it's no surprise we have different views that are equally valid.       

Ken

Eric Kessler

unread,
Jun 20, 2018, 12:55:33 AM6/20/18
to Cukes


On Tuesday, June 19, 2018 at 8:25:23 PM UTC-4, Roberto Lo Giacco wrote:
On Wed, Jun 20, 2018 at 1:46 AM <kpughc...@gmail.com> wrote:
Here's a link to the PDF of the presentation:   :



​Thanks a million for sharing Ken. 
Sorry, but I once again have to disagree: using Cucumber for unit testing is a certain path toward failure... I say that for personal experience.


And from personal experience as well, I'm going to have to disagree with you on that, Roberto. There are times when writing unit tests in a business readable format (e.g. Gherkin) is totally appropriate. They aren't as common as non-unit business readable test but, none the less, they exist. It turned out quite well.



Enjoy,
Eric

Massimo Manca

unread,
Jun 20, 2018, 1:23:08 AM6/20/18
to Cucumber Users
My 5 cents: unit tests are not in the business/customer domain but in the developer domain so there is no good reason to describe them using Gherkin that is on the business/customer domain. The natural use of Gherkin should be facilitate the process from eliciting requirements to executable requirements so from requirements to acceptance tests that are on the business/customer domain.

--
Posting rules: http://cukes.info/posting-rules.html
---
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cukes+un...@googlegroups.com.

Roberto Lo Giacco

unread,
Jun 20, 2018, 4:07:02 AM6/20/18
to cu...@googlegroups.com
Il giorno mer 20 giu 2018 alle 06:55 Eric Kessler <morr...@gmail.com> ha scritto:


On Tuesday, June 19, 2018 at 8:25:23 PM UTC-4, Roberto Lo Giacco wrote:
On Wed, Jun 20, 2018 at 1:46 AM <kpughc...@gmail.com> wrote:
Here's a link to the PDF of the presentation:   :



​Thanks a million for sharing Ken. 
Sorry, but I once again have to disagree: using Cucumber for unit testing is a certain path toward failure... I say that for personal experience.


And from personal experience as well, I'm going to have to disagree with you on that, Roberto. There are times when writing unit tests in a business readable format (e.g. Gherkin) is totally appropriate. They aren't as common as non-unit business readable test but, none the less, they exist. It turned out quite well.


Right Eric, 
But I never said "never use Cucumber to describe a business rule". What I am trying to say is "don't use Cucumber as a replacement for JUnit", unless you are willing to piss off everybody around you ;)

The importance I'm trying to stress is testing should not be the focus of Gherkin, but the communication and discussion properties it sparks.

But I'm clearly failing in communicating that



Enjoy,
Eric

 
The developers will hate you because ​you are forcing them to write and maintain doubled files (one for the feature, one for the stepdef)
The QAs will hate you because they will have to maintain a lot of files (that explains your #include and #define to me now)
The Project Manager will hate you because you are spending a lot more effort in testing
The Product Owner will hate you because you will be forcing him to read and validate tons of files he doesn't really care of (or he will just nod at you while you go through all of them)

Did you really manage to have "los tres amigos" work on those together? Sorry buddy, I can't believe that...
Trust me, you'll do yourself a favour if you don't use Cucumber for unit testing: it is truly not meant for that.

Another certain path toward failure is trying to generalize stepdefs: that's another error I've made and paid on my own skin.... Don't try to reduce the number of stepdefs so to have "only one stepdef to click a button": you'll end up having very complex and costly to maintain stepdefs. But that's another story, may be worth another blog post :-D Please note that post has been there since January 2014...

Roberto

 
Ken 

Roberto Lo Giacco

unread,
Jun 20, 2018, 5:41:33 AM6/20/18
to Cukes


Il giorno mercoledì 20 giugno 2018 04:57:58 UTC+2, kpughc...@gmail.com ha scritto:
Roberto,

As I mentioned, we differ on perspectives.   

Yup, and allow me to stress I'm not saying mine is more correct than yours: I'm debating with you with the purpose of clarity and communication, not trying to force you abandon Cucumber ;)
 

Here are an article on  writing tests for business rules using an ATDD/BDD framework:   

 
Do we at least agree there are huge differences between TDD, ATDD and BDD? I mean, do we agree they are very different approaches? Because I'm starting to have the impression you consider all tests as acceptance tests...
Well, I believe I had already a decent understanding of an acceptance test: why did you feel I needed that link?
 
My approach is that if business rules are important, then having business readable tests for those rules is also important.    Using developer-centric tools like JUnit does not make those tests business readable.  

I agree 100% with the above statement, but I perceive those #define and #include as bringing "developer-centric tools" inside what is meant not to be developer centric, so making the feature file less "business readable".
 

Now our views are shaped by our context and experience.   We have different contexts and experiences.    So it's no surprise we have different views that are equally valid.       

Sure, I hope the opposite has never come across.
 
Please Ken, have a read at https://cucumber.io/posting-rules, in particular to the item number 3

Tim Walker

unread,
Jun 20, 2018, 8:14:59 AM6/20/18
to cu...@googlegroups.com


On Tue, Jun 19, 2018, 06:29 <kpughc...@gmail.com> wrote:
One of the reasons for using #defines is to clearly indicate domain terms (as in Domain Driven Design) which should be global as you mentioned.   As George suggested, he didn't like the term MAXIMUM_VALUE,  he would rather have it be MAXIMUM_ALLOWED_VALUE.    By agreeing on the term and using it everywhere, then misunderstanding decreases.     


For example, one might write two scenarios containing:   

When value is less than maximum value 

When values is greater than maximum allowed value 

Then one might ask whether these are referring to the same domain term and simply expressed with different text.     

With #defines, scenarios would look like:

When value is less than MAXIMUM_VALUE 

When values is greater than MAXIMUM_ALLOWED_VALUE

The terms stand out.   

[tim] Creeping towards programmatic notation in my mind. You can upper case that term in the Gherkin, match it, and give it context all in the glue and the SUT already?
--
Posting rules: http://cukes.info/posting-rules.html
---
You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cukes+un...@googlegroups.com.

kpughc...@gmail.com

unread,
Jun 20, 2018, 11:11:19 PM6/20/18
to Cukes
Let me re-focus this discussion around the pre-processor, not about other issues. 

I thank you for your suggestions:     

1.) Different syntax for include files

e.g.  <filetoinclude.csv>    or something similar

instead of

#include filetoinclude.csv

2.) Different style for #defines,
e.g. MaximumAllowedValue  

instead of

MAXIMUM_ALLOWED_VALUE

3.) Different format for #defines.

e.g.
#definevalues   (or something similar)  
| MaximumAllowedValue | 200 |
| MinimumAllowedValue   | 100 |

instead of

#define MaximumAllowedValue 200
#define MinimumAllowedValue   100

Have I captured the suggestions correctly or have I missed something?   

Thanks.

Ken


On Tuesday, June 12, 2018 at 10:28:08 AM UTC-4, kpughc...@gmail.com wrote:
Here's a pre-processor for Cucumber   An explanation of its purpose is here: 

https://github.com/atdd-bdd/preprocessor/blob/master/Cucumber%20Preprocessor%20Introduction.pdf

It uses #define and #include directives to transform feature files in one directory into processed files in another directory.    It stands separate from Cucumber and is executed prior in the build to running cucumber.    I'm trying it out as an experiment.    One feature is the ability to include csv files as tables.   Someone had mentioned that a few years ago in a separate thread.    

Massimo Manca

unread,
Jun 20, 2018, 11:57:41 PM6/20/18
to Cucumber Users
Mmmmm.... you can refocus to the preprocessor and use it as you want but seems to me and others that is not in the spirit of Cucumber. I know that the syntax of Gherkin may be nice also to describe tests and unit tests but... I am quite surprise if you need Gherkin to describe/implement unit tests, in this case there is something to improve in your development process. On the other side using Gherkin to describe acceptance tests you should be able to realize what you want using Cucumber as is eventually extending it using the wire protocol. I really do not see any help coming from a preprocessor.

--

Roberto Lo Giacco

unread,
Jun 21, 2018, 5:15:02 AM6/21/18
to cu...@googlegroups.com
On Thu, Jun 21, 2018 at 5:11 AM <kpughc...@gmail.com> wrote:
Let me re-focus this discussion around the pre-processor, not about other issues.  

​Apologies if I was the cause of such diversion​
 
3.) Different format for #defines.

e.g.
#definevalues   (or something similar)  
| MaximumAllowedValue | 200 |
| MinimumAllowedValue   | 100 | 

​That is NOT what I was suggesting​

Matt Wynne

unread,
Jun 21, 2018, 5:51:19 AM6/21/18
to cukes
@Ken I’m wondering, would one way of solving this problem be to add a new keyword to Gherkin that acts like a global Background, say we call it Define? You could use it to specify global terms like in Gherkin this which could then be used by steps elsewhere:

# in Gherkin (somewhere)

Define:
Given the Maximum Allowed Value is 500


# in steps:

Given(“the Maximum Allowed Value is {int}”) do |max|
  @maximum_allowed_value = max
end

When(“the value is less that the Maximum Allowed Value”) do
  @value = @maximum_allowed_value - 1
end

WDYT?

--
Posting rules: http://cukes.info/posting-rules.html
---
You received this message because you are subscribed to a topic in the Google Groups "Cukes" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cukes/F0AQ0DpVoZU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cukes+un...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

The Cucumber logo is the intellectual property of Cucumber Ltd, a limited company registered in Scotland, number 456793.


Registered address: Cucumber Ltd, The Melting Pot, 5 Rose Street, Edinburgh EH2 2PR, Scotland, United Kingdom.


CONFIDENTIALITY NOTICE: The information in this e-mail is confidential and privileged; it is intended for use solely by the individual or entity named as the recipient hereof. Disclosure, copying, distribution, or use of the contents of this e-mail by persons other than the intended recipient is strictly prohibited and may violate applicable laws. If you have received this e-mail in error, please delete the original message and notify us by email immediately. Thank you. Cucumber Ltd.

Roberto Lo Giacco

unread,
Jun 21, 2018, 6:12:14 AM6/21/18
to cu...@googlegroups.com
On Thu, Jun 21, 2018 at 11:51 AM Matt Wynne <ma...@cucumber.io> wrote:
@Ken I’m wondering, would one way of solving this problem be to add a new keyword to Gherkin that acts like a global Background, say we call it Define? You could use it to specify global terms like in Gherkin this which could then be used by steps elsewhere:

# in Gherkin (somewhere)

​The "somewhere" is what makes me think about this: aren't we going to end up with something like the old Constants java interface antipattern?​

​I do understand it can be a commodity, but it also​ tend to mess things up: you are prone to create one long file with lots of definitions and colliding names...

 
Define:
Given the Maximum Allowed Value is 500

​Let's make it more real:

Define:
​    Given the maximum password lenght is 25 chars
    And the maximum username lenght is 120 chars
    And the maximum first name lenght is 60 chars
    And the maximum email address lenght is 255 chars
    And the minimum witdrawal value is 1 USD
    And the maximum withdrawal value is 9999 USD
    And the maximum comment lenght is 3000 chars
    And the minimum comment lenght is 30 chars
    And the longest loan duration is 12 months
    But the longest mortgage duration is 240 months
    And ...
    And ...
    And ...


I see this list growing pretty fast, with increasing risk of naming collisions and misuse...

Matt Wynne

unread,
Jun 21, 2018, 6:20:11 AM6/21/18
to cukes
Roberto,

I see this list growing pretty fast, with increasing risk of naming collisions and misuse…

There are already myriad ways for people to abuse Gherkin and get themselves into a mess. I’m not really convinced that this is a good reason for not adding a feature that other people are saying they would find useful.

Would you mind holding fire for a bit while we explore this with Ken and see where it leads?

Roberto Lo Giacco

unread,
Jun 21, 2018, 7:42:19 AM6/21/18
to cu...@googlegroups.com
No worries Matt, my mistake.



The Cucumber logo is the intellectual property of Cucumber Ltd, a limited company registered in Scotland, number 456793.


Registered address: Cucumber Ltd, The Melting Pot, 5 Rose Street, Edinburgh EH2 2PR, Scotland, United Kingdom.


CONFIDENTIALITY NOTICE: The information in this e-mail is confidential and privileged; it is intended for use solely by the individual or entity named as the recipient hereof. Disclosure, copying, distribution, or use of the contents of this e-mail by persons other than the intended recipient is strictly prohibited and may violate applicable laws. If you have received this e-mail in error, please delete the original message and notify us by email immediately. Thank you. Cucumber Ltd.

--

Matt Wynne

unread,
Jun 21, 2018, 7:56:40 AM6/21/18
to cu...@googlegroups.com
😃 thanks! 👍

kpughc...@gmail.com

unread,
Jun 22, 2018, 11:05:36 PM6/22/18
to Cukes


On Thursday, June 21, 2018 at 5:51:19 AM UTC-4, Matt Wynne wrote:
@Ken I’m wondering, would one way of solving this problem be to add a new keyword to Gherkin that acts like a global Background, say we call it Define? You could use it to specify global terms like in Gherkin this which could then be used by steps elsewhere:

# in Gherkin (somewhere)

Define:
Given the Maximum Allowed Value is 500


That's a possibility, particularly if the missing step def creator did the creation of   @maximum_allowed_value


Another possibility could be:

Define Maximum Allowed Value is 500

The question is when would the substitution  be made.   It could be that

Given the value is less that the Maximum Allowed Value

matches the step def

"the value is less that the Maximum Allowed Value"
i
or it could match a step def with a parameter :  

"the value ish less that the %d"

Ken

 



Matt Wynne

unread,
Jun 25, 2018, 9:52:16 AM6/25/18
to cukes

On 23 Jun 2018, at 04:05, kpughc...@gmail.com wrote:



On Thursday, June 21, 2018 at 5:51:19 AM UTC-4, Matt Wynne wrote:
@Ken I’m wondering, would one way of solving this problem be to add a new keyword to Gherkin that acts like a global Background, say we call it Define? You could use it to specify global terms like in Gherkin this which could then be used by steps elsewhere:

# in Gherkin (somewhere)

Define:
Given the Maximum Allowed Value is 500


That's a possibility, particularly if the missing step def creator did the creation of   @maximum_allowed_value 


Another possibility could be: 

Define  Maximum Allowed Value is 500

The question is when would the substitution  be made.   It could be that 

Given the value is less that the Maximum Allowed Value

matches the step def 

"the value is less that the Maximum Allowed Value"
i
or it could match a step def with a parameter :  

"the value ish less that the %d" 

Ken

We have a new thing in Cucumber called parameter types[1] which, if these Define steps became simply global Givens, could I think be used to set up a placeholder that would then be substituted in whether the name of the domain term was used.


Ken, do you think it’s worth us turning this specific idea (a global Background) into a ticket on the Gherkin repo for further discussion there?

Inspiring meaningful, effective collaboration in every software delivery organisation.


The Cucumber logo is the intellectual property of Cucumber Ltd, a limited company registered in Scotland, number 456793.

Justin

unread,
Jun 25, 2018, 5:19:54 PM6/25/18
to cu...@googlegroups.com

kpughc...@gmail.com

unread,
Jun 25, 2018, 9:11:17 PM6/25/18
to Cukes

On Monday, June 25, 2018 at 9:52:16 AM UTC-4, Matt Wynne wrote:


We have a new thing in Cucumber called parameter types[1] which, if these Define steps became simply global Givens, could I think be used to set up a placeholder that would then be substituted in whether the name of the domain term was used.


Ken, do you think it’s worth us turning this specific idea (a global Background) into a ticket on the Gherkin repo for further discussion there?

That's an interesting idea.  As understand them to work from that description, one could have:

ParameterType(
  name: 'MaximumValue',
  regexp: /(MaximumValue)/,
  transformer: -> (identifer) { 200 }
)

And then:

When value is less than MaximumValue
would have MaximumValue replaced by 200

Here's another example following along the previous ideas.

#defines (or Define if a Gherkin keyword)
| SomeOne| "Bill" |
| SomeOneElse | "Jane" |
| ValidMessage | "Hi" |
| DistanceInRange | 100 |
| MaximumDelay | 2 |

Scenario: Shout Out
Given that SomeOne and SomeOneElse are in DistanceInRange
When SomeOne shouts a ValidMessage
Then SomeOneElse sees ValidMessage before MaximumDelay

This abstracts out a specific example into a generic one.
The preprocessor would transform it back to a specific one.

The question is whether having the specific values be available in the feature file or having them in the glue code would be preferable.

If you think putting this on the Gherkin repo would be a good idea, I'll do it. I was keeping things as a preprocessor for more experimentation purposes.



Ken








 

kpughc...@gmail.com

unread,
Jun 25, 2018, 9:16:32 PM6/25/18
to Cukes
I'm not sure how the wire protocol would match the preprocessor constructs.  Could you give me an example of using the wire protocol that matches the example:

#defines  (or Define if a Gherkin keyword)
| SomeOne| "Bill" |
| SomeOneElse | "Jane" |
| ValidMessage | "Hi" |
| DistanceInRange | 100 |
| MaximumDelay | 2 |

Scenario: Shout Out
Given that SomeOne and SomeOneElse are in DistanceInRange
When SomeOne shouts a ValidMessage
Then SomeOneElse sees ValidMessage before MaximumDelay

Matt Wynne

unread,
Jun 26, 2018, 2:37:30 AM6/26/18
to cu...@googlegroups.com
On Tue, Jun 26, 2018 at 2:11 AM <kpughc...@gmail.com> wrote:

On Monday, June 25, 2018 at 9:52:16 AM UTC-4, Matt Wynne wrote:


We have a new thing in Cucumber called parameter types[1] which, if these Define steps became simply global Givens, could I think be used to set up a placeholder that would then be substituted in whether the name of the domain term was used.


Ken, do you think it’s worth us turning this specific idea (a global Background) into a ticket on the Gherkin repo for further discussion there?

That's an interesting idea.  As understand them to work from that description, one could have:

ParameterType(
  name: 'MaximumValue',
  regexp: /(MaximumValue)/,
  transformer: -> (identifer) { 200 }
)

Well, kinda. I more thought that you'd want to keep the 200 on the surface in the Gherkin, so something more like:

ParameterType(
  name: 'MaximumValue',
  regexp: /(MaximumValue)/,
  transformer: -> (identifer) { @maximum_value }
)
Given(/the MaximumValue is {int}/) do |max|
  @maximum_value = max
end

And then:

When value is less than MaximumValue
would have MaximumValue replaced by 200

Here's another example following along the previous ideas.

#defines (or Define if a Gherkin keyword)
| SomeOne| "Bill" |
| SomeOneElse | "Jane" |
| ValidMessage | "Hi" |
| DistanceInRange | 100 |
| MaximumDelay | 2 |

Scenario: Shout Out
Given that SomeOne and SomeOneElse are in DistanceInRange
When SomeOne shouts a ValidMessage
Then SomeOneElse sees ValidMessage before MaximumDelay

This abstracts out a specific example into a generic one.
The preprocessor would transform it back to a specific one.

The question is whether having the specific values be available in the feature file or having them in the glue code would be preferable.

My thinking is that if these values are important to the example, it would make sense to surface them to the reader, at least at some level.

What do you think?

Matt Wynne

unread,
Jun 26, 2018, 2:44:36 AM6/26/18
to cu...@googlegroups.com
On Tue, Jun 26, 2018 at 2:16 AM <kpughc...@gmail.com> wrote:
I'm not sure how the wire protocol would match the preprocessor constructs.  Could you give me an example of using the wire protocol that matches the example:

#defines  (or Define if a Gherkin keyword)
| SomeOne| "Bill" |
| SomeOneElse | "Jane" |
| ValidMessage | "Hi" |
| DistanceInRange | 100 |
| MaximumDelay | 2 |

Scenario: Shout Out
Given that SomeOne and SomeOneElse are in DistanceInRange
When SomeOne shouts a ValidMessage
Then SomeOneElse sees ValidMessage before MaximumDelay

The wire protocol looks for steps with a given text and asks the thing at the other end whether they can match them.

So if the new Define keyword was a global background, each scenario would effectively be prefixed with a step like:

Given these domain terms:
  | SomeOne         | "Bill" |
  | SomeOneElse     | "Jane" |
  | ValidMessage    | "Hi"   |
  | DistanceInRange | 100    |
  | MaximumDelay    | 2      |

It would then be up to the user to implement the glue code on the end of the wire to set these values somewhere, and use them in the other steps.

I don't *think* parameter types (as discussed in the other thread) work over the wire protocol, but I might be wrong.

Can you get a bit more concrete and explain what you want to do using the wire protocol?

You received this message because you are subscribed to a topic in the Google Groups "Cukes" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cukes/F0AQ0DpVoZU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cukes+un...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

kpughc...@gmail.com

unread,
Jun 30, 2018, 10:42:02 AM6/30/18
to Cukes



On Tuesday, June 26, 2018 at 2:37:30 AM UTC-4, Matt Wynne wrote:

Well, kinda. I more thought that you'd want to keep the 200 on the surface in the Gherkin, so something more like:

ParameterType(
  name: 'MaximumValue',
  regexp: /(MaximumValue)/,
  transformer: -> (identifer) { @maximum_value }
)
Given(/the MaximumValue is {int}/) do |max|
  @maximum_value = max
end



I really like the idea of a Define keyword.  It might allow both

Define MaximumAllowedValue 200

and

Define:
|MaximumAllowedValue|200|
|SomethingElse| 300|

One key idea as you mentioned is to have the 200 value transparent to the reader of the feature.  Another is to have the domain term MaximumAllowedValue be part of the ubiquitous language.   Taking a key from wikis, the syntax of a Define term could be anything in camel case. That would keep the term visibly separated from the rest of the statement.   The parser could denote any undefined terms.   

Ken

kpughc...@gmail.com

unread,
Jul 2, 2018, 12:23:12 PM7/2/18
to Cukes


On Saturday, June 30, 2018 at 10:42:02 AM UTC-4, kpughc...@gmail.com wrote:

I really like the idea of a Define keyword.  It might allow both

Define MaximumAllowedValue 200

and

Define:
|MaximumAllowedValue|200|
|SomethingElse| 300|


Just thought of another thing that could be added that goes along with the Parameter Types.   Suppose there was one like:  

ParameterType(
  name: 'Dollar',
  regexp: /(\$?\d+\.?)/,
  transformer: -> (identifer) { new Dollar(identifier) }
)


Define MaximumAllowedValue is 200 as Dollar

or

Define:
|MaximumAllowedValue | 200 | Dollar |
|SomethingElse       | 300 | Dollar | 

Now the domain terms can have formatting applied to them to make sure they match up to the expected parameter type when used.  
Ken



Matt Wynne

unread,
Jul 2, 2018, 12:27:56 PM7/2/18
to cukes
Yep that’s pretty much how parameter types are intended to be used!

To be clear, I’m thinking we would be best to add Define: as another keyword a lot like Background:, but applying to all scenarios in your whole suite. It would have one or more steps, and it would be up to the step definitions to use them in a way that added these definitions of terms.

e.g.

Define:
  Given the MaximumAllowedValue is $200

It would be really useful to get some triangulation on this. Is there anyone else on this list who thinks they might make use of this feature?

Ken




--
Posting rules: http://cukes.info/posting-rules.html
---
You received this message because you are subscribed to a topic in the Google Groups "Cukes" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cukes/F0AQ0DpVoZU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cukes+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

aslak hellesoy

unread,
Jul 2, 2018, 12:47:00 PM7/2/18
to cu...@googlegroups.com
On Mon, 2 Jul 2018 at 17:27, Matt Wynne <ma...@cucumber.io> wrote:

On 2 Jul 2018, at 17:23, kpughc...@gmail.com wrote:



On Saturday, June 30, 2018 at 10:42:02 AM UTC-4, kpughc...@gmail.com wrote:

I really like the idea of a Define keyword.  It might allow both

Define MaximumAllowedValue 200

and

Define:
|MaximumAllowedValue|200|
|SomethingElse| 300|


Just thought of another thing that could be added that goes along with the Parameter Types.   Suppose there was one like:  

ParameterType(
  name: 'Dollar',
  regexp: /(\$?\d+\.?)/,
  transformer: -> (identifer) { new Dollar(identifier) }
)


Define MaximumAllowedValue is 200 as Dollar

or

Define:
|MaximumAllowedValue | 200 | Dollar |
|SomethingElse       | 300 | Dollar | 

Now the domain terms can have formatting applied to them to make sure they match up to the expected parameter type when used.  

Yep that’s pretty much how parameter types are intended to be used!

To be clear, I’m thinking we would be best to add Define: as another keyword a lot like Background:, but applying to all scenarios in your whole suite.

That won’t work if it’s defined in a.feature and you only run b.feature.

I’m not very keen on adding more “programmer” features to Gherkin. That’s been my stance for 10 years now.

Aslak

You received this message because you are subscribed to the Google Groups "Cukes" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cukes+un...@googlegroups.com.

George Dinwiddie

unread,
Jul 2, 2018, 1:23:38 PM7/2/18
to cu...@googlegroups.com
On 7/2/18 12:46 PM, aslak hellesoy wrote:
>
> That won’t work if it’s defined in a.feature and you only run b.feature.

If it's going to be done, I suggest making it explicitly global. Perhaps
a somename.global file to hold this for all runs, no matter what feature
file or portion thereof is being run.

If there's ever a before_all and after_all at the gherkin level, it
could live here, too.

>
> I’m not very keen on adding more “programmer” features to Gherkin.
> That’s been my stance for 10 years now.

I thank you for that. I wonder if this is something that would
communicate with business users. It's awfully easy to accomplish the
same results in the code level, using a step definition to retrieve the
constant from the name.

E.g.,
When the customer withdraws the maximum amount
can be handled by a step definition that looks up what is the current
value defined for "maximum amount" and use that.

>
> Aslak

My 2 cents,
George

kpughc...@gmail.com

unread,
Jul 7, 2018, 4:46:32 PM7/7/18
to Cukes


On Monday, July 2, 2018 at 1:23:38 PM UTC-4, George Dinwiddie wrote:
>
> I’m not very keen on adding more “programmer” features to Gherkin.
> That’s been my stance for 10 years now.

I thank you for that. I wonder if this is something that would
communicate with business users. It's awfully easy to accomplish the
same results in the code level, using a step definition to retrieve the
constant from the name.

E.g.,
   When the customer withdraws the maximum amount
can be handled by a step definition that looks up what is the current
value defined for "maximum amount" and use that.


There are a couple of issues here.   The first is domain terms.  .   If the term Maximum Allowed Value is significant to the customer, then I feel it should appear somewhere in the scenarios.    The second is transparency.   If the value of Maximum Allowed Value is significant to the customer, than it also should appear somewhere in the scenarios.   I've been in situations where both are of interest to the customer.   Having a consistent way of expressing a domain  term and its value makes for more readable scenarios.    Others may not have had those situations.  

If the #include filename (or equivalent) is added, then the defines can be included where they are needed.  

One could also use the defines as generic values, e.g.

define InvalidUserName fred(123)
When user enters InvalidUserNameis

instead of

When user enters fred(123)

I've seen a lot of scenarios where this added layer of abstraction can make them more readable and decrease the number of step defs.   

Ken


    

kpughc...@gmail.com

unread,
Jul 9, 2018, 1:15:02 PM7/9/18
to Cukes


There are at least three ways that domain terms and their values could be visible in feature files.  Here are some facets of each as I see them. 

 

 

Preprocessor

 

#define MaximumAllowedValue  32

When amount is greater than MaximumAllowedValue

 

or 


#define 

| MaximumAllowedValue  | 32 | 

When amount is greater than MaximumAllowedValue

  • No additional step definition code to implement
  • Additional step in transformation (preprocessor) 
  • New "keyword" in feature files (but not in Gherkin) 

 

Code

 

Background:

Given Defines are:

| MaximumAllowedValue | 32 |

 

The corresponding step def saves away these strings in a DefineCollection. 

A step def that wants to use them would change from:

 

@Given (“^amount is greater than (\\d+)$")

void StepDefinition(int value){

 

To


@Given (“^amount is greater than (\\w+)$")

void StepDefinition(String inputValue){

     int value = DefineCollection.getAsInt(inputValue);

 

  • Uses current Gherkin syntax
  • Change in step definitions needed where used

 

 

New keyword

 

Define:

  Given the MaximumAllowedValue is 32

 

with step definitions containing: 


ParameterType(

  name: 'MaximumAllowedValue',

  regexp: /(MaximumAllowedValue)/,

  transformer: -> (identifer) { @maximum_value }

)

Given(/the MaximumAllowedValue is {int}/) do |max|

  @maximum_value = max

end


  • Requires ParameterType for each value 

 



  

Tim Walker

unread,
Jul 9, 2018, 4:29:54 PM7/9/18
to cu...@googlegroups.com
[tim] I line below
[tim] I would very respectfully submit the Define: keyword is unnecessary as the same thing could exist in a Background: with very little loss in performance or expressiveness. Just my opinion. Thank you!

with step definitions containing: 


ParameterType(

  name: 'MaximumAllowedValue',

  regexp: /(MaximumAllowedValue)/,

  transformer: -> (identifer) { @maximum_value }

)

Given(/the MaximumAllowedValue is {int}/) do |max|

  @maximum_value = max

end


  • Requires ParameterType for each value 

 



  

--
Reply all
Reply to author
Forward
0 new messages