Inline Temp Refactoring in Swift

In “Refactoring, Improving the Design of Existing Code” by Martin Fowler, he presents the Inline Temp refactoring.

Here’s a video walkthrough of the Inline Temp refactoring in Swift and when you might want to use it:

Video Transcription

Hey, what’s up everybody? It’s Andy from cleanswifter.com and I’m here to show you another refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” This week we’re looking at a refactoring called “Inline Temp.” Inline temp is one that once you learn it, you’ll realize that you’ve been using all over for a while. Essentially what inline temp does, is that when you have a temporary variable that’s only ever written to once, you can remove that variable, and move the computation that assigns it a value into every other place it’s read. The benefit of doing this, is that it can actually help you do a larger refactoring. For example, say you had a piece of code you wanted to apply Extract Method to, if you’re using a temporary variable within that code, it might be hard to extract because, what could happen is that the temp variable could be declared many lines above the code that you want to extract, and if you extract that method, the reference to the temp variable will be lost. You’ll have to figure out how to recreate it within the extracted method. What you can easily end up doing though is inline the temp. Take whatever computation that initially populates the value (that is only getting a value written to it once), and then, replace the reference to the temporary variable in the code that you’re trying to extract with a call to the method that provides the initial value. Let’s take a look at some Swift code and see it in action.

Example

Here’s some code that is a pretty simple view controller. We’re overriding viewDidLoad() and there’s another method in here called getAppTitle(). getAppTitle() is fairly simple in that it is just returning a static string. Use your imagination here. Imagine it is calling another class that is doing something more interesting to retrieve the app title. The code that I want to apply this refactoring to is actually up here, in viewDidLoad(). You can see in viewDidLoad(), we have a temporary variable created, titleString, and that is populated from getAppTitle(). titleString is then used in two different places. It’s used first to create a label, and then set that string as the text on the label, and add it as a subview on the view. titleString is then used again later on to be set as the title on the view controller. The first indication here that we can use the inline temp refactoring is that the Swift compiler is prompting us with a warning saying that we have declared this variable as a var despite it never being mutated, which means never changed. The Swift compiler is suggesting to us that it can be defined as a let which is a constant. I’ll never be able to write to that again. To show this, if I try to assign a new value to it, now that it is defined as a let, the Swift compiler will tell me I can’t do that. What I’m getting at here is that a variable defined with let and used as a temp, it’s a good candidate to be ready for inline temp refactoring. The refactoring here is that I’m going to delete this line of code. First I’m going to then take the code that defines the value, and the apply this anywhere else that titleString is referenced. The temp is gone, and it’s been inlined with the code that referenced it. Now, what I was saying before, why might you want to use this refactoring? Well, it sets you up to then do a greater refactoring, extract method. This code that creates and populates the label could be used in several places and is probably better served as its own method. Now that the temp has been inlined, I can extract the the label creation into a new method, createTitleLabel(). That’s actually two refactorings in one. First I used Inline Temp, and then followed that up with Extract Method.

Again, inline temp is kind of straightforward. You’ll remove a temporary variable that’s only ever written to once, and then instead put the call to the actual method within each line that references the temp. I hope you liked this video from cleanswifter.com. Check back next week for another video demonstrating a refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” Thanks.

Weekend Reading for July 15, 2016

Weekend Reading for July 15, 2016, click here

Happy Weekend fellow Clean Swifters. I’ve been spending all week in “sprint.” Not the agile software kind, but instead it’s a format proposed by Jake Knapp of Google Ventures. It’s designed to learn what product you should build based on your customer needs in a short period of time (one week). I’m looking forward to some downtime over the weekend. Here’s what I’ll be catching up on.

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

Swift Playground Books

Swift Playground Books are going to usher in an entirely new interactive experience to learning a programming language. There have been various creative ways to learn new programming languages for years, but nothing like what Swift Playground Books will provide. I see two key factors that will enable Swift Playground Books to revolutionize the way that programming languages are learned, while also making Swift mega popular:

  1. Apple controls the whole ecosystem – iPad, IDE, and language. Well ya okay technically Swift is open source, but at least Apple controls the hardware and the IDE. The hardware being the iPad, and the IDE being the Swift Playgrounds app. Just like they’ve done for years, by controlling the whole ecosystem, Apple gets to ensure a top notch experience.
  2. iPad learning – Learning on a tablet, an iPad to be specific, will appeal to a much wider audience in a much wider set of circumstances. Ya the iPad has lost some appeal lately, but despite that, I foresee huge sections of people in new age groups using Swift Playground Books to learn the Swift programming language (not just “kids”).

Why Playground Books?

The new iOS 10 iPad app, Swift Playgrounds, is pretty cool on its own. Awesome autocompletion, touching and dragging brackets around, immediate feedback on written code, and more all contribute to a whole new way of programming. I’m not going to rehash the app in detail, this blog has a nice summary, and I also suggest watching the WWDC 2016 session “Introducing Swift Playgrounds”. (The last 10 minutes are super cool where a Sphero robot is controlled from an iPad, live on stage).

We can’t actually create apps in Swift Playgrounds yet, so until then, Swift Playgrounds is pretty much designated an exploratory and educational tool, and I’m okay with that. Regarding informal exploration of the Swift language, I see a lot of this happening in one-off playgrounds themselves. A standalone playground file is the perfect resource to try things out, learn about a specific topic, and just have fun. Swift Playground Books though is a giant step forward in organized and collated learning. Rather than just consuming a single playground, Swift Playground Books allow authors to aggregate content into an actual book-like, yet interactive experience.

Playground Books support a nested chapter and page structure, just like a real book. Additionally, there’s a cool new type of “page” called a cut-scene. Imagine that you complete a chapter in the book, and as a reward get to watch a little animation celebrating your victory, while also setting up the next challenge. As an author, you can also programmatically designate assessments on a chapter – did the user complete it successfully? This shows up in the Table of Contents as a green checkmark.

swift playground books

Striving to get all the green checkmarks like that are what make me so prone to get sucked into compulsively completing something, and in this case learning. 🙂

In addition to the assessments, there is built in support for the following:

  • Glossary – You can link terms at the tap of a finger.
  • Regions – Annotate pieces of code so that the user literally only needs to fill in specific parts to complete the challenge.
  • Shortcuts – Control what shows in the Helper Bar.
  • Hints – After the user has provided a response, if it isn’t quite correct you can code a “hint” to be displayed.
  • Resetting – The reader can either reset a page, or the entire document to start all over.
  • Live View – You can trigger a Live View to interact with that takes up half the screen. The idea is that the user writes code on the left hand side of the window – the Contents View, while interactive results are displayed on the right hand side – the Live View.

swift playground books

(There are actually some specific APIs to use in order to pass data back and forth between the Contents View and the Live View. See PlaygroundLiveViewMessageHandler, PlaygroundValue, and PlaygroundRemoteLiveViewProxy.

Playground Book Format

Swift Playground Books are easy to create. They are literally just a folder, with a particular structure, and a couple configuration files. Check Apple’s official documentation for details on setting up the directory and file structure, it’s dead simple. And since it’s all just text and folders, it can be version managed just like any other code or project!

Despite it being simple, I’ve had some issues getting it actually working on iOS 10 Developer Beta 1 and 2. For some reason, Swift Playgrounds isn’t recognizing my Swift Playground Books as something it can read. Instead, it just lets me browse the directory hierarchy, never actually opening it as a Swift Playground Book.

swift playground books

This folder should be detected as a Swift Playground Book that may be opened. Apple even recognizes the .folder extension in their documentation as something expected, and something that should be there. Maybe it’s just too early of a beta, or maybe I’m having problems since I’m trying to create these on OS X El Capitan rather than Sierra? I’ll continue to dig and post and update when I figure it out.

Playground Book Store?

One thing on my mind is whether Apple will provide some sort of store front for the Swift Playground Books. I could see significant effort and time spent on developing complex books that could provide hours of entertainment and learning for end users through discovery within a Swift Playground Book. It’s certainly a ripe business opportunity. Right now, there are only two tabs in the Swift Playground app: Featured, and My Playgrounds. I wonder if they will eventually create a store front to purchase Swift Playground Books through? And if so, will be be protected my DRM at all?

Learning More

I have so many ideas for content to create and distribute in Swift Playground Books. And besides that, I can’t wait to sit on the couch with my kids and reveal the amazing world of computer programming to them through Swift Playgrounds. How about you?

Happy cleaning.

VIDEO: Inline Method Refactoring in Swift

In “Refactoring, Improving the Design of Existing Code” by Martin Fowler, he presents the Inline Method refactoring. It is the opposite of Extract Method, which I’ve already covered.

Here’s a video walkthrough of the Inline Method refactoring in Swift and its benefits:

Video Transcription

Hey, what’s up everybody, it’s Andy from cleanswifter.com, and I’m back here to talk about another refactoring in my video series covering Martin Fowler’s book, Refactoring, Improving the Design of Existing Code. This week we’re going to talk about Inline Method and it’s a refactoring which is actually the exact opposite of the refactoring we talked about last time, Extract Method. With Extract Method, it was all about taking common functionality from a larger piece of code and extracting it into a new method. With Inline Method, it’s doing the exact opposite. You’re going to take code in a method and delete that method, and move the functionality back to where’s it’s called from.

Why Inline Method Is Useful

This is useful for a couple reasons. In one case, if the code being called is so simplistic that putting it in another method just distracts you, you might as well just put it back in the original place and delete the simple method.

Another reason you may want to do it, is that, if you have a series of different methods that are all called from a bigger method, and those other methods being called are smaller, you can then move that functionality back to the original method, delete all those other smaller methods, and then once the functionality is back together in the calling method, then extract that as one method, that then serves a better purpose in being a cohesive unit of code that actually does something.

We’re not going to do that right now. First we’re going to look at inline method all by itself. Let’s take a look at an example.

The Example

Here we have some code that calculates the length of a hypotenuse according to the Pythagorean Theorem. This code right here adds the squares of two numbers, the base and height of a right triangle, then takes the square root of the result. That’s the length of the hypotenuse of the right triangle. Reading this line of code by itself is pretty decent. I can read this and understand what it’s doing. But then I look at all these methods being called, and all of these are just doing a single line of code, which is just built in math. I want to propose an Inline Method refactoring to delete all three of these methods and move this functionality to be directly included with this method. Let’s do this one by one.

Starting in the middle we have the numbers being squared. That’s going to be my target method to first delete. I can see that this is just multiplying two numbers together, simple enough. I can come down here and square the numbers directly, and now since square is no longer being called, I’ll delete that. Voilah, that is the Inline Method refactoring.

I’m going to do this again for add. I can then delete add, and the call to it, and instead, just put that functionality directly in this line. Now you can see that I’m adding the result of the methods being squared. Add is no longer called, so delete that custom method. And the same square root, which just wraps the Foundation function for doing the same thing, I can then delete this and instead call the Foundation function directly. You can see the refactored result.

This example is kind of simplistic, but I think the simplisticness of it is a good example of when you would want to do this refactoring. In each of these cases and methods that I deleted, there was one line of code that called a function right from Foundation: add, multiply, and square root. When looking at this code, I think it’s much more obvious what it does, and there’s not these extraneous methods that cause my eyes to jump around. Now, imagine you’re doing this in a class, or series of classes, where those methods being called actually existed in a different place. Now, not only do you need to look somewhere else, but where you have to look is in a totally different file. For me, that jumping around, especially when the method is so simple, I think it’s better served to have it right inline with the code that is performing the function.

Again, it’s just a tool to add to your toolbox. Inline Method appears in Martin Fowler’s book, Refactoring, Improving the Design of Existing Code. You can buy it in the description for this video. Again, check out the original post on my blog, cleanswifter.com. Thanks a lot for watching, and I’ll see you next time.

Weekend Reading for July 10, 2016

Weekend Reading for July 10, 2016, click here

Happy Weekend fellow Clean Swifters. Here’s some suggested reading to keep you busy!

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

UIRefreshControl in iOS 10

Did you know that adding a UIRefreshControl in iOS 10 to a table view, a collection view, or a scroll view has never been easier? UIRefreshControl is now a first class citizen in all of these scrollable views and officially supported by the iOS SDK. Having fought through hacked solutions to use a UIRefreshControl in anything but the officially supported UITableViewController in the past, I’m really pumped to see this. This change for iOS 10 first caught my eye in the WWDC 2016 session, What’s New in UICollectionView in iOS 10 (which was a really good session by the way).

How It Works

The key to easily adding a UIRefreshControl to a UITableView, a UICollectionView, and a UIScrollView is the UIRefreshControlHosting protocol. Just like UIRefreshControl in iOS 10, this is also new in iOS 10. It’s a protocol adopted by UIScrollView. And coincidentally, UITableView and UICollectionView inherit from UIScrollView so they easily get this behavior.

Adding a UIRefreshControl in iOS 10

Here’s how simple it is to add a UIRefreshControl in iOS10:

let tableView = UITableView()
let rc = UIRefreshControl()
tableView.refreshControl = rc

Yep, it’s that dirt simple. Want to add a UIRefreshControl to a UIScrollView? It’s just as easy!

let scrollView = UIScrollView()
let rc = UIRefreshControl()
scrollView.refreshControl = rc

And want to add it to a UICollectionView? Well, you probably get the idea:

let collectionView = UICollectionView()
let rc = UIRefreshControl()
scrollView.refreshControl = rc

Now don’t forget to add a target to the UIRefreshControl so it has some behavior associated with it. Luckily, nothing has changed with that API, so it’s just as you remember it from pre iOS 10 days. Here’s a full example with a UITableView:

override func viewDidLoad() {
  super.viewDidLoad()
  let tableView = UITableView()
  let rc = UIRefreshControl()
  rc.addTarget(self, action: #selector(TableViewController.refresh(refreshControl:)), for: UIControlEvents.valueChanged)
  tableView.refreshControl = rc
  view.addSubview(tableView)
}

func refresh(refreshControl: UIRefreshControl) {
  tableView.reloadData()
  refreshControl.endRefreshing()
}

Refreshingly Simple

If you got this far, you probably aren’t rolling your eyes at how easy this is. If you’re questioning whether this is worth a blog post or not, fine. I believe it is. This is a subtle, yet awesome API change coming in iOS 10. I love to see that Apple continues to refine their API and adding niceties like this for developers. I look at this change and think, “Ya, this is how it always should have been.” Thank you, Apple. Has there been anything else on the edges that you’ve noticed and felt good about?

Happy cleaning.

Asynchronous Xcode UI Testing

As I continue to delve into Xcode UI tests, I’m starting to discover some of the lesser advertised benefits and drawbacks of the tool. One specific nuance that has caught my eye is how to deal with asynchronous Xcode UI testing. Xcode UI tests are asynchronous in that they simulate end user interaction with your application. End user interaction triggers animation (and in some cases waiting on remote services), and animation doesn’t happen instantaneously. There is a disconnect between the speed at which the lines of code in your tests can be executed, and whether the simulator (where the app under test is located and running) can keep up or not. In most cases, the simulator can’t keep up. As a result, you need to explicitly instruct your tests to wait for the app to catch up in the simulator. There are two ways to do this that I’ve been using.

Smart Waiting

waitForExpectationsWithTimeout(_:handler:)

When performing asynchronous Xcode UI testing, it’s often really useful to be able to verify something has appeared on screen. This way you know that the application is a certain state, and can continue executing a test script. For example, imagine an application with a tab bar, selecting a different tab should show a different view controller. If you were writing a test that relied on features within the second tab of the tab bar, it’s important have some assurances that when you instruct your test to tap the second tab, the tab actually appears. Furthermore, the act of waiting for something on screen can also act as a test in itself. If tapping the second tab doesn’t actually show what you expect, something probably went wrong and the test should fail.

Inspired from Joe Masilotti’s Cheat Sheet for Xcode UI testing, here’s how you can leverage waitForExpectationsWithTimeout(_:handler:) to verify that something appeared on screen:

// 1
let goLabel = self.app.staticTexts["Go!"]
let exists = NSPredicate(format: "exists == true")
expectationForPredicate(exists, evaluatedWithObject: goLabel, handler: nil)

// 2 
app.buttons["Ready, set..."].tap()

// 3
waitForExpectationsWithTimeout(5, handler: nil)
XCTAssert(goLabel.exists)

Here’s an explanation for this code:

  1. Define a NSPredicate to be used in a XCTestExpectation to verify that the Go! button exists in the app.
  2. Tap the Ready, set… button.
  3. Wait for the Go! button to appear.

waitForExpectationsWithTimeout(_:handler:) will repeatedly look for the NSPredicate to be true within the timeout provided, in this case 5 seconds.

This approach to verifying that something exists on the screen is incredibly useful. It’s very much like my old favorite KIF API waitForViewWithAccessibilityLabel. The thing is, it isn’t perfect.

Not Perfect

I’ve observed a number of cases when using this approach has led to false positives that an element “exists” on the screen. Essentially the XCTest UI framework observes that the element exists, but isn’t actually tappable, or in a state that a human-end-user would consider “on the screen.” If seen this most often happen when this technique is used in combination with animations happening in conjunction with the test action. For example, if you have an application that taps a button, which triggers a navigation controller to push a new view controller onto the stack, there’s a relatively slow animation that happens. With the predicate approach laid out above, asynchronous Xcode UI testing will actually identify incoming screen elements as “existing” before they are in their “final resting spot” at the end of the animation. So if you gate further steps of your test on the presence of something on the screen as determined by the XCTest UI framework, you’ll get false positives that the element is on the screen and ready for further interaction. Essentially, Xcode UI tests will tell you, “Yes, that button exists on the screen,” but in reality it isn’t yet “on the screen.” Don’t worry though, there’s a solution, and it’s incredibly dumb.

Dumb Waiting

sleep(1)

In those cases when you need to a little extra pause in your asynchronous Xcode UI testing in response to an asynchronous event like an animation, I’ve found that just using a sleep(1) goes a long way. Essentially this will block your tests from continuing for the specified duration of time, while the application under test is allowed to continue. To update the example code above, I add the sleep(1) in conjunction with the NSPredicate technique as follows:

let goLabel = self.app.staticTexts["Go!"]
let exists = NSPredicate(format: "exists == true")
expectationForPredicate(exists, evaluatedWithObject: goLabel, handler: nil)

app.buttons["Ready, set..."].tap()

waitForExpectationsWithTimeout(5, handler: nil)
XCTAssert(goLabel.exists)
sleep(1)

Notice that the sleep(1) happens right after the NSPredicate is determined to be true. This follows my discovery that Xcode UI tests identify things as “existing” before they are actually on screen. Using the NSPredicate technique with the sleep(1) let’s you verify the presence of specify UI elements, while also giving the app time to complete long running tasks like animations before continuing.

What’s funnier is that this sample code shown on screen at WWDC 2016 caught my eye:

asynchronous Xcode UI testing

Turns out, Apple uses the same technique!

Assertions in Closures

Another useful technique in asynchronous Xcode UI testing is to perform assertions on user-interface elements in response to closure execution. Often, indication of completion of long running calls like web service retrievals will be implemented with closures. I’ve written Xcode UI tests that explicitly call the web service separate from the application in order to cross-check data returned. Basically, I’ll ensure that the data the raw web service returns matches what is in the application. Whether this is your use case or not, you can use this pattern to make assertions in the closure on callback completion. The only requirement is that Xcode UI API calls need to happen on the main thread:

// 1
let expectation = expectationWithDescription("API Request Complete")
var response: Response?

// 2
RequestUpManager().get(id: "3688840") {
  (response: Response?, error: NSError?) -> () in
  
  if let response = response {
    response = response

    // 3
    dispatch_async(dispatch_get_main_queue(),{
      // Verify there is something on screen that matches what the API provided.
      let cell = self.app.cells.elementBoundByIndex(0)
      XCTAssertEqual(cell.staticTexts[response!.position].identifier, "Position")
      expectation.fulfill()
     })
  }
  else {
    // 4
    XCTFail("Unexpected object returned from API")
    expectation.fulfill()
  }
}
// 5
waitForExpectationsWithTimeout(WAIT_TIMEOUT, handler: nil)
  1. Use expectations to keep the test running while the request loads.
  2. Synchronously load data from the API.
  3. Tell the main thread to verify what’s on screen. (This will crash if not done on the main thread).
  4. Explicitly fail the test if unwrapping the optional data returned from the API fails.
  5. Using XCTestExpectations, wait for the asynchronous code to complete.

Wrap Up

These are just a couple little tricks I’ve learned for asynchronous Xcode UI testing when taking my first dive into the API. It’s always nice to get in and try out a tool beyond what’s shown in documentation or videos, you get a much better handle for nuances of what’s available. Have you come up with any solutions for these challenges in asynchronous Xcode UI testing?

Happy cleaning.

Weekend Reading, July 1, 2016

Weekend Reading for July 1, 2016, click here

Happy Friday fellow Clean Swifters. We’re looking at a 3-day weekend here in the United States, I can’t wait. More time to catch up on WWDC sessions! Here’s some other suggested reading if you find yourself with free time this weekend.

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning

How to Disable Tests in Xcode

It’s easy to disable tests in Xcode, but not entirely obvious. A lot of people give Xcode flack in terms of how far behind other IDEs it is with regard to its support for automated testing. I don’t entirely disagree with this. On the other hand, it’s come so far from just five years ago and I’m thankful for that.

Why Disable Tests

You might be wondering, if I’ve spent all this time writing tests, why would I ever want to disable tests in Xcode? I’m not advocating permanently disabling them, instead, I’m advocating disabling them temporarily to speed up your development or to unblock progress. Just this week, I returned to an old project of mine, one that hasn’t had an app store update in over a year. It still uses CocoaPods version 0.33.0, and Swift 1. Needless to say, it needed some work getting it up to speed. (Side note: I have a lot of ammunition for future blog posts on how to NOT let a project get this stale, but we’ll save those for a future camp fire). First, I needed to get the project to actually compile. Second, I needed to get the tests passing. And finally, I needed to update our continuous integration machines and jobs to also compile and successfully run the tests. I had my work cut out for me.

When working with a project this old, sometimes advanced techniques like TDD aren’t immediately useful if you can’t even get the project to simply compile. When working through compilation errors and test failures at a large scale, it’s useful to selectively turn off a subset of the errors or test failures so you can eliminate noise, focus on a piece of the problem, and make progress. You can easily disable tests in Xcode in two ways: disable compilation, and disable test execution. Both of these are scheme changes. Here’s how:

How To Disable Tests

Disable Tests From Building

To simply disable all your tests from building, you can do this in the Scheme editor. From the menu bar, select Product -> Scheme -> Edit Scheme.

In the left hand bar, select Build.

Then in the main pane, you can disable tests from compiling for any action in your project. If you’re project is in a really bad state, you can disable tests from compiling when running your application.

disable tests in Xcode

By disabling any of those checkboxes, when you run your application, anything in the associated targets will not be compiled.

Disable Tests From Running

Similarly, you can use the Scheme Editor for selectively turning tests and off. Still in the Scheme Editor, select Test in the left hand bar. Then, in the main pane, you’ll see each target associated with tests. The checkbox will let you enable or disable the tests from being run when you run tests for your project (Command-U, or Product -> Test).

disable tests in Xcode

Disabling an entire target may not be as granular as you’d like. In fact, it’s pretty coarse. You can expand any of the targets in that list and see specific test classes, and then selectively enable or disable tests by test class. And if that isn’t granular enough, you can drill one level deeper and then selectively turn tests on or off by test method!

disable tests in Xcode

Give it a try.

xcodebuild in Xcode 8

One thing I’m really excited for in Xcode 8 is that xcodebuild, the command line interface for building Xcode projects, was updated with similar functionality. With xcodebuild in Xcode 8 you can selectively pick which tests are built and executed. The use case is a little different for this tool. xcodebuild is often used as part of a continuous integration setup. With the new changes, you no longer need to compile tests to run them. xcodebuild will be able to run tests previously compiled. This means that you can compile your app and tests on one machine, and then distribute the load of testing it across other machines!

disable tests in Xcode

To build you app for testing, but not actually run the tests:

xcodebuild build-for-testing -workspace <path>
                             -scheme <name>
                             -destination <specifier>

Then you can use the produced bundle on different machines to run the tests without compiling! Combine that with the following steps for selectively running tests, and you’ll be able to distribute the execution of your test suite across different machines, in parallel!

To selectively specify which tests to run for xcodebuild:

xcodebuild test -workspace <path>
                -scheme <name>
                -destination <specifier>
                -only-testing:TestBundleA/TestSuiteA/TestCaseA
                -only-testing:TestBundleB/TestSuiteB
                -only-testing:TestBundleC

You can also specify tests to be skipped:

xcodebuild test -workspace <path>
                -scheme <name>
                -destination <specifier>
                -skip-testing:TestBundleA/TestSuiteA/TestCaseA

Don’t Abuse It

With great power comes great responsibility. Please don’t disable tests in Xcode, either from running or compiling, and leave it that way. That’s like driving without a seatbelt. Only do it if you are working in effort to improve your project. I know that working with a dusty and stale project isn’t the only time that it may be useful to disable tests in Xcode. I’m sure you’ll find your own reasons. I’d love to hear what they are.

Happy cleaning.

Xcode UI Tests Review

After writing Xcode UI tests for the first time today, immediately some things formed my initial impression. I wanted to pass along my Xcode UI tests review here on cleanswifter.com in effort to help educate others. For at least the pass year, if not longer, I’ve been using KIF for writing my functional UI tests. I love KIF. KIF is a third party, open source tool. That brings both benefits and drawbacks. Right off the bat, due to changes in the iOS 10/Xcode 8 Accessibility Inspector, KIF was broken in the beta versions of our tools. It was quickly fixed, and the impact was low, but it does make you wonder about what’s in store for the future when there are less people available to maintain it? This wasn’t the only thing that drove me towards Xcode UI tests for this project, but it was certainly a concern. I still love KIF and will continue to use it on other projects for the foreseeable future.

Background

Xcode UI tests build on an older tool from Apple called UI Automation. UI Automation enabled the iOS developer to write UI tests for their apps, and it was officially supported by Apple. “Officially supported” is certainly a loaded term, especially with UI Automation. The documentation was pretty bad. While there was some light guides on developing UI Automation tests, the actual API documentation had very little information. Combine that with the fact that the tests were written in JavaScript and run with Instruments (outside of Xcode), I was never happy with the tool.

Then last year, in WWDC 2015, Apple announced a reimagined solution for writing UI tests, Xcode UI tests. Here’s my Xcode UI tests review.

Pros

Officially Supported by Apple

This shouldn’t be underplayed. I’d live through a lot of crappy documentation just to use an officially supported tool. Apple officially supports Xcode UI tests, and that means a lot to me. It means you get WWDC videos on the subject. You get subtle integration with Xcode that only Apple could have access to. It means that your tests are less likely to break in future versions of iOS and Xcode.

Tests Written In Swift

Unlike UI Automation tests, Xcode UI tests can be written in either Objective-C or Swift. This could be the single best improvement. This means that you get everything from code completion, to compile-time syntax checking, to full Xcode integration.

Integration with Xcode

It was really annoying with UI Automation that you needed to switch to Instruments just to run your UI tests. Furthermore, JavaScript support in Xcode is pretty bad too, so one was left searching for a good editor experience when writing tests. Xcode UI tests change this. Now, the tests are first-class citizens right in the same IDE that we are using to write our actual application code. There’s even a “New File template” for Xcode UI tests.

Xcode UI Tests Review

XCTestCase subclasses

Buliding on the integration with Xcode, Xcode UI tests subclass XCTestCase just like unit tests. This means the full API of XCTest is available. Methods like XCTestAssertEqual and XCTestAssertTrue can be leveraged for writing your tests. Additionally, things like Scheme integration into your Test action enable execution of your Xcode UI tests when running tests, right from Xcode. Also, all those others niceties of running unit tests and the wonderful keyboard shortcuts can also be used with your Xcode UI tests.

Xcode UI Tests Review

UI Recording

UI Recording for Xcode UI tests is pretty cool. You can click a “Record” button in Xcode, and your app will launch in the simulator. Then, as you tap and navigate through your app, actual code will be generated in a test reflecting the path through your app that you took. It’s not perfect though, and more importantly, it doesn’t actually generate any assertions. Also, to prevent your test from being really brittle, you do need to consider breaking your tests up into cohesive chunks, and not one giant test.

Cons

Xcode UI tests aren’t without their flaws.

Documentation Is Still Light

The documentation for Xcode UI tests is still light. It’s not as bad as UI Automation was, but it’s still not perfect. KIF has been around for years. There are tons of stackoverflow.com questions and answers for it, the GitHub repository is mature, and you’ll find plenty of tutorials. I still can’t find an official piece of web-hosted API documentation for Xcode UI tests.

See the end of the article for a list of resources that I’ve been using as reference for Xcode UI testing.

Slow

Obviously all UI tests are going to be slow, regardless of whatever platform and tools you are using. Something uniquely slow jumps out at me about Xcode UI tests though. As a developer, you are required to call XCUIApplication().launch() from your tests when you want the app to launch. Each test must call this. The common pattern from what I’ve seen is to place the call to XCUIApplication().launch() in setUp(). setUp() is an overridden method from the XCTestCase base class, and is executed by the XCTest framework before each test. The thing is, XCUIApplication().launch() is REALLY SLOW. It triggers a fresh launch of your app. Now I guess this is useful from the context of resetting state in your app, but if you aren’t careful about structuring your tests, you could inadvertently introduce a lot of overhead in the speed of your tests.

iOS9 and Up

One of the main advantages of a suite of automated tests, regardless of the platform or type of tests, is to be able to run those tests in all places that your code base is supported. If you are writing a web application, this might be different browsers at different screen resolutions and window sizes. In iOS development, you can exponential benefit from running the same suite of tests across different devices of different form factors and different iOS versions. Unfortunately, Xcode UI tests put a major hamstring in this, in that they will only run on devices with iOS 9 and greater. To me, this is a big deal. We don’t all have the luxury of requiring the minimum iOS version to be the latest on the market. At the time of this post, iOS 9 is the latest iOS version, so that means I can’t even run my automated UI test suite on one version back, iOS 8. There have been so many times in my testing career in which UI tests identify and/or verify a bug that is present on one iOS version and not another. I’m really disappointed that Xcode UI tests don’t work on anything older than iOS 9. I guess I just have to hope for my applications, we’ll soon be able to require iOS 9 and greater.

XCUIElement != UIView

One of the most awesome things about KIF is the overlap between the KIF APIs and UIKit. When writing KIF tests, there are many methods like:

func waitForViewWithAccessibilityLabel(label: String!) -> UIView!

It’s so useful to have a UIView returned. This can be cast to more specialized subclasses that actually represent the object returned. And once you do that, you have full access to all the methods available on that object as defined in the actual code. Code like this is possible:

let saveButton = tester().waitForViewWithAccessibilityLabel("Save") as! UIButton
XCTAssertEqual(UIColor.blue(), saveButton.currentTitleColor)

This code is really useful because once you have a handle on the UIView, you can access so many APIs to verify behavior.

Unfortunately, there is no such intersection in Xcode UI tests. In Xcode UI tests, the object returned from similar method calls is a XCUIElement, and there’s no way to translate this to UIView (that I’ve found). As such, you are limited to the limited API available through Xcode UI tests and XCUIElement – none of which translates to a UIKit equivalent.

Final Thoughts

Despite the drawbacks, I’m still excited to use Xcode UI tests and I hope this Xcode UI tests review conveys that. It’s always fun to learn something new, and I think there are plenty of positives to using the tool. Have you used Xcode UI tests? What’s your Xcode UI tests review?

Happy cleaning.

Useful Resources