Previously we refactored a small snapshot testing library that worked with images of UIView
s and we generalized it to work with even more types by using protocols. This first let us write tests against values of any type that could produce an image! We conformed UIImage
, CALayer
, and UIViewController
and instantly unlocked the ability to write snapshot tests against them. None of these types worked with our original API.
We then generalized it even further to work with any kind of snapshot format, not just images! This gave us the ability to write snapshot tests against blobs of text, and by the end of the episode we had a truly impressive, flexible library that we could have continued to extend in interesting ways.
However it wasn’t all roses. We hit a bunch of protocol-oriented bumps along the way: we butted heads with complicated features like capital Self
requirements, dodged naming collisions, and recovered some ergonomics by way of protocol extensions and default conformances (oh my!). We finally hit the ultimate bump that stopped us in our tracks: types can only conform to protocols a single time, so our library is limited by the language to a single snapshot format per type. This may not seem like a big deal. As a community we do so much with protocols and they really don’t seem like a limiting factor in our APIs. However, we saw that even the type we started with, UIView
s, had multiple useful conformances, including screen shots of how the views render and text-based descriptions of the view’s state and hierarchy.
Luckily, over the past weeks we’ve built up the muscles to convert protocols to concrete datatypes and functions, and we’ve seen firsthand how it helps us solve this multiple conformances problem! So let’s re-refactor our library and see what plain ole datatypes and functions can do for us.