Karate: Call the same feature file with multiple url paths - karate

I need to run the tests in a feature file with multiple endpoint urls. All the tests hit REST endpoints and I need to hit multiple endpoints for the same tests. I came up with the two below working solutions, but they both have maintenance overhead. So I was wondering if there is a better solution.
1. Add a dummy feature file:
Add a new dummy feature file and call the actual feature file with the endpoint url as argument like below. The actual feature file has test data of 100 rows. So when this was executed individually, the cucumber report showed 100 scenarios and it was easy to see how many passed/failed. But when executed with the dummy feature file, the report shows only 1 scenario from the dummy feature file and shows all the 100 test cases underneath it.
Scenario: Call actual feature file with internal URL
* def params = { endpoint_url: 'internal' }
* karate.callSingle('actualTestCases.feature', params);
Scenario: Call actual feature file with public URL
* def params = { endpoint_url: 'public' }
* karate.callSingle('actualTestCases.feature', params);
2. Duplicate the test data rows and add a new column endpoint_url:
In the test data, add duplicate test data rows, and add a column 'endpoint_url' with values like 'internal', 'public'. Use this column data in the actual feature file. This has the overhead that test data needs to be duplicated. I have more than 3000 rows of test data.
|testcaseName|email|endpoint_url
|"Valid Parameters"|["validtests#test.com"]|"internal"
|"Valid Parameters"|["validtests#test.com"]|"public"

Just use JSON as input file.
If you need to create even more dynamic urls, use karate.map to fill the variable with more values and pass to your feature.
Remember to use Verbs (When, Then, And), so report will show the content.
Otherwise you need to configure manually.
Input file urls.json:
[
{"url" : "https://jsonplaceholder.typicode.com/users/1"},
{"url" : "https://jsonplaceholder.typicode.com/users/2"},
{"url" : "https://jsonplaceholder.typicode.com/users/3"}
]
Main feature file main.feature:
Feature: Test REST
Scenario: Dynamic URL Test
When def urls = read('./urls.json')
Then call read('_sub.feature') urls
Sub feature file _sub.feature:
#ignore
Feature:
Scenario: Call URL
* def keyword = __arg.url
Given driver keyword
Then retry(5, 1000).waitUntil("document.readyState == 'complete'")

Use 2 loops or a Scenario Outline:
Scenario Outline:
* call read('actualTestCases.feature')
Examples:
| endpoint_url |
| internal |
| public |
Note that endpoint_url will be visible to the "called" feature, so you don't need to worry about passing parameters. Actually I think you can do all of this in a single feature file.

Related

Intercepting multiple graphql operations in a karate UI scenario always returns the first response from mock feature

My scenario in the top feature file looks like this:
Scenario: Fetch a cat type id and create a cat
* driver.intercept({ patterns: [{ urlPattern: '*api/graphql*'}], mock:
'Mock.feature' })
When I click on the button to add a cat (//first graphql call happens. This gets cat types from the mock as expected)
And input a name
And select the cat type
And click create (//second graphql call happens here. But this returns the cat types again)
Then I see a success message
Here is the mock.feature:
Scenario: karate.match("request contains operationName: 'getCatTypes'")
def response = call read ('response.json')
Scenario: karate.match("request contains operationName: 'AddCat'")
def response = call read ('response1.json')
We use karate standalone jar and on version v1.2.0.RC1 (tried with 1.1.0 as well).
Appreciate any suggestions/directions.
Your use of karate.match() is wrong, note that it does not directly return a boolean. Read this for more: https://stackoverflow.com/a/50350442/143475
Try this change:
Scenario: karate.match("request contains operationName: 'getCatTypes'").pass
I also think there are much better ways to do the above, so read this also: https://stackoverflow.com/a/63708918/143475

How to validate API response against multiple instance of data base from feature file in Karate API automation?

I have developed a script which executes against one DB instance e.g.: db1. The code to connect to DB is written in Background section. Now what i want to do is, i have to execute same test script against diffrent db instance e.g.:db2
Feature:Execution against multiple DB instance.
##############################################
Background:
* def db_properties = {db_username,db_password,db_connection_string,driver}
* def createConnection = path to read .java file
* def readFromDB = new createConnection(db_properties)
##############################################
In * def db_properties, i have hard coded the actual values of username, password, conenction string and driver.What exactly i want to do is, i have to validate my API response agains't another DB instance e.g. build is deployed in another environment, and db properties which i have mentioned is diffrent environment. How can i do it?
This has nothing to do with Karate. Maybe the solution is to have 2 sets of DB connection values in your karate-config.js. Please figure out a solution that is appropriate for your situation.

Returning Variable from Feature File With Multiple Scenarios - Karate

We already know that scenarios are run paralelly. But we had the case where we need to return variables from feature files (that are gonna be called from another feature file).
We had multiple scenarios in the feature file as below:
#mutation
Feature: Test GraphQL Create Item
Background:
Given url baseUrl
* configure headers = { Authorization: '#(token)' }
#negative
Scenario: Create item unauthorized
* configure headers = { Authorization: ""}
#Features calling function and others
And match response.errors[0].message == errorUnauthorized
Scenario: Create story authorized
#Features calling function and others
And def idItem = response.data.CreateItem.id
We are reusing the feature file above to obtain variable to be used on another feature file. However it seems that the other feature files fail intermittently complaining the variables obtained from the other feature file is null.
My assumption is that the returned variable is not returned properly since there are more than one scenarios on the feature file. We tried deleting the #negative scenario and have only exactly 1 scenario. Suddenly the intermittent failures gone.
Is there any way to avoid this intermittent failures while still retaining the ability to run scenarios paralelly?
Thanks
Can't say without seeing your code. But you can try using the #parallel=false annotation in the "calling" feature file: https://github.com/intuit/karate#parallelfalse
Otherwise this may be a bug in Karate - so please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue

Karate - callonce feature doesn't cache the response

I have two feature files and I'm trying to reuse the result of the first feature file as a background to the second feature file's scenario
Feature file 1
Feature: First feature file
Scenario: create random session id
* def sessionId = Java.type('com.company.RandomSessionId').getRandomSessionId()
Feature file 2
Feature: calling another feature file
Background:
* def mycall = callonce read('first.feature')
* def randomId = mycall.sessionId
Scenario: print sessionId
* print randomId
Scenario: print sessionId-2
* print randomId
When I execute the scenarios in Feature file 2, I get two different results.
It must be because you are using the IDE support / right-click / "run-as" option. This is an open issue, because Karate needs to cache across Scenarios which "native" Cucumber does not support: https://github.com/intuit/karate/issues/136 - apologies and I need to update the documentation.
Please use a JUnit runner for these cases, I recommend having these in place for dev-mode anyway, and the new HTML dev-mode report makes this even more useful: https://twitter.com/KarateDSL/status/935029435140489216

Retrieve response from a "Run Test Step", using SoapUI/ Groovy?

In SoapUI, I have a host Test Case, which executes another external Test Case (with several test steps) using the "Run Test Case" test step. I need to access a response from the external TC from within my host TC, since I need to assert on some values.
I cannot transfer the properties since they are in XML. Could I get some pointers as to how I could leverage Groovy/SoapUI for this.
For Response you can use the below code.
testRunner.testCase.getTestStepByName("test step").testRequest.response.responseContent
In you external TC create another property and at the end of the TC use Transfer Property step to transfer your XML node to it. In your host TC, just read that property as you would any other.
I also had a look around to see if this can be done from Groovy. SoapUI documentation says that you need to refer to the external name of the testsuite / testcase:
def tc = testRunner.testCase.testSuite.project.testSuites["external TestSuite"].testCases["external TestCase"]
def ts = tc.testSteps["test step"]
But I could not find how to get at the Response after that.
In addition to Guest and SiKing answers, I share a solution to a problem that I've met:
If your step is not of type 'request' but 'calltestcase' you cannot use Guest answer.
I have a lot of requests contained each in a testCase and my other testCases call these testCases each time I need to launch a request.
I configured my request testCases in order to return the response as a custom property that I call "testResponse" so I can easily access it from my other testCases.
I met a problem in the following configuration :
I have a "calltestcase" step that gives me a request result.
Further in the test I have a groovy script that needs to call this step and get the response value
If I use this solution :
testRunner.runTestStepByName("test step")
followed by testRunner.testCase.getTestStepByName("test step").testRequest.response.responseContent
I'm stuck as there is no testRequest property for the class.
The solution that works is :
testRunner.runTestStepByName("test step")
def response_value = context.expand( '${test step#testResponse#$[\'value\']}' )
another solution is :
testRunner.runTestStepByName("test step")
tStep = testRunner.testCase.getTestStepByName("test step")
response = tStep.getPropertyValue("testResponse")
Then I extract the relevant value from 'response' (in my case, it is a json that I have to parse).
Of course it works only because I the request response as a custom property of my request test case.
I hope I was clear enough