Kick off Web services testing with KARATE

A little bit about KARATE

Karate is a test automation framework created to make your web-services testing simple. If you are already a fan of Cucumber, here is the Good news.... Karate is made on top of Cucumber-JVM and it also uses the same Gherkin syntax. So... yes, you can start writing your BDD style tests right away. Even though you have not used any of the above mentioned Cucumber or Gherkin, it's really easy to learn how to write tests with BDD style karate steps.

Oh and did I mention that you can write and execute API tests without a single line of java code? Yes, you heard me right. Karate comes with predefined step definitions, and there is a lot. All the steps you need to test your API functionality is there at your finger tips.

Why use karate?

If all the above mentioned points are not enough to convince you to get start testing your web services with karate, take a look at the following points.

  • Karate helps to get rid of the boilerplate code which is involved in performing the requests and asserting the response contents.
  • Easily written and understood even by non-programmers.
  • Can construct the most complex request-response operations with less effort.
  • Karate sits on top of Cucumber-JVM, you can run tests and generate reports like any standard Java project.
  • Many popular text editors supports Gherkin syntax.
  • Karate can run tests in parallel, and dramatically cut down execution time. 
  • Contains a mock servlet and allows you to create mock APIs. 
  • Let's you use scenarios as Gatling performance tests.
  • Support Schema validations.

Getting Started with Karate

Prerequisites:
  • Java 8
  • Either Maven or Gradle
  • Either Eclipse or InteliJ IDEs

If your project is a maven project you need to add the following dependencies
<dependency>
    <groupId>com.intuit.karate</groupId>
    <artifactId>karate-apache</artifactId>
    <version>0.9.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.intuit.karate</groupId>
    <artifactId>karate-junit4</artifactId>
    <version>0.9.4</version>
    <scope>test</scope>
</dependency>
If your project is a Gradle project, you need to add the following dependencies to your build.gradle
    testCompile 'com.intuit.karate:karate-junit4:0.9.4'
    testCompile 'com.intuit.karate:karate-apache:0.9.4'

Or you can straight away create whole skeleton project with Karate Maven archetype with one command.
mvn archetype:generate \
-DarchetypeGroupId=com.intuit.karate \
-DarchetypeArtifactId=karate-archetype \
-DarchetypeVersion=0.9.4 \
-DgroupId=com.mycompany \
-DartifactId=myproject
The above code snippet will create the project skeleton and when you import the project to your IDE it will look like this.

Now you can start writing tests. The created project will have a sample test feature. But I am going to create a separate package called "features" and write my tests inside that package.

In order to execute the test features I am about to write, karate needs a .java file created in the same package as the .feature files. The .java file will look like below.

package features;

import com.intuit.karate.junit4.Karate;
import org.junit.runner.RunWith;

@RunWith(Karate.class)
public class Products {
 
}

Karate-config.js

If you look at the previously created project structure again you will see a karate-config.js file. This file let's you add all your global variable and javaScript functions that you are going to use in your features.When you execute tests, karate is going to execute this config.js file first. This comes in handy when you have different variables when switching between environments.

function() {
  var env = karate.env; // get java system property 'karate.env'

  karate.log('karate.env selected environment was:', env);
  karate.configure("ssl", true)

  if (!env) {
    env = 'dev'; //env can be anything: dev, qa, etc.
  }

  var config = {
    env: env,

    AM_USERNAME: 'devuser',
    AM_PASSWORD: 'devpass',
    AM_HOST: 'https://am.'+env+'.example.net',
    AM_AUTHENTICATE_PATH: '/am/json/realms/root/authenticate',

  };

  if(env == 'qa') {
    config.AM_USERNAME: 'myUserName'
    config.AM_PASSWORD: 'myPa55word'
  }

  karate.log('OpenAM Host:', config.AM_HOST);

  karate.configure('connectTimeout', 60000);
  karate.configure('readTimeout', 60000);

  return config;
}

Read more about environment configurations in here.

KARATE sample scenario 


I bet anyone can understand the above test scenario just by reading the steps. I have only used very small amount of steps from karate in above demo. You can refer to the Karate Repository to find many more tricks you can do with karate.

When to use karate

As you have already seen, karate is a powerful framework built with all the API testing capabilities to make your life easier. 
When you need to achieve higher test coverage for a complex API, need to do lots of response validations, Karate will come in very handy.
As karate can be execute with maven it can be run in your CI environment.
Karate is mostly recommended for unit testing the APIs. As the main points of having karate is to have predefined step definitions to test your API and get rid of the boiler plate code, adding more java classes and other dependencies will mess with the main goal of using karate. If you are going to stick in to testing the APIs only without having any other dependency steps, you probably will be able to do the testing without needing add any java code.
If you are following TDD or BDD it's important that you have the tests ready as soon as possible before the development is done, with Karate you can easily achieve this as it will consume the minimum time to design the tests.

So when not to use Karate 

Even though Karate is build on cucumber-jvm it will not allow you to add any custom step definitions as in cucumber. But you can add your steps as javaScript functions or using Java interop.

When your Rest services have many dependencies like JMS, Databases, It may not be the best idea to use Karate for testing the integrated behavior. If you try to add many dependency steps with karate, the scenarios will get unreadable and more complex.
But it does mean that you can not use JMS or Databases in karate. Look at the following code snippet of calling JDBC.

Given path 'dogs'
When method get
Then status 200
And match response contains { id: '#(id)', name: 'Scooby' }
# use jdbc to validate
* def config = { username: 'sa', password: '', url: 'jdbc:h2:mem:testdb', driverClassName: 'org.h2.Driver' }
* def DbUtils = Java.type('com.karate.demo.util.DbUtils')
* def db = new DbUtils(config)
# since the DbUtils returns a Java Map, it becomes normal JSON here !
# which means that you can use the full power of Karate's 'match' syntax
* def dogs = db.readRows('SELECT * FROM DOGS')
* match dogs contains { ID: '#(id)', NAME: 'Scooby' }
* def dog = db.readRow('SELECT * FROM DOGS D WHERE D.ID = ' + id)
* match dog.NAME == 'Scooby'
* def test = db.readValue('SELECT ID FROM DOGS D WHERE D.ID = ' + id)
* match test == id

Below is a comparison of Karate Vs Cucumber done by intuit guys.

CucumberKarate
Step Definitions Built-InNo. You need to keep implementing them as your functionality grows. This can get very tedious, especially since for dependency-injection, you are on your own.✅ Yes. No extra Java code needed.
Single Layer of Code To MaintainNo. There are 2 Layers. The Gherkin spec or *.feature files make up one layer, and you will also have the corresponding Java step-definitions.✅ Yes. Only 1 layer of Karate-script (based on Gherkin).
Readable SpecificationYes. Cucumber will read like natural language if you implement the step-definitions right.❌ No. Although Karate is simple, and a true DSL, it is ultimately a mini-programming language. But it is perfect for testing web-services at the level of HTTP requests and responses.
Re-Use Feature FilesNo. Cucumber does not support being able to call (and thus re-use) other *.feature files from a test-script.✅ Yes.
Dynamic Data-Driven TestingNo. Cucumber's Scenario Outline expects the Examples to contain a fixed set of rows.✅ Yes. Karate's support for calling other *.feature files allows you to use a JSON array as the data-source and you can use JSON or even CSV directly in a data-driven Scenario Outline.
Parallel ExecutionNo. There are some challenges (especially with reporting) and you can find various discussions and third-party projects on the web that attempt to close this gap.✅ Yes. Karate runs even Scenario-s in parallel, not just Feature-s.
Run 'Set-Up' Routines Only OnceNo. Cucumber has a limitation where Backgroundsteps are re-run for every Scenario and worse - even for every Examples row within a Scenario Outline. This has been a highly-requested open issue for a long time.✅ Yes.
Embedded JavaScript EngineNo. And you have to roll your own approach to environment-specific configuration and worry about dependency-injection.✅ Yes. Easily define all environments in a single file and share variables across all scenarios. Full script-ability via JS or Java interop.
If you have experience with Rest Assured or trying to decide whether to use Rest Assured or Karate for automating api tests, here is comparison of Karate vs Rest Assured done by intuit guys.

One more important thing to remember is using karate will not mean you are following BDD. Karate is built on cucumber to take the advantages of cucumber capabilities but it does not follow BDD practices. Anyway it does not matter whether it breaks BDD or not, as long as it makes your life better than today and NOT worse!

Comments