Monday, April 20, 2026
HomeiOS DevelopmentThe last word information to unit and UI testing for novices in...

The last word information to unit and UI testing for novices in Swift

[ad_1]

Discover ways to write real-world Unit/UI take a look at instances on your iOS app. This one is a sensible 101 testing article for absolute novices.

Bitrise

Automated testing utilizing Xcode

In case you are working with Xcode you possibly can arrange two sorts of testing bundles:


Unit assessments

Testing particular person software program parts is named unit testing. This type of testing is often completed by the programmer and never by testers, as a result of it requires an in-depth data of the app’s inner design.


UI (consumer interface) assessments

UI testing helps you to take a look at interactions with the graphical consumer interface to be able to validate the GUI in opposition to the enterprise necessities, so principally checking if the buttons truly work or not.


Different kinds of testing

There are many different kinds of testing, however on this article I am not going to focus an excessive amount of on them since I am working with Xcode bundles. It is value mentioning although which you could make your personal e.g. regression take a look at bundle by utilizing the built-in take a look at bundles. In case you are interested in another methods of validating your software program you could find a short abstract right here.



Pretend, mock, stub, oh my spy… 😐

Earlier than we dive into sensible testing, we have to make clear some ideas. A number of builders are confused with these phrases, and I am not judging anyone, since they are often simply misinterpreted. In my dictionary:


Pretend

A pretend has the identical habits because the factor that it replaces.

Pretend objects are nearer to the true world implementation than stubs. Which means pretend objects often have the identical habits because the factor that they change. For instance a pretend login can return a pretend token identical to an precise API service would do (with actual information after all). They’re helpful if you would like to run assessments, since a complete service layer will be changed utilizing these objects.


Stub

A stub has a “fastened” set of “canned” responses which might be particular to your take a look at(s).

Stub objects are often hardcoded values which might be anticipated in some form of take a look at instances. They’re actually dumb, they do not comprise a lot logic, they’re simply pre-programmed objects with some fastened set of information. If I am going again to our pretend authentication instance, the response generally is a stub authorization token object together with some random consumer information.


Mock

A mock has a set of expectations for calls which might be made. If these expectations are usually not met, the take a look at fails.

Mock objects can change complete lessons and so they present the power to verify if specific strategies or properties have been referred to as or not. They will additionally return stub values as defaults, errors or throw exceptions if wanted. A mock has a set of expectations for calls, you possibly can verify these expectations in your assessments, if these are usually not met, your take a look at ought to fail.


Spy

If you use a spy then the true strategies are referred to as.

Spy objects can actually spy on present objects or strategies. That is helpful when you have got a much bigger class and you do not wish to mock every part, however you might be interested in some smaller piece of the interior habits of that object. You’ll be able to think about spy objects as wrappers round an present class. They do some spying and so they name the unique implementation afterwards.



Unit testing in observe

Now that you recognize the fundamentals, let’s write some sensible UI/Unit assessments in Swift. ⌨️


Wait… what the heck is a take a look at?

Properly the brief reply a take a look at is a perform that may have two distinct outcomes:

  • ✅ – success
  • ❌ – failure

Defining good a unit take a look at is difficult, however thankfully Vadim has some glorious articles about this subject, so it is best to undoubtedly verify his weblog as nicely. 😉


The anatomy of a unit take a look at goal in Xcode


A number of take a look at instances will be grouped collectively inside a category in Xcode. It is a neat option to write associated assessments for a software program element. Simply import the XCTest framework, (which can also be accessible for Linux), subclass the XCTestCase class and prefix your take a look at strategies with the take a look at key phrase to have the ability to take a look at them. 🔨


The setUp and tearDown strategies might be referred to as earlier than each single take a look at perform, however often I do not like to make use of them, I all the time provoke a brand new atmosphere for my assessments for each single case. The explanation behind that is that assessments can run in parallel, which is admittedly superb in case you have a lot of them. Additionally you do not wish to find yourself with some damaged take a look at case, simply due to some silly shared state or aspect impact.


Additionally it is best to observe that you must import your app goal as @testable import Goal in your take a look at goal so as to have the ability to attain your objects & strategies. This fashion you’ll take a look at your inner lessons and strategies as nicely. 📝


import XCTest
@testable import Instance

class ExampleTests: XCTestCase {

    override func setUp() {
        XCTAssertTrue(true)
        
    }

    override func tearDown() {
        
    }

    func testExample() {
        
    }

    func testPerformanceExample() {
        
        self.measure {
            
        }
    }

}



How ought to I write a take a look at?

Think about a way that validates an e-mail handle, which has an enter parameter (String), and a return worth (Bool). We do not care concerning the internals proper now, this technique is a black field, perhaps another person will write it, perhaps you’ll, from the purpose of unit testing it would not matter. Simply take into consideration the interface for now:

func validate(e-mail: String) -> Bool

Okay, so we have now our perform prototype, now take into consideration what sort of inputs can we give this perform, and what is going on to be the anticipated output:

  • "instance@handle.com" -> true
  • "my.private.handle@google.co.uk" -> true
  • "" -> false
  • "invalid@handle." -> false
  • "lorem ipsum dolor sit amet" -> false
  • "injection@instance.com; DROP TABLE customers" -> false
  • "✉️" -> false
  • "23983ujnvmfbbg73209refagjklnku129@adf@asdf.com" -> false

The aim of a unit take a look at is to catch all the sting instances. The built-in XCTest framework has some useful strategies to judge your assessments. So for instance, if you wish to make a easy unit take a look at to verify the end result in opposition to the enter examples from above, you may use the next features to judge your outcomes:


XCTAssert(validator.validate(e-mail: "my.private.handle@google.co.uk") == true)
XCTAssertTrue(validator.validate(e-mail: "instance@handle.com"))
XCTAssertFalse(validator.validate(e-mail: ""))
XCTAssertEqual(validator.validate(e-mail: "invalid@handle."), false)
XCTAssertNotEqual(validator.validate(e-mail: "lorem ipsum dolor sit amet"), true)


You can even present a customized failure message as a final parameter for each single assertion technique, however often I am simply superb with the default worth. 🤷‍♂️


What sort of unit assessments ought to I write?

Properly my fast reply is to consider the next situations first:

  • a case that’ll match your expectation (legitimate case)
  • invalid case (one thing that ought to elevate an error / exception)
  • edge instances (limitations like higher bounds of an integer)
  • harmful instances (particular inputs that may break your code)
  • monkey assessments (take a look at with utterly random values)

As you possibly can see, for the e-mail validation instance I principally adopted these primary guidelines. Simply take into consideration the pretty easy use instances, the principle objective right here is to not cowl each single one in every of them, however to get rid of essentially the most crucial situations.


What about async strategies?

You’ll be able to take a look at async strategies as nicely utilizing an expectation. You would possibly ask now:

What’s an expectation?

In case you heard about futures and guarantees, you will see that expectations are considerably related, besides that you do not have to offer a achievement worth and so they can by no means fail, however timeout. Vadim additionally has some good articles about unit testing async code in Swift and the busy assertion sample. I am not going into the small print, since we have now to cowl much more, however right here is how one can watch for one thing to occur:


func testAsyncMethod() {
    let expectation = XCTestExpectation(description: "We must always watch for the pattern async technique.")

    mySampleAysncMethod(delay: 2, response: "Hiya Async!") { [weak expectation] end result in
        XCTAssertEqual(end result, "Hiya Async!")
        expectation?.fulfill()
    }
    self.wait(for: [expectation], timeout: 3)
}


As you possibly can see, you simply should outline your expectation(s) first, then you definitely wait for them utilizing the wait technique with a given timeout parameter. When your async technique returns with a callback, you possibly can name fulfill in your expectation to mark it prepared. In case your expectations are usually not prepared earlier than the timeout… nicely the take a look at will fail. ☹️


Measure your code

Measurements are an effective way to hurry up slower components of your utility. If in case you have a way that appears to be gradual, you possibly can put it inside a measure block to verify its timings. You can even iterate the strategy a couple of (hundred) occasions, this manner you will get a greater baseline quantity.


func testSlowMethod() {
    self.measure {
        for _ in 0..<100 {
            slowMethodCall()
        }
    }
}


If you wish to know extra about measurements it is best to learn this superb article by Paul Hudson about the right way to optimize gradual code.

Run your take a look at & set a baseline by clicking the little grey indicator on the left. Subsequent time your take a look at runs you will see how a lot the code improved or wicked since final time.


When to jot down assessments?

Writing a take a look at takes time. Time is cash. ⏳ = 💰

I haven’t got time for assessments (press CMD+R to check a characteristic…)

However it could possibly additionally prevent loads of time, since you do not have to rebuild / rerun your complete utility simply to see if a perform works or not. In the long run, it is undoubtedly value it to have these assessments for no less than the enterprise logic of your utility. Within the brief time period you would possibly say you do not have the time, however after a couple of hundred guide assessments you would possibly end up in a state of affairs like this:

Oh man right here we go once more… (presses CMD+R to check a characteristic…)


TDD vs the common strategy?

I might say in case you have a very good specification and also you already understand how you’ll construct up your utility it is protected to go together with TDD and even BDD. In any other case if the undertaking is “agile” (meaning you will have fixed adjustments in your necessities) it could possibly lead you to place loads of work into fixing your code AND your take a look at instances.


When to check?

Anyway, in case you made the choice and you might be prepared to jot down your assessments, right here is my nr.1 tip: do not transfer on creating the following characteristic till you’ve reached your required protection, in any other case you will have an enormous tech debt sooner or later. I do know this for certain, I have been there, you do not wish to make this error, as a result of it is not enjoyable to jot down lots of of unit assessments without delay. Even a couple of actually primary assessments for a single performance is best than zero.


What to check?

I might say that it is best to take a look at primarily what you are promoting layer utilizing unit assessments. This generally is a presenter, or particular features inside a view controller, a supervisor or a service. It actually would not matter the place the implementation is, however till it does some form of “calculation” it is all the time good to have take a look at instances to validate that piece of code.

Additionally you possibly can’t merely cowl every part with unit assessments, generally you wish to verify some options that require consumer interactions…



UI testing in observe

Now that you’ve a greater understanding about how unit testing works, let’s discuss UI assessments. These sorts of assessments are actually helpful in case you do not wish to spend your time with the boring repetitive activity of attempting out stuff in your telephone on a regular basis throughout growth. Excellent news is that the iOS simulator can handle most of that.


The anatomy of a UI take a look at goal in Xcode

So as to have the ability to run UI assessments, it is best to arrange a brand new goal on your undertaking. Here’s a fast information that’ll present you the method if you do not know the right way to do it.


import XCTest

class TestUITests: XCTestCase {

    override func setUp() {
        
        continueAfterFailure = false

        
    }

    override func tearDown() {
        
    }

    func testExample() {
        
        let app = XCUIApplication()
        app.launch()

        
    }

    func testLaunchPerformance() {
        if #accessible(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
            
            measure(metrics: [XCTOSSignpostMetric.applicationLaunch]) {
                XCUIApplication().launch()
            }
        }
    }
}


A UI take a look at bundle is dynamically injected into your utility, so you possibly can’t merely provoke a view controller occasion for instance, however you must use a particular option to attain your UI components and carry out actions on them by way of:


Accessibility

Each single UI ingredient has an accessibilityIdentifier property by default. It is a string that uniquely identifies that view. In a while you possibly can question the view occasion by utilizing the beforehand related accessibility identifier, which is available in actually helpful since you aren’t allowed to provoke views immediately.

There’s a particular XCUIApplication (a reference to your working utility) object that has some useful properties to question references to numerous consumer interface components, similar to buttons, photographs, assortment views, and many others., you possibly can verify your complete accessibility cheat-sheet right here, however I am going to present you some examples in a while.

Okay, however what occurs after I do not wish to use accessibilityIdentifiers? Can I merely seize the UI hierarchy one way or the other and do some actions with out coding?


Ought to I file my UI assessments?

Properly, the factor is which you could simply press the file button in Xcode and the system will seize all of your consumer interactions routinely, however please do not try this.

Why do I choose coding? Properly:

  • the UI testing API is fairly easy
  • writing advanced UI assessments might be method sooner in case you be taught the accessibility API
  • generally you will not be capable to seize what you need utilizing the recorder
  • utilizing identifiers as a substitute of captured labels are higher (for localized assessments)
  • you do not all the time wish to get by way of the identical course of many times
  • studying new issues is enjoyable, a brand new API means extra data! 😀

Let’s try how easy it’s to jot down some UI assessments…


Writing iOS UI assessments programmatically

I choose to make use of accessibility identifiers for a number of causes. It isn’t only a very nice factor to make your app accessible for a a lot wider viewers, however in case you arrange each ingredient correctly accessible, writing UI assessments might be a bit of cake, since you possibly can question every part by its distinctive identifier. Let me present you a fast instance.



class ViewController: UIViewController {

    @IBOutlet weak var resultLabel: UILabel!
    @IBOutlet weak var inputField: UITextField!
    @IBOutlet weak var submitButton: UIButton!

    override func viewDidLoad() {
        tremendous.viewDidLoad()

        self.resultLabel.accessibilityIdentifier = "result-label"
        self.inputField.accessibilityIdentifier = "input-field"
        self.submitButton.accessibilityIdentifier = "submit-button"
    }
}


non-public extension XCUIApplication {
    var inputField: XCUIElement { self.textFields["input-field"] }
    var submitButton: XCUIElement { self.buttons["submit-button"] }
}

class TestUITests: XCTestCase {

    func testSubmitValue() {
        let app = XCUIApplication()
        app.launch()

        let expectation = "Hiya world"
        app.inputField.faucet()
        app.inputField.typeText(expectation)
        app.submitButton.faucet()

        XCTAssertTrue(app.staticTexts[expectation].exists)
    }
}


As you possibly can see I prolonged the XCUIApplication class, since I do not wish to take care of identifiers many times. It is a type of good / unhealthy habits I picked up since I needed to write a lot of UI take a look at instances. I am not 100% certain about it but, perhaps there’s a higher strategy however for me it was fairly handy and turned out to be actually useful. It is also non-public anyway so nobody else can see it. 🤫

Querying accessible consumer interface components is so simple as utilizing these extension properties, which is ridiculously handy. You should utilize the accessible strategies and properties on these XCUIElement cases, similar to exists, faucet, typeText, nonetheless you could find another challenges throughout the highway:


Deal with alerts

The primary impediment for me was interacting with iOS alert home windows. Happily Keith Harrison has an awesome article about dealing with system alerts in UI assessments. You need to undoubtedly verify in case you are working into the identical concern.


Scroll to cell

One other deal breaker is to simulate scrolling habits. Since accessibility actions are restricted to faucets and primary UI actions, this snippet helped me so much.


Person enter

Getting into consumer enter will be fairly difficult, since you must concentrate on the enter area first, however provided that the sector will not be chosen but, so watch out. You also needs to observe that plain textual content fields and safe textual content fields are separated into two distinct properties within the XCUIAppliaction object. Additionally placeholders are form of tough ones, as a result of the placeholderValue property adjustments in case you enter some textual content. ⚠️


Change system preferences

One humorous factor that you are able to do with UI testing is to alter a system choice by altering iOS settings. Right here you possibly can verify the right way to work together with the settings app.


The best way to write UI assessments?

Properly, there isn’t any definitive reply, as a result of your consumer interface is exclusive to your utility. Actually all of it is dependent upon you and your designer, however for me the important thing issue was utilizing accessibility identifiers and getting used to the accessibility queries and APIs. I feel it was value studying it, I can solely encourage you to get aware of the framework and mess around just some hours, you will not remorse it. 😉


When to jot down UI assessments?

It relies upon (do not hate me). These days, I choose to have a take a look at for all of the options I am engaged on, however generally I notice that I am merely tapping by way of my app doing guide testing. Outdated habits die arduous, proper? 😂

Ah overlook it, simply write assessments if you wish to save time in the long run. Within the brief time period you will solely see that every part takes longer to attain, however belief me if it involves bugs or sudden behaviours, having these assessments pays out massively. 💵



Steady integration and testing

On this part I’ll focus (a bit of bit) on Bitrise, since I feel they supply one of the best CI service in the marketplace for iOS builders proper now. 📱


Check stories

They’re engaged on some cool new (beta) options referred to as Add-ons. One among them is specializing in take a look at stories. This implies which you could see the end result of your assessments straight from the construct dashboard. The report display screen will offer you a fast abstract of all of the profitable and failed assessments outcomes, however you possibly can filter them by standing manually or verify particular person take a look at instances as nicely. Tremendous good, I like it. ❤️


Bitrise test results



Code protection

In pc science, take a look at protection is a measure used to explain the diploma to which the supply code of a program is executed when a specific take a look at suite runs.

Some say it is nothing only a quantity or a bunch of numbers. Properly, if it is true then why do individuals use analytics software program on a regular basis? I feel code protection must be enabled in each single Xcode undertaking by default.

There are some instruments referred to as xccov and slather. In case you run them on the CI and make the report accessible on your QA crew, they will actually see which a part of the app wants extra testing and what’s already checked by the automated assessments. I feel this can be a actually invaluable perception, however sadly most firms do not “have the sources” for devoted QA (and UX) groups. 🧠


Pull requests & automated code evaluate

One other good factor is which you could run your assessments earlier than you merge your adjustments into a particular department. This fashion you possibly can make sure that nothing severe is damaged within the undertaking. Automated assessments and code evaluate is a should on the subject of teamwork.

It actually would not matter in case your crew could be very little or an enormous one engaged on an infinite codebase, security is all the time security. Begin using the ability of automation at this time, do not waste your time on boring, repetitive duties. It’s going to assist your crew so much. 👍



Unit / UI testing finest practices

Once more I’ve to provide some credit score to Vadim, since he collected a pleasant record of unit testing finest practices on iOS with Swift. My record might be a bit of bit totally different…

All the time run assessments in parallel

As I discussed earlier than, it is best to use parallel testing to be able to pace up the entire course of. This implies which you could’t share states between assessments, which is an efficient factor. Do not be afraid, simply initialize a brand new “atmosphere” for each single time on your SUT (system underneath testing). If you do not know the right way to arrange parallel testing, it is best to learn this text.


Use the brand new take a look at plans format

There’s a new factor in Xcode 11 referred to as take a look at plans. It provides higher assist for testing a number of localisations, arguments, atmosphere and a lot extra. I do not wish to write down the strategy of changing to the brand new format, as a result of there may be one other weblog put up written about Check Plans in Xcode 11, I extremely suggest it.


Use mock / pretend / stub / spy objects

Do not use growth / manufacturing environments, however implement your personal simulated service layers (API, sensors e.g. CoreLocation, Bluetooth, and many others.). You should utilize a manufacturing facility design sample or dependency injection to attain this habits. This fashion you possibly can management the returned information and you do not have to attend for laggy networks. Utilizing a managed atmosphere for assessments is the precise option to go. Be at liberty to make use of as a lot mock / pretend / stub / spy object as you want, return errors or failures if wanted and hold your delays and timeouts low to complete your assessments sooner.


Solely launch a particular display screen for UI testing

If in case you have a big utility with a lot of screens you do not often wish to run by way of your complete login / onboarding process that you just often should throughout a clear begin, however you simply wish to take a look at the display screen that you’re engaged on. Is that this doable? Can I try this? Is that even authorized? 🤔

Haha, completely! As a way to launch a customized display screen first you must put together your app goal to assist it. You should utilize the launch arguments or the method data property to verify if a particular key exists and current a display screen based mostly on that. This requires a bit of bit extra work, additionally it is best to be capable to establish all of your screens one way or the other if you wish to do that, however that is why we have now routers, am I proper? #viper

Let me present you actually rapidly the right way to make it work.


import UIKit

func scene(_ scene: UIScene,
           willConnectTo session: UISceneSession,
           choices connectionOptions: UIScene.ConnectionOptions) {

    guard let windowScene = scene as? UIWindowScene else {
        return
    }
    let window = UIWindow(windowScene: windowScene)
    let processInfo = ProcessInfo.processInfo
    var moduleName = "Fundamental"
    if processInfo.arguments.comprises("-test") {
        if let identify = processInfo.atmosphere["module"] {
            moduleName = identify
        }
    }
    window.rootViewController = UIStoryboard(identify: moduleName, bundle: nil).instantiateInitialViewController()
    self.window = window
    self.window?.makeKeyAndVisible()
}


In your SceneDelegate.swift file you must instantiate your personal display screen (or ought to I name it module?) and go it to the window. The snippet above does the very same factor. First it checks if the processInfo comprises the -test flag, if that is true it will attempt to load the given module from the atmosphere.

It is fairly easy, however nonetheless we have now so as to add assist for launching our utility from the UI take a look at goal with these parameters. Let’s make an extension for that.


import XCTest

extension XCUIApplication {

    static func launchTest(module: String = "Fundamental") -> XCUIApplication {
        let app = XCUIApplication()
        app.launchArguments = ["-test"]
        app.launchEnvironment = ["module": module]
        app.launch()
        return app
    }
}


Right here is the right way to use the extension in observe:


func testHello() {
    let app = XCUIApplication.launchTest(module: "Hiya")

    XCTAssertTrue(app.staticTexts["Hello"].exists)
}


By utilizing this strategy you can begin with a given display screen, however nonetheless you would possibly have to pretend / mock / stub some companies or properties, since it is not an strange utility launch. Understand that you possibly can go a number of atmosphere variables round, and you may all the time verify the arguments if it comprises a given flag. 😉


Pace up your UI assessments by disabling animations

This one can actually prevent loads of time and it is very straightforward to implement.


if processInfo.arguments.comprises("-test") {
    UIView.setAnimationsEnabled(false)
    self.window?.layer.pace = 100
}


See? Just some traces of code, however the pace affect will be huge. 🚀


Designing your code for testability

Something is best than spaghetti code. MVP will be nicely examined, however some properly architected clear MVC sample can work as nicely. I just like the idea of presenters, since they encapsulate enterprise logic and often the presentation logic will be examined with no trouble. Transferring one step additional…


VIPER

Right here comes the “insert abbreviation right here” vs the overcomplicated VIPER structure holy battle once more… nope, not at this time. I actually do not care about your structure of alternative. What I care about is testability, however you possibly can’t actually take a look at a way that has a excessive complexity charge.

If you wish to have good take a look at protection, it is essential to separate your code into smaller chunks that may work collectively nicely. I all the time see unhealthy pattern codes with so many uncomfortable side effects, unhealthy perform APIs and plenty of extra ugly practices. I do know that piece of code generally has historic causes, however different occasions the programmer was simply merely a lazy bastard. 😴

All the time take into consideration your future self (and different programmers). Think about that you must return to your code in a 12 months or two… in case you write traces after traces with out pondering (and I might additionally say feedback, docs, take a look at instances right here as nicely) you might need loads of issues in a while, as a result of nobody will be capable to determine what you wished to attain.

Breaking your code into smaller useful items is crucial takeaway right here. This strategy can even be useful on your API designer mindset and the testability of your codebase.

In case you are utilizing VIPER you have got a very easy activity to do. Write unit assessments solely on your presenter and interactor strategies. In fact in case you are following my service layer based mostly VIPER strategy (Vapor is doing this as nicely and it is superb) it is best to take a look at your complete service layer API. It would not make an excessive amount of sense to unit take a look at a UI element, or a routing habits, you need to use the UI take a look at bundle for these duties.


Work & take a look at regionally, “regression” take a look at on CI

I choose to solely run these assessments regionally that I am engaged on. All the things else belongs to the continual integration server (CI). I do not wish to waste my time and {hardware} by working 500 assessments on my mac, there isn’t any want for that. Setup a CI service and run your assessments there whether or not it is regression, acceptance or integration.

You can even run assessments from the command line, plus if it is advisable, you possibly can go round atmosphere variables, for instance if you must take care of delicate information.



Conclusion

Some individuals love to jot down assessments and a few individuals hate, however one factor is for certain: assessments will make your code safer and extra dependable. If in case you have by no means written any assessments earlier than I might say it is best to begin forming a behavior and begin it now. The whole steady integration and supply business was born that will help you with this, so do not waste your valuable time… oh and begin utilizing Bitrise! 🤖


[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments