I'm trying to write some Gherkin feature files in order to do BDD acceptance testing using SpecFlow. The system I'm trying to test consists of multiple RESTful APIs - system has a microservice architecture. In a scenario, I need to be certain that some records already exist in the database prior to going with the actual scenario, so I've included a Background section with a given part. The problem I'm having is that each of those records that need to exist are created through APIs that require lots of data in their schema contact and the team requires that I specify each and every fields and their respective values in a record in a gherkin table. The result is something like this:
| PassportExpireDate|PassportNumber|PassportCountry |Firstname|Lastname|LocalFirstname|LocalLastname | Birthday | NationalNumber | NationalityCountryId | PassengerType | Gender |PartyId | SourceTravelerId | CellNumber | Price|
This is the header of one of my tables which is going to be used to create a Traveler record in the database before starting the actual test by specification. However, as you can see this table has too much fields and therefore is too long too fit on the screen and thus very hard to read and maintain. secondly it's tightly coupled to the DTO schema. I argued that we shouldn't put this much detail on our specificatons, trying to include only vital high-level data (e.g. given we have an existing traveler named "James Peterson") but the team and the CTO insisted that these details should be present on the feature file. In my next attempt, I broke the tables into multiple tables (e.g. personal data, order data, passport data, etc.).
But I'm still confused and I think I'm still not doing the wrie thing. What's your recommendation? Do we have any rule of thumb or best practices for this?
Can you transpose the filed and values in the data table as below.
|field |values |
| PassportExpireDate |[] |
| PassportNumber |[] |
| PassportCountry |[] |
| Firstname |[] |
| Lastname |[] |
| LocalFirstname |[] |
| LocalLastname |[] |
| Birthday |[] |
| NationalNumber |[] |
| NationalityCountryId |[] |
| PassengerType |[] |
| Gender |[] |
| PartyId |[] |
| SourceTravelerId |[] |
| CellNumber |[] |
| Price |[] |
And in the step def implement the logic to get the values from the values array.
Specflow supports external data binding for such cases. You can use Excel binding to keep your feature file fit.
Scenario Outline: Add Traveler
Given ...
When ....
Then ....
#source:TravelerRecordsExamples.xlsx
Examples:
| PassportExpireDate|PassportNumber|PassportCountry |Firstname|Lastname|LocalFirstname|LocalLastname | Birthday | NationalNumber | NationalityCountryId | PassengerType | Gender |PartyId | SourceTravelerId | CellNumber | Price|
TLDR None
Don't put definitions and data in a Gherkin tables, its incredibly counter productive and error prone. Instead use something else to specify the fields (ideally the source code of the api) and name each thing.
Then use simple Givens to create you things.
Now in your case you seem to be creating travelers. The behavior your Gherkin is documenting is the creation of travelers. HOW travelers are created and what their characteristics are have no place in this description of the behavior.
So your background steps become something like
Given there are foo travelers
an the implementation is something like
Given 'there are foo travelers' do
create_foo_travelers
end
and now you have translated you problem from
from
How do I do something incredibly stupid and difficult in Gherkin
to
How do I write some code to create travelers
This is the approach you should take to writing all scenarios when Cuking. The scenario should only document the WHAT and WHY of the behavior. Any details about HOW the behavior is implemented have no place in the scenario.
The true power of cuking is using natural language, naming and abstraction to make you cukes simple. Use these skills to delegate the complexity of HOW to more appropriate tools.
Related
I need to verify bunch of sites that are using our templates. After login in I need to verify many info which I will put in the second table. How to write the gherkin code so that For each item in table "userinfo" it goes through All the items in table "siteinfo". I am seeing error calling them by userinfo.url or siteMenu.menuiitem. I am using python-bdd.
Scenario Outline: Login to SAP
Given User is on login page url <url>
When User enters username <username> and passwrod <password>
Then user should see <menuitem> <title> and <description>
Example: usefinfo
| url | username| password |
| siteA | Userx | pass1 |
| siteB | UserY | pass1 |
Example: siiteInfo
|menuitem | title | description |
|Community Managment | T1 | Text1 |
|User Managment | T2 | Text2 |
|Environment Management | T3 | Text3 |
|Loggin | T4 | Text4 |
|Miscellaneous | T5 | Text5 |
Use a different approach. Instead of trying to write one hugely complex low quality Cuke, write several simple high quality cukes.
Once you have a set of cukes that verify correctly that one particular site works correctly with your templates, then run that set of cukes against your other sites. You can do this by externalising site, perhaps as an environment variable, or by modifying cuke config, or by running the same set of cukes in different places.
This will be a much more sustainable solution in the medium term particularly when
you get asked to add new tests for each site
you get asked to add a site specific test.
Lets say that my app works with some books with real titles "The Old Man and the Sea", "War and Peace", etc., when creating scenarios, should I use real title like:
Given I have a book "War and Peace" persisted
When ...
or should I do something like:
Given I have a book "Book1" persisted
When ...
Option 2 is more generic, but artificial example. And If I use first option, person who is reading the test has to have domain knowledge, and he will also have some presumptions about the scenario as soon as he reads the title of the book.
Also, is there some simpler way for me to create data table without repeating data (in this case page where I have always to repeat 1,1,2,2,2,2...)? example:
When we receive book with following content:
| Page | Line | Text |
| 1 | 1 | a |
| 1 | 2 | b |
| 2 | 1 | a |
| 2 | 2 | b |
is this standard way to do it:
When we receive a book
And page 1 has content
| Line | Text |
| 1 | a |
| 2 | b |
And page 2 has content
| Line | Text |
| 1 | a |
| 2 | b |
First of all start with the name of the scenario, this name should be meaningful and should be like a summary about what is about the test.
Once you have the name then the other steps should describe a business flow that of course should contain domain language, because for example if i don't know nothing about healthcare, banking etc then why would I understand a test about a specific domain subject?, the scenarios are for a specific group of people (the ones that are working in the specific domain).
One of the BDD role is to help in understanding better the specifications and the application on all levels (technical to non-technical, but on the same business domain), to improve communication.
Now for your specific issue.
Given I have a book "War and Peace" persisted does not offer to much info since the title of the book says nothing about the test data; is a new book that just was added/created?, is a type of book technical/poetry or just some book?
What was useful for me is use a name for the the data that says something about the data used in the test.
If you don't have different types of books you can use any name, else a more complete name would be more useful.
As for the table, that represents a data set and you need to tell what to check and where; depending by case you could group some checks, if you can read all data at once or not, or if you need to specify the texts/pages.
One option would be to hide the data set and say something like:
Given I have a book "War and Peace" persisted
Then the book contains the expected content for "War and Peace"
in the first step "War and Peace" - gets/creates a specific book that is identified by this title
in the second step "War and Peace" - identifies a set of data for the expected result using the same name since is the expected for that specific data set, this set of data can be list/array/map ... depending of what programming language you are using.
Don't think to much to the details, just define the scenario in human readable language using outside-in approach, then see if you can refine it and after start the implementation.
Always use a description for the feature and a meaningful title for each scenario
In my feature file, using the same scenario I am checking more than one requirements. I have written the scenario like below:
Scenario: My first requirement ID
My second requirement ID
My third requirement ID
Etc
After execution, the extend report shows only the result as
Scenario: My first requirement ID
How can I get all the three I D,s in extent report.
NOTE:Each of my scenario title is lengthy.
Can you explain your scenario text a little bit more? According to the documentation, the scenario should describe in human terms what we expect the software to do. It is quite unusual to include expected data in that scenario text. Are you using the ID from an enum? If that is the case, it would be better to spell out the enum in human readable terms. Scenario: UserType is Administrator for example. Another option would be to use a Scenario Outline, something like
Scenario Outline: My generic requirement statement
Given Id <whateverId> is provided
When I do <activity>
Then I expect to see <result>
Examples:
| whateverId | activity | result |
| 12 | firstMethod | MyResult |
| 20 | secondActivity | anotherResult |
| 42 | thirdExample | thirdResult |
The variable names provided in the outline in angle brackets become the column headers in the examples grid. Just be sure to indent the grid below the Examples: line and also include the pipe | on both the left and right boundaries of the grid. Hopefully that helps.
I have a situation where I need to run the scenario outline along with all the datatable for different set of value. I am looking for an datatable inside another datatable. That I need to run my entire list of examples of a scenario outline repeatedly for the given list of products.
Note: I am trying to avoid write different scenario for each product.
I have given some example and my problem statement for better understanding as below
Scenario Outline : Check the behaviour of all the products
Given the POST retrieveProductdetails api url with valid authorization
When POST api is applied for the <"Products">
Then verify the behaviour of all the <"Properties"> and its <"result">
Examples:
|Properties |result|
|Appearance | Successful|
|reading | Successful|
|writing |Successful|
|memo |Successful|
|Singing |Successful|
|Help |Successful|
|Adancefeature |Successful|
|Antiquefeatuer |Succesful|
|AI nature |Successful|
|Interaction |Successful|
Note : I have around 20 Products to be validated and for each and every product i need validate all the 10 properties as mentioned .
If I start to write a an third Variable like as below , I will end up in writing 200 lines/examples (20 *10 = 200 ). And similar to the above scenario i have around 25 to 30 details which needed to be validate for all 20 products . The maintenance will be very difficult. Is there any better option for this ?
Examples:
|Properties |result |Products|
|Appearance | Successful |Alexa|
List of Products
|Products|
|Alexa|
|firetv|
|GoogleHome|
|Chromecast|
|SmartHub|
|SmartTV|
|AmazonVideo|
|AmazonPhoto|
|Echo|
|Echo Dot|
|Echo Show|
|Ring|
.
.
.
.
|SmartHome|
You are making this very difficult on yourself for a couple of reasons.
You are not describing the behavior of the system. I'm not sure what your application is supposed to do but it seems that you have a particular type of product and all instances of that type of product should have certain flags set.
However you didn't write this down, rather you appear to be retrieving all products of that type from a database and checking if these have the right flags set. So I have to infer the behavior of the system from your scenario. This should be the other way around.
You are trying to programming in Gherkin. Steps in Gherkin are not steps in a test script. They do not have to describe the exact operation needed to get some result. When you use Gherkin to describe the behavior of a system it shouldn't matter if you talk to the system in a unit tests, via http or a browser.
However by describing the exact operations you are painting yourself in a corner. It means that you can't effectively generalize without using programming language constructs like loops. If you step away from describing exact operations and rather try to describe what the system does you can use a much bigger vocabulary.
You appear to be testing against fixed data. Your data appears to have been put into the system already. You are merely checking if it comes out alright. This is not a good test because it assumes the system is in a particular state rather then creating the system in that state or verifying it is.
So to fix your feature file you might want to something like this:
Scenario: All smart home products are in the category of AI powered spy-devices
Given the smart home product "<Product>"
When I inspect this smart home product
Then it has all the properties of an AI powered spy-device:
| Appearance |
| reading |
| writing |
| memo |
| Singing |
| Help |
| Adancefeature |
| Antiquefeatuer |
| AI nature |
| Interaction |
Examples:
| Product |
| Alexa |
| firetv |
| GoogleHome |
| Chromecast |
| SmartHub |
| SmartTV |
| AmazonVideo |
| AmazonPhoto |
| Echo |
| Echo Dot |
| Echo Show |
| Ring |
.
.
.
.
| SmartHome |
While in the Given step you'd normally create the product, in your case you'll have to fetch the catalogue of products and verify that the catalogue contains the product. In the When step you'd probably fetch the details for the product. Finally in the Then step you'd verify if all properties have been set when looking at the details.
edit:
If you actually want to check if all the data has been entered into the system correctly you could also do something like this:
Scenario: All smart home products are in the category of AI powered spy-devices
Given the smart home product "<Product>"
When I inspect this smart home product
Then it has all the properties:
| Appearance | <Apperance> |
| reading | <Reading> |
| writing | <....> |
| memo | |
| Singing |
| Help |
| Adancefeature |
| Antiquefeatuer |
| AI nature |
| Interaction |
Examples:
| Product | Apperance | Reading | ....
| Alexa | Yes | No
| firetv | No | Yes
| GoogleHome | Yes | No
.
.
.
.
| SmartHome | No | Yes | ....
But I would suggest not using Cucumber for this. In that case you'd be better of putting your data into an excel file and using JUnit5s parameterized test.
I'm creating informational output with console.log() in Node.js however, I would like to create a split screen that somehow outputs different data.
Example:
---------------------------------
| value a.1 | value b.1 |
| value a.2 | value b.2 |
| value a.3 | value b.3 |
| value a.4 | value b.4 |
| value a.5 | value b.5 |
| | value b.6 |
| | value b.7 |
---------------------------------
It could be that value b.x is updating very fast, and value a.1 very slowly.
What could I use? Maybe something else then console.log()?
UPDATE:
I needed a UI library for the console.
It sounds like you want a UI library for the console. You're in luck. This sort of thing has been around for a while.
You essentially have two choices:
https://github.com/chjj/blessed - A simple graphics library for terminals that lets you do stuff like what you're describing above.
https://github.com/mscdex/node-ncurses - node bindings for ncurses (this is a standard terminal graphics library).
I think blessed has a nicer API, but the choice is yours!
For the sake of others looking around for more options:
Along with blessed and node-ncurses, you have Colors, Chalk and Terminal-Kit as well.
However, if one do not want to use console.log(), Terminal-Kit could be of use.