SlideShare a Scribd company logo
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

More Related Content

KEY
Selenium at STPCon - Dallas 2011
PDF
Appium Dockerization: from Scratch to Advanced Implementation - HUSTEF 2019
KEY
Development workflow
PDF
Developing Native Mobile Apps Using JavaScript, ApacheCon NA 2014
PPTX
[ApacheCon 2016] Advanced Apache Cordova
PPTX
Apache Cordova In Action
PPTX
CC-Castle; The best Real-Time/Embedded/HighTech language EVER?
PPT
The Future of Selenium Testing for Mobile Web and Native Apps
Selenium at STPCon - Dallas 2011
Appium Dockerization: from Scratch to Advanced Implementation - HUSTEF 2019
Development workflow
Developing Native Mobile Apps Using JavaScript, ApacheCon NA 2014
[ApacheCon 2016] Advanced Apache Cordova
Apache Cordova In Action
CC-Castle; The best Real-Time/Embedded/HighTech language EVER?
The Future of Selenium Testing for Mobile Web and Native Apps

What's hot (20)

PPTX
Ios driver presentation copy
PPTX
Do's and Do not's about p2
PDF
利用 Appium + Robot Framework 實現跨平台 App 互動測試
PDF
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
PDF
Using the latest Java Persistence API 2 Features - Tech Days 2010 India
ODP
JavaOne 2009 BOF-5189 Griffon In Depth
PPT
Thinking tts - Eric Floe
PPTX
Uber mobility - Build & Release
PPTX
Uber Mobility Meetup: Mobile Testing
PDF
Console Apps: php artisan forthe:win
PPTX
Testdroid:
PDF
Apache Cordova: Overview and Introduction
PPTX
[AnDevCon 2016] Mutation Testing for Android
PPTX
Codestrong 2012 breakout session exploring the new titanium command line in...
PDF
iPhone Coding For Web Developers
PDF
Observability and Troubleshooting in Forge
PDF
Dominik Veselý - Vše co jste kdy chtěli vědět o CI a báli jste se zeptat
PPTX
QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...
PPTX
Cross Platform Native Development with Appcelerator Titanium (2015 DevNexus)
PDF
[E-Dev-Day-US-2015][9/9] High Level Application Development with Elua (Daniel...
Ios driver presentation copy
Do's and Do not's about p2
利用 Appium + Robot Framework 實現跨平台 App 互動測試
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Using the latest Java Persistence API 2 Features - Tech Days 2010 India
JavaOne 2009 BOF-5189 Griffon In Depth
Thinking tts - Eric Floe
Uber mobility - Build & Release
Uber Mobility Meetup: Mobile Testing
Console Apps: php artisan forthe:win
Testdroid:
Apache Cordova: Overview and Introduction
[AnDevCon 2016] Mutation Testing for Android
Codestrong 2012 breakout session exploring the new titanium command line in...
iPhone Coding For Web Developers
Observability and Troubleshooting in Forge
Dominik Veselý - Vše co jste kdy chtěli vědět o CI a báli jste se zeptat
QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...
Cross Platform Native Development with Appcelerator Titanium (2015 DevNexus)
[E-Dev-Day-US-2015][9/9] High Level Application Development with Elua (Daniel...
Ad

Similar to Mobile Development integration tests (20)

PPTX
Expo - Zero to App.pptx
PDF
Seattle StrongLoop Node.js Workshop
PDF
Fixing the mobile web - Internet World Romania
PDF
Shifting landscape of mobile automation, and the future of Appium - Jonathan ...
PPTX
Appium solution
KEY
Rails Presentation (Anton Dmitriyev)
PPT
State ofappdevelopment
PDF
Java Test Automation for REST, Web and Mobile
PPTX
Mobile Application and Developments.pptx
PDF
[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium
PDF
iOS Parallel Automation: run faster than fast — Viktar Karanevich — SeleniumC...
PDF
The Present and Future of Mobile Test Automation with Appium
PDF
Dev ops for cross platform mobile modeveast 12
PDF
Ruby on Google App Engine: Upgrade to Google App "Turbo" Engine
PPTX
Deploying applications to Cloud with Google App Engine
PDF
Robot Framework Introduction & Sauce Labs Integration
PDF
Launch Arguments & NSUserDefaults by Franck Lefebvre
PDF
Building Mobile Friendly APIs in Rails
KEY
Play Support in Cloud Foundry
PDF
All the Laravel Things – Up & Running to Making $$
Expo - Zero to App.pptx
Seattle StrongLoop Node.js Workshop
Fixing the mobile web - Internet World Romania
Shifting landscape of mobile automation, and the future of Appium - Jonathan ...
Appium solution
Rails Presentation (Anton Dmitriyev)
State ofappdevelopment
Java Test Automation for REST, Web and Mobile
Mobile Application and Developments.pptx
[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium
iOS Parallel Automation: run faster than fast — Viktar Karanevich — SeleniumC...
The Present and Future of Mobile Test Automation with Appium
Dev ops for cross platform mobile modeveast 12
Ruby on Google App Engine: Upgrade to Google App "Turbo" Engine
Deploying applications to Cloud with Google App Engine
Robot Framework Introduction & Sauce Labs Integration
Launch Arguments & NSUserDefaults by Franck Lefebvre
Building Mobile Friendly APIs in Rails
Play Support in Cloud Foundry
All the Laravel Things – Up & Running to Making $$
Ad

More from Kenneth Poon (7)

PDF
Make XCUITest Great Again
PDF
Mobile Testing Tips - Let's achieve fast feedback loops
PDF
Network Interception - Write Swift codes to inspect network requests (even wi...
PDF
PropertyGuru is Hiring. iOS / Android Engineer (Bangkok, Thailand)
PPTX
iOS Automation: XCUITest + Gherkin
PDF
Advanced Project 1: Heart Bleed
PDF
CNY Distribution of Oranges, Uplifting the spirit [@TPCTMC]
Make XCUITest Great Again
Mobile Testing Tips - Let's achieve fast feedback loops
Network Interception - Write Swift codes to inspect network requests (even wi...
PropertyGuru is Hiring. iOS / Android Engineer (Bangkok, Thailand)
iOS Automation: XCUITest + Gherkin
Advanced Project 1: Heart Bleed
CNY Distribution of Oranges, Uplifting the spirit [@TPCTMC]

Recently uploaded (20)

PPTX
Transform Your Business with a Software ERP System
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
Understanding Forklifts - TECH EHS Solution
PDF
AI in Product Development-omnex systems
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PPTX
ManageIQ - Sprint 268 Review - Slide Deck
PDF
top salesforce developer skills in 2025.pdf
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
System and Network Administraation Chapter 3
PDF
Nekopoi APK 2025 free lastest update
Transform Your Business with a Software ERP System
Softaken Excel to vCard Converter Software.pdf
Design an Analysis of Algorithms I-SECS-1021-03
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Understanding Forklifts - TECH EHS Solution
AI in Product Development-omnex systems
Which alternative to Crystal Reports is best for small or large businesses.pdf
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
2025 Textile ERP Trends: SAP, Odoo & Oracle
ManageIQ - Sprint 268 Review - Slide Deck
top salesforce developer skills in 2025.pdf
Operating system designcfffgfgggggggvggggggggg
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
L1 - Introduction to python Backend.pptx
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Navsoft: AI-Powered Business Solutions & Custom Software Development
System and Network Administraation Chapter 3
Nekopoi APK 2025 free lastest update

Mobile Development integration tests

  • 1. Introducing API Contract and Localhost 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 Software Engineer @ 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 iOS Dev Scout Meetup iOS Conf SG 2019 Agile Singapore Testing Mobile Conf TH
  • 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 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.
  • 8. Life of a Mobile Developer Mobile Developer Backend Engineer API Contract Feature
 1 Not Readyv1 v1
  • 9. Life of a Mobile Developer Mobile Developer Backend EngineerAPI Contract Feature
 1 v1 v1
  • 10. 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!!
  • 11. Life of a Mobile Developer Mobile Developer Feature
 1
  • 12. 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?
  • 13. Life of a Mobile Developer Mobile Developer QA
  • 14. 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
  • 15. 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
  • 16. Test Pyramid Unit Tests E2E Tests Integration Tests XCUITest / Appium XCTest / JUnit API Contract Tests Mock Response Tests
  • 17. Integration Tests Api Contract Tests Mock Mock Response Tests Mock Localhost Localhost XCUITest - iOS SwiftLocalhost
  • 18. Setup 
 Swift Localhost Tests Unit Tests E2E Tests Integration Tests Mock Response Tests
  • 19. 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
  • 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() //Add XCUITest Codes Setup Localhost - [Mock] 
 
 self.localhostServer.route(method: .GET, path: "/3/movie/popular", responseJsonFileName: "home_popular")
  • 28. List Asserting Localhost Requests Use case 1. Listing View Item List Request Localhost Requests
  • 29. Asserting Localhost Requests Use case 1. Listing View 2. Detail View Item List Request Localhost Requests Detail Item Detail Request
  • 30. 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
  • 31. Asserting Localhost Requests public class 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 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
  • 35. FAQ on Localhost UITests Why can’t we add stub responses in the code? Localhost Server Mock HTTP TCP HTTP TCP Mock
 Response
  • 36. 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?
  • 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 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
  • 39. 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
  • 40. 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
  • 41. API Contract Tests Unit Tests E2E Tests Integration Tests API Contract Tests
  • 42. 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.
  • 43. API Contract Tests API Contract v1
  • 44. 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
  • 45. 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.
  • 46. 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
  • 47. 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
  • 48. Introducing
 Cucumber API Unit Tests E2E Tests Integration Tests API Contract Tests
  • 49. 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
  • 50. 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