reuse karate tests from other feature file by passing in params [duplicate] - karate

This question already has an answer here:
Pass Json to karate-config.js file
(1 answer)
Closed 1 year ago.
We have a set of services that all expose certain common endpoints such as a health check, version information etc. I am trying to use karate to write smoke tests for these multiple services in a reusable way that i can just pass in the service name and endpoint and have the tests executed for each service.
basicChecks.feature
Feature: Smoke Test. verify health check and version and index are ok
Scenario: Verify that test server health check is up and running
Given url '#(baseUrl)'
Given path '/health'
When method get
Then status 200
And match response == "'#(name)' ok"
Given path '/version'
When method get
Then status 200
And match response contains {'#(name)'}
testServices.feature
Feature: Smoke Test for services.
Scenario: Verify that test server health check is up and running
* call read('basic.feature') { name: 'service1' , baseUrl : service1Url }
* call read('basic.feature') { name: 'service2' , baseUrl : service2Url }
karate-config.js
function fn() {
var env = karate.env; // get java system property 'karate.env'
karate.log('karate.env system property was:', env);
if (!env) {
env = 'local'; // a custom 'intelligent' default
}
var config = { // base config JSON
appId: 'my.app.id',
appSecret: 'my.secret',
service1Url: 'https://myserver/service1'
service2Url: 'https://myserver/service2'
};
// don't waste time waiting for a connection or if servers don't respond within 5 seconds
karate.configure('connectTimeout', 5000);
karate.configure('readTimeout', 5000);
return config;
}
When i run this i get an error suggesting that the baseUrl is not being picked up when passed in
20:27:22.277 karate.org.apache.http.ProtocolException: Target host is not specified, http call failed after 442 milliseconds for url: /health#(baseUrl) 20:27:22.278 cas/src/test/java/karate/smoke/basic.feature:7 When method get http call failed after 442 milliseconds for url: /health#(baseUrl) cas/src/test/java/karate/smoke/basic.feature:7
I looked at https://intuit.github.io/karate/#code-reuse--common-routines but could not figure out how to use the same tests but pass in different endpoints?
Or maybe since i am totally new to karate there is a much better way of doing this than what i have outlined?
Thank you for your time.
Edit - I am trying to test different micro services in the same environment and not trying to switch different environments etc.

This is not the recommended approach. When you have different URL-s for different environments, you should switch environments using the approach in the documentation (setting karate.env) and NOT depend on re-use via "call" etc.
Example: https://stackoverflow.com/a/49693808/143475
And if you really want you can run suites one after the other switching the karate.env, although that is rare.
Or if you just trying "data" driven testing, there are plenty of ways, just read the docs and search Stack Overflow for Scenario Outline: https://stackoverflow.com/search?tab=newest&q=%5bkarate%5d%20Scenario%20Outline
If you are trying to do this "clever" re-use using "call" I strongly recommend that you don't and please read this for why: https://stackoverflow.com/a/54126724/143475
EDIT - I think you ran into this problem, read the docs please: https://github.com/intuit/karate#rules-for-embedded-expressions

Related

How to do softassertion with karate? [duplicate]

This question already has an answer here:
Is it possible to do soft assertion in the karate
(1 answer)
Closed 1 year ago.
I have a feature that use other two features something like that:
When call read(ser.getCarList) headers
When call read(ser.getTaxes) headers
So the first feature getCarList has two validations
When method Get
* configure continueOnStepFailure = true
Then status 200
And match response = read ('this:getCarAssertion')
* configure continueOnStepFailure = true
I have tried with the new keyword but when I get a status code 200 but a bad response the next feature getTaxes does not continue in the execution
The continueOnStepFailure is a new keyword that was meant to be used when looking to validate results and not fail immediately on the first failure. The purpose was for assertions or validations so as much information can be validated when asserting results of tests.
To avoid its usage to be as a pure if condition for several steps (with unexpected consequences), the default behavior of * configure continueOnStepFailure = true will only continue the execute if the fails happen in a match step and once you disable the mechanism with * configure continueOnStepFailure = false the test will fail (but still provide details for each step within the continueOnStepFailure block). This is because match is the recommended keyword for any sort of validations and is how you can leverage the powerful JSON assertions library etc.
It is also recommended to also explicity set * configure continueOnStepFailure = false after the set of match keywords so there are no unexpected behaviors after that conscious decision of continuing to evaluate keywords after a failure.
That being said there are ways to extend and configure the behavior of the continueOnStepFailure beyond the default behavior. The keyword also takes a JSON input, instead of a boolean, that allows some more extensibility. E.g. the default behavior of the keyword can be represented as follows:
* configure continueOnStepFailure = { enabled: true, continueAfter: false, keywords: ['match'] }
This means the continueOnStepFailure mechanism will be enabled, the scenario execution will not continue after the mechanism is disabled and it'll only accept failures if those happen in the match keyword. Note that if you set continueAfter to true the scenario will continue to execute the remaining steps but the scenario itself will still be marked as failed (with appropriate output in the report and typical failed behavior for any caller of that scenario). I highly discourage to set continueAfter to true.
For your specific use case, the status keyword is definitely within the boundaries of assertions that I've described. status 200 is just a shortcut for match responseStatus == 200. Very likely we should add status to the default behavior, given that it's a match assertion. With the extended configuration in JSON you can do the following for your use-case:
When method Get
And configure continueOnStepFailure = { enabled: true, continueAfter: false, keywords: ['match', 'status'] }
Then status 200
And match response = read ('this:getCarAssertion')
And configure continueOnStepFailure = false
Some additional examples can be found in the unit tests in this pull request. For quick reference, this is how your Karate Test report will look like:

In karate mocking (karate-netty), how can we override request header value?

Objective:
We want few API calls should go to mock-server(https://192.x.x.x:8001) and others should go to an actual downstream application server(https://dev.api.acme.com).
Setup :
On local, mock server is up with standalone jar on port 8001. e.g https://192.x.x.x:8001
In application config file (config.property)downstream system(which need to mock) defined with mockserver IP i.e https://192.x.x.x:8001
Testing scenario and problem:
1.
Scenario: pathMatches('/profile/v1/users/{id}/user')
* karate.proceed('https://dev.api.acme.com')
* def response = read ('findScope.json')
* def responseStatus = 200ˀˀ
* print 'created response is: ' + response
Now, when we hit API request via postman or feature file then it does karate.proceed properly to https://dev.api.acme.com/profile/v1/users/123/user instead of 192.x.x.x. However, in this request, host is referring to https://192.x.x.x:8001 instead of https://dev.api.acme.com which create a problem for us.
How can we override request header in this case? I did try with karate.set and also with header host=https://192.x.x.x:8001 but no luck.
Thanks!
Please see if the 1.0 version works: https://github.com/intuit/karate/wiki/1.0-upgrade-guide
Unfortunately https proxying may not work as mentioned. If you are depending on this, we may need your help (code contribution) to get this working
If the Host header is still not mutable, that also can be considered a feature request, and here also I'd request you to consider contributing code

Postman Testing Scripts: How to change env variable after one test case?

So my issue is that I want to have 2 tests for a single api call - one pass and one fail with missing params.
Here is what I have:
pm.test("Successful Login", function () {
pm.response.to.have.status(200);
});
pm.test("Missing Parameters", function () {
const currentUsername = pm.environment.get("username");
pm.environment.set("username", null);
pm.response.to.have.status(400);
//pm.environment.set("username", currentUsername);
});
So as you can see, I set username to null for the second test, only to set it back to is original value after the test. What I found was that instead of running the script sequentially, postman set my username to null before the first test could have been run, so I fail the first test. What should I do ?
Ok guys. Apparently you cannot set variables in the testing scripts because the testing script is run after the api call has been made. This needed to be set in the pre-request script. As for how to set all various tests in just on request I dont think this can be done. Therefore, I am just making a new request per test case.

Passing a variable from one feature file into another as a part of request URL(not query parameter) in Karate

I have a feature that generates a vehicle id and is stored as a variable in the feature. I want to pass this id as a part of the request URL in another feature as a sort of a teardown activity.
This is how I called it from a feature called activateVehicle.feature
Scenario : Activate a vehicle
* header X-API-Key = apiKey
* def result = callonce read('createVehicle.feature')
* def vehicleId = result.vId
# some workflow steps
........
........
........
# tear down - delete the vehicle created
* call read('deleteVehicle.feature'){ vehcileId: '#(vehicleId)' }
In the called feature - deleteVehicle.feature
Scenario: Delete a vehicle
* header X-API-Key = apiKey
* def myurl = 'https://xxx/vehicle'+ vehicleId +'?permanent=yes'
Given myurl
And request ''
When method delete
Then status 200
Am I right in the approach? I want to reuse deleteVehicle.feature in other workflows as well and hence not doing this operation in the same activateVehicle.feature(which would have been very easy). I referred to the documentation too but it shows how we can use the variables in in the request body but not as a variable that can be used anywhere in the called feature. I don't want to use it in the request body (but want to use it as a part of the request URL) For example:
Scenario:
Given url loginUrlBase
And request { userId: '#(username)', userPass: '#(password)' }
I also referred to How can I call a variable from one feature file to another feature file using Karate API Testing. I followed suit for a solution but am getting a javascript error:
feature.deleteVehicle: -unknown-:11 - javascript evaluation failed:
'https://xxx/vehicle'+ vehicleId +'?permanent=yes', ReferenceError: "vehicleId"
is not defined in <eval> at line number 1
feature.SVT: SVT.feature:80 - javascript evaluation failed: vehicleId: '#(vehicleId)' }, <eval>:1:14 Expected eof
but found }
vehicleId: '#(vehicleId)' }
^ in <eval> at line number 1 at column number 14
Can someone kindly help and advise please?
Can you simplify your example ? The only thing I can make out is you need a space after the call feature and before the call argument:
* call read('deleteVehicle.feature') { vehcileId: '#(vehicleId)' }
The pattern we generally recommend is to setUp not tearDown as tearDown has a risk of not executing if you had an error. That said, please see hooks: https://github.com/intuit/karate#hooks
Sometimes you should just keep it simple and call a feature (with args) only where you need it.

Not able to run the feature files written in karate as a cucumber feature in eclipse

I have my cucumber eclipse plug in installed. I have written my simple feature file in karate and when I was trying to run this as a cucumber test, I have been asked to implement the missing steps. When I run the same feature file with a dedicated runner, it executes without any issues. Request you to please help on this. I am trying to get this test run without the use of a dedicated runner
Scenario: Validate that the sample webservice is up and running
Given url sampleUrl
When method get
Then status 200
Scenario: Validate a Json key value pair from the received response
Given url sampleUrl
When method get
Then status 200
And match $.RestResponse.result contains {name: 'United States of America', alpha2_code: 'US', alpha3_code: 'USA' }
*** Console output
Feature: Test a sample RESTFUL webservice
15:05:10.725 INFO - Starting scenario: Validate that the sample webservice is up and running
15:05:10.725 INFO - Ending scenario: Validate that the sample webservice is up and running
15:05:10.741 INFO - Starting scenario: Validate a Json key value pair from the received response
#Test Scenarios
Scenario: Validate that the sample webservice is up and running # C:/Users/sxs8680/git/BDDCucumberJVM/src/test/java/com/thd/common/karatesupport/karatesample.feature:6
Given url sampleUrl
When method get
Then status 200
15:05:10.741 INFO - Ending scenario: Validate a Json key value pair from the received response
Scenario: Validate a Json key value pair from the received response # C:/Users/sxs8680/git/BDDCucumberJVM/src/test/java/com/thd/common/karatesupport/karatesample.feature:11
Given url sampleUrl
When method get
Then status 200
And match $.RestResponse.result contains {name: 'United States of America', alpha2_code: 'US', alpha3_code: 'USA' }
2 Scenarios (2 undefined)
7 Steps (7 undefined)
0m0.006s
You can implement missing steps with the snippets below:
Given("^url sampleUrl$", () -> {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
});
When("^method get$", () -> {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
});
Then("^status (\\d+)$", (Integer arg1) -> {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
});
Then("^match \\$\\.RestResponse\\.result contains {name: 'United States of America', alpha(\\d+)_code: 'US', alpha(\\d+)_code: 'USA' }$", (Integer arg1, Integer arg2) -> {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
});
You may have the wrong Cucumber Eclipse plugin or you need to do some minor configuration.
Please refer to this section of the documentation: Troubleshooting Cucumber IDE support