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

[ad_1]

Learn to write real-world Unit/UI take a look at circumstances in your iOS app. This one is a sensible 101 testing article for absolute novices.

Bitrise

Automated testing utilizing Xcode

If you’re working with Xcode you’ll be able to arrange two sorts of testing bundles:


Unit assessments

Testing particular person software program elements is named unit testing. This sort of testing is normally finished by the programmer and never by testers, as a result of it requires an in-depth information 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 with a view to validate the GUI towards the enterprise necessities, so mainly checking if the buttons really work or not.


Different sorts of testing

There are many different sorts 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 that you would be able to make your personal e.g. regression take a look at bundle by utilizing the built-in take a look at bundles. If you’re interested in another methods of validating your software program you’ll find a short abstract right here.



Faux, mock, stub, oh my spy… 😐

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


Faux

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

Faux objects are nearer to the true world implementation than stubs. Which means that pretend objects normally have the identical conduct 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 may be changed utilizing these objects.


Stub

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

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


Mock

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

Mock objects can change complete courses they usually present the power to examine if explicit strategies or properties have been referred to as or not. They’ll additionally return stub values as defaults, errors or throw exceptions if wanted. A mock has a set of expectations for calls, you’ll be able to examine these expectations in your assessments, if these will not be met, your take a look at ought to fail.


Spy

Once 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’ve an even bigger class and you do not wish to mock every thing, however you might be interested in some smaller piece of the inner conduct of that object. You’ll be able to think about spy objects as wrappers round an present class. They do some spying they usually name the unique implementation afterwards.



Unit testing in apply

Now that 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 tough, however luckily Vadim has some glorious articles about this matter, so you must positively examine his weblog as nicely. 😉


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


A number of take a look at circumstances may be grouped collectively inside a category in Xcode. This can be a neat method to write associated assessments for a software program element. Simply import the XCTest framework, (which can also be out there 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 shall be referred to as earlier than each single take a look at perform, however normally I do not like to make use of them, I all the time provoke a brand new setting for my assessments for each single case. The rationale behind that is that assessments can run in parallel, which is admittedly superb if in case you have plenty 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 facet impact.


Additionally you must word that it’s important to 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 can take a look at your inner courses 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 technique that validates an e-mail tackle, 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, possibly another person will write it, possibly 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:


The aim of a unit take a look at is to catch all the sting circumstances. 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 examine the end result towards the enter examples from above, you possibly can use the next capabilities to judge your outcomes:


XCTAssert(validator.validate(e-mail: "[email protected]") == true)
XCTAssertTrue(validator.validate(e-mail: "[email protected]"))
XCTAssertFalse(validator.validate(e-mail: ""))
XCTAssertEqual(validator.validate(e-mail: "[email protected]"), false)
XCTAssertNotEqual(validator.validate(e-mail: "lorem ipsum dolor sit amet"), true)


It’s also possible to present a customized failure message as a final parameter for each single assertion technique, however normally I am simply nice with the default worth. 🤷‍♂️


What sort of unit assessments ought to I write?

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

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

As you’ll be able to see, for the e-mail validation instance I largely adopted these primary guidelines. Simply take into consideration the pretty easy use circumstances, the principle objective right here is to not cowl each single considered one of them, however to remove probably the most vital eventualities.


What about async strategies?

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

What’s an expectation?

Should you heard about futures and guarantees, you may see that expectations are considerably related, besides that you do not have to offer a success worth they usually 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 should always watch for the pattern async technique.")

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


As you’ll be able to see, you simply should outline your expectation(s) first, you then wait for them utilizing the wait technique with a given timeout parameter. When your async technique returns with a callback, you’ll be able to name fulfill in your expectation to mark it prepared. In case your expectations will not be 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 elements of your utility. In case you have a technique that appears to be sluggish, you’ll be able to put it inside a measure block to examine its timings. It’s also possible to iterate the strategy just a few (hundred) occasions, this fashion you will get a greater baseline quantity.


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


If you wish to know extra about measurements you must learn this superb article by Paul Hudson about the way to optimize sluggish 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 may 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 function…)

Then again it might additionally prevent a whole lot 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 positively value it to have these assessments for at the least the enterprise logic of your utility. Within the brief time period you may say you do not have the time, however after just a few hundred guide assessments you may end up in a state of affairs like this:

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


TDD vs the common method?

I would say if in case you have a extremely 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 mission is “agile” (meaning you may have fixed modifications in your necessities) it might lead you to place a whole lot of work into fixing your code AND your take a look at circumstances.


When to check?

Anyway, in the event 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 subsequent function till you’ve reached your required protection, in any other case you may 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 isn’t enjoyable to jot down a whole lot of unit assessments directly. Even just a few actually primary assessments for a single performance is healthier than zero.


What to check?

I would say that you must take a look at primarily your online business layer utilizing unit assessments. This is usually a presenter, or particular capabilities 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 circumstances to validate that piece of code.

Additionally you’ll be able to’t merely cowl every thing with unit assessments, generally you wish to examine some options that require consumer interactions…



UI testing in apply

Now that you’ve a greater understanding about how unit testing works, let’s speak about UI assessments. These sorts of assessments are actually helpful in the event you do not wish to spend your time with the boring repetitive activity of making an attempt out stuff in your telephone on a regular basis throughout growth. Excellent news is that the iOS simulator can maintain 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, you must arrange a brand new goal in your mission. Here’s a fast information that’ll present you the method if you do not know the 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 #out there(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’ll be able to’t merely provoke a view controller occasion for instance, however it’s important to use a particular method to attain your UI components and carry out actions on them via:


Accessibility

Each single UI aspect has an accessibilityIdentifier property by default. It is a string that uniquely identifies that view. Afterward you’ll be able to 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 varied consumer interface components, corresponding to buttons, photos, assortment views, and so forth., you’ll be able to examine your complete accessibility cheat-sheet right here, however I will present you some examples in a while.

Okay, however what occurs once I do not wish to use accessibilityIdentifiers? Can I merely seize the UI hierarchy someway and do some actions with out coding?


Ought to I document my UI assessments?

Properly, the factor is that you would be able to simply press the document 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 complicated UI assessments shall be manner sooner in the event you be taught the accessibility API
  • generally you will not be capable of seize what you need utilizing the recorder
  • utilizing identifiers as an alternative of captured labels are higher (for localized assessments)
  • you do not all the time wish to get via the identical course of time and again
  • studying new issues is enjoyable, a brand new API means extra information! 😀

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 is not only a very nice factor to make your app out there for a a lot wider viewers, however in the event you arrange each aspect correctly accessible, writing UI assessments shall be a bit of cake, since you’ll be able to question every thing 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 = "Hi there world"
        app.inputField.faucet()
        app.inputField.typeText(expectation)
        app.submitButton.faucet()

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


As you’ll be able to see I prolonged the XCUIApplication class, since I do not wish to cope with identifiers time and again. It is a kind of good / dangerous habits I picked up since I needed to write plenty of UI take a look at circumstances. I am not 100% certain about it but, possibly there’s a higher method 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 out there consumer interface components is so simple as utilizing these extension properties, which is ridiculously handy. You should use the out there strategies and properties on these XCUIElement situations, corresponding to exists, faucet, typeText, nonetheless you’ll find another challenges throughout the highway:


Deal with alerts

The primary impediment for me was interacting with iOS alert home windows. Luckily Keith Harrison has an amazing article about dealing with system alerts in UI assessments. It is best to positively examine in case you are working into the identical situation.


Scroll to cell

One other deal breaker is to simulate scrolling conduct. Since accessibility actions are restricted to faucets and primary UI actions, this snippet helped me rather a lot.


Person enter

Getting into consumer enter may be fairly difficult, since it’s important to deal with the enter discipline first, however provided that the sector is just not chosen but, so watch out. You must also word 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 modifications in the event 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’ll be able to examine the way to work together with the settings app.


How you can write UI assessments?

Properly, there is no such thing as a definitive reply, as a result of your consumer interface is exclusive to your utility. Actually all of it is determined by 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 acquainted with 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 understand that I am merely tapping via my app doing guide testing. Outdated habits die laborious, proper? 😂

Ah overlook it, simply write assessments if you wish to save time in the long run. Within the brief time period you may solely see that every thing 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 will focus (somewhat bit) on Bitrise, since I feel they supply the most effective CI service in the marketplace for iOS builders proper now. 📱


Check reviews

They’re engaged on some cool new (beta) options referred to as Add-ons. One among them is specializing in take a look at reviews. This implies that you would be able to see the end result of your assessments straight from the construct dashboard. The report display will give you a fast abstract of all of the profitable and failed assessments outcomes, however you’ll be able to filter them by standing manually or examine particular person take a look at circumstances as nicely. Tremendous good, I adore 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 selected 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 needs to be enabled in each single Xcode mission by default.

There are some instruments referred to as xccov and slather. Should you run them on the CI and make the report out there in your QA workforce, they’ll actually see which a part of the app wants extra testing and what’s already checked by the automated assessments. I feel it is a actually priceless perception, however sadly most firms do not “have the assets” for devoted QA (and UX) groups. 🧠


Pull requests & automated code evaluate

One other good factor is that you would be able to run your assessments earlier than you merge your modifications into a selected department. This fashion you’ll be able to be certain that nothing critical is damaged within the mission. Automated assessments and code evaluate is a should relating to teamwork.

It actually would not matter in case your workforce may be very little or an enormous one engaged on an unlimited codebase, security is all the time security. Begin using the facility of automation right now, do not waste your time on boring, repetitive duties. It’s going to assist your workforce rather a lot. 👍



Unit / UI testing finest practices

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

At all times run assessments in parallel

As I discussed earlier than, you must use parallel testing with a view to velocity up the entire course of. This implies that you would be able to’t share states between assessments, which is an efficient factor. Do not be afraid, simply initialize a brand new “setting” for each single time in your SUT (system below testing). If you do not know the way to arrange parallel testing, you must 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, setting 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’s one other weblog put up written about Check Plans in Xcode 11, I extremely advocate 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 so forth.). You should use a manufacturing unit design sample or dependency injection to attain this conduct. This fashion you’ll be able to management the returned information and you do not have to attend for laggy networks. Utilizing a managed setting for assessments is the best method to go. Be happy to make use of as a lot mock / pretend / stub / spy object as you want, return errors or failures if wanted and maintain your delays and timeouts low to complete your assessments sooner.


Solely launch a selected display for UI testing

In case you have a big utility with plenty of screens you do not normally wish to run via your complete login / onboarding process that you simply normally should throughout a clear begin, however you simply wish to take a look at the display that you’re engaged on. Is that this potential? Can I try this? Is that even authorized? 🤔

Haha, completely! With a view to launch a customized display first it’s important to put together your app goal to assist it. You should use the launch arguments or the method data property to examine if a selected key exists and current a display based mostly on that. This requires somewhat bit extra work, additionally you must be capable of determine all of your screens someway if you wish to do that, however that is why we have now routers, am I proper? #viper

Let me present you actually shortly the 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 = "Principal"
    if processInfo.arguments.comprises("-test") {
        if let identify = processInfo.setting["module"] {
            moduleName = identify
        }
    }
    window.rootViewController = UIStoryboard(identify: moduleName, bundle: nil).instantiateInitialViewController()
    self.window = window
    self.window?.makeKeyAndVisible()
}


In your SceneDelegate.swift file it’s important to instantiate your personal display (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’s going to attempt to load the given module from the setting.

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 = "Principal") -> XCUIApplication {
        let app = XCUIApplication()
        app.launchArguments = ["-test"]
        app.launchEnvironment = ["module": module]
        app.launch()
        return app
    }
}


Right here is the way to use the extension in apply:


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

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


By utilizing this method you can begin with a given display, however nonetheless you may must pretend / mock / stub some companies or properties, since it isn’t an odd utility launch. Take into account that you’ll be able to go a number of setting variables round, and you’ll all the time examine the arguments if it comprises a given flag. 😉


Velocity up your UI assessments by disabling animations

This one can actually prevent a whole lot of time and it is very straightforward to implement.


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


See? Only a few traces of code, however the velocity influence may be huge. 🚀


Designing your code for testability

Something is healthier than spaghetti code. MVP may 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 normally the presentation logic may be examined with out a problem. Shifting one step additional…


VIPER

Right here comes the “insert abbreviation right here” vs the overcomplicated VIPER structure holy struggle once more… nope, not right now. I actually do not care about your structure of selection. What I care about is testability, however you’ll be able to’t actually take a look at a technique that has a excessive complexity price.

If you wish to have good take a look at protection, it is vital to separate your code into smaller chunks that may work collectively nicely. I all the time see dangerous pattern codes with so many uncomfortable side effects, dangerous 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. 😴

At all times take into consideration your future self (and different programmers). Think about that it’s important to return to your code in a 12 months or two… in the event you write traces after traces with out pondering (and I might additionally say feedback, docs, take a look at circumstances right here as nicely) you might need a whole lot of issues in a while, as a result of nobody will be capable of determine what you needed to attain.

Breaking your code into smaller practical items is an important takeaway right here. This method may also be helpful in your API designer mindset and the testability of your codebase.

If you’re utilizing VIPER you’ve a very easy activity to do. Write unit assessments solely in your presenter and interactor strategies. In fact in case you are following my service layer based mostly VIPER method (Vapor is doing this as nicely and it is superb) you must 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 conduct, 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. Every thing 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 is no such thing as a want for that. Setup a CI service and run your assessments there whether or not it is regression, acceptance or integration.

It’s also possible to run assessments from the command line, plus if you want to, you’ll be able to go round setting variables, for instance if it’s important to cope with 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. In case you have by no means written any assessments earlier than I would say you must begin forming a behavior and begin it now. Your entire steady integration and supply business was born that will help you with this, so do not waste your treasured time… oh and begin utilizing Bitrise! 🤖


[ad_2]

Leave a Reply