Then, I packaged it into a Google Test matcher, and from now on, the problem you describe is gone. I write:
EXPECT_THAT(someObject, IsEqAsJSON(someBlobFromADifferentFile));
and if it fails, I get output like this: Expected someObject to be structurally equivalent to someBlobFromADifferentFile; it is not;
- #/object/key - missing in expected, found in actual
- #/object/key2 - expected string, actual is integer
- #/object/key3/array1 - array lengths differ; expected: 3, actual: 42
- #/object/key4/array1/0/key3 - expected "foo" [string], actual "bar" [string]
Etc.It was a rather simple exercise, and the payoff is immense. I think it's really important for programmers to learn to help themselves. If there's something that annoys you repeatedly, you owe it to yourself and others to fix it.
It's a cultural problem. _I_ can do that, but my colleagues will just continue to write minimum effort tests against huge json files or database dumps where you have no idea why something failed and why there are a bunch of assertions against undocumented magic numbers in the first place. It's like you're fighting against a hurricane with a leaf blower. A single person can only do so much. I end up looking bad in the daily standup because I take longer to work on my tickets but the code quality doesn't even improve in a measurable way.
Assuming that’s not the case and you’re interested in the state of two object graphs then you just compare those, not the json string they deserialize to.
https://github.com/skyscreamer/JSONassert seems decent.
but it can be done from scratch in a few hours (I'd recommend this if you have 'standardized' fields which you may want to ignore):
1) Move to a matcher library for assertions (Hamcrest is decent), and abstract `toJSON` into the a matcher, rather on the input.
This would change the assertion from:
`assertEquals(toJson(someObject), giantJsonBlobFromADifferentFile)`
to:
`assertThat(someObject, jsonEqual(giantJsonBlobFromADifferentFile))`
The difference here is subtle: it allows `jsonEqual` to control the formatting of the test failure output, so on a failure you can:
* convert both of the strings back to JSON
* perform a diff, and provide the diff in the test output.
Decent blog post on the topic: https://veskoiliev.com/use-custom-hamcrest-matchers-to-level...
I'd actually rather people just assert on the fields they need, but it's a larger team than I can push that on.
Hamcrest is a drop-in replacement for `assertEquals`, and provides obvious benefits. Politically, it's easy to convince developers onboard once you show them:
* You just need to change the syntax of an assertion - no thought required
* You (Macha) will take responsibility for improving the formatting of the output, and developers have someone to reach out to to improve their assertions.
From this: you'll get a very small subset of missionaries who will understand the direction that you're pushing the test code in, and will support your efforts (by writing their own matchers and evangelising).
The larger subset of the developer population won't particularly care, but will see the improved output from what you're proposing, and will realise that it's a single line of code to change to reap the benefits.
EDIT: I've added a lint rule into a codebase to guide developers away from `assertEquals()`. Obviously this could backfire, and don't burn your political capital on this issue.
The problem is, since it's a legacy codebase, there's many fields which are only tested incidentally by this behaviour, by tests that actually aren't intending to test that functionality.