Clocks: Controlling Time

Episode #210 • Oct 24, 2022 • Subscriber-Only

With “immediate” and “unimplemented” conformances of the Clock protocol under our belt, let’s build something more complicated: a “test” clock that can tell time when and how to flow. We’ll explore why we’d ever need such a thing and what it unlocks.

Previous episode
Controlling Time
Introduction
00:05
The problem
01:48
The solution: test clocks
11:11
Testing time exhaustively
32:12
Conclusion
39:54

Unlock This Episode

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

Introduction

So, this is pretty amazing. After diving deep into the Clock protocol so that we could understand what core concept it represents, and seeing how it differs from Combine schedulers, we showed how to make use of clocks in our features. There were a number of false starts to do that, first needing to wrap our minds around clock existentials and primary associated types and then coming to grips with some missing APIs in the standard library, but once we got out of the weeds we had the ability to swap clocks in and out of our feature code. We could use a continuous clock in the feature when running on a device, but sub out for a more controllable clock in tests and SwiftUI previews.

That led us to the creation of the “immediate” clock and the “unimplemented” clock. Both are powerful, and allow you to make your tests stronger and make it so that you don’t have to literally wait for time to pass in order to see how your feature behaves.

But there’s one more kind of clock that we want to have for our tests, and it’s even more powerful than any of the other clocks we have discussed. While the immediate clock allows us to squash all of time into a single instant, that isn’t always what we want. Sometimes we want to actually control the flow of time in our feature so that we can see how multiple time-based asynchronous tasks interleave their execution, or so that we can wiggle ourselves in between time-based tasks to see what is happening between events.

This is something we explored quite a bit in our series of episodes on Combine schedulers. When writing highly reactive code that needs to leverage time-based operators, such as delays, debounces and throttles, it becomes very important to have a scheduler for which you can explicitly control the flow of time.

So, let’s see why exactly we want this tool, and what it takes to implement it.

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

SE-0329: Clock, Instant, and Duration

Philippe Hausler • Wednesday Sep 29, 2021

The proposal that introduced the Clock protocol to the Swift standard library.

Reliably testing code that adopts Swift Concurrency

Brandon Williams and Stephen Celis • Friday May 13, 2022

A Swift forum post in which we highlight a problem with testing Swift concurrency with the tools that ship today.

Downloads

Sample Code

0210-clocks-pt2