Converting from Scenario to Scenario Outline
To summarize, here are the things that we need to do to successfully convert our test scenario to a scenario outline
Identify the Test data that will most likely change in the Test Steps and replace it with a generic name that will describe the data itself and enclose it with < >.
Change the Scenario keyword to Scenario Outline and then add an Example Table at the bottom with the Test Data that we need to use for substitution.
Update the Steps Implementation by replacing the specific test data in the annotation with the generic name that we've used in the feature file.
Identify the Data that will most likely change and replace the Data with generic variables.
Feature: Create a user in go rest database
Scenario: Create a User using valid data
Given A user with valid access token
And the user wants to create a record with first name as "John X"
And the user record has a last name of "Rocket"
And the gender is "male"
And date of birth is "1962-08-12"
And an email of "johnrocketx@yopmail.com"
And a phone number of "+637832233"
And a website of "https://bit.ly/IqT6zt"
And the address is "Platform 3/4 end of rainbow street"
And the user status is "active"
When user submits the user data in "https://gorest.co.in/public-api/users"
Then you should receive a "200" status code
And first name "John X" should be in response body
And last name "Rocket" should be in response body
And gender "male" should be in response body
And date of birth "1962-08-12" should be in response body
And email "johnrocketx@yopmail.com" should be in response body
And phone number "+637832233" should be in response body
And website "https://bit.ly/IqT6zt" should be in response body
And address "Platform 3/4 end of rainbow street" should be in response body
And user status "active" should be in response body
From the feature file, you can see that the data inputs are already enclosed by double quotes and almost all of them will mostly change when you run the test with the exception of the endpoint url. The next thing that we need to do is to replace it with a generic variable enclosed with angle brackets <> that will describe the data that you want to substitute it with. From the Feature File above it will then look like the one you see below
Feature: Create a user in go rest database
Scenario: Create a User using valid data
Given A user with valid access token
And the user wants to create a record with first name as "<first_name>"
And the user record has a last name of "<last_name>"
And the gender is "<gender>"
And date of birth is "<date_of_birth>"
And an email of "<email>"
And a phone number of "<phone_number>"
And a website of "<website>"
And the address is "<address>"
And the user status is "<user_status>"
When user submits the user data in "https://gorest.co.in/public-api/users"
Then you should receive a "<status_code>" status code
And first name "<first_name>" should be in response body
And last name "<last_name>" should be in response body
And gender "<gender>" should be in response body
And date of birth "<date_of_birth>" should be in response body
And email "<email>" should be in response body
And phone number "<phone_number>" should be in response body
And website "<website>" should be in response body
And address "<address>" should be in response body
And user status "<user_status>" should be in response body
Change the Scenario keyword to Scenario Outline and add an Example Table with Test Data
The variables that we add on the Scenario Outline will act as a placeholder to the Test Data that we will define in the Example Table. When we run the tests, each row on the Example Table will be used to run the test steps by replacing the variable in the test steps by the data defined in the column name. So if you have a total of 2 rows in the example table, the test Scenario will run twice. Here's how the Feature File will look after completing the Scenario Outline.
Scenario Outline: Create a User using valid data
Given A user with valid access token
And the user wants to create a record with first name as "<first_name>"
And the user record has a last name of "<last_name>"
And the gender is "<gender>"
And date of birth is "<date_of_birth>"
And an email of "<email>"
And a phone number of "<phone_number>"
And a website of "<website>"
And the address is "<address>"
And the user status is "<user_status>"
When user submits the user data in "https://gorest.co.in/public-api/users"
Then you should receive a "<status_code>" status code
And first name "<first_name>" should be in response body
And last name "<last_name>" should be in response body
And gender "<gender>" should be in response body
And date of birth "<date_of_birth>" should be in response body
And email "<email>" should be in response body
And phone number "<phone_number>" should be in response body
And website "<website>" should be in response body
And address "<address>" should be in response body
And user status "<user_status>" should be in response body
Examples: Valid data
| last_name | first_name | gender | date_of_birth | email | phone_number | website | address | user_status |
| Rocket | John X | male | 1962-08-12 | johnrocketx@yopmail.com | +637832233 | https://bit.ly/IqT6zt | Platform 3/4 end of rainbow street | active |
| Assassin | Space | female | 1987-09-12 | space.x@yopmail.com | 98832343 | www.youtube.com | Black hole Avenue | inactive |
Update The Steps Implementation by Replacing Specific Data with Variable Names used in the Feature File
Aside from updating the feature file we also need to replace the code implementation for it to work. Changing the code follows the same pattern on what we did to the Feature File. We just need to update the specific test data defined in the annotation and add another parameter to the function that corresponds to the generic variable used.
Here's a nice dissection of what happened when I updated the code implementation of the set_first_name() function so it will properly map the step in the feature file.
@step('the user wants to create a record with first name as "{first_name}"')
def set_first_name(context, first_name):
context.request_body = {"first_name": first_name}
Here are the things that I did
I updated the actual data with the variable name used in the feature file and enclosed it with curly braces
Added another variable as a parameter to the function similar to what I've used inside the annotation.
Use the parameter to compose the request body.
And to complete the remaining of the implementation you can check out the full source below.
from behave import given, when, then, step
import requests
@given('A user with valid access token')
def set_access_token_in_header(context):
context.header = {"Authorization": "Bearer " + "JITQ3sA3SE4AJWtvzRpj-uG8cyiTdPrDRNmK"}
@step('the user wants to create a record with first name as "{first_name}"')
def set_first_name(context, first_name):
context.request_body = {"first_name": first_name}
@step('the user record has a last name of "{last_name}"')
def set_last_name(context, last_name):
context.request_body['last_name'] = last_name
@step('the gender is "{gender}"')
def set_last_name(context, gender):
context.request_body['gender'] = gender
@step('date of birth is "{date_of_birth}"')
def set_date_of_birth(context, date_of_birth):
context.request_body['dob'] = date_of_birth
@step('an email of "{email}"')
def set_email(context, email):
context.request_body['email'] = email
@step('a phone number of "{phone_number}"')
def set_phone_number(context, phone_number):
context.request_body['phone'] = phone_number
@step('a website of "{website}"')
def set_website(context, website):
context.request_body['website'] = website
@step('the address is "{address}"')
def set_address(context, address):
context.request_body['address'] = address
@step('the user status is "{user_status}"')
def set_user_status(context, user_status):
context.request_body['status'] = user_status
@when('user submits the user data in "https://gorest.co.in/public-api/users"')
def execute_post_request_for_user_creation(context):
response = requests.post('https://gorest.co.in/public-api/users', headers=context.header, json=context.request_body)
context.response_body = response.json()
context.status_code = response.status_code
print(context.response_body)
@then('you should receive a "{status_code}" status code')
def check_status_code(context, status_code):
assert context.status_code == int(status_code)
@step('first name "{first_name}" should be in response body')
def check_first_name(context, first_name):
assert context.response_body['result']['first_name'] == first_name
@step('last name "{last_name}" should be in response body')
def check_last_name(context, last_name):
assert context.response_body['result']['last_name'] == last_name
@step('gender "{gender}" should be in response body')
def check_gender(context, gender):
assert context.response_body['result']['gender'] == gender
@step('date of birth "{date_of_birth}" should be in response body')
def check_date_of_birth(context, date_of_birth):
assert context.response_body['result']['dob'] == date_of_birth
@step('email "{email}" should be in response body')
def check_email(context, email):
assert context.response_body['result']['email'] == email
@step('phone number "{phone_number}" should be in response body')
def check_phone_number(context, phone_number):
assert context.response_body['result']['phone'] == phone_number
@step('website "{website}" should be in response body')
def check_website(context, website):
assert context.response_body['result']['website'] == website
@step('address "{address}" should be in response body')
def check_address(context, address):
assert context.response_body['result']['address'] == address
@step('user status "{user_status}" should be in response body')
def check_user_status(context, user_status):
assert context.response_body['result']['status'] == user_status
All you need to do now when you want to tests the user creation functionality with a new batch of data is to add another row at the bottom of the Example Table inside the feature file. There's no need to copy paste some code and add an additional block of Scenario in the feature file.
Comments