Cucumber: nested scenario outline cycles - cucumber

Scenario to automate:
Given <precondition> was fulfilled
And <user> is authorized
When user requests <endpoint>
Then user should receive <code> response
Test data matrix:
| precondition | endpoint | user1 | user 2 | ....
| | /users | OK | Not Found |
| | /roles | OK | OK |
| | /create_user | OK | OK |
| object user exists | /update_user | OK | OK |
| object user exists | /delete_user | OK | OK |
| | /create_data_role | OK | Not Found |
| data role exists | /update_data_role | OK | Not Found |
....
There's around 20 users with different role combination and around 20 endpoints.
Need to verify each endpoint for each user - so it should be a nested cycle.
How do I do it?

Don't do this in Cucumber - reasons
1) You get no benefit from putting all these routes and conditions in Gherkin. Nobody can read them and make sense of them especially if you trying something combinatorial
2) Cuke scenarios run slowly, and you want to run lots of them, you could dramatically reduce your run time by writing a fast unit test instead.
3) If you write this test in code you can write it much more elegantly than you can in Gherkin.
4) Dealing with errors is painful (as you've already pointed out)
You are using the wrong tool for this particular job, use something else.

Yet I come up with this option, but it doesn't follow gherkin convention because When and Then steps a jammed in one
1. Preconditions moved to #Before hook
2. Scenario
Given <user> is authorized
Then <user> requests functionality appropriate response code should be received
| ENDPOINT | USER1 | USER2|
| /users | 200 | 404 |
| /create_user | 200 | 404 |
| /update_user | 200 | 404 |
Examples:
| username |
| USER1 |
| USER2 |
It's also inconvenient because when tests failed it takes time to identify faulty endpoint(S)

Related

Large number of parameters in cucumber

We are writing test scenarios using Cucumber and rest-assured. we have a large number of parameters which we want to write in one test step.
For example:
Given register using api endpoint "http://stage.restapi/api/v2/register" and register info
| email | email_confirmation | password | password_confirmation |.....
| 81test#data.com | 81test#data.com | 123456789 | 123456789 | .....
We have more than 20 parameters and we do not want to write them side by side. Can we write them one under the other, from top to down, by using datatable or any other method?
For example:
Given register using api endpoint "http://stage.restapi/api/v2/register" and register info
|email |81test#data.com |
|email_confirmation |81test#data.com |
|password |123456789 |
|password_confirmation |123456789 |
|first_name |jack |
......
Thank you in advance....

How to conditionally query tables based on oData request in an Azure Logic App

I am a total newbie when it comes to both oData and Logic Apps.
My scenario is as follows:
I have an Azure SQL database with two tables (daily_stats, weekly_stats) for users
I have a Logic App I managed to test successfully but that targets one table, triggered by an HTTP request and initialises a variable using the following expression to get the query
if(equals(coalesce(trigger()['outputs']?['queries']?['filter'],''),''),'1 eq 1',trigger()['outputs']?['queries']?['filter'])
The problem comes with how to query a different table based on what the user passes as an ODATA GET request
I imagine I need a condition and the pseudo code of this would be something like:
For daily stats the ODATA query URL would be
https://myproject.logic.azure.com/workflows/some-guid-here/triggers/manual/paths/invoke/daily_stats/api-version=2016-10-01/&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=my-key-here&filter=userid eq 'richard'
For weekly stats the ODATA query URL would be
https://myproject.logic.azure.com/workflows/some-guid-here/triggers/manual/paths/invoke/weekly_stats/api-version=2016-10-01/&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=my-sig-here&filter=userid eq 'richard'
If it is daily_stats, it queries the daily_stats stored procedure/table for the user = richard
If it is weekly_stats, it queries the weekly_stats stored procedure/table for the user = richard
Edit: Added an ASCII flow diagram
+----------------------+
| HTTP ODATA GET |
| Reguest |
| |
+----------+-----------+
|
|
|
|
v
+-------+---------+
| |
| |
| |
| filter has |
| daily_stats |
| |
+-------+---------+
|
|
|
|
+-------------+ | +--------------+
| | | | |
| | YES | NO | |
| query +<--------------+-----------------+ query |
| daily | | monthly |
| stats | | stats |
| table | | table |
| | | |
+-------------+ +--------------+
There is a switch action, further more information you could refer to here:Create switch statements that run workflow actions based on specific values in Azure Logic Apps.
Below is my sample, switch statements support only equality operators. If you need other relational operators, such as "greater than", use a conditional statement.

How to show “if” condition on a use case description?

When we write a use case table * (id, description, actor, precondition, postcondition, basic flow, alternate flow)*, in basic flow, we show plain steps of interactions between the actors and the system. I wonder how to show a condition in the use case basic flow? AFAIK, the basic flow contains plain simple steps one by one for use case. But I cannot show conditions without pseudocode? Are pseudocodes allowed in the basic flow of UML use case description?
What would be steps for below sequence?
For the above diagram, should be the table below?
-------------------------------------------------------------
| ID | UC01 |
-------------------------------------------------------------
| Description | do something |
-------------------------------------------------------------
| Precondition | -- |
-------------------------------------------------------------
| Postcondition | -- |
-------------------------------------------------------------
| Basic flow | 1. actor requests system to do something |
| | 2. if X = true |
| | 2.1 system does step 1 |
| | else |
| | 2.3 system does step 2 |
| | 3. system return results to actor |
-------------------------------------------------------------
| Alternate flow| -- |
-------------------------------------------------------------
In tools like Visual Paradigm you can model flow of events with the if/else and loop conditions, and specify the steps as user input and system response.
Use Alternate and Exceptional flows to document such behavior.
do something and step 1 are clearly of different levels, better put them into separate use cases.
Actor is not the best name for actor's role, let's say it's a User.
I had to change Step 1 to Calculation 1 to avoid confusion.
Example
------------------------------------------------------------------------
| ID | UC01 |
------------------------------------------------------------------------
| Level | User goal, black box |
------------------------------------------------------------------------
| Basic flow | 1. User requests Robot System to do something. |
| | 2. Robot System performs UC02. |
| | 3. Robot System return results to User. |
------------------------------------------------------------------------
------------------------------------------------------------------------
| ID | UC02 |
------------------------------------------------------------------------
| Level | SubFunction, white box |
------------------------------------------------------------------------
| Basic flow | 1. Robot System validates that X is true. |
| | 2. Robot System does Calculation 1. |
------------------------------------------------------------------------
| Alternate flow 1 | Trigger: Validation fails at step 1, X is false. |
| | 2a. Robot System does Calculation 2. |
------------------------------------------------------------------------

What are the Lexing Errors in Cucumber?

I was trying to run a simple Feature file but i was getting Exception like :
Exception in thread "main" cucumber.runtime.CucumberException: Error parsing feature file.
which is Caused by: gherkin.lexer.LexingError: Lexing error
i am trying to parametrized a When statement and got this Exception:
Scenario: Login to Gmail
Given User is on Gmail login page
When User enters <userName> and <pwd>
And Clicks on login button
Then User should redirect to home page
scenario outline(tried Examples as well but didn't worked):
|userName | pwd |
|ravivani10 | abc |
The correct syntax for a scenario outline is to start with the keyword Scenario Outline: and list the examples with the Examples: keyword.
Scenario Outline: Login to Gmail
Given User is on Gmail login page
When User enters <userName> and <pwd>
And Clicks on login button
Then User should redirect to home page
Examples:
| userName | pwd |
| ravivani10 | abc |
I had this same problem but I was using correct syntax. Turns out my formatting was wrong, yes you read correctly: formatting. My scenario looked like this:
Scenario Outline: Confirm that hitting the endpoint returns the expected data
Given uri url/to/a/service/to/test/param/{interval} and method GET
And system user
When I call the web service
Then I expect that 'http status is' '200'
And the following rules must apply to the response
| element | expectation | value |
| $ | is not null | |
| objectType | value = | Volume |
| objectData | is not null | |
| objectData | count = | 1 |
| objectData[0].value | is not null | |
| objectData[0].value | data type is | float |
| objectData[0].value | value = | <value> |
Examples:
| interval | value |
| int1 | 355.77 |
| int2 | 332.995 |
| int3 | 353.71125 |
Above test will fail with Lexing Error. Now take a look at the indentation of the Example piece of my test (it is indented one level down the Scenario Ouline).
If I indent my test as follows (same level as Scenario Outline):
Scenario Outline: Confirm that hitting the endpoint returns the expected data
Given uri url/to/a/service/to/test/param/{interval} and method GET
And system user
When I call the web service
Then I expect that 'http status is' '200'
And the following rules must apply to the response
| element | expectation | value |
| $ | is not null | |
| objectType | value = | Volume |
| objectData | is not null | |
| objectData | count = | 1 |
| objectData[0].value | is not null | |
| objectData[0].value | data type is | float |
| objectData[0].value | value = | <value> |
Examples:
| interval | value |
| int1 | 355.77 |
| int2 | 332.995 |
| int3 | 353.71125 |
Above test will pass. Totally dumb to me but that's how it works.
This can be caused by not having the final | at the end of each line of data. That's not the reason for the OP but might help someone else.
A lexing error from cucumber just means that the feature file wasn't in the format that cucumber is expecting. This could be things like having a scenario title with no content or having the title "Feature: blah" twice. This will happen even if the error isn't in the scenario that you are running.
The lexing error will usually give you a line number. Can you post the line it complains about please?
I got the same error and it was caused by having a space between the word 'Outline' and the colon symbol
Scenario Outline : Convert currencies
When I removed the space, I had this:
Scenario Outline: Convert currencies
..and the issue got resolved.
To find out the offender, check your error logs and you will find in the output the line number where the error lies. I hope this helps someone
You need to do a couple of things: A) remove the spaces in Feature : and Scenario Outline : keywords; and B) change the Scenario Outline to Scenario (or add the missing examples for the outline).
If you run this feature:
Feature: Proof of concept that my framework works
Scenario: My first Test
Given this is my first test
When This is my second step
Then This is the final step
Then cucumber will output the to-be-completed step definitions:
You can implement step definitions for undefined steps with these snippets:
Given(/^this is my first test$/) do
pending # Write code here that turns the phrase above into concrete actions
end
When(/^This is my second step$/) do
pending # Write code here that turns the phrase above into concrete actions
end
Then(/^This is the final step$/) do
pending # Write code here that turns the phrase above into concrete actions
end

How should I name my steps in a scenario outline

I've got a handful of specflow tests that look something like this:
Scenario: Person is new and needs an email
Given a person
And the person does not exist in the repository
When I run the new user batch job
Then the person should be sent an email
Scenario: Person is not new and needs an email
Given a person
And the person does exist in the repository
When I run the new user batch job
Then the person should not be sent an email
Except instead of just 2 scenarios, I've got 10 very similar scenarios, all with the type of steps so I want to use a "Scenario Outline". Unfortunately, I'm having a really hard time coming up with a readable way to re-write my steps.
Currently, I've come up with this but looks clunky:
Scenario: Email batch job is run
Given a person
And the person '<personDoes/NotExist>' exist in the repository
When I run the new user batch job
Then the person '<personShould/NotGetEmail>' be sent an email
Examples:
| !notes | personDoes/NotExist | personShould/NotGetEmail |
| Exists | does not | should |
| No Exist | does | should not |
I also considered this, and while it is cleaner it doesn't convey meaning nearly as well
Scenario: Email batch job is run
Given a person
And the person does exist in the repository (is '<personExist>')
When I run the new user batch job
Then the person should be sent an email (is '<sendEmail>')
Examples:
| !notes | personExist | sendEmail |
| Exists | false | true |
| No Exist | does | false |
Does anybody have a better way of parameterizing concepts like "does", "does not", "should", "should not", "has", "has not"? At this point, I'm thinking about leaving the everything as a different scenario because it is more readable.
Here is what I've done in the past:
Given these people exist in the external system
| Id | First Name | Last Name | Email |
| 1 | John | Galt | x |
| 2 | Howard | Roark | y |
And the following people exist in the account repository
| Id | External Id | First Name | Last Name |
| 45 | 1 | John | Galt |
When I run the new user batch job
Then the following people should exist in the account repository
| External Id | First Name | Last Name | Email |
| 1 | John | Galt | x |
| 2 | Howard | Roark | y |
And the following accounts should have been sent an email
| External Id | Email |
| 2 | y |
You can use the table.CreateSet() and table.CreateSet() helper methods in SpecFlow to quickly turn the tables into data for your fake external system repository and your account table in the database.
Then you can use table.CompareToSet(accountRepository.GetAccounts() to compare the table in your "Then" clause to the records in your database.
The neat thing is, all of the steps you wrote are reusable for multiple situations. All you do is change the data in the tables, and SpecFlow writes the tests for you.
Hope that helps!
Maybe you should split them into two scenarios
Scenario Outline: User exists in the repository
Given a person
| Field | Value |
| First | <first> |
| Last | <last> |
And the person exists in the repository
When the user attempts to register
Then the person should be sent an email
Examples:
| first | last |
| Bob | Smith |
| Sarah | Jane |
And then another scenario for the opposite. This keeps the scenario meaning very clear. If your common steps are worded genericly you can reuse them. I also try to come from the approach of the user

Resources