How do we write clean code to evaluate one scenario against two different interfaces?

67 views
Skip to first unread message

Leslie Brooks

unread,
Aug 10, 2016, 3:40:16 PM8/10/16
to Cukes

Well-written Gherkin can be re-used to test the same functionality at different system interfaces; this is described in Recipe 12 of ‘Cucumber Recipes’. That is, if we write:


               Given an active customer account

               When the customer enters a new credit card number

               Then the new card number is billed

 

We can test this against the customer website or against the API behind that website, or perhaps against the billing system itself, or the Android and iOS apps, because the scenario talks purely about business purpose, not about implementation details such as text boxes or buttons.

 

Testing against two interfaces is simple; we create two JAR files that implement the classes and methods we need; one JAR implements them through Selenium and the website, and the other JAR implements them through the API. When we launch Cucumber we decide which JAR file we will pass to it, and that determines whether we test through the website or through the API.

 

However, how should we structure our code if we want to decide after Cucumber has launched whether a particular method goes through the UI or through the API? If we write this Gherkin:

 

               Given the customer has entered a new credit card number today

               When the customer enters another new credit card number

               Then we ask whether they really intended to change it twice

 

Let’s assume that we have decided to test this through the UI. The ‘When’ clause calls a method that updates the credit card number, and that method must go through the UI since the ‘When’ clause is the entire purpose of the scenario.

 

The ‘Given’ clause also calls the method that updates the credit card number – but there is no requirement that it go through the UI; it could go through the API because the ‘Given’ is NOT the purpose of the scenario. Going through the API may be considerably faster, and if we do this with all of our ‘Givens’ we might save a large portion of our test execution time.

 

What is the best way to implement this? That is, how do we write clean code that can decide which route to take, based on whether it is in the ‘Given’ or the ‘When’ clause of the Gherkin? We could pass a Boolean into the method, but ‘Uncle Bob’ Martin tells us this is bad, “loudly proclaiming that this function does more than one thing” and violating the Single Responsibility Principle.

 

What are good ways to write this? What design pattern solves this problem?

Richard Lawrence

unread,
Aug 10, 2016, 3:50:56 PM8/10/16
to cu...@googlegroups.com
I'm not entirely sure I understand the scenario, but I think I'm hearing that you want to use different code for a particular domain action depending on whether it's in a Given or a When step. In that case, the simplest pattern is two step definitions. Givens are usually past tense (or more accurately, present perfect), while Whens are present tense, so they naturally match different regular expressions.

This then begs the question, "What about those times when I want to run the same code for a Given and a When?" You could write a regular expression that handles both. I used to do that. But I've learned that my comfort with regular expressions is unusual, and I've worked hard to keep them simple. These days, when I want two steps to run the same code, unless the differences in the steps are trivial, I'll often just have two separate step defs call the same helper method.

Richard
 

--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Message has been deleted

Leslie Brooks

unread,
Aug 10, 2016, 5:14:48 PM8/10/16
to Cukes
Correct, I "want to use different code for a particular domain action depending on whether it's in a Given or a When step". However, two step definitions don't solve the problem, they must both call enterCreditCardNumber(). This is really an object-oriented design question: How do I have this one method decide to call the API when I call it from the Given, but call the UI when I call it from the When? Passing in a Boolean isn't the right answer either; passing a Boolean shows that this method violates the Single Responsibility Principle. What design pattern solves this problem?

Paul Rayner

unread,
Aug 10, 2016, 5:17:13 PM8/10/16
to cu...@googlegroups.com
On Wed, Aug 10, 2016 at 2:57 PM, 'Leslie Brooks' via Cukes <cu...@googlegroups.com> wrote:


On Wednesday, August 10, 2016 at 3:50:56 PM UTC-4, Richard Lawrence wrote:

On Wed, Aug 10, 2016 at 2:40 PM, 'Leslie Brooks' via Cukes <cu...@googlegroups.com> wrote:

Well-written Gherkin can be re-used to test the same functionality at different system interfaces; this is described in Recipe 12 of ‘Cucumber Recipes’. That is, if we write:


               Given an active customer account

               When the customer enters a new credit card number

               Then the new card number is billed

 

We can test this against the customer website or against the API behind that website, or perhaps against the billing system itself, or the Android and iOS apps, because the scenario talks purely about business purpose, not about implementation details such as text boxes or buttons.

 

Testing against two interfaces is simple; we create two JAR files that implement the classes and methods we need; one JAR implements them through Selenium and the website, and the other JAR implements them through the API. When we launch Cucumber we decide which JAR file we will pass to it, and that determines whether we test through the website or through the API.

 

However, how should we structure our code if we want to decide after Cucumber has launched whether a particular method goes through the UI or through the API? If we write this Gherkin:

 

               Given the customer has entered a new credit card number today

               When the customer enters another new credit card number

               Then we ask whether they really intended to change it twice

 

Let’s assume that we have decided to test this through the UI. The ‘When’ clause calls a method that updates the credit card number, and that method must go through the UI since the ‘When’ clause is the entire purpose of the scenario.

 

The ‘Given’ clause also calls the method that updates the credit card number – but there is no requirement that it go through the UI; it could go through the API because the ‘Given’ is NOT the purpose of the scenario. Going through the API may be considerably faster, and if we do this with all of our ‘Givens’ we might save a large portion of our test execution time.

 

What is the best way to implement this? That is, how do we write clean code that can decide which route to take, based on whether it is in the ‘Given’ or the ‘When’ clause of the Gherkin? We could pass a Boolean into the method, but ‘Uncle Bob’ Martin tells us this is bad, “loudly proclaiming that this function does more than one thing” and violating the Single Responsibility Principle.

 

What are good ways to write this? What design pattern solves this problem?


I'm not entirely sure I understand the scenario, but I think I'm hearing that you want to use different code for a particular domain action depending on whether it's in a Given or a When step. In that case, the simplest pattern is two step definitions. Givens are usually past tense (or more accurately, present perfect), while Whens are present tense, so they naturally match different regular expressions.

Correct, I "want to use different code for a particular domain action depending on whether it's in a Given or a When step". However, two step definitions don't solve the problem, they must both call enterCreditCardNumber(). This is really an object-oriented design question: How do I have this one method decide to call the API when I call it from the Given, but call the UI when I call it from the When? Passing in a Boolean isn't the right answer either; passing a Boolean shows that this method violates the Single Responsibility Principle. What design pattern solves this problem?

A simple implementation of either decorator or strategy pattern would allow you to selectively create objects to encapsulate the behavioral variation around UI vs. non-UI.
 

This then begs the question, "What about those times when I want to run the same code for a Given and a When?" You could write a regular expression that handles both. I used to do that. But I've learned that my comfort with regular expressions is unusual, and I've worked hard to keep them simple. These days, when I want two steps to run the same code, unless the differences in the steps are trivial, I'll often just have two separate step defs call the same helper method.

Richard
 

--
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.

Andrew Premdas

unread,
Aug 11, 2016, 11:34:25 AM8/11/16
to cu...@googlegroups.com
I use convention and naming to deal with this issue. I also follow a convention that all 'creators' bypass the UI. Finally I never put code in step definitions I only put calls to code, and generally just one call. Some examples might help

Given 'I am registered' do
  @i = create_new_user  # api
end

Given 'there are some products' dp
  create_products amount: some  # api
end

Given 'I am registering' do # tense implies UI action
  start_registering # tense implies UI
end

GIven 'I am creating a product' do
  # tense implies UI so
  start_creating_a_product
end

Now in your scenario, create_new_user does not have to be conditional (all your jars can use the same method). However start_registering does have to be conditional.

This is an adequate approach for small teams of literate developers with a very strict review process of features and their implementation. It also requires the ability to craft given scenarios into the language required to follow these conventions.

The idea here is that steps that break this convention should be obvious. However this is not easy e.g

Given 'I am creating some products' do
    create_products amount: some # obviously wrong!!!
end


One thing I get from this is that I will never have the same piece of code in a Given and a When, so no method has to understand where it is called from.

These solutions are no 'silver bullet' but hopefull they can help, or at least give some ideas.

All best

Andrew

 

--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
------------------------
Andrew Premdas
Message has been deleted

Leslie Brooks

unread,
Sep 12, 2016, 5:34:39 PM9/12/16
to Cukes
@apremdas
   I like your approach of putting only method calls in the step definitions; it forces you to write your step definitions at an appropriately high level of abstraction.

I also understand how you are using convention - using past tense in the Given and present tense in the When, and then calling two different methods even if the underlying function is the same. The method called from the Given goes through the API, and the method called from the When goes through the UI.

That is a workable approach, but I would rather hide those details behind an abstraction and use only one method name. If it has only one purpose, it shouldn't have two names.

@Paul Rayner
   Yes, the Decorator or Strategy patterns will work, however Aslak says elsewhere "The equivalent of the World in Cucumber-Java is _all of the objects with hook or stepdef annotations_. In other words, any class with methods annotated with @Before, @After, @Given and so on will be instantiated exactly once for each scenario." So these design patterns won't work, because they have only a single object with which to work.

So is the best tradeoff to have two different method names for the same purpose, or is there a clean, readable, and maintainable way to have just one method name?

Leslie Brooks

unread,
Sep 12, 2016, 5:47:27 PM9/12/16
to Cukes
I should have written:
--------
@Paul Rayner
   Yes, the Decorator or Strategy patterns _would_ work, however... So these design patterns won't work _here_, because they have only a single object with which to work.
Reply all
Reply to author
Forward
0 new messages