I intentionally left it vague because I wanted to see what other people are doing. I cannot rule out that my subjective metrics for bad or good are not misguided. All that having been said...
The goal that I have is to verify the structure/semantics of the encoded JSON in isolation. The secondary issue is being able to succinctly identify what is actually wrong.
For instance, in a overly simplified case, if I had these JSON strings:
a
{
"dateAdded": "2020-09-23T17:58:14Z",
"id": 1,
"value": "super duper value"
}
b
{ "value": "super duper value", "dateAdded": "2020-09-23T17:58:14Z", "id": 1 }
c
{
"id": 2,
"value": "super duper value",
"dateAdded": "2020-09-23T17:58:14Z"
}
a
and b
are equal because property order and white-space is irrelevant to me. Likewise, a
and c
are unequal as are b
and c
. In the case of the unequal case I'd like some way to succinctly report, in the event of failure, that the id
property was 2
instead of 1
(or vice versa).
Writing the code I wish I had would look something like this:
// The result of `JSONEncoder.encode(a)` is the JSON illustrated as `a` above
XCTAssertHypotheticalWish(try JSONEncoder.encode(a), matches: """
{
"value": "super duper value",
"dateAdded": "2020-09-23T17:58:14Z",
"id": 1
}
""")
Most of what I have tried to get to XCTAssertHypotheticalWish
usually ends up making me decode encodedA
, then decode the matches
argument (into the same type). Then assert their equality. I dislike that approach because:
- It relies on a correct implementation of
Decodable
.
- Am I testing my implementation of
Decodable
or Encodable
?
- Also, what if I have no need for an implementation of
Decodable
? I had to write one just for the tests? Where does that implementation live?
- What if my decoding is different than what I encode to?
- Now I also have to implement
Equatable
.
Then there is the naive string comparison solution. But it is easily broken if the keys are out of order...