Calling karate feature with variable - cucumber-jvm

In karate you can call feature by sending json/list & map. There are multiple ways I have tried to send the value and use it in the called feature but it throws error
For example:
Error thrown : path: $, actual: '', expected:
'30e093da-c4e3-4ee0-b180-e5d0b4302d9f', reason: not a sub-string
Step:* call read('Logcheck.feature') {requestId : "#(responseHeaders['request-id'][0])"}
In the logCheck feature I am trying to get requestId by using #(requestId)
Logcheck feature Step
* def resultFromServiceLog = utils.getResultFromLog(baseUrl,'#(requestId)','service')
I have tried another approach where I have assigned it to
* def x = {requestId : responseHeaders['request-id'][0]}
* call ('logcheck.feature;) x
Another approach where I will send the json
* json req = {requestId : "#(responseHeaders['request-id'][0])"}
* call read('logcheck.feature') req
Step for logcheck.feature
* print req
* def resultFromServiceLog = utils.getResultFromLog(baseUrl,'#(requestId)','service')
For example:
Error thrown : com.intuit.karate.exception.KarateException:
javascript evaluation failed: utils.getResultFromLog(baseUrl,'#>
(requestId)','service'), null
print req output is
[print] {"requestId": "c996f752-c288-40c7-9398-c913254971e6"}

You need to be clear about using embedded expressions, please read the docs again: https://github.com/intuit/karate#rules-for-embedded-expressions
For example this is wrong:
* def resultFromServiceLog = utils.getResultFromLog(baseUrl,'#(requestId)','service')
Instead:
* def resultFromServiceLog = utils.getResultFromLog(baseUrl, requestId, 'service')
And this is wrong:
* call ('logcheck.feature') x
You probably meant:
* call read('logcheck.feature') x

Related

Karate: How can we retrieve the value from called feature file

I have two parameter in feature file A and I pass those values to another feature file called B.
But I am unable to retrieve the values as expected in Feature file B
CODE:
Feature File A:
And def Response = response
And def token = response.metaData.paging.token
And def totalPages = response.metaData.paging.totalPages
* def xyz =
"""
function(times){
for(currentPage=1;currentPage<=times;currentPage++){
karate.log('Run test round: '+(currentPage));
karate.call('ABC.feature', {getToken:token, page:currentPage});
}
java.lang.Thread.sleep(1*1000);
}
"""
* call xyz totalPages
Feature File B:
* def token = '#(getToken)'
* def currentPage = '#(page)'
But the output was
#getToken
#page
What would be the best way? to these values for further utilization.
Try this:
* def token = getToken
* def currentPage = page
Here's another thing, any variable defined in the calling feature will be visible, e.g. token so most of the time you don't need to pass arguments:
* print token
* print totalPages
Please avoid JS for loops as far as possible: https://github.com/intuit/karate#loops - and actually you seem to have missed the data-driven testing approach that Karate recommends: https://github.com/intuit/karate#the-karate-way
If you are still stuck, please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue

call the first feature from the second feature file, failed without specified clue

Run the first.feature file successfully,however, call it from the second.feature failed without any clue to analysis. Do you have any idea help me find the root cause?
The source of my first.feature:
Feature: 采样管理-样本登记
Background: 读取随机生成的条形码、手机号、采样类型等作为入参
* url baseURL
* def randomData = Java.type('utils.RandomData')
* def barcode = randomData.getRandom(11)
* def randomPhone = randomData.getTelephone()
* def sampletype = randomData.getNum(0,1)
Scenario: 输入合法参数进行正常样本登记,确认能够登记成功
Given path 'iEhr/PersonSample'
# * header Content-type = 'application/x-www-form-urlencoded; charset=UTF-8'
* cookies { JSESSIONID: '#(jsessionID)',SESSION: '#(sessionID)', ACMETMP: '#(acmetmpID)'}
* def autoMotherName = "autoMname"+ barcode
# * def confData = {mothername: "#(autoMotherName)", barcode: "#(barcode)", mobile: '#(randomPhone)', sampletype:"#(sampletype)" }
# 设置sampletype为1,已被采样
* def confData = {mothername: "#(autoMotherName)", barcode: "#(barcode)", mobile: '#(randomPhone)', sampletype:"1" }
# 打印入参变量输出
* print confData
# 用例与数据分离
* def paramObj = read('classpath:mainFlow/sampleSaveReqTest.json')
* print paramObj
* form field param = paramObj
When method post
Then status 200
* json result = response[0].result
* def personId = result[0].personid
* def sampleid = result[0].sampleid
* print personId
* print sampleid
The source of my second.feature:
Feature: 提交递送样本
Background:
* def sampleResult = call read('classpath:mainFlow/first.feature')
* print sampleResult
I run the first.feature singly, it works. However, karate reports the error below after running the second.feature. Any idea how can I debug to find the root cause? I have no idea what's wrong with the second read. Many thanks!
* def sampleResult = call read('classpath:mainFlow/first.feature')
-unknown-:14 - javascript evaluation failed: read('classpath:mainFlow/first.feature'), null
Look for some issue with karate-config.js. As Babu said in the comments, it is very hard to make out what the problem is, I suggest you follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
Also try if the latest preview version 0.9.3.RC2 is better at showing what the error is.
If you can replicate the problem as a small example, it will help us - because we really need to do better at showing more useful error logs, instead of just null.

How to pass single param to separate feature file

I've tried below to send a param to separate feature file ( by following this example ) but, it is not working as expected.
project.feature
* def id = '55000000005021'
* def result = call read('delete_project.feature')
delete_project.feature
Given path 'project', '#(id)'
When method DELETE
Then status 200
Then match response.status == 'success'
Getting below exception
com.intuit.karate.exception.KarateException: projects.feature:48 -
delete_project.feature:11 - status code was: 404, expected: 200,
response time: 239, url: https://localhost:8080/project/%23(id)
response:
{"status":"failure","data":{"error_code":"INVALID_URL_PATTERN","message":"Please
check if the URL trying to access is a correct one"}} at ✽.* def
result = call read('delete_project.feature') (projects.feature:48)
One more doubt, How to iterate this by passing list of ids. I've multiple id in foo variable, I would like call delete_project.feature for each id availble in that foo variable.
* def foo = get response.data[*].id
I think you over-complicated the path params, change to:
Given path 'project', id
And read this part of the docs: https://github.com/intuit/karate#rules-for-embedded-expressions

How to pass the json list response of one feature file as parameter to another feature file

My requirement is, I want to pass the response of first feature file as input to second feature file. The first feature file response is a json list, so the expectation is second feature file should be called for each value of json list.
Feature:
Scenario: identify the reference account
* def initTestData = read('../inputData.feature')
* def accountData = $initTestData.response
* print “Account Details”+accountData // output of this is a json list [“SB987658”,”SB984345”]
* def reqRes = karate.call('../Request.feature', { accountData : accountData })
In Request.feature file we are constructing the url dynamically
Given url BaseUrl + '/account/'+'#(accountId)' - here am facing issue http://10.34.145.126/account/[“SB987658”,”SB984345”]
My requirement is Request.feature should be called for each value in ‘accountData’ Json list
I have tried:
* def resAccountList = karate.map(accountData, function(x){accountId.add(x) })
* def testcaseDetails = call read('../requests/scenarios.feature') resAccountList.accountId
Result is same, accountId got replaced as [“SB987658”,”SB984345”]
my I need to call Request.feature twice http://10.34.145.126/account/SB987658 http://10.34.145.126/account/SB984345 and use the response of each call to the subsequent feature file calls.
I think you have a mistake in karate.map() look at the below example:
* def array = ['SB987658', 'SB984345']
* def data = karate.map(array, function(x){ return { value: x } })
* def result = call read('called.feature') data
And called.feature is:
Feature:
Scenario:
Given url 'https://httpbin.org'
And path 'anything', value
When method get
Then status 200
Which makes 2 requests:
https://httpbin.org/anything/SB987658
https://httpbin.org/anything/SB984345

How to call a feature file using a for loop. The feature file being called will also accept parameters from the feature file calling it

example :
Contents of FooGetRequest.feature file
* eval for (var i=0; i<foobarInDB.length; i++) call read('../features/BarGetRequest.feature') { foo_code:'#(foo_code)' , bar_code:'#(foobarInDB[i])'}
This is how BarGetRequest.feature file looks like :
Background:
* url baseUrl
Given path
"/v1/foo/"+foo_code+"/skus/"+bar_code+"/bar"
When method get
Then status 200
When I execute FooGetRequest.feature file i get the following error
[java.lang.RuntimeException: javascript evaluation failed: Expected ; but found read
you can use driven data driven feature in karate for loop over feature multiple times
Assuming foobarInDB is an array of bar_code and foo_code will always be same
* set foobarInDB[*].foo_code = foo_code
* call read('../features/BarGetRequest.feature') foobarInDB
refer Data driven feature
I wrote a small java script to return me a map like { foo : bar}
* def fun = function(x){return {foo :x }}
* def fooBarMap = karate.map(fooBarMap,fun)
* def validateResponse = call read('../features/BarGetRequest.feature) propertySkuMap
and in the BarGetRequest.feature I read the values accordingly.