Skip to content

Instantly share code, notes, and snippets.

@giljr
Created October 25, 2025 16:10
Show Gist options
  • Select an option

  • Save giljr/748dc558a71e6315a438a4d6ff6f2933 to your computer and use it in GitHub Desktop.

Select an option

Save giljr/748dc558a71e6315a438a4d6ff6f2933 to your computer and use it in GitHub Desktop.
Rails Conf 2013 The Magic Tricks of Testing by Sandi Metz https://youtu.be/URSWYvyc42M?si=dFF6lqd_dsJjoJeK

The Six Magic Tricks

by Sandi Metz

Origin Query (returns something) Command (changes something)
Incoming ① ✅ Assert return value ② ✅ Assert public side effect
To Self ③ 🚫 Ignore ④ 🚫 Ignore
Outgoing ⑤ 🚫 Ignore ⑥ ✅ Mock expectation

Let’s decode how to test each one.

① Incoming Query Message

Example:

wheel.diameter

✅ Test by checking what it returns

assert_in_delta(29, wheel.diameter, 0.01)

② Incoming Command Message

Example:

gear.set_cog(27)

✅ Test by checking the public side effect

gear.set_cog(27)
assert_equal 27, gear.cog

③ & ⑤ Messages to Self / Outgoing Queries

  • These are internal or read-only calls.

  • 🚫 Don’t test them directly.

  • They’re invisible to the outside world — so ignore them.

If your public test passes, your private method must work.

④ Private Commands (to self)

Same rule: don’t test private methods.

If you must test while debugging, keep them in a separate block with a note:

“If these tests fail — delete them.”

⑥ Outgoing Command Message

Example: Your object tells another to do something:

observer.changed(chainring, cog)

✅ Use mocks/stubs to verify the message was sent

observer = Minitest::Mock.new
observer.expect(:changed, true, [52, 27])

gear = Gear.new(chainring: 52, cog: 27, observer: observer)
gear.set_cog(27)

observer.verify

💡 Don’t test distant side effects (like database writes). That’s integration territory, not unit testing.

Rails Conf 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment