SlideShare a Scribd company logo
Striking a Balance with UI Tests
By: Jesse Black
Software Engineer
stable|kernel

jesse.black@stablekernel.com
@stablekernel
Hi, I’m Jesse Black.
• Programming for over nine years
• Created a Mac App for my family business
• Worked for 3 years with Gramercy Consultants developing iOS and Android apps
• Working for stable|kernel for the past 4 years developing iOS apps, Android apps
and their supporting APIs
We’re stable|kernel.
stable|kernel is an Atlanta-based mobile development company 

to craft smartly-designed mobile applications that connect brands 

directly with their users. 



Striking a Balance with UI Tests
@stablekernel
Overview
• General Testing
• Demo: Introducing UI Tests
• Improving UI Tests with Robots
• Mocking Dependencies
• Discussion
Types of Tests
@stablekernel
• Manual testing
• Automated testing
• Unit / Integrated / End to End
• Continuous Testing
Unit Tests
@stablekernel
• Tests a small amount of code with limited inputs and output
• Should be F.I.R.S.T.
• Fast
• Isolated
• Repeatable
• Self - Verifying
• Timely
Why test?
@stablekernel
• Fast feedback
• Help prevent regressions
• Improve code design
Demo
@stablekernel
UI Test Recording and Playback
Recording observations
@stablekernel
• Black box
• User’s perspective
• No Asserts (Assertion by tapping)
Example: Login Error
@stablekernel
let app = XCUIApplication()
let usernameTextField = app.textFields["Username"]
usernameTextField.tap()
usernameTextField.typeText("invalid")
app.children(matching: .window).element(boundBy:
0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap()
let passwordSecureTextField = app.secureTextFields["Password"]
passwordSecureTextField.tap()
passwordSecureTextField.typeText("invalid")
app.children(matching: .window).element(boundBy:
0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap()
app.buttons[“Login"].tap()
app.alerts["Username and password combo not found."].buttons["OK"].tap()
Example: Login Error
@stablekernel
let app = XCUIApplication()
let usernameTextField = app.textFields["Username"]
usernameTextField.tap()
usernameTextField.typeText("invalid")
app.children(matching: .window).element(boundBy:
0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap()
let passwordSecureTextField = app.secureTextFields["Password"]
passwordSecureTextField.tap()
passwordSecureTextField.typeText("invalid")
app.children(matching: .window).element(boundBy:
0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap()
app.buttons[“Login"].tap()
app.alerts["Username and password combo not found."].buttons["OK"].tap()
• Scary strings
• Will fail without network
• Chunks of very similar code
• Fragile tap to dismiss lines
Wrangle user facing strings
@stablekernel
• Localize all user facing strings
• Add localized string file to both targets; app and UI Test targets
• Create abstraction around NSLocalizedString to avoid using stringly
typed keys when accessing user facing strings
Wrangle user facing string
@stablekernel
enum UIString: String {
case usernamePlaceholder = "username-placeholder"
func localized() -> String {
return UIStringsHelper.getLocalizedString(key: rawValue)
}
}
private class UIStringsHelper {
static func getLocalizedString(key: String) -> String {
let bundle = Bundle(for: UIStringsHelper.self)
return NSLocalizedString(key, bundle: bundle, comment: "")
}
}
Factor out user actions into Robots
@stablekernel
struct LoginRobot {
let app: XCUIApplication
var usernameTextField: XCUIElement {
return app.textFields[UIString.usernamePlaceholder.localized()]
}
func dismissKeyboard() {
app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching:
.other).element(boundBy: 0).tap()
}
func enterUsername(text: String) {
usernameTextField.tap()
usernameTextField.typeText(text)
}
}
Example: Login Error Refactored
@stablekernel
func testInvalidCredentials() {
loginRobot.enterUsername(text: "invalid@email")
loginRobot.dismissKeyboard()
loginRobot.enterPassword(text: "invalid")
loginRobot.dismissKeyboard()
loginRobot.loginButton.tap()
let alertRobot = AlertRobot(app: XCUIApplication(), title: "Username and password combo
not found.")
alertRobot.dismiss(withButtonTitled: UIString.okButton.localized())
}
Dependencies
@stablekernel
• Data persistence
• Networks
• Third Party Libraries
Mock Out Dependencies
@stablekernel
Mock Example: Login Credentials
@stablekernel
// UI Test Setup
override func setUp() {
super.setUp()
// ...
XCUIApplication().launchArguments = [“USE_MOCK_LOGIN_STORE”, “HAS_SAVED_USERNAME”]
XCUIApplication().launch()
}
Mock Example: Login Credentials
@stablekernel
protocol LoginCredentialsStore: class {
func saveUsername(username: String?)
func readUsername() -> String?
}
Mock Example: Login Credentials
@stablekernel
class MockLoginCredentialsStore: LoginCredentialsStore {
var savedUsername: String?
init() {
if CommandLine.arguments.contains("HAS_SAVED_USERNAME") {
savedUsername = "jesse.black@stablekernel.com"
}
}
func saveUsername(username: String?) {
savedUsername = username
}
func readUsername() -> String? {
return savedUsername
}
}
Realistic Goals
@stablekernel
• Automate screen shots of your app as you roll out changes
• Be prepared for demos with stakeholders as you close out units of
work
• Increase confident that previously demoed work does not have any
regressions
Final Remarks
@stablekernel
Questions?
Business Inquiries:
Sarah Woodward
Director of Business Development
sarah.woodward@stablekernel.com
Jesse Black
Software Engineer
jesse.black@stablekernel.com
blog.stablekernel.com
@JesseBlack82

More Related Content

What's hot

A Second Look at Unit Testing by Roy Osherove
A Second Look at Unit Testing by Roy OsheroveA Second Look at Unit Testing by Roy Osherove
A Second Look at Unit Testing by Roy Osherove
Roy Osherove
 
Functional Testing
Functional TestingFunctional Testing
Functional Testing
Adam Hill
 
Angular Unit Test
Angular Unit TestAngular Unit Test
Angular Unit Test
Michael Haberman
 
c3ee900a-894b-4680-894c-42f77ffd4446-160308162303
c3ee900a-894b-4680-894c-42f77ffd4446-160308162303c3ee900a-894b-4680-894c-42f77ffd4446-160308162303
c3ee900a-894b-4680-894c-42f77ffd4446-160308162303Robert Warren
 
A second look at Unit Testing with Roy Osherove at Microsoft Swit
A second look at Unit Testing with Roy Osherove at Microsoft SwitA second look at Unit Testing with Roy Osherove at Microsoft Swit
A second look at Unit Testing with Roy Osherove at Microsoft SwitRoy Osherove
 
inline function
inline function inline function
inline function
imran khan
 
Elixir
ElixirElixir
Elixir
Robert Brown
 
You Used To Inject Me In Your Constructor
 You Used To Inject Me In Your Constructor You Used To Inject Me In Your Constructor
You Used To Inject Me In Your Constructor
Veronica Lillie
 
API Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj RollisonAPI Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj Rollison
TEST Huddle
 
Functions, anonymous functions and the function type
Functions, anonymous functions and the function typeFunctions, anonymous functions and the function type
Functions, anonymous functions and the function type
Chang John
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
Maris Prabhakaran M
 
Java Batch
Java BatchJava Batch
API Testing: Answers to Your Top 3 Questions
API Testing: Answers to Your Top 3 QuestionsAPI Testing: Answers to Your Top 3 Questions
API Testing: Answers to Your Top 3 Questions
QASource
 
Super powered API testing
Super powered API testing Super powered API testing
Super powered API testing
postmanclient
 
What's New in C# ? C# 6, 7.0, 7.1 and 7.2
What's New in C# ? C# 6, 7.0, 7.1 and 7.2What's New in C# ? C# 6, 7.0, 7.1 and 7.2
What's New in C# ? C# 6, 7.0, 7.1 and 7.2
David Stevenson
 
Angular performance improvments
Angular performance improvmentsAngular performance improvments
Angular performance improvments
Eliran Eliassy
 
Some experiences building an Android app with React Native & Redux
Some experiences building an Android app with React Native & ReduxSome experiences building an Android app with React Native & Redux
Some experiences building an Android app with React Native & Redux
Alex Bepple
 
Apache Flink - A Sneek Preview on Language Integrated Queries
Apache Flink - A Sneek Preview on Language Integrated QueriesApache Flink - A Sneek Preview on Language Integrated Queries
Apache Flink - A Sneek Preview on Language Integrated Queries
Fabian Hueske
 
Automated tests to a REST API
Automated tests to a REST APIAutomated tests to a REST API
Automated tests to a REST API
Luís Barros Nóbrega
 
Default constructors in C++
Default constructors in C++Default constructors in C++
Default constructors in C++
Learn By Watch
 

What's hot (20)

A Second Look at Unit Testing by Roy Osherove
A Second Look at Unit Testing by Roy OsheroveA Second Look at Unit Testing by Roy Osherove
A Second Look at Unit Testing by Roy Osherove
 
Functional Testing
Functional TestingFunctional Testing
Functional Testing
 
Angular Unit Test
Angular Unit TestAngular Unit Test
Angular Unit Test
 
c3ee900a-894b-4680-894c-42f77ffd4446-160308162303
c3ee900a-894b-4680-894c-42f77ffd4446-160308162303c3ee900a-894b-4680-894c-42f77ffd4446-160308162303
c3ee900a-894b-4680-894c-42f77ffd4446-160308162303
 
A second look at Unit Testing with Roy Osherove at Microsoft Swit
A second look at Unit Testing with Roy Osherove at Microsoft SwitA second look at Unit Testing with Roy Osherove at Microsoft Swit
A second look at Unit Testing with Roy Osherove at Microsoft Swit
 
inline function
inline function inline function
inline function
 
Elixir
ElixirElixir
Elixir
 
You Used To Inject Me In Your Constructor
 You Used To Inject Me In Your Constructor You Used To Inject Me In Your Constructor
You Used To Inject Me In Your Constructor
 
API Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj RollisonAPI Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj Rollison
 
Functions, anonymous functions and the function type
Functions, anonymous functions and the function typeFunctions, anonymous functions and the function type
Functions, anonymous functions and the function type
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Java Batch
Java BatchJava Batch
Java Batch
 
API Testing: Answers to Your Top 3 Questions
API Testing: Answers to Your Top 3 QuestionsAPI Testing: Answers to Your Top 3 Questions
API Testing: Answers to Your Top 3 Questions
 
Super powered API testing
Super powered API testing Super powered API testing
Super powered API testing
 
What's New in C# ? C# 6, 7.0, 7.1 and 7.2
What's New in C# ? C# 6, 7.0, 7.1 and 7.2What's New in C# ? C# 6, 7.0, 7.1 and 7.2
What's New in C# ? C# 6, 7.0, 7.1 and 7.2
 
Angular performance improvments
Angular performance improvmentsAngular performance improvments
Angular performance improvments
 
Some experiences building an Android app with React Native & Redux
Some experiences building an Android app with React Native & ReduxSome experiences building an Android app with React Native & Redux
Some experiences building an Android app with React Native & Redux
 
Apache Flink - A Sneek Preview on Language Integrated Queries
Apache Flink - A Sneek Preview on Language Integrated QueriesApache Flink - A Sneek Preview on Language Integrated Queries
Apache Flink - A Sneek Preview on Language Integrated Queries
 
Automated tests to a REST API
Automated tests to a REST APIAutomated tests to a REST API
Automated tests to a REST API
 
Default constructors in C++
Default constructors in C++Default constructors in C++
Default constructors in C++
 

Similar to Striking a Balance With UI Tests - ConnectTech

Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor ExtensionsConnect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
stable|kernel
 
XCUITest for iOS App Testing and how to test with Xcode
XCUITest for iOS App Testing and how to test with XcodeXCUITest for iOS App Testing and how to test with Xcode
XCUITest for iOS App Testing and how to test with Xcode
pCloudy
 
Getting Started with XCTest and XCUITest for iOS App Testing
Getting Started with XCTest and XCUITest for iOS App TestingGetting Started with XCTest and XCUITest for iOS App Testing
Getting Started with XCTest and XCUITest for iOS App Testing
Bitbar
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
Hendrik Ebbers
 
Testing and Building Android
Testing and Building AndroidTesting and Building Android
Testing and Building AndroidDroidcon Berlin
 
Selenium in the palm of your hand: Appium and automated mobile testing
Selenium in the palm of your hand: Appium and automated mobile testingSelenium in the palm of your hand: Appium and automated mobile testing
Selenium in the palm of your hand: Appium and automated mobile testing
Isaac Murchie
 
Eclipse Testing Day 2010. Xored Q7
Eclipse Testing Day 2010. Xored Q7Eclipse Testing Day 2010. Xored Q7
Eclipse Testing Day 2010. Xored Q7
platoff
 
Fashionable XCUITest for iOS Apps by Shashikant Jagtap
Fashionable XCUITest for iOS Apps by Shashikant JagtapFashionable XCUITest for iOS Apps by Shashikant Jagtap
Fashionable XCUITest for iOS Apps by Shashikant Jagtap
Sauce Labs
 
Nativescript
NativescriptNativescript
Introduction to Kotlin for Android developers
Introduction to Kotlin for Android developersIntroduction to Kotlin for Android developers
Introduction to Kotlin for Android developers
Mohamed Wael
 
Angular 2 for Java Developers
Angular 2 for Java DevelopersAngular 2 for Java Developers
Angular 2 for Java Developers
Yakov Fain
 
What's new in Xamarin.iOS, by Miguel de Icaza
What's new in Xamarin.iOS, by Miguel de IcazaWhat's new in Xamarin.iOS, by Miguel de Icaza
What's new in Xamarin.iOS, by Miguel de IcazaXamarin
 
Guide to the jungle of testing frameworks
Guide to the jungle of testing frameworksGuide to the jungle of testing frameworks
Guide to the jungle of testing frameworks
Tomáš Kypta
 
What's new in c# 8.0
What's new in c# 8.0What's new in c# 8.0
What's new in c# 8.0
Moaid Hathot
 
Microservices Chaos Testing at Jet
Microservices Chaos Testing at JetMicroservices Chaos Testing at Jet
Microservices Chaos Testing at Jet
C4Media
 
Ignite your app development with Angular, NativeScript and Firebase
Ignite your app development with Angular, NativeScript and FirebaseIgnite your app development with Angular, NativeScript and Firebase
Ignite your app development with Angular, NativeScript and Firebase
Jen Looper
 
Functional Testing Swing Applications with Frankenstein
Functional Testing Swing Applications with FrankensteinFunctional Testing Swing Applications with Frankenstein
Functional Testing Swing Applications with Frankenstein
vivek_prahlad
 
利用 Appium + Robot Framework 實現跨平台 App 互動測試
利用 Appium + Robot Framework 實現跨平台 App 互動測試利用 Appium + Robot Framework 實現跨平台 App 互動測試
利用 Appium + Robot Framework 實現跨平台 App 互動測試
Jeremy Kao
 
Testing Angular
Testing AngularTesting Angular
Testing Angular
Lilia Sfaxi
 
Unit testing and Android
Unit testing and AndroidUnit testing and Android
Unit testing and Android
Tomáš Kypta
 

Similar to Striking a Balance With UI Tests - ConnectTech (20)

Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor ExtensionsConnect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
 
XCUITest for iOS App Testing and how to test with Xcode
XCUITest for iOS App Testing and how to test with XcodeXCUITest for iOS App Testing and how to test with Xcode
XCUITest for iOS App Testing and how to test with Xcode
 
Getting Started with XCTest and XCUITest for iOS App Testing
Getting Started with XCTest and XCUITest for iOS App TestingGetting Started with XCTest and XCUITest for iOS App Testing
Getting Started with XCTest and XCUITest for iOS App Testing
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
 
Testing and Building Android
Testing and Building AndroidTesting and Building Android
Testing and Building Android
 
Selenium in the palm of your hand: Appium and automated mobile testing
Selenium in the palm of your hand: Appium and automated mobile testingSelenium in the palm of your hand: Appium and automated mobile testing
Selenium in the palm of your hand: Appium and automated mobile testing
 
Eclipse Testing Day 2010. Xored Q7
Eclipse Testing Day 2010. Xored Q7Eclipse Testing Day 2010. Xored Q7
Eclipse Testing Day 2010. Xored Q7
 
Fashionable XCUITest for iOS Apps by Shashikant Jagtap
Fashionable XCUITest for iOS Apps by Shashikant JagtapFashionable XCUITest for iOS Apps by Shashikant Jagtap
Fashionable XCUITest for iOS Apps by Shashikant Jagtap
 
Nativescript
NativescriptNativescript
Nativescript
 
Introduction to Kotlin for Android developers
Introduction to Kotlin for Android developersIntroduction to Kotlin for Android developers
Introduction to Kotlin for Android developers
 
Angular 2 for Java Developers
Angular 2 for Java DevelopersAngular 2 for Java Developers
Angular 2 for Java Developers
 
What's new in Xamarin.iOS, by Miguel de Icaza
What's new in Xamarin.iOS, by Miguel de IcazaWhat's new in Xamarin.iOS, by Miguel de Icaza
What's new in Xamarin.iOS, by Miguel de Icaza
 
Guide to the jungle of testing frameworks
Guide to the jungle of testing frameworksGuide to the jungle of testing frameworks
Guide to the jungle of testing frameworks
 
What's new in c# 8.0
What's new in c# 8.0What's new in c# 8.0
What's new in c# 8.0
 
Microservices Chaos Testing at Jet
Microservices Chaos Testing at JetMicroservices Chaos Testing at Jet
Microservices Chaos Testing at Jet
 
Ignite your app development with Angular, NativeScript and Firebase
Ignite your app development with Angular, NativeScript and FirebaseIgnite your app development with Angular, NativeScript and Firebase
Ignite your app development with Angular, NativeScript and Firebase
 
Functional Testing Swing Applications with Frankenstein
Functional Testing Swing Applications with FrankensteinFunctional Testing Swing Applications with Frankenstein
Functional Testing Swing Applications with Frankenstein
 
利用 Appium + Robot Framework 實現跨平台 App 互動測試
利用 Appium + Robot Framework 實現跨平台 App 互動測試利用 Appium + Robot Framework 實現跨平台 App 互動測試
利用 Appium + Robot Framework 實現跨平台 App 互動測試
 
Testing Angular
Testing AngularTesting Angular
Testing Angular
 
Unit testing and Android
Unit testing and AndroidUnit testing and Android
Unit testing and Android
 

Recently uploaded

E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
Hornet Dynamics
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
timtebeek1
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
Hironori Washizaki
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 

Recently uploaded (20)

E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 

Striking a Balance With UI Tests - ConnectTech

  • 1. Striking a Balance with UI Tests By: Jesse Black Software Engineer stable|kernel
 jesse.black@stablekernel.com
  • 2. @stablekernel Hi, I’m Jesse Black. • Programming for over nine years • Created a Mac App for my family business • Worked for 3 years with Gramercy Consultants developing iOS and Android apps • Working for stable|kernel for the past 4 years developing iOS apps, Android apps and their supporting APIs
  • 3. We’re stable|kernel. stable|kernel is an Atlanta-based mobile development company 
 to craft smartly-designed mobile applications that connect brands 
 directly with their users. 
 

  • 4. Striking a Balance with UI Tests @stablekernel Overview • General Testing • Demo: Introducing UI Tests • Improving UI Tests with Robots • Mocking Dependencies • Discussion
  • 5. Types of Tests @stablekernel • Manual testing • Automated testing • Unit / Integrated / End to End • Continuous Testing
  • 6. Unit Tests @stablekernel • Tests a small amount of code with limited inputs and output • Should be F.I.R.S.T. • Fast • Isolated • Repeatable • Self - Verifying • Timely
  • 7. Why test? @stablekernel • Fast feedback • Help prevent regressions • Improve code design
  • 9. Recording observations @stablekernel • Black box • User’s perspective • No Asserts (Assertion by tapping)
  • 10. Example: Login Error @stablekernel let app = XCUIApplication() let usernameTextField = app.textFields["Username"] usernameTextField.tap() usernameTextField.typeText("invalid") app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap() let passwordSecureTextField = app.secureTextFields["Password"] passwordSecureTextField.tap() passwordSecureTextField.typeText("invalid") app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap() app.buttons[“Login"].tap() app.alerts["Username and password combo not found."].buttons["OK"].tap()
  • 11. Example: Login Error @stablekernel let app = XCUIApplication() let usernameTextField = app.textFields["Username"] usernameTextField.tap() usernameTextField.typeText("invalid") app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap() let passwordSecureTextField = app.secureTextFields["Password"] passwordSecureTextField.tap() passwordSecureTextField.typeText("invalid") app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap() app.buttons[“Login"].tap() app.alerts["Username and password combo not found."].buttons["OK"].tap() • Scary strings • Will fail without network • Chunks of very similar code • Fragile tap to dismiss lines
  • 12. Wrangle user facing strings @stablekernel • Localize all user facing strings • Add localized string file to both targets; app and UI Test targets • Create abstraction around NSLocalizedString to avoid using stringly typed keys when accessing user facing strings
  • 13. Wrangle user facing string @stablekernel enum UIString: String { case usernamePlaceholder = "username-placeholder" func localized() -> String { return UIStringsHelper.getLocalizedString(key: rawValue) } } private class UIStringsHelper { static func getLocalizedString(key: String) -> String { let bundle = Bundle(for: UIStringsHelper.self) return NSLocalizedString(key, bundle: bundle, comment: "") } }
  • 14. Factor out user actions into Robots @stablekernel struct LoginRobot { let app: XCUIApplication var usernameTextField: XCUIElement { return app.textFields[UIString.usernamePlaceholder.localized()] } func dismissKeyboard() { app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element(boundBy: 0).tap() } func enterUsername(text: String) { usernameTextField.tap() usernameTextField.typeText(text) } }
  • 15. Example: Login Error Refactored @stablekernel func testInvalidCredentials() { loginRobot.enterUsername(text: "invalid@email") loginRobot.dismissKeyboard() loginRobot.enterPassword(text: "invalid") loginRobot.dismissKeyboard() loginRobot.loginButton.tap() let alertRobot = AlertRobot(app: XCUIApplication(), title: "Username and password combo not found.") alertRobot.dismiss(withButtonTitled: UIString.okButton.localized()) }
  • 16. Dependencies @stablekernel • Data persistence • Networks • Third Party Libraries
  • 18. Mock Example: Login Credentials @stablekernel // UI Test Setup override func setUp() { super.setUp() // ... XCUIApplication().launchArguments = [“USE_MOCK_LOGIN_STORE”, “HAS_SAVED_USERNAME”] XCUIApplication().launch() }
  • 19. Mock Example: Login Credentials @stablekernel protocol LoginCredentialsStore: class { func saveUsername(username: String?) func readUsername() -> String? }
  • 20. Mock Example: Login Credentials @stablekernel class MockLoginCredentialsStore: LoginCredentialsStore { var savedUsername: String? init() { if CommandLine.arguments.contains("HAS_SAVED_USERNAME") { savedUsername = "jesse.black@stablekernel.com" } } func saveUsername(username: String?) { savedUsername = username } func readUsername() -> String? { return savedUsername } }
  • 21. Realistic Goals @stablekernel • Automate screen shots of your app as you roll out changes • Be prepared for demos with stakeholders as you close out units of work • Increase confident that previously demoed work does not have any regressions
  • 23. Questions? Business Inquiries: Sarah Woodward Director of Business Development sarah.woodward@stablekernel.com Jesse Black Software Engineer jesse.black@stablekernel.com blog.stablekernel.com @JesseBlack82