Home    |    Articles    |    Talks

Testing Publishers Synchronously with a Blocking Recorder

Combine publisher blocking recorder

When releasing Combine, Apple didn’t show us what their vision for testing the codebase with Combine was. Surely they must have thought about it.

Fortunately, the authors of Combine didn’t try to reinvent the wheel. The concepts, they built the framework around, are quite similar to the concepts in other reactive frameworks used on iOS. It means we can reuse the knowledge and best practices that evolved in the existing iOS-reactive-framework communities.

Let’s take RxSwift as (probably) the most used reactive framework of the pre-Combine era. It has a convenient set of tools for use in tests. We’ll use it as inspiration for today.

We’re going to build a simple Combine test helper allowing us to record and synchronously assert values produced by a publisher.

Continue reading ...>

iOS Code Review #2: Adding Tests to an Existing App (Networking)

Adding tests to an existing app can be challenging and sometimes intimidating. In this episode of iOS Code Review, I go through the process step-by-step.

You’ll see how to refactor existing code to make it testable by identifying dependencies and side-effects; how to write elementary tests to “lock” the current configuration of simple elements; how to mock network calls using a custom URLProtocol subclass. Finally, I’ll show how to easily mock dependencies using in-line closures.

Don’t forget to submit a project to the next iOS code review using https://vojtastavik.typeform.com/to/Y5p1BU.

Building a Custom XCTAssert for Multiline Strings

XCTest provides a bunch of XCTAssert... functions to be used for assertions in your tests. Sometimes, however, the functionality you need is different from what the built-in assertions can provide. Sometimes, all you really need is a custom XCTest assertion.

Custom multiline assertion

Custom assertions can make your tests more expressive, readable and maintainable by reducing boilerplate. Expressive and readable tests are crucial to understanding what’s happening and why the tests are failing. Having to write less boilerplate code makes people more inclined to writing new tests.

Let’s build a custom XCTAssertEqual overload which will work nicely with multiline strings. You’ll see how easy it is to improve the information value of tests and make the developer’s life more comfortable.

Continue reading ...>

Why You Should Be Using `unowned` More Often

I’ve seen a lot of interesting codebases in the last two months: new clients of Industrial Binaries, submissions for my iOS Code Review series, and also code challenges of the candidates we’re recruiting.

I was surprised how rarely unowned is used in the wild.

Weak everywhere

I think this is a huge missed opportunity. Not using unowned in the right places makes the code harder to maintain and can hide some serious and hard-to-replicate errors.

Continue reading ...>

Mocking Network Calls Using URLProtocol

For many apps, the networking code is one of the most important parts of the whole codebase. Yet it’s also a part which is quite difficult to test properly.

Some people just give up and rely on thorough manual testing. This approach doesn’t really scale well. A medium-sized app can have hundreds of various API requests. Having to test all of them manually makes any future changes and refactoring tedious and dangerous.

URLProtocol Xcode screenshot

Another popular solution you can see in the wild is making real network calls, especially in integration and UI tests. Not great, not terrible ☢️.

Real network calls make tests simple but slower by the order of several magnitudes. It also makes them much less reliable. The success of the tests depends on your current network conditions. Ask yourself if it’s OK that your tests fail when the train you’re working from enters a tunnel.

Can we somehow keep the simplicity of real network calls while making it more reliable and network-conditions independent?

Continue reading ...>

iOS Code Review #1: A Simple Weather App

I decided to try something new and recorded a YouTube video. This is the first video of the iOS Code Review series I’d like to do. In this series I’m going to review iOS projects which you can submit using this form.

I’ll remove all traces of the author or name of the project from the codebase. I’d like to focus solely on the code and show how to improve problematic parts.

Submit a project to the next iOS code review using https://vojtastavik.typeform.com/to/Y5p1BU.

Advanced testing using `Behavior` in Quick

Behavior<Context> is a hidden gem in the Quick testing framework. It was introduced silently in 2017 and it’s not even mentioned in the documentation! Here’s my PR which fixes that. The more I know about it the more I think this should be the way we write specs in Quick.

Behavior Xcode screenshot

So, what’s Behavior? You can think of it as of a better and safer way of defining shared expectation. But that would be very shortsighted. There’s much more!

Continue reading ...>

Simple XCTest Log Formatter in Swift

The raw output from xcodebuild is very detailed and hard to read. The community go-to tool for fixing this is xcpretty. Unfortunately, it happens to me regularly, that the formatted log xcpretty produces doesn’t contain the details I consider important. For example, I’d like to see the raw console output when a test case fails.

xcpretty example

I realized recently that I tend to build more and more parts of the tooling I need myself. Especially, when the functionality I usually need is trivial, and writing scripts in Swift is so easy! So I decided to write my own XCTest log formatter; because why not?

Continue reading ...>