Peter Thomas | Architect | Intuit
@ptrthomas | @KarateDSL
Karate
Web Service API Testing Made Simple
Intuit Open Source
Released 09-Feb-2017
A DSL for writing web-service acceptance tests
Built on Cucumber | BDD syntax
Karate github.com/intuit/karate
3
Karate in the top 5 OSS API Testing Tools (TechBeacon)
Tool Inception Years
REST-assured 2010 7
Postman 2012 5
SoapUI 2005 12
JMeter 1998 19
Karate 2017 0.5
4
• Easier to Write
• Readable and Concise
• Faster Execution
• Better Assertions
• Integrates into existing CI / CD
API-tests with Karate
Developer
Productivity
Maintain-
ability
Quality
5
Many teams use Java for writing HTTP-API regression tests.
Java is not the best language to manipulate JSON / XML.
Consequences:
• Over-dependence on Java objects for building and validating
data-payloads
• Object-equality checks done by hand, effort-intensive
• So tests end-up taking “short-cuts”, and don’t validate the full
response, coverage & quality suffers
• Proliferation of helper methods, code bloat & in-house layers
• Result: poor Dev Productivity & Maintainability
Current State of Web-API Testing
• DSL laser-focused on HTTP
• JSON and XML are “first-class”
citizens of the syntax
• Compare deeply-nested payloads in
a single step
• 3:1 Reduction in Lines of Code
• Tests are super-readable and
concise
• Testing is Easier & actually Fun
Karate’s Solve
6
Scenario: create and retrieve a cat
Given url 'http://myhost.com/v1/cats'
And request { name: 'Billie' }
When method post
Then status 201
And match response == { id: '#notnull', name: 'Billie' }
Given path response.id
When method get
Then status 200
Hello World
Intuitive DSL
for HTTP
Payload
assertion in one
line
Second HTTP
call using
response data
JSON is ‘native’
to the syntax
7
Java
vs
JSON
8
Validation examples: JsonPath & RegEx
Type Directive
Ignore / Exists #ignore | #null | #notnull
Primitive Type #boolean | #number | #string
Complex Type #array | #object
Special #uuid
RegEx #regex <regex string>
Predicate #? <expression>
9
JSON ‘templating’
Type Directive
Replace #(<expression>)
10
XML and XPath
11
Standard form In-line form
* match foo[0] == exact * match foo[0] == '#(exact)'
* match foo[0] contains partial * match foo[0] == '#(^partial)'
* match foo[0] !contains nope * match foo[0] == '#(!^nope)'
* match each foo == exact * match foo == '#[] exact'
* match each foo contains partial * match foo == '#[] ^partial'
* match each foo !contains nope * match foo == '#[] !^nope'
* match foo contains only reversed * match foo == '#(^^reversed)'
* match foo contains first * match foo == '#(^first)'
* match foo !contains others * match foo == '#(!^others)'
* assert foo.length == 2 * match foo == '#[2]'
Schema Validations
12
Comparison with REST-assured
http://tinyurl.com/karateraREST-assured Karate
Plain Text ❌ (needs compilation) ✅
Parallel Execution ? (partial) ✅
Data Driven Testing ❌ (needs TestNG etc.) ✅ (built-in)
Environment Switching ❌ ✅ (built-in)
Match full payload in one step ❌ ✅
Update JSON payload / object ❌ ✅
@Test public void
lotto_resource_returns_200_with_expected_id_and_winners() {
when().
get("/lotto/{id}", 5).
then().
statusCode(200).
body("lotto.lottoId", equalTo(5),
"lotto.winners.winnerId", containsOnly(23, 54));
Scenario: lotto resource returns 200 with expected id and winners
Given path ‘lotto’, 5
When method get
Then status 200
And match $.lotto.lottoId == 5
And match $.lotto.winners[*].winnerId contains only [23, 54]
given().
param("key1", "value1").
param("key2", "value2").
when().
get("/somewhere").
then().
body(containsString("OK"));
Given param key1 = ‘value1’
And param key2 = ‘value2’
And path ‘somewhere’
When method get
Then response contains ‘OK’
Detailed Comparison
13
14
Metrics – port of an open-source example
Reduction of lines of code from 431  67
Link: https://github.com/mwinteringham/api-framework/pull/3
15
Components
Karate DSL interpreter
(Cucumber “Step Definitions”)
HTTP Client Abstraction
JSON XML
JS
Engine
(Nashorn)
Karate ScriptJUnit / Test
NG
(Runner)
Java8JRE
HTTP/S calls
Cucumber-
JVM
Data / Assertions
match, get, set
Reports
Apache Jersey
Mock
Servlet
16
The “missing” Cucumber Features that Karate adds
Capability Cucumber Karate
Step Definitions built-in, no Java code needed ❌ ✅
Re-Use Feature files from other Features ❌ ✅
Dynamic Data-Driven Testing ❌ ✅
Parallel Test Execution and Reporting ❌ ✅
Option to run routines only once per Feature ❌ ✅
17
Example Report
18
• Scripts are plain-text, no compilation or IDE required
• REST as well as SOAP support
• Assert, manipulate, compare and re-use JSON / XML
• User defined functions (Java or JavaScript)
• Configuration switching (e.g. dev | e2e | pre-prod)
• Simple ‘plug and play’ HTTP Header & Auth management
• Comprehensive HTTP support: SSL, Proxy, File-Upload
• JUnit XML reports compatible with all CI tools
• Speed - Parallel Execution of Tests
• Mock Servlet – test without starting a container
Karate Features
BDD
Full HTTP
CI / CD
Ready
Demos
Q & A
https://github.com/intuit/karate
@ptrthomas | @KarateDSL
Thank You !
Extra Slides
22
Karate UI (Alpha)
23
CI Report
(Jenkins)

Karate - MoT Dallas 26-Oct-2017

  • 1.
    Peter Thomas |Architect | Intuit @ptrthomas | @KarateDSL Karate Web Service API Testing Made Simple
  • 2.
    Intuit Open Source Released09-Feb-2017 A DSL for writing web-service acceptance tests Built on Cucumber | BDD syntax Karate github.com/intuit/karate
  • 3.
    3 Karate in thetop 5 OSS API Testing Tools (TechBeacon) Tool Inception Years REST-assured 2010 7 Postman 2012 5 SoapUI 2005 12 JMeter 1998 19 Karate 2017 0.5
  • 4.
    4 • Easier toWrite • Readable and Concise • Faster Execution • Better Assertions • Integrates into existing CI / CD API-tests with Karate Developer Productivity Maintain- ability Quality
  • 5.
    5 Many teams useJava for writing HTTP-API regression tests. Java is not the best language to manipulate JSON / XML. Consequences: • Over-dependence on Java objects for building and validating data-payloads • Object-equality checks done by hand, effort-intensive • So tests end-up taking “short-cuts”, and don’t validate the full response, coverage & quality suffers • Proliferation of helper methods, code bloat & in-house layers • Result: poor Dev Productivity & Maintainability Current State of Web-API Testing • DSL laser-focused on HTTP • JSON and XML are “first-class” citizens of the syntax • Compare deeply-nested payloads in a single step • 3:1 Reduction in Lines of Code • Tests are super-readable and concise • Testing is Easier & actually Fun Karate’s Solve
  • 6.
    6 Scenario: create andretrieve a cat Given url 'http://myhost.com/v1/cats' And request { name: 'Billie' } When method post Then status 201 And match response == { id: '#notnull', name: 'Billie' } Given path response.id When method get Then status 200 Hello World Intuitive DSL for HTTP Payload assertion in one line Second HTTP call using response data JSON is ‘native’ to the syntax
  • 7.
  • 8.
    8 Validation examples: JsonPath& RegEx Type Directive Ignore / Exists #ignore | #null | #notnull Primitive Type #boolean | #number | #string Complex Type #array | #object Special #uuid RegEx #regex <regex string> Predicate #? <expression>
  • 9.
  • 10.
  • 11.
    11 Standard form In-lineform * match foo[0] == exact * match foo[0] == '#(exact)' * match foo[0] contains partial * match foo[0] == '#(^partial)' * match foo[0] !contains nope * match foo[0] == '#(!^nope)' * match each foo == exact * match foo == '#[] exact' * match each foo contains partial * match foo == '#[] ^partial' * match each foo !contains nope * match foo == '#[] !^nope' * match foo contains only reversed * match foo == '#(^^reversed)' * match foo contains first * match foo == '#(^first)' * match foo !contains others * match foo == '#(!^others)' * assert foo.length == 2 * match foo == '#[2]' Schema Validations
  • 12.
    12 Comparison with REST-assured http://tinyurl.com/karateraREST-assuredKarate Plain Text ❌ (needs compilation) ✅ Parallel Execution ? (partial) ✅ Data Driven Testing ❌ (needs TestNG etc.) ✅ (built-in) Environment Switching ❌ ✅ (built-in) Match full payload in one step ❌ ✅ Update JSON payload / object ❌ ✅ @Test public void lotto_resource_returns_200_with_expected_id_and_winners() { when(). get("/lotto/{id}", 5). then(). statusCode(200). body("lotto.lottoId", equalTo(5), "lotto.winners.winnerId", containsOnly(23, 54)); Scenario: lotto resource returns 200 with expected id and winners Given path ‘lotto’, 5 When method get Then status 200 And match $.lotto.lottoId == 5 And match $.lotto.winners[*].winnerId contains only [23, 54] given(). param("key1", "value1"). param("key2", "value2"). when(). get("/somewhere"). then(). body(containsString("OK")); Given param key1 = ‘value1’ And param key2 = ‘value2’ And path ‘somewhere’ When method get Then response contains ‘OK’ Detailed Comparison
  • 13.
  • 14.
    14 Metrics – portof an open-source example Reduction of lines of code from 431  67 Link: https://github.com/mwinteringham/api-framework/pull/3
  • 15.
    15 Components Karate DSL interpreter (Cucumber“Step Definitions”) HTTP Client Abstraction JSON XML JS Engine (Nashorn) Karate ScriptJUnit / Test NG (Runner) Java8JRE HTTP/S calls Cucumber- JVM Data / Assertions match, get, set Reports Apache Jersey Mock Servlet
  • 16.
    16 The “missing” CucumberFeatures that Karate adds Capability Cucumber Karate Step Definitions built-in, no Java code needed ❌ ✅ Re-Use Feature files from other Features ❌ ✅ Dynamic Data-Driven Testing ❌ ✅ Parallel Test Execution and Reporting ❌ ✅ Option to run routines only once per Feature ❌ ✅
  • 17.
  • 18.
    18 • Scripts areplain-text, no compilation or IDE required • REST as well as SOAP support • Assert, manipulate, compare and re-use JSON / XML • User defined functions (Java or JavaScript) • Configuration switching (e.g. dev | e2e | pre-prod) • Simple ‘plug and play’ HTTP Header & Auth management • Comprehensive HTTP support: SSL, Proxy, File-Upload • JUnit XML reports compatible with all CI tools • Speed - Parallel Execution of Tests • Mock Servlet – test without starting a container Karate Features BDD Full HTTP CI / CD Ready
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

Editor's Notes

  • #7 Points to call out: No syntax “noise” JSON in-line, first-class citizen, no “escaping” Carefully crafted DSL for HTTP, the keywords are intuitive for someone who knows HTTP / REST Full-payload assertion in one line, and the ability to ignore dynamic server-side generated values at the same time.
  • #8 This shows how many lines of Java code are required for what is a “one-liner” in Karate. It also makes clear how easy it is to express data in JSON. The “impedance mismatch” between Java and JSON is clear. This is one of the reasons people find JS easier to work with and why NodeJS became so popular.
  • #13 Link to the detailed comparison (living) document: http://tinyurl.com/karatera Link to twitter thread where the creator of REST-assured weighed in: https://twitter.com/johanhaleby/status/846412707364552705
  • #14 Karate’s closest competitor is REST-Assured. This is a side-by-side comparison of a test in REST-Assured (plus TestNG) after porting to Karate. The example shows off Karate’s data-driven testing capability. Again, the readability and lack of “noise” stands out. RestAssured: http://bit.ly/2kGxiU0 Karate: https://gist.github.com/ptrthomas/0f5c00582b345a74d20261fb346225d0
  • #16 Things to call out: - re-use of Cucumber for syntax and unit-test / report integration - pluggable “future-proof” HTTP client abstraction Nashorn is the “secret sauce” that bridges the world of Java and JS and allows for easy user-defined functions & pluggability, without the need to re-compile any code JSON and XML are “first class” citizens with “equal rights”