To use or not to use assert_predicate with minitest in Ruby
Reading time: 3 minutes
Recently RuboCop started to blame my
assert something.booked? style tests in
minitest and telling me this:
Minitest/AssertPredicate: Prefer using `assert_predicate(something, :booked?)`.
I’ve looked for the corresponding Pull Request and also checked the final Rubocop Minitest Style Guide: Assert Predicate.
According to the documentation, we can read:
Use assert_predicate if expecting to test the predicate on the expected object and on applying predicate returns true. The benefit of using the assert_predicate over the assert or assert_equal is the user friendly error message when assertion fails. – assert_predicate
Compare the difference
First I try the simple
assert and let the test fail
test 'something must be booked before it can be used' do something = Something.new assert something.booked? end # resulting fail output Expected true to not be truthy.
Now the version with
test 'something must be booked before it can be used' do something = Something.new assert_predicate something, :booked? end # resulting fail output Expected <something> to be booked?
If you compare the two outputs, you will see, that using
produces a more readable output, what is also mentioned in the documentation.
How to proceed with such a new rule?
As this is a pretty new (March 2022) RuboCop rule in
rubocop-minitest, it will hit a
lot of projects. For me using plain assert where it is useful like in
assert something.booked? is a rule of thumb, as I left RSpec,
because it has for almost everything a separate command, which I became tired to
learn or lookup. Well, how to proceed?
You can ignore it
You can just ignore the rule and add these lines to your .rubocop.yml file in your project:
Minitest/AssertPredicate: Enabled: false Minitest/RefutePredicate: Enabled: false
Remember to add both rules for
RuboCop will blame
refute something.booked? too.
You can accept the new rule
If you accept this new rule, it is good to have an up-to-date project with all other rules being already applied. To apply all current rule just run:
All new rules will be applied to all files, which may be more than the rules you wanted to be applied.
As projects for many reasons may be:
- Not up to date with RuboCop rules on all files.
- The RuboCop update has several new rules included.
- The RuboCop update is a jump on several versions and have a lot of new rules, which hit your project.
You can apply only these two relevant to your project and ask RuboCop to fix them for you:
bundle exec rubocop -A --only Minitest/AssertPredicate bundle exec rubocop -A --only Minitest/RefutePredicate
Afterward commit them with a corresponding explanation, as it may hit a lot of test files.
My current approach
Most of the time I used simple
assert with ruby code and not test
specific language (like it is more common in RSpec). I
thing a simple assert followed by good named ruby code more readable and less to
think about while trying to understand test code.
In this case
refute_predicate produce a better output
on a failed test, but check the same as a simple
assert would do. That’s why I