I am trying to read a json payload from a file and setting the values from CSV file using scenario outline and examples - karate

I have a sample json file as below
{
book : {bookId : '<bookId>' ,
bookName : '<bookName>'
},
staff : {
sfattid : '<sfattid>',
name : '<name>'
},
libraryMember : {
libMembId : '<libMembId>',
name : '<libraryMember>'
}
}
I have a csv file with below information
I want to set the values for each variable from csv file and set the REST request 3 times during run time .
Feature: scenario outline using a dynamic table
from a csv file
Scenario Outline: staffname name: <name>
# When json payload = {book : {bookId : '<bookId>' , bookName : '<bookName>',},staff : {sfattid : '<sfattid>', name : '<name>'},libraryMember : { libMembId : '<libMembId>' ,name : '<libraryMember>'}}
When json payload = read("request.json")
Given url 'http://localhost:8089/'
And path 'returnBook'
And request payload
When method post
Then status 200
Then match karate.jsonPath(response,"$.status") == '<status>'
Examples:
| read('bookreturn.csv') |
I have wrote below code which works perfectly but in below case the same json payload is present in feature file which I want to keep in a text file .Please suggest some code .
Feature: scenario outline using a dynamic table
from a csv file
Scenario Outline: staffname name: <name>
# When json payload = {book : {bookId : '<bookId>' , bookName : '<bookName>',},staff : {sfattid : '<sfattid>', name : '<name>'},libraryMember : { libMembId : '<libMembId>' ,name : '<libraryMember>'}}
When json payload = read("request.json")
Given url 'http://localhost:8089/'
And path 'returnBook'
And request payload
When method post
Then status 200
Then match karate.jsonPath(response,"$.status") == '<status>'
Examples:
| read('bookreturn.csv') |

Sorry, you can't optimize this any further because for <name> to work it has to be within the feature file itself. Personally I think you are un-necessarily trying to over-engineer your tests. There is nothing wrong with what you have already.
If you really insist - here is the alternative, refer: https://github.com/intuit/karate#data-driven-features
* def books = read('bookreturn.csv')
* def result = call read('called.feature') books
But you will need to use 2 feature files. Each book in the loop can be used in embedded expressions. So you can read from a JSON file, and any embedded expressions in the file will work.
Just stick to what you have, seriously !

Related

How to fetch the list of dynamic ID one at a time by applying ID as a parameter in GET URL of API testing using karate [duplicate]

This question already has an answer here:
How to navigate and validate through all the pages of a api response
(1 answer)
Closed 1 year ago.
I am trying to fetch the list of dynamic id's one at a time by application ID as a parameter in GET URL
Example : below response is for POST call
{"Car": 1,
content:[{
"type" : "A"
"Id" : "1"
},
{
"type" : "B"
"Id" : "2"
}
]}
Now for the above POST response I am trying to fetch the data using dynamic Id as a parameter in GET URL
ex:
def ID = karate.jsonPath(response, '$.content[*].id')
Given URL 'https://localhost:8080'
And path '/'+ID+'/id
When method GET
Then status 200
in GET response I am getting list of Id's instead of single Id in URL as shown below
This is the output : http://localhost:8080/1,2/id
As Id's are generating dynamically, so instead of calling one by one ID manually I want to call using parameter
Can any one suggest me how can I fetch one ID at a time using GET URL ?
Try this example, and observe the output and then try to understand how it works:
* def response = {"Car": 1, content:[{ "type" : "A", "Id" : "1" }, { "type" : "B", "Id" : "2" } ]}
* def ids = $response.content[*].Id
* match ids == ['1', '2']
* def data = karate.mapWithKey(ids, 'id')
* call read('called.feature') data
And called.feature looks like this:
#ignore
Feature:
Scenario:
* url 'https://httpbin.org/anything'
* param id = id
* method get
Please try to read the docs, it is worth it: https://github.com/karatelabs/karate#json-transforms

I have a json file where I am setting variables and I have CSV file to read value from it .How can I use intuit Karate to do it easily?

I have json file as below.
{
book : {bookId : '<bookId>' ,
bookName : '<bookName>'
},
staff : {
sfattid : '<sfattid>',
name : '<name>'
},
libraryMember : {
libMembId : '<libMembId>',
name : '<libraryMember>'
}
}
I have below CVS
enter image description here
The CSV file which have headers as the above variable in json file .I want to use CSV file in scenario outline table and set values for the JSON file .Can you please suggest some code which automatic reads the json set the corresponding value for each row .
I was thinking below code should work but it is not working
Feature: scenario outline using a dynamic table
from a csv file
Scenario Outline: staffname name: <name>
* text jsonPayLoad = call read('readJson.feature')
Given url 'http://localhost:8089/'
And path 'returnBook'
And request jsonPayLoad
When method post
Then status 200
Then match karate.jsonPath(response,"$.status") == '<status>'
Examples:
| read('bookreturn.csv') |
The value of read('bookreturn.csv') should be an Array of JSON objects.
For example in this example: https://github.com/intuit/karate#dynamic-scenario-outline
Make this change:
Background:
* def kittens = [{name: 'Billie'}, {name: 'Wild'}]

Karate - Not able to run dynamic scenario outline in a loop

Here is my feature file , which just loads the json file and wants to iterate over the same
Background:
* def kittens = read('../json/test.json')
Scenario Outline: cat name: <name>
* print <name>
Examples:
| name |
| kittens |
Here is the output
[
{
"name": "Bob"
},
{
"name": "Wild"
},
{
"name": "Nyan"
},
{
"name": "Keyboard"
},
{
"name": "LOL"
},
{
"name": "Ceiling"
}
]
As per my understanding this should run 7 times and give me individual variable values , But its running only once and giving me full json as output .
Let me know if I am missing anything.
You are passing the list/array with a variable name in it, it will run only once as it interprets your entire json data as single variable name.
you could have noted it printed the entire data in your test.json
once, as it acted as normal scenario outline.
You should pass the array directly as below to make it as dynamic scenario outline.
Feature: Dynamic Scenario Outline
Background:
* def kittens = read('../json/test.json')
Scenario Outline: cat name: <name>
* print <name>
Examples:
| kittens |
For dynamic scenario outline, the variables <name> will actually derived from your json, if there is key in your json as "name". Not as the header of the list in Examples:.
Karate docs- Dynamic Scenario Outline
#Babu Sekaran. It was not priting cat names as used as above.
It was iterating number of times but not printing anything. Then i used * print '' means included quotes. then it started printing cat names.
Feature: Dynamic Scenario Outline
Background:
* def kittens = read('test.json')
Scenario Outline: cat name: <name>
* print '<name>'
Examples:
| kittens |

Facing challenges while using relative path and mapping test data from a json file to a request

I am facing few issues while using relative path and mapping test data from a JSON file. I am having JSON POST request and a test data file in JSON format.
This is the test data I am using.
{
"name": "Test Data",
"description": "Information's mainly related with Users",
"testData": [
{
"Scenario1": {
"givenName": "Joseph",
"familyName": "George",
"addressType": "Current",
"lineOne": "BNRA-222, Kowdiar lane",
"cityName": "Trivandrum",
"countryID": "India",
"postcode": "695006"
}
},
{
"Scenario2": {
"givenName": "Sreenath",
"familyName": "Bhasi",
"addressType": "Current",
"lineOne": "HSE-123, Karyavatom",
"cityName": "Trivandrum",
"countryID": "India",
"postcode": "695552"
}
}
]
}
This is the feature file
Feature: Test using the Data from a JSON file
Background:
* def baseJsonRequest = read('../requests/jsonrequest.json')
* def baseData = read('../data/sampledata.json')
* def endPointURL = endPointURI + path
Scenario: A sample scenario to test the data parametrization
Given url endPointURL
And request baseJsonRequest
* set baseJsonRequest.autoRequest.applicants.applicant.specifiedPerson.givenName = baseData.testData[*].Scenario1.givenName
* set baseJsonRequest.autoRequest.applicants.applicant.specifiedPerson.familyName = baseData.testData[*].Scenario1.familyName
* set baseJsonRequest.autoRequest.applicants.applicant.specifiedPerson.residenceAddress.addressType = baseData.testData[*].Scenario1.addressType
* set baseJsonRequest.autoRequest.applicants.applicant.specifiedPerson.residenceAddress.lineOne = baseData.testData[*].Scenario1.lineOne
* set baseJsonRequest.autoRequest.applicants.applicant.specifiedPerson.residenceAddress.cityName = baseData.testData[*].Scenario1.cityName
* set baseJsonRequest.autoRequest.applicants.applicant.specifiedPerson.residenceAddress.countryID = baseData.testData[*].Scenario1.countryID
* set baseJsonRequest.autoRequest.applicants.applicant.specifiedPerson.residenceAddress.postcode = baseData.testData[*].Scenario1.postcode
My Questions are:
I am not able to give relative path on both sides. The relative path is returning me a json array. For eg I cannot use $..Scenario1.givenName, which makes me write longer paths.
To include this mapping on every scenario will be practically difficult. How can we implement a parameterized solution for that. What will better way? Can I invoke the data reading using a feature file and pass the informations to another feature. If that's possible then I need to parameterize . How to do that?
Or do I need to use a java class to read the JSON file?
Yes, the moment you have a wildcard in JsonPath, it returns an array. Anyway, 2 points that should help here straight away:
you can move repeating nested paths into a table-set
you can refer to a nested chunk of JSON by assigning to a variable
So this should be the way to go:
* def first = get[0] baseData.testData[*].Scenario1
* set baseJsonRequest.autoRequest.applicants.applicant.specifiedPerson
| path | value |
| familyName | first.familyName |
| residenceAddress.addressType | first.addressType |
I would try to not use wildcards as far as possible, for e.g.
* def first = $baseData.testData[0].Scenario1
Hope this helps !

Elasticsearch bulk/batch indexing with python requests module

I have a smallish (~50,00) array of json dictionaries that I want to store/index in ES. My preference is to use python, since the data I want to index is coming from a csv file, loaded and converted to json via python. Alternatively, I would like to skip the step of converting to json, and simply use the array of python dictionaries I have. Anyway, a quick search revealed the bulk indexing functionality of ES. I want to do something like this:
post_url = 'http://localhost:9202/_bulk'
request.post(post_url, data = acc ) # acc a python array of dictionaries
or
post_url = 'http://localhost:9202/_bulk'
request.post(post_url, params = acc ) # acc a python array of dictionaries
both request give a [HTTP 500 error]
My understanding is that you have to have one "command" per line (index, create, delete...) and then some of them (like index) takes a row of data on the next line like so
{'index': ''}\n
{'your': 'data'}\n
{'index': ''}\n
{'other': 'data'}\n
NB the new-lines, even on the last row.
Empty index objects like above works if you POST to ../index/type/_bulk or else you need to specify index and type I think, have not tried that.
You the following function will do it:
def post_request(self, endpoint, data):
endpoint = 'localhost:9200/_bulk'
response = requests.post(endpoint, data=data, headers={'content-type':'application/json', 'charset':'UTF-8'})
return response
As data you need to pass a String such:
{ "index" : { "_index" : "test-index", "_type" : "_doc", "_id" : "1681", "routing" : 0 }}
{ "field1" : ... , ..., "fieldN" : ... }
{ "index" : { "_index" : "test-index", "_type" : "_doc", "_id" : "1684", "routing" : 1 }}
{ "field1" : ... , ..., "fieldN" : ... }
Make sure you add a "\n" at the end of each line.
I don't know much about Python, but did you look at Pyes?
Bulk is supported in Pyes.