Reliable Async Tests: The Point

Episode #242 • Jul 17, 2023 • Subscriber-Only

What’s the point of the work we did to make async testing reliable and deterministic, and are we even testing reality anymore? We conclude our series by rewriting our feature and tests using Combine instead of async-await, and comparing both approaches.

The Point
Introduction
00:05
Combinification of our feature
01:42
Writing Combine tests
12:40
Highly asynchronous testing
34:58
Conclusion
38:46

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Introduction

Brandon: Again we’ve seen something incredible. Although the main point of this series is that we want to reliably test async code in Swift, there is the other side benefit that surprisingly pops up. The tool we’ve cooked up for serializing asynchronous work in tests can also be used to make certain kinds of Xcode previews execute faster, and improve our ability to quickly iterate on features that make use of time-based asynchrony.

So, it’s all looking amazing, but I’m sure there’s a number of our viewers who are thinking that we have done some truly bizarre things in these past few episodes. We have completely altered the execution environment our tests run in, seemingly just so that we can get them passing. But doesn’t that mean there was something wrong with our features or tests in the first place? And doesn’t that mean that we aren’t actually testing reality since our apps do not operate on the main serial executor when run on our user’s devices.

Stephen: Well, for the feature we built and the kinds of tests we wrote, neither is true. There is absolutely nothing wrong with our features or tests, and for the kinds of behavior that we are wanting to test, using the main serial executor is essentially equivalent to using default, global executor.

To explore this, we are going rebuild the feature from past episodes using only the tools from Combine. We aren’t going to use any fancy Swift concurrency tools. This will allow us to compare the two styles to see how they differ. In particular, we find that the Combine code is a little more verbose and annoying to work with, but overall looks roughly the same as the async version. The tests also look almost identical, however we will find that they pass deterministically, 100% of the time.

Let’s dig in.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in

References

Reliably testing code that adopts Swift Concurrency?

Brandon Williams & Stephen Celis • Friday May 13, 2022

A Swift Forums post from yours truly about the difficulty of testing async code in Swift.

Concurrency Extras

Brandon Williams and Stephen Celis • Tuesday Jul 18, 2023

An open source Swift package that provides powerful tools for making async code easier to test.

Announcing Concurrency Extras: Useful, testable Swift concurrency.

Brandon Williams and Stephen Celis • Tuesday Jul 18, 2023

The announcement of our new Concurrency Extras library, which provides powerful tools for making async code easier to test.