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

0/5 No votes

Report this app

Description

[ad_1]

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

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 achieved by the programmer and never by testers, as a result of it requires an in-depth data of the app’s inside design.


UI (person interface) assessments

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


Different forms of testing

There are many different forms 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 price mentioning although which you could make your individual e.g. regression take a look at bundle through the use of 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 lot of builders are confused with these phrases, and I am not judging anyone, since they are often simply misinterpreted. In my dictionary:


Pretend

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

Pretend objects are nearer to the true world implementation than stubs. Which means that faux objects often have the identical conduct because the factor that they substitute. For instance a faux login can return a faux token similar to an precise API service would do (with actual knowledge in fact). They’re helpful if you would like to run assessments, since a whole service layer will be changed utilizing these objects.


Stub

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

Stub objects are often 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 fastened set of information. If I’m going again to our faux authentication instance, the response could be a stub authorization token object together with some random person knowledge.


Mock

A mock has a set of expectations for calls which are made. If these expectations aren’t met, the take a look at fails.

Mock objects can substitute whole lessons and so they present the flexibility to verify 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 possibly can verify these expectations in your assessments, if these aren’t met, your take a look at ought to fail.


Spy

While 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 may have an even bigger class and you do not wish to mock all the things, however you might be interested in some smaller piece of the interior conduct 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 understand 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 operate that may have two distinct outcomes:

  • ✅ – success
  • ❌ – failure

Defining good a unit take a look at is tough, however luckily Vadim has some wonderful articles about this matter, so you must 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 circumstances will be grouped collectively inside a category in Xcode. It is a neat approach to write associated assessments for a software program element. Simply import the XCTest framework, (which can be obtainable 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 will probably be referred to as earlier than each single take a look at operate, however often I do not like to make use of them, I at all times provoke a brand new surroundings for my assessments for each single case. The explanation behind that is that assessments can run in parallel, which is de facto wonderful when 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 observe 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 manner you can take a look at your inside 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 tackle, which has an enter parameter (String), and a return worth (Bool). We do not care in regards to the internals proper now, this methodology 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’ve our operate prototype, now take into consideration what sort of inputs can we give this operate, 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 verify the consequence in opposition to the enter examples from above, you might 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)


You may also present a customized failure message as a final parameter for each single assertion methodology, however often I am simply high quality 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 elevate an error / exception)
  • edge circumstances (limitations like higher bounds of an integer)
  • harmful circumstances (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 largely adopted these primary guidelines. Simply take into consideration the pretty easy use circumstances, the principle purpose right here is to not cowl each single one among them, however to eradicate probably the most important eventualities.


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?

If you happen to heard about futures and guarantees, you will see that expectations are considerably related, besides that you do not have to supply 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’ve 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 methodology.")

    mySampleAysncMethod(delay: 2, response: "Hi there Async!") { [weak expectation] consequence in
        XCTAssertEqual(consequence, "Hi there 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 methodology with a given timeout parameter. When your async methodology returns with a callback, you possibly can name fulfill in your expectation to mark it prepared. In case your expectations aren’t 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 software. You probably have a way that appears to be sluggish, you possibly can put it inside a measure block to verify its timings. You may also iterate the strategy a couple of (hundred) instances, 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 wonderful article by Paul Hudson about find out how 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 will see how a lot the code improved or wicked since final time.


When to write 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 may possibly additionally prevent a whole lot of time, since you do not have to rebuild / rerun your whole software simply to see if a operate works or not. In the long run, it is undoubtedly price it to have these assessments for at the very least the enterprise logic of your software. 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 function…)


TDD vs the common method?

I would say when you have a extremely good specification and also you already know the way you’ll construct up your software it is protected to go together with TDD and even BDD. In any other case if the venture is “agile” (meaning you will have fixed modifications in your necessities) it may possibly lead you to place a whole lot of work into fixing your code AND your take a look at circumstances.


When to check?

Anyway, for those who made the choice and you might be prepared to write down your assessments, right here is my nr.1 tip: do not transfer on growing the subsequent function 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 positive, I have been there, you do not wish to make this error, as a result of it isn’t enjoyable to write down lots of of unit assessments directly. Even a couple of actually primary assessments for a single performance is best than zero.


What to check?

I would say that you must take a look at primarily your enterprise layer utilizing unit assessments. This could be 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 at all times good to have take a look at circumstances to validate that piece of code.

Additionally you possibly can’t merely cowl all the things with unit assessments, typically you wish to verify some options that require person interactions…



UI testing in observe

Now that you’ve got a greater understanding about how unit testing works, let’s speak about UI assessments. These sorts of assessments are actually helpful for those who do not wish to spend your time with the boring repetitive activity of attempting out stuff in your cellphone 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, you must arrange a brand new goal to your venture. Here’s a fast information that’ll present you the method if you do not know find out how 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 #obtainable(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 software, so you possibly can’t merely provoke a view controller occasion for instance, however it’s important to use a particular approach to attain your UI components and carry out actions on them via:


Accessibility

Each single UI component has an accessibilityIdentifier property by default. It is a string that uniquely identifies that view. Afterward you possibly can question the view occasion through the use of the beforehand related accessibility identifier, which is available in actually useful since you aren’t allowed to provoke views immediately.

There’s a particular XCUIApplication (a reference to your operating software) object that has some useful properties to question references to varied person interface components, reminiscent of buttons, pictures, assortment views, and so on., you possibly can verify your complete accessibility cheat-sheet right here, however I am going to present you some examples afterward.

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


Ought to I report my UI assessments?

Properly, the factor is which you could simply press the report button in Xcode and the system will seize all of your person interactions mechanically, however please do not do this.

Why do I choose coding? Properly:

  • the UI testing API is fairly easy
  • writing complicated UI assessments will probably be approach sooner for those who be taught the accessibility API
  • typically 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 at all times wish to get via the identical course of time and again
  • studying new issues is enjoyable, a brand new API means extra data! 😀

Let’s take a look at how easy it’s to write 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 obtainable for a a lot wider viewers, however for those who arrange each component correctly accessible, writing UI assessments will probably be a chunk of cake, since you possibly can question all the things 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 possibly can see I prolonged the XCUIApplication class, since I do not wish to take care of identifiers time and again. It is a type of good / unhealthy habits I picked up since I needed to write plenty of UI take a look at circumstances. I am not 100% positive 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 obtainable person interface components is so simple as utilizing these extension properties, which is ridiculously handy. You should utilize the obtainable strategies and properties on these XCUIElement situations, reminiscent of exists, faucet, typeText, nonetheless you could find another challenges in the course of the street:


Deal with alerts

The primary impediment for me was interacting with iOS alert home windows. Happily Keith Harrison has an excellent article about dealing with system alerts in UI assessments. It’s best to undoubtedly verify in case you are operating into the identical challenge.


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 quite a bit.


Person enter

Coming into person enter will be fairly difficult, since it’s important to give attention to the enter subject first, however provided that the sphere shouldn’t be chosen but, so watch out. You must also 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 modifications for those who 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 find out how 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 person interface is exclusive to your software. Actually all of it depends 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 price 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 write 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 typically I understand that I am merely tapping via my app doing guide testing. Previous habits die onerous, proper? 😂

Ah neglect it, simply write assessments if you wish to save time in the long run. Within the brief time period you will solely see that all the things takes longer to realize, however belief me if it involves bugs or sudden behaviours, having these assessments can pay out massively. 💵



Steady integration and testing

On this part I will focus (a bit bit) on Bitrise, since I feel they supply the most effective CI service available on the market for iOS builders proper now. 📱


Take a look at stories

They’re engaged on some cool new (beta) options referred to as Add-ons. One in every of 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 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 circumstances as nicely. Tremendous good, I find it irresistible. ❤️


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 folks use analytics software program on a regular basis? I feel code protection ought to be enabled in each single Xcode venture by default.

There are some instruments referred to as xccov and slather. If you happen to run them on the CI and make the report obtainable to 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 it is a actually useful perception, however sadly most firms do not “have the sources” for devoted QA (and UX) groups. 🧠


Pull requests & automated code assessment

One other good factor is which you could run your assessments earlier than you merge your modifications into a particular department. This manner you possibly can be sure that nothing critical is damaged within the venture. Automated assessments and code assessment is a should in terms of teamwork.

It actually would not matter in case your crew may be very little or an enormous one engaged on an unlimited codebase, security is at all times security. Begin using the ability of automation as we speak, do not waste your time on boring, repetitive duties. It will assist your crew quite a bit. 👍



Unit / UI testing finest practices

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

All the time run assessments in parallel

As I discussed earlier than, you must use parallel testing with a purpose to velocity 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 “surroundings” for each single time to your SUT (system beneath testing). If you do not know find out how 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, surroundings 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 Take a look at Plans in Xcode 11, I extremely advocate it.


Use mock / faux / stub / spy objects

Do not use growth / manufacturing environments, however implement your individual simulated service layers (API, sensors e.g. CoreLocation, Bluetooth, and so on.). You should utilize a manufacturing unit design sample or dependency injection to realize this conduct. This manner you possibly can management the returned knowledge and you do not have to attend for laggy networks. Utilizing a managed surroundings for assessments is the precise approach to go. Be happy to make use of as a lot mock / faux / 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 for UI testing

You probably have a huge software with plenty of screens you do not often wish to run via 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 that you’re engaged on. Is that this potential? Can I do this? Is that even authorized? 🤔

Haha, completely! In an effort to launch a customized display first it’s important to put together your app goal to assist it. You should utilize the launch arguments or the method information property to verify if a particular key exists and current a display primarily based on that. This requires a bit bit extra work, additionally you must be capable to determine all of your screens in some way if you wish to do that, however that is why we’ve routers, am I proper? #viper

Let me present you actually rapidly find out how 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 = "Foremost"
    if processInfo.arguments.incorporates("-test") {
        if let identify = processInfo.surroundings["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 individual display (or ought to I name it module?) and move it to the window. The snippet above does the very same factor. First it checks if the processInfo incorporates the -test flag, if that is true it will attempt to load the given module from the surroundings.

It is fairly easy, however nonetheless we’ve so as to add assist for launching our software 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 = "Foremost") -> XCUIApplication {
        let app = XCUIApplication()
        app.launchArguments = ["-test"]
        app.launchEnvironment = ["module": module]
        app.launch()
        return app
    }
}


Right here is find out how to use the extension in observe:


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 would possibly have to faux / mock / stub some companies or properties, since it isn’t an unusual software launch. Remember that you possibly can move a number of surroundings variables round, and you may at all times verify the arguments if it incorporates a given flag. 😉


Velocity up your UI assessments by disabling animations

This one can actually prevent a whole lot of time and it’s extremely straightforward to implement.


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


See? Just some strains of code, however the velocity impression 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 out a trouble. Transferring one step additional…


VIPER

Right here comes the “insert abbreviation right here” vs the overcomplicated VIPER structure holy struggle once more… nope, not as we speak. 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 at all times see unhealthy pattern codes with so many unwanted side effects, unhealthy operate APIs and lots of extra ugly practices. I do know that piece of code typically has historic causes, however different instances the programmer was simply merely a lazy bastard. 😴

All the time 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… for those who write strains after strains 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 afterward, as a result of nobody will be capable to determine what you wished to realize.

Breaking your code into smaller practical items is crucial takeaway right here. This method may even be helpful to your API designer mindset and the testability of your codebase.

In case you are utilizing VIPER you may have a very easy activity to do. Write unit assessments solely to your presenter and interactor strategies. In fact in case you are following my service layer primarily based VIPER method (Vapor is doing this as nicely and it is wonderful) you must take a look at your whole 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 should utilize 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 little thing else belongs to the continual integration server (CI). I do not wish to waste my time and {hardware} by operating 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.

You may also run assessments from the command line, plus if it is advisable to, you possibly can move round surroundings variables, for instance if it’s important to take care of delicate knowledge.



Conclusion

Some folks love to write down assessments and a few folks hate, however one factor is for positive: assessments will make your code safer and extra dependable. You probably 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 trade was born that will help you with this, so do not waste your valuable time… oh and begin utilizing Bitrise! 🤖


[ad_2]

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.