Home Programming Writing API Tests with Karate

Writing API Tests with Karate

By Benjamin Bischoff
books-svg-icon Book
eBook $31.99 $21.99
Print $39.99
Subscription $15.99 $10 p/m for three months
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $31.99 $21.99
Print $39.99
Subscription $15.99 $10 p/m for three months
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    Chapter 1: Introducing Karate’s Core Concepts
About this book
Software in recent years is moving away from centralized systems and monoliths to smaller, scalable components that communicate with each other through APIs. Testing these communication interfaces is becoming increasingly important to ensure the security, performance, and extensibility of the software. A powerful tool to achieve safe and robust applications is Karate, an easy-to-use, and powerful software testing framework. In this book, you’ll work with different modules of karate to get tailored solutions for modern test challenges. You’ll be exploring interface testing, UI testing as well as performance testing. By the end of this book, you’ll be able to use the Karate framework in your software development lifecycle to make your APIs and applications robust and trustworthy.
Publication date:
May 2023
Publisher
Packt
Pages
326
ISBN
9781837638260

 

Introducing Karate’s Core Concepts

The software testing world is constantly changing. Technologies that were recently state of the art are replaced or turn out to be slow sellers. New frameworks are created all the time to try to solve common testing problems. There are a lot of people who have entrenched opinions about how tests should look, and sometimes this attitude can even block progress. Testing is often still divided into exploratory testing (also called manual testing, which I personally dislike) and code-heavy automation solutions (also known as test automation), which may require a software expert for development and maintenance but might not be feasible for more hands-on exploratory testing.

In between these extremes, there is plenty of room for innovation. There has been quite some progress here during the last few years, and these new technological solutions are in high demand.

The Karate framework is a rather new contender in the software testing field that has set out to solve many of the problems raised, especially the steep learning curve of other solutions.

We are going to cover the following topics:

  • What makes Karate stand out?
  • Behavior-driven development (BDD) versus Karate
  • Supported data types in Karate
  • The JavaScript engine
  • Java interoperability
 

Technical requirements

All code examples for this chapter can be found on GitHub at https://github.com/PacktPublishing/Writing-API-Tests-with-Karate.

Demo code

It is not necessary to set up the programming environment at this point. All code that is shown here is just to demonstrate Karate’s inner workings and core functionality. In the next chapter, we will deal with this thoroughly!

 

What makes Karate stand out?

At its core, Karate is a test automation framework that is written in Java but does not necessarily require programming skills when used for basic software testing. It is heavily based on the Gherkin syntax, made famous by the Cucumber BDD framework. In fact, when it was first introduced to the software testing world, it was designed as an extension of Cucumber but quickly evolved into something of its own. However, some of Cucumber’s core characteristics are still evident and can be put to good use. For example, the very similar file structure, syntax, and compatibility with the standard JSON reporting format.

The first version was released on February 08, 2017, by Peter Thomas while he was working as a test engineer at Intuit India (https://www.intuit.com/in), a large software company in the fintech industry. His motivation was to come up with an easier-to-use and easier-to-understand API testing solution than the in-house framework his team was using at this time.

In Peter’s own words,

Karate strives to reduce the entry barrier to writing a test and more importantly - reduces the friction to maintain a test, because of how readable tests become.

Thomas, P. (2017). Karate: Web-Services Testing Made Simple, https://medium.com/intuit-engineering/karate-web-services-testing-made-simple-366e8eb5adc0

Intuit suggested making his work open source in order to test how this new approach would be received by the community.

At the time of writing this book, the Karate framework sports more than 6.6k stars on GitHub (https://github.com/karatelabs/karate) and even received a GitHub grant for open source software in India.

Peter has apparently struck a nerve with the testing community!

In 2021, after this successful open source launch and adaption period, Peter decided to found Karate Labs (https://www.karatelabs.io), together with Kapil Bakshi, in order to work full-time on the further development and promotion of the framework and to offer some new paid products and services around Karate.

No paywall

The paid services by Karate Labs include subscription-based plugins for IntelliJ IDEA and Visual Studio Code with multiple tiers. In this book, however, we will focus exclusively on the freely available core framework and its various open source components and tools.

Interest in the Karate framework has not waned since then, as can be seen by the plethora of questions on Stack Overflow and its GitHub issues page. Since a lot of information is spread among many different online articles, social media channels, blog posts, and podcasts, I decided to write a book about it to provide a structured, comprehensive, and complete introduction.

In the upcoming sections, we will discover how Karate works in more technical and conceptual detail and what distinguishes this solution from other popular testing frameworks that may be more specialized but are also much harder to learn and use.

Also, we will further explore the similarities and differences between the classic Gherkin syntax and underlying concepts and Karate’s different approach in the next section. We will find out why certain decisions were made by the framework creator and why they were smart moves.

Discovering Karate’s strong points

Karate’s strengths lie in various areas of test automation, which we will discuss in this section. Later on in the book, we will shine a light on these different areas with a strong focus on the framework’s core purpose – testing APIs effectively.

Since there are multiple modules of Karate with different goals, let’s quickly walk through them to see how extensive the framework and its components have become over the years.

Testing APIs

Providing a basis for API tests that is easy to read and follow is the main capacity of Karate – it supports the REST, SOAP, and GraphQL APIs and can be extended to handle other types of APIs and data formats that are not as common. All other framework modules that cover different kinds of testing were gradually added and implemented with the same basic mechanisms and concepts. By focusing on its straightforward domain-specific Gherkin-based language, Karate can map a lot of API test functionality without having to write elaborate code for communicating with web services or handling various payloads and data exchange formats.

Additionally, Karate includes many powerful assertions to verify response data, and its structure, especially JSON and XML, are handled exceptionally well. This makes it a perfect fit for a lot of modern APIs that use these formats.

We will explore all of this in Chapter 3, Writing Karate Tests.

Fun fact

Even though Karate is often associated with JSON, XML support was implemented first in its initial prototype before JSON handling was added!

Test doubles

Testing microservice infrastructures or web services calling other services or databases can get very complex and challenging. Typically, the approach is to spin up all components that make up a full system in order to test it thoroughly. This makes it hard to run tests for a single component because each test needs to go through multiple layers. This means that other dependent services need to be very predictable and reliable in such a setup so you can obtain meaningful and non-flaky test results.

Test doubles, a term coined by agile software development consultant Gerard Meszaros (http://xunitpatterns.com/gerardmeszaros.html), solve this problem. It groups together all forms of fake objects (or fake APIs) that can be used instead of real objects in tests. They behave as if you were making real requests and data transfers but deliver the same predictable responses every time. This allows you to perform testing on a small part of the system without having to directly use all real dependencies and services. Thus, the tests can run faster and more securely because you are not affected by network problems, bad connections, database inconsistencies, and other failures.

Karate can define such doubles easily using nothing but Gherkin, as we will see in Chapter 6, More Advanced Karate Features!

Performance tests

Karate’s main strength in the performance testing field is that it can reuse existing scenarios. The same test cases that are used as acceptance tests can seamlessly act as Gatling performance tests. This means that it is possible to simulate multiple clients or connections that interact with your APIs in order to check their resilience and how they hold up under heavy loads. By integrating the popular Gatling framework, Karate gains a huge advantage here because it frees us from using completely separated solutions, third-party frameworks, and libraries that would require additional research, learning, and onboarding.

Also, due to its ability to reuse already implemented test scenarios, we do not need to spend time and resources duplicating them in another programming language just for the sake of performance tests.

In Chapter 10, Performance Testing with Karate Gatling, we will look deeper at this important testing topic.

Browser automation

The automation of websites and browser-based user interfaces has become much more important in recent years. More and more user-facing software is available as web applications, which can be very complex in design. Also, a lot of functionality and logic can be wired into the frontend, making it necessary to thoroughly test this area as well.

Karate UI is special here because it combines the Chrome DevTools Protocol (CDP) and the WebDriver protocol, so it can accomplish pretty much everything that other popular tools such as Selenium, Cypress, and Playwright can do.

As we will see in Chapter 9, Karate UI for Browser Testing, this module was one of the last ones added to the Karate framework to cover this testing field as well. Among other things, it provides full debugging capabilities and even allows freely mixing API and UI automation to handle even more complex use cases.

Desktop automation

Karate also supports automating desktop applications through its integration with the Robot framework. This is an entirely different use case than the other ones that are discussed in this book, but maybe this will contribute to your decision to give Karate a try.

If you want to know more about this part of Karate, check the documentation at https://github.com/karatelabs/karate/tree/master/karate-robot.

Now that we have gotten to know Karate’s core uses, let’s find out about its main features next.

Core features

Since many useful and often needed functions of other specialized test frameworks are already implemented in the core framework, you will reach useful results fast and without a steep learning curve. This makes Karate ideal for quickly implementing a large number of test cases and working off low-hanging fruits (things that take only a little time while having a great benefit).

Karate’s big advantage is the consistent syntax across test types. This makes switching between different test projects and contexts easier and faster, as there is no need for extensive training. Also, it keeps the test suites very clean, easy to understand, and maintainable when written well.

If, however, you require expanded functionality, you are free to add it as either Java or JavaScript code, depending on which language features can solve your problem better and your respective skills with each of them.

Let’s look at some of its most useful aspects!

Parallel test execution

Often, extensive test suites contain a lot of different scenarios that differ greatly in individual runtime. Executing these tests in sequence, meaning one after the other, can lead to an unnecessarily long feedback time. Many other test frameworks have parallelization built in, at best, as an afterthought or require additional tools for this. Also, it can be complex to execute and evaluate (for example, because test reporting cannot deal with parallel scenarios correctly). Karate has this approach on board as a basic feature for all different test types.

As we will later see in Chapter 4, Running Karate Tests, we will even be able to visualize and track how tests are run on different threads, making this a powerful option for more efficient test runs.

Data-driven testing

In Chapter 3, Writing Basic Karate Tests, we will discover that the Karate framework even supports data-driven tests. That means that one or more test scenarios can be reused with multiple sets of data instead of writing separate ones for each individual use case. This reduces code duplication and errors caused by having to change multiple code locations across a lot of feature files if requirements change.

The unique aspect of Karate in this regard is that these records of data can even be defined in JavaScript Object Notation (JSON) or comma-separated values (CSV) formats. Also, they are not required to be static data as in a Cucumber-based framework but can be generated dynamically.

Auto-generated test reports and logs

Karate has its own built-in reporting library that generates informative HTML-based test reports that show what features and scenarios were run along with requests, responses, and additional information such as tags, screenshots, and even a timeline of parallel runs. These help greatly in analyzing test runs and can act as a form of documentation as well. In case you need to display custom information, Karate even includes a full templating engine that can be programmed to display any additional data you may need.

Additionally, all Karate actions, up to every single request and response, are logged. Even with the most beautiful test reports, it is often simple text logs that provide the most information about errors that have occurred.

We will encounter both variants of debugging, including custom configuration and extension, in Chapter 5, Reporting and Logging.

First-class support of common data formats

Karate, through its Java and JavaScript roots, can handle pretty much any data format found on the web today. This does not only mean processing them but also making assertions, performing schema validations, and efficient fuzzing matching of results. Later in this chapter, we’ll take a closer look at the formats that are natively supported. Additionally, we will explore this topic further in Chapter 3, Writing Basic Karate Tests, and Chapter 4, More Advanced Karate Features.

Beginner friendliness

One of the best characteristics of the Karate framework is that it allows users to start using it as a solution where no coding is necessary and gradually realize more complex test cases by writing Java or JavaScript code on top of it. The Karate domain-specific language (DSL) will be discussed in more detail a little later in this chapter.

When using Karate, it is worth mentioning that it is usually just one single dependency you need that covers most functionality (for example, API testing, UI testing, and performance tests), making this rather simple to set up.

Additionally, there is even a standalone executable version of Karate that can do everything that the Java library can do but without requiring experience with setting up a Java project. This is useful for quickly trying out Karate without extensive preparation. For a production environment, I would nonetheless recommend the Maven setup that we will see in Chapter 2, Setting Up Your KarateProject, and Chapter 4, Running Karate Tests.

Built-in support of different environments

If you have a mature test suite, the goal is typically to run it within a continuous delivery pipeline on different development environments, for example staging, user acceptance, and live. Often, these environments have different URLs, endpoints, access rules, and configurations. So, it is very convenient if the test framework offers a simple way to keep these configurations inside the test repository and switch easily between them.

Karate offers this as a native functionality as we will see in Chapter 6, More Advanced Karate Features.

Read-eval-print loop

A read-eval-print-loop (REPL) is a programming environment that reads user inputs, then processes and executes them as code snippets and prints the results. Karate has a command-line REPL, which allows test code to be inserted or replaced at runtime, making it easier and faster to develop tests. This can save time that would otherwise be spent modifying, adapting, and executing a complete test scenario repeatedly. The REPL is a main component of Karate’s Visual Studio Code plugin and can also be used for UI tests!

One framework for all

All previously mentioned features are anything but self-evident, and it is an accomplishment not to be undersold that they come together here in one integrated software testing solution!

In this section, we looked at Karate’s main use cases and features that make it stand out from other frameworks. Next, we will turn to an aspect of the framework that is controversial to some testers – the difference between the BDD approach and how Karate takes this idea and changes it.

 

BDD versus Karate

Now that we know about the core ideas and features of the Karate framework, let’s look at how it achieves writing meaningful test scenarios without extensive coding.

What is BDD?

BDD comes from the world of agile software development. It focuses on bringing together the different roles in a software project (for example developers, testers, and project owners) and talking about requirements. These requirements should then be put into clear scenarios so that, later, all roles can take these scenarios as a basis for their work.

A core part of BDD is a ubiquitous and simple DSL that can express desired behavior in natural language and is understood by every team member. Its purpose is to form a basis for the development of new features but also be a clear guideline for testing and acceptance. In the following sections, we will look at one of the most well-known and widely used DSLs – Gherkin.

The Gherkin language

If you have been in touch with the Cucumber Open BDD testing tool (https://cucumber.io/), you will have stumbled across the Gherkin language. Gherkin is a very concise and straightforward way to turn acceptance criteria into understandable and well-structured test scenarios. At its core, it is a plain-text format to describe how a system under test should behave. Cucumber can parse this format and link it to custom test code, so it provides a readable wrapper around the technical implementation of tests. This way, other development and QA team members, as well as people with non-technical roles, can read these specifications and know exactly what is expected from the system.

The following is an example of the contents of a typical Gherkin feature file (named webshop.feature):

Feature: Web shop tests
    @smoketest
    # This is an example comment
    Scenario: Product search works as expected
        Given I am on the Web shop homepage
        And I am logged in
        When I search for 'Packt'
        Then I get a list of items containing 'Packt'

Even though this feature file is taken from a website test (commonly called UI test), Gherkin can be used to describe any behavior of any system under test – potentially even cases that have nothing to do with software at all.

Let’s take a look at the different parts of the preceding file.

Features

Gherkin files have the .feature extension and always start with a Feature: line followed by a description. Each feature file collects test scenarios that belong to a defined generic business case indicated by the given description. In our example, the feature name Web shop tests shows that this is a collection of test cases for our imaginary online store.

Scenarios

A feature can include one or more scenarios that are associated with it. Each scenario is a test case related to a specific business case, user journey, or behavior.

Scenarios are made up of different keywords and parts that we will look at in the following sections.

Tags

Within feature files that contain multiple scenarios, you can use one or more custom tags to further group them into test suites (in our case, the tag @smoketest could mean that the following scenario belongs to a set of small, basic tests that are run after a deployment to quickly verify that our application is usable). In the course of this book, you will see how these can be used to pre-select the tests you want to run at a specific point in your software development lifecycle.

Steps

Scenarios are made up of different steps that are executed from top to bottom. Each one describes either the state of the system under test, certain actions, or assertions. Their generic nature makes them excellent for reuse across multiple test cases.

Keywords can be substituted

From the processing of the scenarios by a Gherkin-based framework, it does not matter at all which keywords are used in which order. They are used solely for comprehensibility and semantic correctness. In any case, you should get into the habit of following these conventions.

Next, let’s look at the different types of Gherkin keywords you can use.

The Given keyword

This keyword indicates the initial state and prerequisites of an application, its user, or data. In our example, Given I am on the Web shop homepage tells us where the users of the application start their journey in this test case. It is deliberately kept simple to increase comprehensibility and does not contain any technical details.

The When keyword

Any interactions with or changes to the system under test start with a When keyword. When I search for 'Packt' describes clearly what the users do and what their intention is but not how the webshop deals with this on a technical level. Later, we will see that Karate bends this core BDD rule and why it does it this way.

The Then keyword

The final part of most test scenarios is one or more assertions to verify a certain outcome or state of the system under test. This is expressed by Then as in Then I get a list of items containing 'Packt'. Again, this clearly states what outcome is expected from the system but not how exactly this is solved by the application.

The And keyword

The And keyword can connect multiple Given, When, or Then lines depending on if there is more than one prerequisite, action, or assertion. It is just “syntactic sugar” to make a scenario more readable.

In our example it connects two Given statements:

  • The user is on the homepage and…
  • …the user is logged in

The But keyword

Like And, the But keyword can be used to connect steps. It is not as common as its counterpart but can express certain conditions better. Take the following, for example:

Given I am on the Web shop homepage

And I am not logged in

That can also be formulated as follows:

Given I am on the Web shop homepage

But I am not logged in

This would emphasize even more that the focus of this test is on an unauthorized user.

Catch-all steps (*)

Gherkin has one more step keyword that all different step types (Given, When, Then, And, and But) can be substituted with. A * step is mostly used when it does not really fit the natural flow of what should be tested but instead contains utility functions or setup code, or helps with debugging test scenarios.

An example is Karate’s print function, which logs a string on the command line for simple tracing of values:

* print "The value of my variable is", myVariable

Here, it does not directly play a role in any part of the tested behavior. Instead, it can be considered as a utility step that still has to follow the chronological sequence of events but could easily be separated from them without affecting the overall test functionality. In Karate, an advantage of this is that these bullet points can be suppressed in the generated test reports, as we will later discover.

Comments

Comments can be used to make certain steps clearer, especially when they contain information that might be hard to understand for newer team members or colleagues that are not as familiar with the tested business domain.

Also, they can be used in case a test is temporarily deactivated to explain further why this was done or what needs to happen before it can be active again.

Comments can be placed anywhere in a Gherkin file. They start with a # symbol (like the # This is an example comment line in the example) and are ignored by Cucumber and Karate alike.

Additional Gherkin syntax

In this section, we only looked at the basic Gherkin keywords that will be necessary in the first steps toward writing test cases.

The Gherkin specification has some more advanced language constructs such as the following:

  • Data tables: For specifying multiple sets of data for a step
  • Example tables: For running scenarios with different sets of data
  • Background scenarios: That define common steps in multiple scenarios
  • Scenario outlines: For combining similar scenarios into one
  • Docstrings: For more complex data definition in a step

All of these will play a role in later chapters when we look at code reuse, keeping tests free from code duplication, and the overall structuring and fragmentation of test suites

Writing good BDD scenarios

When doing BDD, test scenarios should typically have the following characteristics to keep them clear, understandable, and concise across your test suites:

  • Scenarios should be able to run independently: This is important because depending on whether all or just a subset of scenarios is run or if they are run in multiple threads at the same time, we cannot always be sure of the order of execution. That means that if scenarios depend on each other (for example, one that creates a new user and one that deletes the new user), we can run into problems if both are executed at the same time or the wrong way around
  • It makes sense to run scenarios in parallel early on to be sure that they can run without disturbing others.
  • Scenarios should be concise and easy to follow: Your scenarios should not execute too many steps even though the Gherkin format is predestined for easy comprehension of the test cases. This is beneficial for a greater understandability and easier analysis of exactly what happened in case of an error.
  • Scenarios should not test too many different things at the same time: This one is closely related to the second point – understandability. Commonly, a scenario fails as soon as a step fails, skipping all subsequent steps. Therefore, if a scenario tests too many things in succession, hints of faulty functions are lost.
  • Scenarios should not duplicate other scenarios: In many cases, it might not make sense to do the same test repeatedly. For example, if you start multiple tests with the same request to the same API, you don’t necessarily need to check that this API delivers the expected data format in every individual scenario. This might not always apply, for example, when similar tests belong to different test suites that might be run at different points in time.
  • Scenarios should not contain concrete technical information: When writing behavior-driven tests, the focus is on high-level behaviors and how a system is interacted with. There should not be any references to implementation details or certain elements a user interacts with. The basic idea is to describe what should be done, but not how.

Karate is not true BDD

Almost all these points are valid tips for writing good Karate tests. However, the last guideline (“Scenarios should not contain concrete technical information”) is one that we will revisit later in this chapter. Karate’s idea is radically different in this regard, and we will see both why this makes sense and why the framework has moved away from BDD altogether.

Now that we have an idea about BDD and the Gherkin language, let’s see in the next section how Gherkin statements can be linked to source code.

Glue code

So-called glue code builds the bridge between the Gherkin steps and the implementation of concrete test code (it glues these two together). This is how the test framework can execute the functions matching the respective step including the passed parameters.

Let’s look at an example implementation of this part of the scenario:

Given I am on the Web shop homepage
When I search for 'Packt'

First, we will look at how Cucumber deals with glue code so that we can better compare it to Karate’s approach afterward.

Cucumber glue code

The general mechanism of Cucumber-based frameworks is working by linking steps whose names fit predefined Cucumber expressions (https://github.com/cucumber/cucumber-expressions#readme) that are assigned to certain Java functions by annotations. In older versions of Cucumber, this matching of steps to glue code was done via regular expressions (https://en.wikipedia.org/wiki/Regular_expression), but Cucumber expressions turned out to be way easier to use when implementing glue code yourself:

Package blog.softwaretester.gherkin;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
public class StepDefinitions {
    @Given("I am on the Web shop homepage")
    public void goToHomepage() {
        System.out.println("Go to homepage");
    }
    @When("I search for {string}")
    public void search(final String searchTerm) {
        System.out.println("Search for " + searchTerm);
    }
}

The goToHomepage() function is invoked when Cucumber encounters a step definition that matches the @Given("I am on the Web shop homepage") annotation. It is good to know that, even though the @Given annotation is used here, this matches any other keyword, too, if the following text part is the same.

It is analogous to the step after that: search(final String searchTerm) is connected by the @When("I search for {string}") annotation. It is noteworthy that here, a dynamic parameter exists that can be any string (defined by the {string} placeholder) so that the following is true:

  • This string parameter can be passed from the scenario step to the connected function (in our example, searchTerm)
  • It can match any string so that here you avoid having to write a new function for each value – this ensures efficient code reusability

Demo steps

Please note that in the preceding method implementations, the steps do not have any concrete functionality except for printing out a message in order to show they are really being invoked.

When running the preceding example in Cucumber, we can see in the console log that this connection works as expected:

[INFO] Running blog.softwaretester.gherkin.RunCucumberTest
Go to homepage
Search for Packt

The complete example can be found at https://github.com/PacktPublishing/Writing-API-Tests-with-Karate/tree/main/chapter01/cucumber-glue-example.

Now that we know how Cucumber handles glue code, let’s check out why Karate separated from Cucumber and implemented its own approach.

The Karate way

Karate uses essentially the same mechanism and concepts as Cucumber but with some interesting differences.

Up until version 0.9.0 of Karate, it was based on Cucumber because of its rich feature set and very good support in common integrated development environments (IDEs). However, Peter Thomas decided in 2018 to separate from Cucumber while keeping Karate fully compatible.

The main reasons for this decision were that Karate should not be dependent on the timeline, priorities, and feature set of Cucumber but instead have the freedom to move ahead with development at a faster pace. Basically, development is more gradual with the Cucumber framework because it must support and coordinate many different language bindings. Since Karate supports only one programming language, there is of course a speed advantage.

Also, this move allowed Karate to control all phases of the test lifecycle, including reporting, and not be tied into the existing Cucumber infrastructure, specifications, and technologies.

Karate, as we have seen, borrows Gherkin but explicitly does not use BDD. The reasoning behind this is that Karate tests are not specifically aimed at non-technical roles but instead at testers and developers with a more technical background.

Peter Thomas explains it like this:

Karate makes sense especially for “platform” teams creating and maintaining web-services, and where product-owner involvement in acceptance-testing is not the highest priority.

Thomas, P. (2017). Karate is not true BDD, https://medium.com/hackernoon/yes-karate-is-not-true-bdd-698bf4a9be39.

Using Gherkin as a test DSL is intended to simplify testing and not just bluntly repeat what other frameworks already provide anyway.

Now, let’s look at an example of how Karate handles glue code internally.

Karate glue code

Karate provides common predefined steps plus the matching glue code directly inside the framework. That means that you do not have to write any code in many cases since the steps you need are already implemented.

Some steps go way beyond the simple conversion of string arguments into primitive method parameters but instead process those further. This makes it possible to use steps that contain JavaScript, JSONPath or XPath expressions, Java function calls, and more. We will see the details of this approach when we deal with this in Chapter 3, Writing Karate Tests.

We can check how this is done by looking at the internal implementation of a scenario step, in this case, Karate’s print statement:

* print "The value of my variable is", myVariable

In Karate’s ScenarioActions class (available in its GitHub repository https://github.com/karatelabs/karate), we find this piece of code that connects the preceding scenario step to the glue code:

@Override
@When("^print (.+)")
public void print(String exp) {
    engine.print(exp);
}

We can clearly see that this is done in analogy to Cucumber. The only differences are that this implementation is predefined and uses a regular expression instead of a Cucumber expression. In this example, the statement "^print (.+)" means find a line starting with print (^print), take everything that follows, and interpret it as a parameter ((.+)). Like in a Cucumber expression, the parameter is then passed on to a function that can process it.

Note

This was just an example to illustrate the inner workings of the framework. You will most likely never be in touch with this kind of code again when authoring software tests with Karate!

The downside of this approach of embedding glue code within the framework should not remain unmentioned. It basically means that this functionality is locked away and cannot be changed anymore by the framework users. Also, adding your own glue code is not possible like it would be in a Cucumber-based framework. Not only is this not available, but it is also not desired by the authors of the framework, as this could violate Karate’s conventions and lead to unforeseen errors. Since Karate’s step implementations are very flexible as they are, they can potentially cover just about any use case without ever needing to be extended with custom glue code anyway.

The overall goal is to keep the framework simple and consistent and limiting the possibilities can be seen as an advantage here.

In this chapter, we covered BDD, the Gherkin language elements, and its technical implementation in Cucumber and Karate. Also, we talked about why and how Karate deviated from Cucumber in some core ideas. Now, let’s look at the different data types that Karate can work with and how this makes it a big strong point for this framework.

 

Supported data types in Karate

One of the strengths of the Karate framework is its native support for a variety of different data types that are typically associated with API payloads and responses. That means that it is possible to use them in their original form within test scripts without the need of escaping certain characters or converting them to be usable.

Let’s look at some widely used data formats here and the way they would represent data about this book and the first chapter for comparison.

JSON

JSON is pretty much the standard exchange format for REST APIs. Additionally, it is the standard format for GraphQL. It is small, structured, and human-readable while being a great format to work with JavaScript because it can be used natively there. This is a simple JSON example that shows how data can be represented by nesting keys and values:

{
    "book": {
        "title": "Writing tests with Karate",
        "author": "Benjamin Bischoff",
        "chapters": [{
            "number": "1",
            "title": "Karate's core concepts"
        }]
    }
}

This is the format we will encounter most throughout the book, as Karate can also represent other formats through JSON and make them testable.

GraphQL

GraphQL was developed by Facebook and released to the public in 2015. In 2018, it was transferred to the newly formed GraphQL foundation under the Linux Foundation (https://www.linuxfoundation.org/).

GraphQL’s request and response format is JSON. Contrary to a REST API that always returns fixed data structures, users can define exactly what data they need in each request and only the requested data is then returned. This saves bandwidth and enables fetching deeply nested data without making multiple requests in a row. From a structural point of view, the only thing different from JSON responses is the added data object that wraps the expected JSON response:

{
    data: {
        "book": {
            "title": "Writing tests with Karate",
            "author": "Benjamin Bischoff",
            "chapters": [{
                "number": "1",
                "title": "Karate's core concepts"
            }]
        }
    }
}

In Chapter 6, More Advanced Karate Features, we will check out how to handle this within the Karate framework.

XML

Like JSON, Extensible Markup Language (XML) is another human-readable format but with some more overhead for the same set of data. Karate handles this format equally well, though:

<?xml version="1.0" encoding="UTF-8" ?>
<book>
    <title>Writing tests with Karate</title>
    <author>Benjamin Bischoff</author>
    <chapters>
        <chapter>
            <number>1</number>
            <title>Karate&#x27;s core concepts</title>
        </chapter>
    </chapters>
</book>

You can see that XML is more redundant than JSON because it uses similarly named opened and closed tags (e.g., <title> and </title>) to enclose values.

YAML

Yet another markup language (YAML) has a very minimalistic, indentation-based syntax. It is a rather new format that gained popularity mainly for its use in configuration files. The book example would look as follows, making this the most readable (but also error prone) format of them all:

---
book:
    title: Writing tests with Karate
    author: Benjamin Bischoff
    chapters:
        - number: 1
          title: Karate's core concepts

Karate can work with the YAML format easily by automatically converting it into JSON!

CSV

Comma-separated values (CSV) files contain rows of data that are separated by line breaks. Each line is a dataset (or record) in which values are typically delimited by commas. It is often used as a data exchange format from and to spreadsheets, such as Excel:

title,author,chapter/number,chapter/title
Writing tests with Karate,Benjamin Bischoff,1,Karate's core concepts

Like YAML, Karate converts CSV into JSON arrays automatically!

Other text-based formats

Luckily, Karate supports all textual formats. For those that are not included natively, we are free to use generic strings. However, depending on how obscure the format in question is, we need to write our own Java or JavaScript handling for such edge cases.

Binary formats

Through Karate’s Java interoperability, it is possible to handle virtually any binary file format. Additionally, Karate has the special bytes type to convert any binary data into standard byte arrays to use as payloads.

If you need to use websocket connections that use binary data, there is even a dedicated built-in method available, karate.webSocketBinary().

In this section, we have seen the different data formats that Karate can understand and work with. You can probably already see how powerful this framework is. Next, we will check how Karate’s JavaScript engine helps even further with this.

 

The JavaScript engine

Karate’s JavaScript engine is what really distinguishes this framework from many others. It is built on GraalVM (https://www.graalvm.org/), which allows so-called polyglot programming. This means that it can mix and match different programming languages together in a single application and even pass values back and forth. This makes it possible to use native JavaScript code both directly embedded into feature files, within Karate’s main configuration, or even stored in external files.

The direct integration of JavaScript in Karate is especially helpful when working with JSON and similar formats. This format is a first-class citizen in JavaScript whereas in Java you would need additional libraries to effectively work with it (for example, Gson or Jackson). This enables test authors to directly write JSON in steps without the need to escape or encode certain characters. It also allows for more straightforward assertions and matching by the direct integration of JSONPath as we will see further on.

In Chapter 7, Extending Karate Functionality, we will explore how JavaScript can be used to customize and simplify more complex validations, matching, or data manipulations.

The JavaScript engine is only one of the parts that power Karate’s internals. Let’s now look at the other one: Java itself.

 

Java interoperability

As we have already learned, despite Karate’s close relationship with JavaScript, it is purely written in Java. This ensures that it is fast, concise, and runs on virtually any local system, CI/CD servers, and clouds. It works perfectly with the Maven build system, which we will use in the next chapter to set up our Karate project. Java also offers mature development tools, extensions, and libraries to enable rapid implementation.

Running unit tests is also very easy and tightly integrated with virtually all common IDEs so that we can check test results directly there without switching between tools.

Additionally, the direct Java access allows for some interesting functionalities that open a whole new world in terms of Karate testing. Since Java has tons of specialized libraries and built-in features for common business-related tasks (for example, database access through Hibernate), we can use these directly. This is a great example of the “use the right tool for the job” mantra – we can use JavaScript or Java, whichever can handle the task better!

As we will explore further in Chapter 7, Extending Karate Functionality, Karate can call Java methods and utilities via JavaScript, which makes this a very powerful and easy-to-extend feature.

 

Summary

In this chapter, we talked about why the Karate framework was developed and the many features and possibilities it has that help write expressive yet simple test cases. Additionally, we learned about the keywords and structure of Gherkin files and explored why Karate adapted this language but not the BDD standard itself.

In Chapter 2, Setting Up Your Karate Project, we will look at how to set up the development environment to be fit for Karate and the various ways to start a new Karate project from scratch using Karate standalone and Maven.

You will learn step-by-step how to configure the necessary environment and IDE plugins to streamline your development experience and make testing fun. Also, we will look at some unique features that are only available in the Karate plugins for Visual Studio Code and IntelliJ IDEA.

About the Author
  • Benjamin Bischoff

    After being a game/application developer and trainer for 15 years, Benjamin decided in 2017 to make test automation his main career. Currently, he works as a Test Automation Engineer (SDET) in trivago's core QA team. His focus lies on the development and maintenance of trivago's in-house end-to-end test framework and related build pipelines as well as developing back-end and API automation solutions. Benjamin is the author and maintainer of two open source projects for Cucumber BDD parallel test execution and reporting. Also, he is a conference speaker and writes about testing and automation topics.

    Browse publications by this author
Writing API Tests with Karate
Unlock this book and the full library FREE for 7 days
Start now