# .css-4zleql{display:block;}Holy Swift  # Curious Ways To Solve Tests Equality Problems in Swift

## It looks the same, but is it?

Subscribe to my newsletter and never miss my upcoming articles

Hallo keizerinnen en keizers, Leo hier.

Today we will explore a somewhat common problem when testing code in Swift/iOS development. I can't stress enough the fact we all should be doing tests, this is a real game changer for any developer.

A long time ago I've watched a lecture about code standards and the speaker said something that echoes in me until today:

"What reasoning someone do to write a line of code and think: "Well I don't have to test this line." When you put this into words, sounds weird isn't it?"

I really hope that all my audience make tests for their code, this leads inevitably to comparisons. Either you use `XCTAssertFalse`, `XCTAssertNil` or any other assertion method eventually you will use some kind of equality. This post is about test equality and how you can compare two things in tests. So be prepared to some non trivial syntax and various ways to solve the same problem.

Let's test! But first...

## The painting

This is 1664 masterpiece called Crimean Falconer of King John Casimir from the genius Daniel Schultz. Born somewhere around 1615 in Gdańsk (Danzig) in Pomeranian Voivodeship, Polish–Lithuanian Commonwealth, Schultz learned the art of painting from his uncle, Daniel Schultz the Elder, another important painter, working in his workshop for about five years. After his uncle's death he travelled to France and the Netherlands to continue his studies for about three years. The inspirations of Rembrandt and Philippe de Champaigne are visible in his works.

I choose this painting because if you pay attention to the most right kid and the king in the middle, they have a very very similar face, but they are not equal... are they? As we will talk about equality, old painting with family are amazing place to acknowledge that not everything that looks the same, are the same.

## The problem

Imagine that you have a complex type that you want to check it equality with another object in the test suite.

Imagine you have this code within your codebase:

``````protocol SimplePrint {
func printAll()
}

struct SimpleManager: SimplePrint {
func printAll() {
print("All")
}
}

struct ComplexType {
let name: String
let action: SimplePrint
}

let complex1 = ComplexType(name: "First", action: SimpleManager())
let complex2 = ComplexType(name: "Second", action: SimpleManager())
``````

What happens if we have to check in the test suit if `complex1` is equal `complex2`? Well the answer is you can't do that because the compiler can't infer how to compare those two objects, so we need to help him. Let's start with the most straightforward and Xcode recommendation strategy: `equatable` protocol.

### Solution 1 - Equatable

First you should `import XCTest` and do a little setup to be able to test. Open Xcode Playground if you want to code along, and I recommend that. And let's dive into the problem:

``````class MyTestCase: XCTestCase {

let complex1 = ComplexType(name: "First", action: SimpleManager())
let complex2 = ComplexType(name: "Second", action: SimpleManager())

func testMyCaseTestsNow() {
XCTAssertEqual(complex1, complex1)
}
}

MyTestCase.defaultTestSuite.run()
``````

You get Global function 'XCTAssertEqual(::_:file:line:)' requires that 'ComplexType' conform to 'Equatable'.

So Swift recommend that you use equatable. Let's conform our ComplexType to Equatable.

``````struct ComplexType: Equatable {

let name: String
let action: SimplePrint

static func == (lhs: ComplexType, rhs: ComplexType) -> Bool {
return lhs.name == rhs.name
}
}
``````

Now you can use `XCTAssertEqual` on the type. But this could be improved right? Ideally we should only assert equality on object that we can uniquely identify or all the properties are not relevant to equality ( like money, a 5 dollar bill is equal other 5 dollar bill even being different bills). Today is our lucky day! Swift has it's own protocol that enforces this, let's use it:

``````struct ComplexType: Equatable, Identifiable {
var id: String
let name: String
let action: SimplePrint

static func == (lhs: ComplexType, rhs: ComplexType) -> Bool {
return lhs.id == rhs.id
}
}
``````

Now when we compare two `ComplexType` structs we are sure that they are the same. Calling the tests again:

``````    func testMyCaseTestsNow() {
let complex1 = ComplexType(id: UUID().uuidString, name: "First", action: SimpleManager())
let complex2 = ComplexType(id: UUID().uuidString, name: "Second", action: SimpleManager())

XCTAssertEqual(complex1, complex1)
}
``````

### Solution 2 - Turn All Properties Into Equatable

Now things begin to be interesting. Now our `ComplexType` has three properties: Two `Strings` ( they are already equatable) and a `SimplePrint` type.

``````struct ComplexType: Equatable, Identifiable {
var id: String
let name: String
let action: SimplePrint

static func == (lhs: ComplexType, rhs: ComplexType) -> Bool {
return lhs.id == rhs.id
}
}
``````

But how can we use equatable inference for `ComplexType`? We need that `SimplePrint` protocol be equatable too. Like this code below right....? :

``````let action: SimplePrint & Equatable
``````

Not exactly, because the `Equatable` protocol has Self requirements. And the code below show how Generics come to safe the day again:

``````struct ComplexType<ActionType: SimplePrint & Equatable>: Identifiable {
var id: String
let name: String
let action: ActionType
}
``````

But now we have another problem. `SimpleManager` is not `Equatable`. This will force us two choose.... If we can turn `SimpleManager` a `Equatable` struct is solved, but if not we can also use a conditional protocol conformance, like the example below:

``````struct ComplexType<ActionType: SimplePrint>: Identifiable {
var id: String
let name: String
let action: ActionType
}

extension ComplexType: Equatable where ActionType: Equatable {}
``````

This way our `ComplexType` can be equatable or not depending on what conform to `ActionType`. Really amazing, isn't it?

Now we have to change the tests and create some manager that conform to `Equatable` and `SimplePrint`:

``````struct SimpleComparableManager: SimplePrint, Equatable, Identifiable {
var id: String

func printAll() {
print("All")
}
}

class MyTestCase: XCTestCase {

func testMyCaseTestsNow() {
let complex1 = ComplexType(id: UUID().uuidString, name: "First", action: SimpleComparableManager(id: "Manager 1"))
//let complex2 = ComplexType(id: UUID().uuidString, name: "Second", action: SimpleManager())

XCTAssertEqual(complex1, complex1)
}
}
``````

### Solution 3 - Use Enums

So if you are sure that you have limited and well defined implementations of the `SimplePrint` protocol, you can substitute that type by a enum in the `ComplexType`, check the enum below:

``````enum PrintManager: Equatable {
case simple(SimpleManager)
case comparable(SimpleComparableManager)

static func == (lhs: PrintManager, rhs: PrintManager) -> Bool {
switch (lhs, rhs) {
case (.simple(_), .simple(_)):
return true
case let (.comparable(a), .comparable(b)):
return a == b
case (.simple(_), _):
return false
case (.comparable(_),_):
return false
}
}
}
``````

This way you can still here we force the enum itself to implement the `Equatable` protocol to give us freedom for our types to not implement at all! Now fixing the `ComplexType` and the tests:

``````struct ComplexType: Identifiable, Equatable {
var id: String
let name: String
let action: PrintManager
}

class MyTestCase: XCTestCase {

func testMyCaseTestsNow() {
let complex1 = ComplexType(id: UUID().uuidString, name: "First", action: .comparable(SimpleComparableManager(id: "123123")))
//let complex2 = ComplexType(id: UUID().uuidString, name: "Second", action: SimpleManager())

XCTAssertEqual(complex1, complex1)
}
}
``````

And... Voilà! You have your comparison and the flexibility to yours managers not being necessarily equatable. By the way, this is the only way to compare two things that are not `Equatable`, you have to wrap your not `Equatable` Type into a `Equatable` one... Or maybe there's others ways!

### Solution 4 - Using XCTAssertIdentical and XCTAssertNotIdentical

For this you will need to transform your structs into classes. This way you leave behind the value type nature of you object and embrace the reference type nature. Enabling us to compare not only values, but also identities. Let's do the code changes:

``````class ComplexType: Identifiable {
var id: String
let name: String
let action: SimplePrint

init(id: String, name: String, action: SimplePrint) {
self.id = id
self.name = name
self.action = action
}
}
``````

We have to add the initialiser because we don't receive a default one from classes. (Well, I know some classes you can create without init but this is topic for another post). Now we can compare their identities:

``````class MyTestCase: XCTestCase {

func testMyCaseTestsNow() {
let complex1 = ComplexType(id: UUID().uuidString, name: "First", action: SimpleComparableManager(id: "123123"))

XCTAssertIdentical(complex1, complex1)
}
}
``````

And of course we have the `nonIdentical` too:

``````class MyTestCase: XCTestCase {

func testMyCaseTestsNow() {
let complex1 = ComplexType(id: UUID().uuidString, name: "First", action: SimpleComparableManager(id: "123123"))
let complex2 = ComplexType(id: UUID().uuidString, name: "First", action: SimpleComparableManager(id: "123123"))

XCTAssertNotIdentical(complex1, complex2)
}
}
``````

Important note: When comparing classes with `XCTAssertIdentical` or `XCTAssertNotIdentical` you are just testing with both of the variables points to the same object in the memory. You are not pointing to values here, keep this in your head!

### Solution 5 - The Legendary Triple Equal Identity Operator

Another way to compare pointers in the memory ( classes ) is using the legendary triple equals identity operator `===`:

``````class MyTestCase: XCTestCase {

func testMyCaseTestsNow() {
let complex1 = ComplexType(id: UUID().uuidString, name: "First", action: SimpleComparableManager(id: "123123"))

XCTAssertTrue(complex1 === complex1)
}
}
``````

It's the same result as using `XCTAssertIdentical`.

### Solution 6 - Use ObjectIdentifier

Same as above but using the struct `ObjectIdentifier` to unique identify a class instance or metatype.

``````class MyTestCase: XCTestCase {

func testMyCaseTestsNow() {
let complex1 = ComplexType(id: UUID().uuidString, name: "First", action: SimpleComparableManager(id: "123123"))

XCTAssertEqual(ObjectIdentifier(complex1), ObjectIdentifier(complex1))
}
}
``````

And we are done!

## Summary

Today we learn many ways to do object comparison in Swift. Using structs with generics with optional conformance protocol, or enums to wrap the non-equatable content or making it a class and comparing pointers in memory, the most important thing to keep in mind is what makes sense to your codebase. If using structs is fine, so let it be. Now we've explored a lot of options for you and I'm sure that are many other ones!