I’ve been working on DeltaCheck lately, a small testing library that provides a concise API for tracking and asserting on what changes your code makes and doesn’t make in the database.
Example
test "create a user" do
assert_changes(insert: %User{name: "John Doe"}) do
Accounts.create_user(%{name: "John Doe"})
end
end
I’m not sure about powerful—you can achieve the same thing with queries—but I’d say it’s much more concise. By asserting on the delta you can make a lot of implicit assertions with very little code.
Let’s say you want to test a function that creates a reply on a forum post (I think I might lack imagination). This function also updates the reply count on the post, which we for some reason cache.
This doesn’t only assert that we inserted a reply and updated the post, it also asserts that:
the reply was inserted with the values we expect,
reply_count and updated_at were the only fields that were updated on the post,
reply_count went from 0 to 1,
nothing else was affected.
When not testing the happy path, it generally gets even more concise:
assert_no_changes do
Posts.create_reply(%{content: nil, post_id: post_id})
end
I’ve used DeltaCheck for a while in a personal project, and I’ve found the tests to be more thorough and consistent, while still being shorter, than before I was using it.
I’ll have to say this seems like an appealing solution to the boilerplate one usually needs and I’m usually rather critical about trying to compare before/after records to each other. Being able to say “I don’t care how this field changed” makes db driven changes less of a hassle. This style of testing certainly couples the tests to the exact db representation of the values though.
Personally, I had some parts of the project where wrong/failed DB operations would introduce inconsistency in the system, so I had to test that all of the entries were correctly inserted/updated, of course there may be other ways to ensure that.
In a more general approach, I totally agree, these kind of tests tend to make subsequent modification of code a hassle.