Introducing API Contract
and Localhost UI Tests
Kenneth Poon
https://medium.com/@kennethpoon
App Development Integration Tests
https://medium.com/@kennethpoon
https://github.com/depoon
Kenneth Poon
https://sg.linkedin.com/in/kenneth-poon-84217019
de_poon@hotmail.com
Principal Software Engineer @ SP Digital
Agile Development in iOS Development Space
Tech talk contributor in iOS Dev Scout Meetup group in Singapore
About me
Testing Testing
Past talks
https://engineers.sg/presenter/kenneth-poon--533
Testing
iOS Dev Scout
Meetup
iOS Conf SG 2019
Agile Singapore
Testing
Mobile Conf TH
Past talks
https://engineers.sg/presenter/kenneth-poon--533
iOS Dev Scout
Meetup
HackingHacking
Development
Agenda
Contract Tests (Ruby) - Cucumber API
Background and motivation for this sharing this talk
Localhost UI Test (iOS) - Swift Localhost
Background and Motivation
J2EE -> iOS Development
Not much iOS Test + CI Practices out there (2010)
Sinatra (Ruby)Calabash (Ruby) Cucumber (Ruby)
SwiftLocalhost (Swift)Cucumberish (Swift)
Life of a Mobile Developer
Mobile Developer Backend EngineerQA
I’m a mobile developer.
In terms of testing, I
write Unit tests to
ensure that my
modules are working
as expected.
I will also ensure that I
achieve high code
coverage for my native
app codes
I’m a QA engineer. I take
ownership of mobile
E2E tests.
When the mobile app
build is ready , I will
verify it in our test/QA
environment
I’m a backend engineer.
I write tests that cover
the behaviour of the
services I build.
Life of a Mobile Developer
Mobile Developer Backend Engineer
API Contract
Feature

1
Not Readyv1
v1
Life of a Mobile Developer
Mobile Developer Backend EngineerAPI Contract
Feature

1
v1
v1
Life of a Mobile Developer
Mobile Developer Backend EngineerAPI Contract
Feature

1
v1
v1
V2
v1
App Breaks - API Contract
• Contract definition has changed
• Backend Engineer may not be
aware of what services app is
consuming
• QA may only find out after running
test suite
APPLICATION
BREAKS
QA: WHAT’S HAPPENING!!
Life of a Mobile Developer
Mobile Developer
Feature

1
Life of a Mobile Developer
Mobile Developer
Feature

1
Database 3rd Party Services
App Breaks - Dependencies
• Services down
• Test Data Fixtures are not
synced up
• Engineers may only discover
broken dependencies by
running E2E tests
APPLICATION
BREAKS
QA: My E2E Tests
failed again!

What is happening
this time?
Life of a Mobile Developer
Mobile Developer QA
Life of a Mobile Developer
Mobile Developer QA
Dev, the app is breaking
very often in Test/
Staging environment
Sorry about it, QA.

My native code is
fine. It seems like
the backend
services are down
at the moment
Grrr.. it took me an hour
of tests execution just
to discover that that.
This is driving me crazy.
Other times, the backend engineer
unknowingly changed the API schema I understand but I will always find
you first whenever I discover any of
these issues.
Hmmm… let me come up with a
solution for this
About End-to-End Tests
QA
As QA, we own and take responsibility in the development
and maintenance of the mobile E2E tests
But E2E tests are very brittle
Mobile Apps typically have multiple dependencies
Difficult to write tests that are dependent on shared
resources
E2E Tests are generally slow and expensive
Even if we can write E2E tests, we may not be
able to achieve comprehensive UI Automation
test coverage
Test Pyramid
Unit Tests
E2E Tests
Integration
Tests
XCUITest / Appium
XCTest / JUnit
API Contract Tests
Mock Response Tests
Integration Tests
Api Contract Tests
Mock
Mock Response Tests
Mock
Localhost
Localhost XCUITest - iOS SwiftLocalhost
Setup 

Swift Localhost
Tests
Unit Tests
E2E Tests
Integration
Tests
Mock Response Tests
L
A
I
M
[Localhost] Setup in-memory localhost server
[API] Redirect API calls to localhost server
[Info.plist] Patch Info.plist
[Mock] Setup mock responses
Setup Localhost
Setup Localhost - [Localhost]
Localhost
Server
Use a unique port number
Setup an in-memory server in the test runner
Setup and tear down localhost server when
executing each test
import XCTest
class MovieListTest: XCTestCase {
}
import SwiftLocalhost
var localhostServer: LocalhostServer!
override func setUp() {
}
self.localhostServer =
LocalhostServer(portNumber: 9001)
self.localhostServer.startListening()
override func tearDown() {
}
Setup Localhost - [Localhost]
self.localhostServer.stopListening()
self.localhostServer =
LocalhostServer.initializeUsingRandomPortNumber()
Setup Localhost - [API]
Localhost
Server
Actual
Server
Update URL Domain to localhost

(with port number)
private let baseUrl: String = "http://localhost:9001/3/movie"
Setup Localhost - [API]
class NetworkOperations {
}
private let baseUrl: String = "https://api.themoviedb.org/3/movie"//private let baseUrl: String = "https://api.themoviedb.org/3/movie"
Setup Localhost - [Info.plist]
Localhost
Server Update Info.plist
iOS >=10
iOS 9
path["/login"] = {

“status" = "login successful"

}
path["/movies"] = [

{

"title": "Batman",

"subtitle": "XXX"

},

{

“title": "Matrix",

"subtitle: "YYY"

},

]
Setup Mock
Responses
Setup Localhost - [Mock]
Localhost
Server
func testMoviePopularList() {



}




XCUIApplication().launch()
//Add XCUITest Codes
Setup Localhost - [Mock]




self.localhostServer.route(method: .GET,
path: "/3/movie/popular",
responseJsonFileName: "home_popular")


Asserting
Localhost
Requests
Unit Tests
E2E Tests
Integration
Tests
Mock Response Tests
List
Asserting Localhost Requests
Use case
1. Listing View
Item List Request
Localhost Requests
Asserting Localhost Requests
Use case
1. Listing View
2. Detail View Item List Request
Localhost Requests
Detail
Item Detail Request
Asserting Localhost Requests
Use case
1. Listing View
2. Detail View Item List Request
Localhost Requests
Detail
Item Detail Request
3. Bookmark Item
Bookmark Item Request
Expected Requests Order
Asserting Localhost Requests
public class LocalhostServer {
public var recordedRequests: [URLRequest]
}
LocalhostServer records all received URLRequest(s)
Asserting Localhost Requests
//#### By URL Paths---------




let expectedRequestPaths: [String] = [
"/3/movie/popular",
"/identitytoolkit/v3/relyingparty/verifyPassword",
"/identitytoolkit/v3/relyingparty/getAccountInfo"
]






let actualRequestPaths = self.localhostServer.recordedRequests.map {
return $0.url!.path
}






XCTAssertEqual(expectedRequestPaths, actualRequestPaths)


let expectedCURLs: [String] = [
"curl -X GET ’http://localhost:9001/3/movie/popular?api_key=71b'",
"curl -X POST ’http://localhost:9001/relyingparty/verifyPassword?
key=AIzaSy' -d '{n "email" : "apple@gmail.com",n "password" :
"password"}'",
"curl -X POST ’http://localhost:9001/relyingparty/getAccountInfo?
key=AIzaSy' -d '{n "idToken" : "eyJhbj"n}'"
]




let expectedCURLs: [String] = [
"curl -X GET ’http://localhost:9001/3/movie/popular?api_key=71b'",
"curl -X POST ’http://localhost:9001/relyingparty/verifyPassword?
key=AIzaSy' -d '{n "email" : "apple@gmail.com",n "password" :
"password"}'",
"curl -X POST ’http://localhost:9001/relyingparty/getAccountInfo?
key=AIzaSy' -d '{n "idToken" : "eyJhbj"n}'"
]




let actualCURLs = self.localhostServer.recordedRequests.map {
return $0.cURL(withHeaders: false)
}
Asserting Localhost Requests
//#### By describing cURL commands ---------








XCTAssertEqual(expectedCURLs, actualCURLs)


let expectedCURLs: [String] = [
"curl -X GET ’http://localhost:9001/3/movie/popular?api_key=71b'",
"curl -X POST ’http://localhost:9001/relyingparty/verifyPassword?
key=AIzaSy' -d '{n "email" : "apple@gmail.com",n "password" :
"password"}'",
"curl -X POST ’http://localhost:9001/relyingparty/getAccountInfo?
key=AIzaSy' -d '{n "idToken" : "eyJhbj"n}'"
]


https://github.com/mkamhawi/ios-movies-app [orginal]
Special Thanks to

Mohamed El-Kamhawi
https://github.com/depoon/ios-movies-app [forked]


Swift Localhost
Demo
Unit Tests
E2E Tests
Integration
Tests
Mock Response Tests
FAQ on Localhost UITests
Why can’t we add stub responses in the code?
Localhost
Server
Mock
HTTP
TCP
HTTP
TCP
Mock

Response
FAQ on Localhost UITests
Swift Localhost Vapor (Swift)
WireMock (Java)
Typicode (JS)
Sinatra (Ruby)
What are the advantages of using Swift Localhost over other localhost
web server solutions?
FAQ
Swift Localhost
Vapor (Swift)
WireMock (Java)
Typicode (JS)
Sinatra (Ruby)
What are the advantages of using Swift Localhost over other localhost
web server solutions?
FAQ on Localhost UITests
Swift Localhost
Vapor (Swift)
WireMock (Java)
Typicode (JS)
Sinatra (Ruby)
What are the advantages of using Swift Localhost over other localhost
web server solutions?
Advantages
✓ Easy Installation and Setup via Cocoapods

✓ Use Swift to setup mock server

✓ In line mock responses in the same test scope

✓ Use same runtime XCode debugger

✓ Ctrl + U
FAQ
How does the Localhost UITest technique fit in my development
process?
List
2. Fetch list of items using server/list api
1. Navigate to List view
3. Tap on 1st Item. App navigates to Detail view
4. Fetch item detail using server/detail api
5. Bookmark item
6. Bookmark item detail using
server/bookmark api
Bookmarking Use Case
DetailDetail
server/list
server/detail
server/bookmark
7. Assert Bookmark Icon is correctly reflected
FAQ
How does the Localhost XCUITest technique fit in my development
process?
Detail
server/list
server/detail
server/bookmark
Localhost Mock Responses
Test Case
1. Navigate to List view
2. Tap on 1st Item. App navigates to Detail view
3. Bookmark item
4. Assert Bookmark Icon is correctly reflected
Never Ever Fails
✓ Early Development
✓ Use Case Wont Fail
API Contract
Tests
Unit Tests
E2E Tests
Integration
Tests
API Contract Tests
API Contract Tests
Mobile Developer QA
Dev, I know it’s great
that you have Mock
Response Tests that
never fails.
But the APIs do change
and they might break
the app.
Yes, QA. You are
absolutely right
API Contract
v1
But our app
releases are
bounded by the
pre-agreed
APIContracts
We can write a script to ensure the
APIs are working as agreed upon
We can use this script to discover
which services are affecting the app.
API Contract Tests
API Contract
v1
API Contract Tests
API Contract
v1 /v1/login -> schema1_v1
/v1/shoppingList -> schema2_v1
/v1/productDetails -> schema3_v1
/v1/productDetails -> schema4_v1
API Contract Script
v1 v1.1 V2
/v1/productDetails -> schema3_v2
Mobile Developer
Gotcha! Latest
API deployment
broke our app
API Contract Tests
Backend Engineer
Hey Mobile Dev,
Why are you writing
tests against my
API? Shouldn’t I be
the one responsible
for that?
Mobile Developer
Our app will
perform correctly
only when
dependent services
are working as
expected.
Our API Contract tests will give you quick feedback
whenever deployed services break the contracts
Mobile developers will be responsible to maintain
tests that describe the services the app consume.
API Contract Tests
Backend Engineer
That sounds
awesome to me.
You know what? I
think we should
automatically
trigger the API
Contract tests
every time we
deploy any changes
Mobile Developer
Nice! This encourages backend developers to
deploy changes without worrying whether it
will affect the mobile app clients.
… BECAUSE WE WILL CATCH ANY BREAKING CHANGES
API Contract Tests
Mobile Developer QA
Dev, I feel annoyed that
after running my tests, I
discover my test
fixtures are not ready
(or incorrect).



eg. Login credentials,
Product Details on
Staging environment
are incorrect
Your test cases
actually describe
the request/
response exchange
that will be
expected.
We can write API Contract tests that chain the order
of API requests that simulates a use case on the app
You can simply run the API Contract tests before any
automated/manual execution of tests. This will give
you a headsup whether your tests will fail
Since API Contract tests are generally fast, you will
get your feedback in no time.
Wow, this sounds
awesome. I am
eager to have a go
at it
Introducing

Cucumber API
Unit Tests
E2E Tests
Integration
Tests
API Contract Tests
What is your take on API Contract Tests (ACT)
Mobile Developer Backend EngineerQA
ACT checks whether
our app dependencies
are working as
expected.
The contract definition
aids us in designing
our localhost tests
ACT is a cheap and fast
way for QA to ensure
that all dependencies,
including data fixtures
are ready before we
start testing.

The fast feedback saves
us time especially when
we can get feedback
within seconds
With ACT, I have more
confidence to refactor
my code base.



We are now
encouraged to run ACT
tied to released app
versions and check if
older versions will be
broken by new API code
deployments
Closing
Consider having both Mock Response and API Contract Tests
Integration tests are meant to compliment but not replace E2E
API Contract Tests is the low hanging fruit
Confidently run localhost tests to verify that native app codes is
working under normal, valid conditions
It may be difficult (but not impossible) to mock services used by 3rd party
services.
Do visit your existing tools and see how you can bring integration tests
into your development
https://medium.com/better-programming/how-to-import-
swift-urlrequests-into-postman-ef6c65c20834
https://github.com/depoon/SwiftLocalhost
https://github.com/hidroh/cucumber-api
https://github.com/depoon/ios-movies-app
Demo App
Import Swift URLRequests into Postman
Setting up Swift localhost for testing
Cucumber API
References
References
https://bit.ly/2ZbDcA3
https://medium.com/@kennethpoon
Questions

Mobile Development integration tests

  • 1.
    Introducing API Contract andLocalhost UI Tests Kenneth Poon https://medium.com/@kennethpoon App Development Integration Tests
  • 2.
    https://medium.com/@kennethpoon https://github.com/depoon Kenneth Poon https://sg.linkedin.com/in/kenneth-poon-84217019 de_poon@hotmail.com Principal SoftwareEngineer @ SP Digital Agile Development in iOS Development Space Tech talk contributor in iOS Dev Scout Meetup group in Singapore About me
  • 3.
    Testing Testing Past talks https://engineers.sg/presenter/kenneth-poon--533 Testing iOSDev Scout Meetup iOS Conf SG 2019 Agile Singapore Testing Mobile Conf TH
  • 4.
  • 5.
    Agenda Contract Tests (Ruby)- Cucumber API Background and motivation for this sharing this talk Localhost UI Test (iOS) - Swift Localhost
  • 6.
    Background and Motivation J2EE-> iOS Development Not much iOS Test + CI Practices out there (2010) Sinatra (Ruby)Calabash (Ruby) Cucumber (Ruby) SwiftLocalhost (Swift)Cucumberish (Swift)
  • 7.
    Life of aMobile Developer Mobile Developer Backend EngineerQA I’m a mobile developer. In terms of testing, I write Unit tests to ensure that my modules are working as expected. I will also ensure that I achieve high code coverage for my native app codes I’m a QA engineer. I take ownership of mobile E2E tests. When the mobile app build is ready , I will verify it in our test/QA environment I’m a backend engineer. I write tests that cover the behaviour of the services I build.
  • 8.
    Life of aMobile Developer Mobile Developer Backend Engineer API Contract Feature
 1 Not Readyv1 v1
  • 9.
    Life of aMobile Developer Mobile Developer Backend EngineerAPI Contract Feature
 1 v1 v1
  • 10.
    Life of aMobile Developer Mobile Developer Backend EngineerAPI Contract Feature
 1 v1 v1 V2 v1 App Breaks - API Contract • Contract definition has changed • Backend Engineer may not be aware of what services app is consuming • QA may only find out after running test suite APPLICATION BREAKS QA: WHAT’S HAPPENING!!
  • 11.
    Life of aMobile Developer Mobile Developer Feature
 1
  • 12.
    Life of aMobile Developer Mobile Developer Feature
 1 Database 3rd Party Services App Breaks - Dependencies • Services down • Test Data Fixtures are not synced up • Engineers may only discover broken dependencies by running E2E tests APPLICATION BREAKS QA: My E2E Tests failed again!
 What is happening this time?
  • 13.
    Life of aMobile Developer Mobile Developer QA
  • 14.
    Life of aMobile Developer Mobile Developer QA Dev, the app is breaking very often in Test/ Staging environment Sorry about it, QA.
 My native code is fine. It seems like the backend services are down at the moment Grrr.. it took me an hour of tests execution just to discover that that. This is driving me crazy. Other times, the backend engineer unknowingly changed the API schema I understand but I will always find you first whenever I discover any of these issues. Hmmm… let me come up with a solution for this
  • 15.
    About End-to-End Tests QA AsQA, we own and take responsibility in the development and maintenance of the mobile E2E tests But E2E tests are very brittle Mobile Apps typically have multiple dependencies Difficult to write tests that are dependent on shared resources E2E Tests are generally slow and expensive Even if we can write E2E tests, we may not be able to achieve comprehensive UI Automation test coverage
  • 16.
    Test Pyramid Unit Tests E2ETests Integration Tests XCUITest / Appium XCTest / JUnit API Contract Tests Mock Response Tests
  • 17.
    Integration Tests Api ContractTests Mock Mock Response Tests Mock Localhost Localhost XCUITest - iOS SwiftLocalhost
  • 18.
    Setup 
 Swift Localhost Tests UnitTests E2E Tests Integration Tests Mock Response Tests
  • 19.
    L A I M [Localhost] Setup in-memorylocalhost server [API] Redirect API calls to localhost server [Info.plist] Patch Info.plist [Mock] Setup mock responses Setup Localhost
  • 20.
    Setup Localhost -[Localhost] Localhost Server Use a unique port number Setup an in-memory server in the test runner Setup and tear down localhost server when executing each test
  • 21.
    import XCTest class MovieListTest:XCTestCase { } import SwiftLocalhost var localhostServer: LocalhostServer! override func setUp() { } self.localhostServer = LocalhostServer(portNumber: 9001) self.localhostServer.startListening() override func tearDown() { } Setup Localhost - [Localhost] self.localhostServer.stopListening() self.localhostServer = LocalhostServer.initializeUsingRandomPortNumber()
  • 22.
    Setup Localhost -[API] Localhost Server Actual Server Update URL Domain to localhost
 (with port number)
  • 23.
    private let baseUrl:String = "http://localhost:9001/3/movie" Setup Localhost - [API] class NetworkOperations { } private let baseUrl: String = "https://api.themoviedb.org/3/movie"//private let baseUrl: String = "https://api.themoviedb.org/3/movie"
  • 24.
    Setup Localhost -[Info.plist] Localhost Server Update Info.plist iOS >=10 iOS 9
  • 25.
    path["/login"] = {
 “status"= "login successful"
 } path["/movies"] = [
 {
 "title": "Batman",
 "subtitle": "XXX" },
 {
 “title": "Matrix",
 "subtitle: "YYY" },
 ] Setup Mock Responses Setup Localhost - [Mock] Localhost Server
  • 26.
    func testMoviePopularList() {
 
 } 
 
 XCUIApplication().launch() //AddXCUITest Codes Setup Localhost - [Mock] 
 
 self.localhostServer.route(method: .GET, path: "/3/movie/popular", responseJsonFileName: "home_popular")
  • 27.
  • 28.
    List Asserting Localhost Requests Usecase 1. Listing View Item List Request Localhost Requests
  • 29.
    Asserting Localhost Requests Usecase 1. Listing View 2. Detail View Item List Request Localhost Requests Detail Item Detail Request
  • 30.
    Asserting Localhost Requests Usecase 1. Listing View 2. Detail View Item List Request Localhost Requests Detail Item Detail Request 3. Bookmark Item Bookmark Item Request Expected Requests Order
  • 31.
    Asserting Localhost Requests publicclass LocalhostServer { public var recordedRequests: [URLRequest] } LocalhostServer records all received URLRequest(s)
  • 32.
    Asserting Localhost Requests //####By URL Paths--------- 
 
 let expectedRequestPaths: [String] = [ "/3/movie/popular", "/identitytoolkit/v3/relyingparty/verifyPassword", "/identitytoolkit/v3/relyingparty/getAccountInfo" ] 
 
 
 let actualRequestPaths = self.localhostServer.recordedRequests.map { return $0.url!.path } 
 
 
 XCTAssertEqual(expectedRequestPaths, actualRequestPaths)
  • 33.
    
 let expectedCURLs: [String]= [ "curl -X GET ’http://localhost:9001/3/movie/popular?api_key=71b'", "curl -X POST ’http://localhost:9001/relyingparty/verifyPassword? key=AIzaSy' -d '{n "email" : "apple@gmail.com",n "password" : "password"}'", "curl -X POST ’http://localhost:9001/relyingparty/getAccountInfo? key=AIzaSy' -d '{n "idToken" : "eyJhbj"n}'" ] 
 
 let expectedCURLs: [String] = [ "curl -X GET ’http://localhost:9001/3/movie/popular?api_key=71b'", "curl -X POST ’http://localhost:9001/relyingparty/verifyPassword? key=AIzaSy' -d '{n "email" : "apple@gmail.com",n "password" : "password"}'", "curl -X POST ’http://localhost:9001/relyingparty/getAccountInfo? key=AIzaSy' -d '{n "idToken" : "eyJhbj"n}'" ] 
 
 let actualCURLs = self.localhostServer.recordedRequests.map { return $0.cURL(withHeaders: false) } Asserting Localhost Requests //#### By describing cURL commands --------- 
 
 
 
 XCTAssertEqual(expectedCURLs, actualCURLs) 
 let expectedCURLs: [String] = [ "curl -X GET ’http://localhost:9001/3/movie/popular?api_key=71b'", "curl -X POST ’http://localhost:9001/relyingparty/verifyPassword? key=AIzaSy' -d '{n "email" : "apple@gmail.com",n "password" : "password"}'", "curl -X POST ’http://localhost:9001/relyingparty/getAccountInfo? key=AIzaSy' -d '{n "idToken" : "eyJhbj"n}'" ] 

  • 34.
    https://github.com/mkamhawi/ios-movies-app [orginal] Special Thanksto
 Mohamed El-Kamhawi https://github.com/depoon/ios-movies-app [forked] 
 Swift Localhost Demo Unit Tests E2E Tests Integration Tests Mock Response Tests
  • 35.
    FAQ on LocalhostUITests Why can’t we add stub responses in the code? Localhost Server Mock HTTP TCP HTTP TCP Mock
 Response
  • 36.
    FAQ on LocalhostUITests Swift Localhost Vapor (Swift) WireMock (Java) Typicode (JS) Sinatra (Ruby) What are the advantages of using Swift Localhost over other localhost web server solutions?
  • 37.
    FAQ Swift Localhost Vapor (Swift) WireMock(Java) Typicode (JS) Sinatra (Ruby) What are the advantages of using Swift Localhost over other localhost web server solutions?
  • 38.
    FAQ on LocalhostUITests Swift Localhost Vapor (Swift) WireMock (Java) Typicode (JS) Sinatra (Ruby) What are the advantages of using Swift Localhost over other localhost web server solutions? Advantages ✓ Easy Installation and Setup via Cocoapods ✓ Use Swift to setup mock server ✓ In line mock responses in the same test scope ✓ Use same runtime XCode debugger ✓ Ctrl + U
  • 39.
    FAQ How does theLocalhost UITest technique fit in my development process? List 2. Fetch list of items using server/list api 1. Navigate to List view 3. Tap on 1st Item. App navigates to Detail view 4. Fetch item detail using server/detail api 5. Bookmark item 6. Bookmark item detail using server/bookmark api Bookmarking Use Case DetailDetail server/list server/detail server/bookmark 7. Assert Bookmark Icon is correctly reflected
  • 40.
    FAQ How does theLocalhost XCUITest technique fit in my development process? Detail server/list server/detail server/bookmark Localhost Mock Responses Test Case 1. Navigate to List view 2. Tap on 1st Item. App navigates to Detail view 3. Bookmark item 4. Assert Bookmark Icon is correctly reflected Never Ever Fails ✓ Early Development ✓ Use Case Wont Fail
  • 41.
    API Contract Tests Unit Tests E2ETests Integration Tests API Contract Tests
  • 42.
    API Contract Tests MobileDeveloper QA Dev, I know it’s great that you have Mock Response Tests that never fails. But the APIs do change and they might break the app. Yes, QA. You are absolutely right API Contract v1 But our app releases are bounded by the pre-agreed APIContracts We can write a script to ensure the APIs are working as agreed upon We can use this script to discover which services are affecting the app.
  • 43.
  • 44.
    API Contract Tests APIContract v1 /v1/login -> schema1_v1 /v1/shoppingList -> schema2_v1 /v1/productDetails -> schema3_v1 /v1/productDetails -> schema4_v1 API Contract Script v1 v1.1 V2 /v1/productDetails -> schema3_v2 Mobile Developer Gotcha! Latest API deployment broke our app
  • 45.
    API Contract Tests BackendEngineer Hey Mobile Dev, Why are you writing tests against my API? Shouldn’t I be the one responsible for that? Mobile Developer Our app will perform correctly only when dependent services are working as expected. Our API Contract tests will give you quick feedback whenever deployed services break the contracts Mobile developers will be responsible to maintain tests that describe the services the app consume.
  • 46.
    API Contract Tests BackendEngineer That sounds awesome to me. You know what? I think we should automatically trigger the API Contract tests every time we deploy any changes Mobile Developer Nice! This encourages backend developers to deploy changes without worrying whether it will affect the mobile app clients. … BECAUSE WE WILL CATCH ANY BREAKING CHANGES
  • 47.
    API Contract Tests MobileDeveloper QA Dev, I feel annoyed that after running my tests, I discover my test fixtures are not ready (or incorrect).
 
 eg. Login credentials, Product Details on Staging environment are incorrect Your test cases actually describe the request/ response exchange that will be expected. We can write API Contract tests that chain the order of API requests that simulates a use case on the app You can simply run the API Contract tests before any automated/manual execution of tests. This will give you a headsup whether your tests will fail Since API Contract tests are generally fast, you will get your feedback in no time. Wow, this sounds awesome. I am eager to have a go at it
  • 48.
    Introducing
 Cucumber API Unit Tests E2ETests Integration Tests API Contract Tests
  • 49.
    What is yourtake on API Contract Tests (ACT) Mobile Developer Backend EngineerQA ACT checks whether our app dependencies are working as expected. The contract definition aids us in designing our localhost tests ACT is a cheap and fast way for QA to ensure that all dependencies, including data fixtures are ready before we start testing.
 The fast feedback saves us time especially when we can get feedback within seconds With ACT, I have more confidence to refactor my code base.
 
 We are now encouraged to run ACT tied to released app versions and check if older versions will be broken by new API code deployments
  • 50.
    Closing Consider having bothMock Response and API Contract Tests Integration tests are meant to compliment but not replace E2E API Contract Tests is the low hanging fruit Confidently run localhost tests to verify that native app codes is working under normal, valid conditions It may be difficult (but not impossible) to mock services used by 3rd party services. Do visit your existing tools and see how you can bring integration tests into your development
  • 51.
  • 52.
  • 53.