Does test-driven development (TDD) even make sense for SwiftUI?
Nine years ago, I started a TDD sample app in Objective-C, then I did a redo in Swift. The app didn’t get far, but it give me material for many interesting articles.
As I worked on finishing my book, which focuses on testing UIKit-based apps, along came SwiftUI. The framework was immature, I didn’t know anything about it, and I was trying to wrap up a book. So, I added a section in the preface that said, “Disclaimer: No SwiftUI Support.”
[This post is part of the TDD with SwiftUI series.]
SwiftUI: It’s Time
But now it’s time. Let’s start a new sample app, this time in modern Swift!
A quick survey on GitHub turns up quite a few examples of SwiftUI apps. But I’ve seen only a tiny handful of unit tests on most projects. And absolutely no tests on the SwiftUI portions.
Are folks not writing unit tests for SwiftUI because they don’t know how? Or because it doesn’t make sense? This is the space I intend to explore.
I’ll also need your input. You can help me with SwiftUI.
More Than SwiftUI, More Than TDD
Though I’m calling this “TDD with SwiftUI,” there’s more to it.
I say “SwiftUI,” but an app is more than UI. Swift has changed a lot since I wrote iOS Unit Testing by Example. We’ll use modern Swift ideas like async/await, actors, and tasks.
And I say “TDD,” but there are plenty of software engineering practices I’d like to explore. Some practices have become habits for me:
- Discovery Trees to do just-in-time planning and make the work visible. You can see my whiteboard.
- Arlo’s Commit Notation to note the risk of each commit.
- Story Slicing to deliver functionality as soon as possible.
- Evolutionary Design to maintain simplicity with just-in-time design.
But there are many more practices that I’ve tried only lightly. Every personal project is a chance for me to exercise something new by leaning into it. Here are the practices I want to, well, practice:
- Refactoring in Xcode. I’m so used to the power of AppCode, but that doesn’t help you Xcode folks. So Xcode refactoring it is, which means (sigh) giving up most automated refactoring. What does that look like?
- TDD As If You Meant It. I want to try growing the code directly in the tests, moving it to the production code side only as we need to.
- Microobjects, a set of practices by Quinn Gil. They include classic OO ideas like “no getters or setters.”
- Nullables, a pattern language by James Shore. The language describes a style of Hexagonal or Clean Architecture that avoids mocks and spies.
- Avoiding setUp and tearDown. Will tests be cleaner if we always use helpers instead?
So these articles will span a variety of topics. I expect they will cover the main categories of this blog: unit testing, TDD, refactoring, and tools. To make things easier to find, I’ve made a dedicated TDD with SwiftUI page to collect the articles that come from this project, as I start from an empty GitHub repo.
How to Follow Along
There will be Xcode project configuration. There will be architecture, design, and refactoring. There will be test-driven development. And how will I approach SwiftUI?
Stick around to find out.
My plan is to live-code this project on Twitch, post the recordings on YouTube, and then turn what we discover into articles on this blog.
Live-Coding on Twitch
I’ll be streaming Sundays at 9:00 am Pacific (17:00 UTC) for roughly 60 minutes. Join so you can chat with me live. Chances are, you know more about SwiftUI than I do, and I’ll need your help. But I’ll be trying to apply the interesting practices above. This will be real, warts and all!
Consider subscribing to support my stream
Recorded Sessions on YouTube
The following day, I’ll put the recording onto my YouTube channel. Your comments there will also be helpful.
Articles on This Blog
Then I’ll refine what we discover into articles which I’ll post here. Make sure you don’t miss a single post in this series. Subscribe to my newsletter, and I’ll notify you about new posts by email.
Which topics do you look forward to the most? Any specific requests? Let me know in the comments below.
[This post is part of the TDD with SwiftUI series.]
