## Make UI testing that bit easier!

Photo by ShareGrid on Unsplash
Difficulty: Beginner | Easy | Normal | Challenging
This article has been developed using Xcode 12.0, and Swift 5.3
- You will be expected to be aware how to make a Single View Application, or a Playground to run Swift code
Snapshot testing: A way to test UI by rendering a UI component, take a snapshot, and then compare it to a reference snapshot file
UBER have ios-snapshot-test-case. At the time of writing, this library does not support Swfit Package Manager - and as I result I used PODS to install this dependency (adding the following in my Podfile)
target 'SnapshotTestingTests' do
inherit! :search_paths
# Pods for testing
pod 'iOSSnapshotTestCase'
endmeaning the reader should use SnapshotTesting.xcworkspace to open this project, and if you have downloaded the repo you are probably best served by performing a pod update in the downloaded/cloned folder.
The following needs to be added to the Run scheme
FB_REFERENCE_IMAGE_DIR = $(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages
IMAGE_DIFF_DIR = $(SOURCE_ROOT)/$(PROJECT_NAME)Tests/FailureDiffs
So we get there by going to Project>Edit scheme
Then clicking Run
The clicking Arguments
Then click the + under Environment Variables
We can then...
Create a new Unit Test Case
File>New>File...
I called my file TestList and saved as usual.
Here is my sample test:
class TestList: FBSnapshotTestCase {
override func setUp() {
super.setUp()
recordMode = true
}
func testList() {
let networkManager = MockNetworkManager(session: URLSession.shared)
networkManager.outputData = photoString.data(using: .utf8)
let listVM = ListViewModel(manager: networkManager)
let list = ListViewController(viewModel: listVM)
FBSnapshotVerifyViewController(list)
}
}We get an error!
failed - Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!Oh dear!
But it isn't as bad as it might seem - reference images have been added in a rather fantastic folder!
So to check against this reference image, we remove the recodeMode!
class TestList: FBSnapshotTestCase {
override func setUp() {
super.setUp()
recordMode = false
}
func testList() {
let networkManager = MockNetworkManager(session: URLSession.shared)
networkManager.outputData = photoString.data(using: .utf8)
let listVM = ListViewModel(manager: networkManager)
let list = ListViewController(viewModel: listVM)
FBSnapshotVerifyViewController(list)
}
}which will match, but if we now change the code to pull in emptyString:
class TestList: FBSnapshotTestCase {
override func setUp() {
super.setUp()
recordMode = false
}
func testList() {
let networkManager = MockNetworkManager(session: URLSession.shared)
networkManager.outputData = emptyString.data(using: .utf8)
let listVM = ListViewModel(manager: networkManager)
let list = ListViewController(viewModel: listVM)
FBSnapshotVerifyViewController(list)
}
}The code even "notices" if I change just one character in the screenshot.
you are even provided with diff images!

What happens if you change device, though? Of course the test will fail!
This is quite automatic - you just need to decide when to record the screenshots.
Your test team will thank you - they can just go through your screenshots and check if they are correct - fantastic!
Who else will thank you? You will thank you when you find those bugs that are hiding in your code!
If you've any questions, comments or suggestions please hit me up on Twitter



