SlideShare a Scribd company logo
USER INTERFACE
TESTING
WITH KIF & SWIFT
CASE FOR UI TESTING
INTEGRATION

NAVIGATION FLOW

DATA FLOW

USER EXPERIENCE

ACCESSIBILITY

REFACTORINGS / REGRESSIONS
UI TESTING IS HARD 

AND TIME CONSUMING
UNLESS

AUTOMATED 

EASYTO MAINTAIN

FAST
Automated UI testing for iOS apps using KIF framework and Swift
NATIVE SUPPORT 

FOR UI TESTING
UI AUTOMATION (JavaScript)

XCUI (Swift/Objective C)

BASED ON UIAcessibility PROTOCOL
KIF

Keep It Functional - An iOS Functional
Testing Framework
https://github.com/kif-framework/KIF

UICONF 2016 TALK BY ELLEN SHAPIRO

https://youtu.be/hYCUy-9yq_M
OBJECTIVE C - KIFTestCase
RUNS IN APP TARGET

beforeAll, beforeEach, afterAll, afterEach

KIFUITestActor - USER ACTIONS

KIFSystemTestActor - SYSTEM/DEVICE ACTIONS
SWIFT - XCTestCase
ADD SIMPLE EXTENSION TO ACCESS
KIFUITestActor AND KIFSystemTestActor
OBJECTIVE C
[tester tapViewWithAccessibilityLabel:@"Login"];


SWIFT
tester().tapView(withAccessibilityLabel : "Login")
EXTENSIONS FOR READIBILITY
extension KIFUITestActor {
@discardableResult func waitForButton(_ label: String) -> UIView! {
let button = self.waitForTappableView(withAccessibilityLabel: label, traits:
UIAccessibilityTraitButton)
return button
}
func tapButton(_ accessibilityLabel: String, value: String) {
let button = waitForButton(accessibilityLabel, value: value)
button?.tap()
}
}
RESULT
tester().tapButton(“Login”) // or even better – tester().tapLoginButton()
PROTOCOLTO ACCESS APP DATA
public protocol UsesCoreDataDatabase {
func dbContext() -> NSManagedObjectContext
func isDbEmpty(_ context: NSManagedObjectContext) -> Bool
func deleteDbData(_ context: NSManagedObjectContext)
}
public extension UsesCoreDataDatabase {
func dbContext() -> NSManagedObjectContext {
let appDelegate: YourAppDelegate = UIApplication.shared.delegate as! YourAppDelegate
let context = appDelegate.value(forKey: "context") as! NSManagedObjectContext
XCTAssertNotNil(context)
return context!
}
func isDbEmpty(_ context: NSManagedObjectContext) -> Bool {
// access model objects from context
let count = ….
return (count == 0)
}
func deleteDbData(_ context: NSManagedObjectContext) {
// Delete data
}
CUSTOM TEST CASES
class MyTestCaseWithEmptyDatabase: KIFTestCase, UsesCoreDataDatabase {
override func beforeEach() {
let context = dbContext()
if ! sDbEmpty(context) {
let name = MyAppServices.deviceModel()
if name == "iPhone Simulator" { deleteDbData(context) } else { } // Are you sure want to delete data from device?
}
}
}
class MyTestCaseWithWizardFilled: MyTestCaseWithEmptyDatabase {
var rentAmount = “100”; var unitName= “M10”; var tenantName = “Anna"
override func beforeEach() {
super.beforeEach()
let context = dbContext()
MyWizardController.saveFromWizard(in: context, address: unitName, tenant: tenantName amount: rentAmount)
}
}
class MyTestCaseWithFixturesLoaded : MyTestCaseWithEmptyDatabase {
// load fixture data in database
}
DRY, READABLE TESTS
class PaymentTests: MyTestCaseWithWizardFilled {
func testAddPayment_fromUnitDashboard() {
// given - tenantName, unitName, today are defined as MyTestCaseWithWizardFilled class variables
let amount = “5.1”; let paymentAmount = “$5.10”
tester().tapPropertiesTabButton()
tester().tapUnit(unitName, tenant: tenantName)
tester().waitForTenantBalanceScreen(tenantName, currentBalance: "$0.00")
tester().waitForLastPaymentLine("No rent payments received", amount: “") // even this should be replaced by waitForNoLastPaymentLine
// when
tester().tapAddPaymentButton()
tester().enterOnKeyboard(amount)
tester().tapSaveButton()
// then
tester().waitForTenantBalanceScreen(tenantName, currentBalance: paymentAmount)
tester().waitForLastRentPaymentLine(today, amount: paymentAmount)
}
}
…
public extension KIFUITestActor {
/// Returns last payment line in rental unit dashboard
@discardableResult func waitForLastPaymentLine(_ date: String, amount: String) -> UIView! {
let view = waitForView("Last rent payment", value: "(date), (amount)”) // Accessibility label & accessibility value
return view
}
}
FAST
NOT REALLY
MAKE UI TESTS FASTER
class MyTestCaseWithEmptyDatabase: KIFTestCase, UsesCoreDataDatabase {
override func beforeAll() {
UIApplication.shared.keyWindow!.layer.speed = 100; // faster animations
}
}
GOTCHAS & HINTS
OCCASIONALLY CAN FAIL WITHOUT A GOOD REASON

¯_( )_/¯

BEWARE OF UITableViewCells

ADD EVERYTHING AS SUBVIEWTO .contentView

SAVE SCREENSHOTS ON TEST FAILURE

SET ENVVARIABLE WITH FOLDER LOCATION- KIF_SCREENSHOTS= …



AFTER FAILING TEST IN MODAL VIEW ALL OTHER TEST RESULTS = USELESS

do { try tester().trySomething(); // then test } catch {}
ACCESSIBILITY
https://youtu.be/no12EfZUSQo
“You have no clue about your app
accessibility until you write app UI tests
that rely on accessibility”
/ me to myself /
Automated UI testing for iOS apps using KIF framework and Swift
UIAccessibility PROTOCOL
UIAccessibilityElement CLASS
UIAccessibilityContainer PROTOCOL
UIAccessibilityTraits



BUNDLED FREE WHEN USING UIKit,JUST SET 

accessibilityLabel, accessibilityValue, accessibilityHint 

IN IB AND/OR CODE
QUESTIONS?
Jurģis Ķiršakmens
jki@jki.lv
@jki / @xjki

More Related Content

What's hot (9)

PDF
Hello watchOS2
Natasha Murashev
 
PDF
Protocol-Oriented MVVM (extended edition)
Natasha Murashev
 
PDF
Présentation de HomeKit
CocoaHeads France
 
PPTX
NodeJs
Orkhan Muradov
 
PDF
Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift
Aaron Douglas
 
PDF
Découvrir dtrace en ligne de commande.
CocoaHeads France
 
PPTX
Reacting with ReactiveUI
kiahiska
 
PDF
Reactive Programming with RxSwift
Scott Gardner
 
PDF
Introduction to RxJS
Brainhub
 
Hello watchOS2
Natasha Murashev
 
Protocol-Oriented MVVM (extended edition)
Natasha Murashev
 
Présentation de HomeKit
CocoaHeads France
 
Swift & ReactiveX – Asynchronous Event-Based Funsies with RxSwift
Aaron Douglas
 
Découvrir dtrace en ligne de commande.
CocoaHeads France
 
Reacting with ReactiveUI
kiahiska
 
Reactive Programming with RxSwift
Scott Gardner
 
Introduction to RxJS
Brainhub
 

Similar to Automated UI testing for iOS apps using KIF framework and Swift (20)

PDF
Striking a Balance With UI Tests - ConnectTech
stable|kernel
 
PDF
Testing view controllers with Quick and Nimble
Marcio Klepacz
 
PDF
Everything You (N)ever Wanted to Know about Testing View Controllers
Brian Gesiak
 
PDF
Tech Talk #5 : KIF-iOS Integration Testing Framework - Nguyễn Hiệp
Nexus FrontierTech
 
PDF
Automated Testing with GHUnit and KIF
Michele Titolo
 
PDF
Automated interactive testing for i os
Mobile March
 
PPT
Automating UI testing
Adam Siton
 
PPTX
UI Testing for Your Xamarin.Forms Apps
Codrina Merigo
 
PDF
Unit testing UIView
Pierre Felgines
 
PDF
X-Code UI testing architecture and tools
Jianbin LIN
 
PPTX
iOS Automation: XCUITest + Gherkin
Kenneth Poon
 
KEY
Automated ui testing
DavidReidy
 
PDF
UI Testing with Spec
Pharo
 
KEY
Ui BDD Testing
Taras Kalapun
 
PDF
Ui testing in xcode
allanh0526
 
PDF
Annihilate test smells by refactoring to patterns
cenny2
 
PPTX
Xam expertday
Codrina Merigo
 
KEY
Frank iOS Testing
sgleadow
 
PDF
Testing (eng)
Derrick Chao
 
PDF
Testing Banking Applications. Here is a practical example
Maveryx
 
Striking a Balance With UI Tests - ConnectTech
stable|kernel
 
Testing view controllers with Quick and Nimble
Marcio Klepacz
 
Everything You (N)ever Wanted to Know about Testing View Controllers
Brian Gesiak
 
Tech Talk #5 : KIF-iOS Integration Testing Framework - Nguyễn Hiệp
Nexus FrontierTech
 
Automated Testing with GHUnit and KIF
Michele Titolo
 
Automated interactive testing for i os
Mobile March
 
Automating UI testing
Adam Siton
 
UI Testing for Your Xamarin.Forms Apps
Codrina Merigo
 
Unit testing UIView
Pierre Felgines
 
X-Code UI testing architecture and tools
Jianbin LIN
 
iOS Automation: XCUITest + Gherkin
Kenneth Poon
 
Automated ui testing
DavidReidy
 
UI Testing with Spec
Pharo
 
Ui BDD Testing
Taras Kalapun
 
Ui testing in xcode
allanh0526
 
Annihilate test smells by refactoring to patterns
cenny2
 
Xam expertday
Codrina Merigo
 
Frank iOS Testing
sgleadow
 
Testing (eng)
Derrick Chao
 
Testing Banking Applications. Here is a practical example
Maveryx
 
Ad

More from Jurgis Kirsakmens (7)

PDF
Using analytics in iOS apps - #uikonf2016 #unconference
Jurgis Kirsakmens
 
PDF
Analytics for iOS apps (crash/diagnostic/usage/sales)
Jurgis Kirsakmens
 
PDF
Take a Break
Jurgis Kirsakmens
 
PDF
How much does it cost to build a mobile app?
Jurgis Kirsakmens
 
KEY
Mobilās aplikācijas un uzņēmumu komunikācija
Jurgis Kirsakmens
 
PDF
Future:apps&mobile - mobile landscape and development platforms
Jurgis Kirsakmens
 
PDF
Netiquette- short introduction
Jurgis Kirsakmens
 
Using analytics in iOS apps - #uikonf2016 #unconference
Jurgis Kirsakmens
 
Analytics for iOS apps (crash/diagnostic/usage/sales)
Jurgis Kirsakmens
 
Take a Break
Jurgis Kirsakmens
 
How much does it cost to build a mobile app?
Jurgis Kirsakmens
 
Mobilās aplikācijas un uzņēmumu komunikācija
Jurgis Kirsakmens
 
Future:apps&mobile - mobile landscape and development platforms
Jurgis Kirsakmens
 
Netiquette- short introduction
Jurgis Kirsakmens
 
Ad

Recently uploaded (20)

PDF
Code Once; Run Everywhere - A Beginner’s Journey with React Native
Hasitha Walpola
 
PDF
The Next-Gen HMIS Software AI, Blockchain & Cloud for Housing.pdf
Prudence B2B
 
PPTX
For my supp to finally picking supp that work
necas19388
 
PPTX
Foundations of Marketo Engage - Programs, Campaigns & Beyond - June 2025
BradBedford3
 
PPTX
CV-Project_2024 version 01222222222.pptx
MohammadSiddiqui70
 
PDF
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
arabelatso
 
PDF
AWS Consulting Services: Empowering Digital Transformation with Nlineaxis
Nlineaxis IT Solutions Pvt Ltd
 
PDF
Best Software Development at Best Prices
softechies7
 
PDF
Telemedicine App Development_ Key Factors to Consider for Your Healthcare Ven...
Mobilityinfotech
 
PPTX
IObit Driver Booster Pro 12.4-12.5 license keys 2025-2026
chaudhryakashoo065
 
PDF
Rewards and Recognition (2).pdf
ethan Talor
 
PPTX
IObit Driver Booster Pro 12 Crack Latest Version Download
pcprocore
 
PPTX
Avast Premium Security crack 25.5.6162 + License Key 2025
HyperPc soft
 
PDF
IObit Uninstaller Pro 14.3.1.8 Crack for Windows Latest
utfefguu
 
PDF
Automated Testing and Safety Analysis of Deep Neural Networks
Lionel Briand
 
PDF
Which Hiring Management Tools Offer the Best ROI?
HireME
 
PPTX
Introduction to web development | MERN Stack
JosephLiyon
 
PPTX
Iobit Driver Booster Pro 12 Crack Free Download
chaudhryakashoo065
 
PPTX
declaration of Variables and constants.pptx
meemee7378
 
PPTX
Threat Modeling a Batch Job Framework - Teri Radichel - AWS re:Inforce 2025
2nd Sight Lab
 
Code Once; Run Everywhere - A Beginner’s Journey with React Native
Hasitha Walpola
 
The Next-Gen HMIS Software AI, Blockchain & Cloud for Housing.pdf
Prudence B2B
 
For my supp to finally picking supp that work
necas19388
 
Foundations of Marketo Engage - Programs, Campaigns & Beyond - June 2025
BradBedford3
 
CV-Project_2024 version 01222222222.pptx
MohammadSiddiqui70
 
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
arabelatso
 
AWS Consulting Services: Empowering Digital Transformation with Nlineaxis
Nlineaxis IT Solutions Pvt Ltd
 
Best Software Development at Best Prices
softechies7
 
Telemedicine App Development_ Key Factors to Consider for Your Healthcare Ven...
Mobilityinfotech
 
IObit Driver Booster Pro 12.4-12.5 license keys 2025-2026
chaudhryakashoo065
 
Rewards and Recognition (2).pdf
ethan Talor
 
IObit Driver Booster Pro 12 Crack Latest Version Download
pcprocore
 
Avast Premium Security crack 25.5.6162 + License Key 2025
HyperPc soft
 
IObit Uninstaller Pro 14.3.1.8 Crack for Windows Latest
utfefguu
 
Automated Testing and Safety Analysis of Deep Neural Networks
Lionel Briand
 
Which Hiring Management Tools Offer the Best ROI?
HireME
 
Introduction to web development | MERN Stack
JosephLiyon
 
Iobit Driver Booster Pro 12 Crack Free Download
chaudhryakashoo065
 
declaration of Variables and constants.pptx
meemee7378
 
Threat Modeling a Batch Job Framework - Teri Radichel - AWS re:Inforce 2025
2nd Sight Lab
 

Automated UI testing for iOS apps using KIF framework and Swift

  • 2. CASE FOR UI TESTING INTEGRATION
 NAVIGATION FLOW
 DATA FLOW
 USER EXPERIENCE
 ACCESSIBILITY
 REFACTORINGS / REGRESSIONS
  • 3. UI TESTING IS HARD 
 AND TIME CONSUMING UNLESS
 AUTOMATED 
 EASYTO MAINTAIN
 FAST
  • 5. NATIVE SUPPORT 
 FOR UI TESTING UI AUTOMATION (JavaScript)
 XCUI (Swift/Objective C)
 BASED ON UIAcessibility PROTOCOL
  • 6. KIF
 Keep It Functional - An iOS Functional Testing Framework https://github.com/kif-framework/KIF
 UICONF 2016 TALK BY ELLEN SHAPIRO
 https://youtu.be/hYCUy-9yq_M
  • 7. OBJECTIVE C - KIFTestCase RUNS IN APP TARGET
 beforeAll, beforeEach, afterAll, afterEach
 KIFUITestActor - USER ACTIONS
 KIFSystemTestActor - SYSTEM/DEVICE ACTIONS SWIFT - XCTestCase ADD SIMPLE EXTENSION TO ACCESS KIFUITestActor AND KIFSystemTestActor
  • 9. EXTENSIONS FOR READIBILITY extension KIFUITestActor { @discardableResult func waitForButton(_ label: String) -> UIView! { let button = self.waitForTappableView(withAccessibilityLabel: label, traits: UIAccessibilityTraitButton) return button } func tapButton(_ accessibilityLabel: String, value: String) { let button = waitForButton(accessibilityLabel, value: value) button?.tap() } } RESULT tester().tapButton(“Login”) // or even better – tester().tapLoginButton()
  • 10. PROTOCOLTO ACCESS APP DATA public protocol UsesCoreDataDatabase { func dbContext() -> NSManagedObjectContext func isDbEmpty(_ context: NSManagedObjectContext) -> Bool func deleteDbData(_ context: NSManagedObjectContext) } public extension UsesCoreDataDatabase { func dbContext() -> NSManagedObjectContext { let appDelegate: YourAppDelegate = UIApplication.shared.delegate as! YourAppDelegate let context = appDelegate.value(forKey: "context") as! NSManagedObjectContext XCTAssertNotNil(context) return context! } func isDbEmpty(_ context: NSManagedObjectContext) -> Bool { // access model objects from context let count = …. return (count == 0) } func deleteDbData(_ context: NSManagedObjectContext) { // Delete data }
  • 11. CUSTOM TEST CASES class MyTestCaseWithEmptyDatabase: KIFTestCase, UsesCoreDataDatabase { override func beforeEach() { let context = dbContext() if ! sDbEmpty(context) { let name = MyAppServices.deviceModel() if name == "iPhone Simulator" { deleteDbData(context) } else { } // Are you sure want to delete data from device? } } } class MyTestCaseWithWizardFilled: MyTestCaseWithEmptyDatabase { var rentAmount = “100”; var unitName= “M10”; var tenantName = “Anna" override func beforeEach() { super.beforeEach() let context = dbContext() MyWizardController.saveFromWizard(in: context, address: unitName, tenant: tenantName amount: rentAmount) } } class MyTestCaseWithFixturesLoaded : MyTestCaseWithEmptyDatabase { // load fixture data in database }
  • 12. DRY, READABLE TESTS class PaymentTests: MyTestCaseWithWizardFilled { func testAddPayment_fromUnitDashboard() { // given - tenantName, unitName, today are defined as MyTestCaseWithWizardFilled class variables let amount = “5.1”; let paymentAmount = “$5.10” tester().tapPropertiesTabButton() tester().tapUnit(unitName, tenant: tenantName) tester().waitForTenantBalanceScreen(tenantName, currentBalance: "$0.00") tester().waitForLastPaymentLine("No rent payments received", amount: “") // even this should be replaced by waitForNoLastPaymentLine // when tester().tapAddPaymentButton() tester().enterOnKeyboard(amount) tester().tapSaveButton() // then tester().waitForTenantBalanceScreen(tenantName, currentBalance: paymentAmount) tester().waitForLastRentPaymentLine(today, amount: paymentAmount) } } … public extension KIFUITestActor { /// Returns last payment line in rental unit dashboard @discardableResult func waitForLastPaymentLine(_ date: String, amount: String) -> UIView! { let view = waitForView("Last rent payment", value: "(date), (amount)”) // Accessibility label & accessibility value return view } }
  • 14. MAKE UI TESTS FASTER class MyTestCaseWithEmptyDatabase: KIFTestCase, UsesCoreDataDatabase { override func beforeAll() { UIApplication.shared.keyWindow!.layer.speed = 100; // faster animations } }
  • 15. GOTCHAS & HINTS OCCASIONALLY CAN FAIL WITHOUT A GOOD REASON
 ¯_( )_/¯
 BEWARE OF UITableViewCells
 ADD EVERYTHING AS SUBVIEWTO .contentView
 SAVE SCREENSHOTS ON TEST FAILURE
 SET ENVVARIABLE WITH FOLDER LOCATION- KIF_SCREENSHOTS= …
 
 AFTER FAILING TEST IN MODAL VIEW ALL OTHER TEST RESULTS = USELESS
 do { try tester().trySomething(); // then test } catch {}
  • 16. ACCESSIBILITY https://youtu.be/no12EfZUSQo “You have no clue about your app accessibility until you write app UI tests that rely on accessibility” / me to myself /
  • 18. UIAccessibility PROTOCOL UIAccessibilityElement CLASS UIAccessibilityContainer PROTOCOL UIAccessibilityTraits
 
 BUNDLED FREE WHEN USING UIKit,JUST SET 
 accessibilityLabel, accessibilityValue, accessibilityHint 
 IN IB AND/OR CODE