Tests Are Just Code, Too

From “Testing, for people who hate testing”:

The thing is, tests are just code. If you have a hard time constructing your own objects with some particular state, it might be a sign that your API is hard to use!

This is all there is to the magic of test-driven development, we could say. A test is client code. This means it doesn’t have the inside perspective of the object or module under test. It has an outside perspective. Through tests you see how your production code is used (by other parts of your code or by other people in the case of libraries, say).

You start with a test. This means: you start with an outside perspective, asking yourself questions like “What would be a good (public) interface for this?” – The opposite is ad hoc reasoning, something along the lines of “I have this NetworkManager there and maybe just call it and return the JSON. Okay. Oh, now JSON doesn’t work, I need to send a custom object along, so I’ll just parse the JSON and create an object. But if that fails, hmm, I cannot send nil, so I’ll force unwrap and let someone else deal with this.” Or something. These improvised solutions can cause trouble because all they do is focus on the perceived requirements of the object you’re writing, ignoring the requirements of code that uses the resulting code.

Writing tests first kind of equals writing your app outside-in, starting with the calling code, then implementing the code that’s to be called. Only test cases are super focused and you verify a lot more behavior and setup code with a single run than you could ever do with manual testing.

Experienced programmers will be able to switch perspectives even without writing tests. Their experience helps them to make it less likely to produce waste, whereas “waste” is code you write and then discard because you find it doesn’t fit.

How to Get Started with Swift: Write New Tests in Swift

Daniel Jalkut of MarsEdit fame is slowly getting up to speed with Swift. I have a few Swift-only projects already (Move!, TableFlip and secret in-progress ones). On top of that, every feature I add to the Word Counter is a Swift module, too. The main code of the Word Counter is still in Objective-C, though.

Integrating new types to the project using Swift is awkward. There’re things you can only use in one direction. Most if not all Objective-C code can be made available for Swift and works great. The other way around, not so much. Also, Objective-C imports from the -Swift.h file won’t be available in Swift-based test targets. So you’ll have to isolate these even further, create wrappers, or whatever. Porting a class to Swift can work, but the side effects on testing make it harder.

I like Daniel’s advice to write your unit tests in Swift if you’re still not certain if you should make the switch to this new and volative language. It’s a good idea to get your feet wet.

Considering the problems I ran into with the Word Counter, though, I wouldn’t know how, honestly.

How to Create Fixture Files for Unit Tests

This is mostly a reminder for my future self: It doesn’t suffice to create a TXT file and add it to the target in the file inspector (⌘⌥1) to be able to read it as part of the bundle. You also have to drag it into the “Copy Bundle Resource” build phase of the target so it get, well, bundled into the product. (In my case, it was the test target.)

screenshot of Xcode
The .md file was part of the test target but loading it from the NSBundle failed until I added it to the proper Build Phase
  1. Create an empty file or add an existing file to the target’s group in Xcode and make it part of the proper target,
  2. drag it into “Copy Bundle Resources” build phase,
  3. load it using NSBundle(forClass: TheTestCase.self).URLForResource("filename", withExtension: "txt").

Storing PLIST or JSON files for structured data works just as well. I happen to require plain text flavors most of the time and always wonder why the loading fails for a couple of minutes.

How do You Really Mock Objects You Don't Own? You Replace Them with Adapters

Teaser image

How do you test NSURLSession properly? After all, using it in tests directly will hit the servers; that’s not what you want to do 1000s of times per day. Even if you use a localhost based server replacement the tests will be slower and potentially error-prone as the server replacement may not be 100% accurate. Anyway – there’s a popular series of posts about that topic. There, you’ll learn how to mock NSURLSession in your tests. I think the advice is good to move on quickly, but it only shifts the problem slightly out of sight. There are better alternatives.

Continue reading …

Extract Private Functions as Collaborators

“Using a private function means having a hardwired link to an anonymous collaborator. Over time, this will slowly hurt more.” (@jbrains) I was thinking about this the other day when I wrote tests for a presenter. It receives a date, formats it, and makes the view update a label with the result. Simple. (The real thing actually does a bit more, but that doesn’t matter much.)

Continue reading …

Block-Based API vs. Delegates – a Comparison

As I’m exploring the use of block based API, which means to assign closures or functions handles to properties or pass them around as parameters to other functions, I found a few benefits and drawbacks in comparison to protocol-based object interactions. Here’s a breakdown of criteria for blocks and delegates.

Continue reading …

Jiggle GCD Queues to Find Problems

To debug my threading issues and help bring forth future problems, I have created a simmple object that slows the current queue down:

let IsRunningTests = NSClassFromString("XCTestCase") != nil

struct QueueJigglePoint {

    /// Randomly interfere with the thread.
    static func jiggle() {
    
        guard !IsRunningTests else { return }
    
        #if DEBUG
            usleep(2*1000000) // 2 seconds
        #endif
    }

}

I got this idea from Brett Schuchert on pages 188–90 of Uncle Bob’s Clean Code. A Handbook of Agile Software Craftsmanship. There, interference with traditional threading should randomly sleep, yield, or fall through. Enqueued blocks are a lot less volatile, so I only came up with sleeping.

Randomizing the sleep interval is up next. But a fixed number of 2–10 seconds helps find UI-blocking code already.

Just throw in a QueueJigglePoint.jiggle() in NSManagedObjectContext.performBlock executions, when dispatching async to the background, or when reading files, for example.

Swift Protocol Extensions as Mixins – And How Do You Test That?

I found a very useful distinction by Matthijs Hollemans to grasp what protocol extensions in Swift 2 can be: instead of interfaces, they are traits or even mixins. At the same time, I want to raise awareness for misuse: just because behavior is mixed-in doesn’t mean it’s additional behavior. The code may live in another file, but its functionality can still clutter your objects.

Continue reading …

How to Write Pragmatic, Testable Singletons in Swift

Singletons have their use. I use two Singletons regularly in my projects: a DomainPublisher and a ServiceLocator. The latter is a registry of service objects which is global so the service objects don’t have to be. For practical use, most Singletons are overcomplicated or overly restrictive. Here’s how I suggest you implement Singletons in your apps:

Continue reading …

Refactoring Legacy Code: Replace Free Function in Tests, Even Swift's Own Functions

Teaser image

Refactoring Legacy Code is hard. There are a few safe refactorings you can do with caution. But most chirurgical cuts require you to put the code in a test harness first to guard against regression. With C and Swift, you can create free functions as part of your app. To verify your objects use that function, you need to find a way to insert a test double.

Continue reading …

How to Write Unit Tests for Storyboard-based Buttons in Swift

Teaser image

I’m writing unit tests for my Storyboard-based view controllers. Button interaction can be tested in view automation tests, but that’s slow, and it’s complicated, and it’s not even necessary for most cases. To write unit tests instead of UIAutomation tests for buttons, you test multiple things. Here are the tests.

Continue reading …

Test doubles for Core Data managed objects might not work as expected

You don’t have to learn anything new if you work with Core Data in Swift. It’s a pain to use NSManagedObject directly, so you better work with custom subclasses all the time. Unboxing optional NSNumbers is just too cumbersome. There are caveats you should be aware of, though: Swift’s static typing makes it a bit harder to write test doubles for managed objects.

Continue reading …

Save Your Butt in Unit Tests With Shallow Reaching

I assume you do write tests. To test system boundaries, you have to find out whether methods are called. Usually, people reach out for mocks to verify behavior.

If you use a lot of mocks, though, the tests can reveal high coupling in your code: either you have to mock objects multiple levels deep, which is a sign of too much knowledge about how the collaborating objects work, or you have to mock lots of objects one level deep. The latter can be acceptable when you test a components which is some kind of coordinator. The former, though, is never to be accepted. Use the feedback of these hard-to-write tests to make your code simpler.

That’s what the Law of Demeter is for. While “law” is way too strict, its principle is sound: strive to call methods on the objects you have direct access to, but avoid calling methods on objects which you obtain through another method call in the first place.

For example, the following violates the principle:

func violateThePrinciple(aCollaborator: Collaborator) {
    let aStranger = aCollaborator.obtainFriend() // this is okay so far
    aStranger.doSomething() // this is not, because it's 2nd level
}

You can get by through providing facade methods:

func respectThePrinciple(aCollaborator: Collaborator) {
    aCollaborator.doSomething()
}

extension Collaborator {
    func doSomething() {
        self.friend.doSomething()
    }
}

In your unit tests, you can add a Collaborator mock to verify the calls and then you’re good to go. No multiple levels of mock objects and stubs. You may call this “shallow reaching” (opposed to “deep reaching”), although no one else calls it that.

That’s the Law of Demeter in a nutshell: only talk to friends which you know through properties or parameters, but don’t talk to strangers which you get to know through the return values of your friends’ methods. You never know what to expect.