Hot questions for Using Cucumber in karate

Question:

I have finally gotten Karate working with GraphQL and able to verify a simple 200 response though I am having trouble verifying the schema and then a response. I am super new so I apologize (not a programmer, just a tester). I want to verify that the schema is correct and for example that the results simply return (providerID, firstName, lastName etc), not the data. I then want to verify the data itself separately. The other thing I do not understand is how to pass in data, for example where I could change the Latitude, Longitude, MaxDistance etc and have it be a variable. I see in the example how "name" as used as a variable yet these seem to be passed in differently so I'm unsure how to do it. Sorry for not knowing so much, I appreciate the help.

Scenario: simple graphql request
    #Verify 200 response status returned    
    Given text query =
        """
     {
                    Results: getSearchResults(searchLatitude:"38.942833", 
    searchLongitude: "-119.984549", providerType: "Primary Care Physicians", 
    sortBy: "distance", maxDistance:"600",skip: 0, take: 10) {
                        providerID
                        firstName 
                        lastName
                        mI
                        title
                        name
                        nameLFMT
                        status
                        specialties
                        locations
                        institutions
                        acceptNewPatient
                        imageUri
                        distanceToNearest
                    }

    } 

        """
    And request { query: '#(query)' }
    When method post
    Then status 200

    # pretty print the response
    * print 'response:', response


    # the '..' wildcard is useful for traversing deeply nested parts of the 
    json
    * def results = get[0] response..Results
    * match results contains { ProviderId: 520, firstName: 'Richard', 
lastName: 'Botto' }

Answer:

Take a look at the replace keyword.

Then try this:

Given text query =
    """
 {
                Results: getSearchResults(searchLatitude:"<searchLatitude>", 
searchLongitude: "<searchLongitude>", providerType: "Primary Care Physicians", 
sortBy: "distance", maxDistance:"600",skip: 0, take: 10) {
                    providerID
                    firstName 
                    lastName
                    mI
                    title
                    name
                    nameLFMT
                    status
                    specialties
                    locations
                    institutions
                    acceptNewPatient
                    imageUri
                    distanceToNearest
                }

} 

    """
* replace query.searchLatitude = '38.942833'
* replace query.searchLongitude = '-119.984549'

Once you get this working search the documentation for "graphql" for more ideas.

For matching schema it should be easy:

* match results contains { ProviderId: '#number', firstName: '#string', lastName: '#string' }

The doc has a whole section on fuzzy matching.

Question:

Unable to execute karate scenario from intellij OS: Mac Intellij version: Karate scenario cannot be executed from intellij Karate version:

compile group: 'io.cucumber', name: 'cucumber-core', version: '4.7.0'

testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'com.intuit.karate', name: 'karate-apache', version: '0.9.3'
testCompile group: 'com.intuit.karate', name: 'karate-junit4', version: '0.9.3'

Error message

Error: Could not find or load main class cucumber.api.cli.Main
Caused by: java.lang.ClassNotFoundException: cucumber.api.cli.Main

Answer:

The issue got resolved by setting the Switch IDE Boot JDK to default and deleting the cache and restart. The cause this was due to multiple jdk I have installed in my machine (JDK8 and JDK 12). Deleted the old one and set the boot JDK to 12.

The issue is not with Karate library, its with the IntelliJ configuration.

Question:

How can I have a karate setup so that I can run a bunch of tests when running locally and a subset with running in pre-prod?

When I run the tests locally, I spin up a mock server and set it up using Background. In pre-prod, no mock server is required, so I would like to skip the Background execution.

Also, I was not able to use the @Before annotation to start my cucumber Test Runner.


Answer:

Use tags. Refer to the documentation: https://github.com/intuit/karate#cucumber-tags

@preprod
Scenario: some scenario

Personally I prefer the approach where you spin up mock servers from your JUnit test classes, and there are a lot of examples, like this one: example

But you can do this also, refer the docs on conditional logic:

* eval if (karate.env == 'preprod') karate.call('mock-start.feature')

I was not able to use the @Before annotation

That's not really helpful, please follow the instructions here: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue

Question:

I want to use single row under examples in cucumber like below: Examples: | data1 | data2|paymentOp| | MySql | uk1 |??????????| Where paymentOp is a number which I am getting from java method which has List as an argument. The method returns each of the numbers which I want to pass it under paymentOp.

There is an absolute way to iterate it by copy the row and paste it again in the table but I don't want that because the method has a dynamic result which may return 2 or 5 set of numbers.

Is it possible to achieve it using Karate? How to proceed further. Any lead here would be much appreciated!


Answer:

You can combine Examples: with dynamic behavior. Please read this example (especially the second one): https://github.com/intuit/karate/blob/master/karate-demo/src/test/java/demo/outline/examples.feature

Since you have difficulties reading the docs and examples (:P) here is a simple example. Take some time to understand it carefully.

Background:
* def data = { one: 1, two: 2, three: 3 }

Scenario Outline:
* match data.<key> == <value>

Examples:
| key   | value |
| one   | 1     |
| two   | 2     |
| three | 3     |

Question:

I could not find anything in the documentation regarding this but I am trying to verify the field names within a response. I do not care what their values are. What would be the proper way to do this using Karate DSL? My focus is on the response match below.

Given path 'serviceRequests', 'tasks'
And param view = 'short' * header Authorization = 'Bearer ' + Token
When method get
Then status 200
And match response == { page:  'i-dont-care', total: 'i-dont-care'}

Answer:

Refer to this section of the doc: Ignore or Validate

And match response == { page: '#ignore', total: '#notnull' }

Question:

I have a need to extract a field parsed from a "complex" response header and use that value later in the test.

It seems that the "header" keyword in Karate is set up for setting request headers, not parsing response headers.

Is there a way to add a custom step definition maintaining access to the scenario variable stores? It appears the variable stores are private in the StepDefs class, and there doesn't seem to be a way to extend it easily.


Answer:

You can get access to the response headers. Please look at the documentation for responseHeaders.

That said, the match header short-cut is most likely what you are looking for.

Karate's philosophy is that you never need to write custom step-definitions.

edit: some examples, sounds like you just need to do some string manipulation of the Location header ? You can freely mix JS code into Karate expressions.

* def location = responseHeaders['Location'][0]
# assume location = 'foo?bar=baz'
* def bar = location.substring(location.indexOf('bar=') + 4)

Question:

I am using Karate for my test scenarios for the requirement to update the contract plan by passing the plan Id's and I am retrieving the planId from the database and passing it to my request json.

But the problem I am facing it comes with the column name whereas I only need the value.

Below is the example of how I am fetching my Id by connecting to the database

`@Scenario1 Scenario:

use jdbc to validate
  • def config = { username: 'mmultapp', password: 'Mmu1t@pp', url: 'jdbc:db2://edb2dev3.momentum.co.za:60022/MMULTTST', driverClassName: 'com.ibm.db2.jcc.DB2Driver' }
  • def DbUtils = Java.type('wellness_core_utils.DbUtils')
  • def db = new DbUtils(config)
  • def productId = db.readRows('select PRODUCT_ID from MULTUSR1.PLANS order by PLAN_ID desc fetch first 1 rows only')
  • print productId`

And I am getting the results in this way

{ "PRODUCT_ID": 68 }

I only need to read the value of 68 so I that I can pass it to my json request

Thanks in advance


Answer:

The query returns a key-value pair which you write in the query, Suppose you write

select PRODUCT_ID AS pId from MULTUSR1.PLANS order by PLAN_ID desc fetch first 1 rows only;

So It returns a PRODUCT_ID with the name pId. Later on, you can use that result as per your requirements

Let's try this in your instance.

def productId = db.readRows('select PRODUCT_ID from MULTUSR1.PLANS order by PLAN_ID desc fetch first 1 rows only').PRODUCT_ID;
const result =  productId.PRODUCT_ID;

Notice: Please check the first type of your query result Like It's in [] or {} In above instance I consider it in {}

const result = [{ PRODUCT_ID: 87 }];
console.log(result[0].PRODUCT_ID);