---
title: "To use or not to use assert_predicate with minitest in Ruby"
description: "Minitest extension in RuboCop recommends to use assert_predicate instead of a simple assert on boolean values. Let's have a look at it."
url: "https://qameta.com/posts/use-assert-predicate-with-minitest-ruby-by-rubocop/"
---

# To use or not to use assert_predicate with minitest in Ruby

Recently [RuboCop](https://rubocop.org) started to blame my `assert
something.booked?` style tests in
[minitest](https://github.com/minitest/minitest) and telling me this:

```
Minitest/AssertPredicate: Prefer using `assert_predicate(something, :booked?)`.
```

I've looked for the corresponding [Pull
Request](https://github.com/rubocop/rubocop-minitest/pull/161) and also checked
the final [Rubocop Minitest Style Guide: Assert
Predicate](https://minitest.rubystyle.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.
> -- <cite>[assert_predicate](https://minitest.rubystyle.guide/#assert-predicate)</cite>

## Compare the difference

First I try the simple `assert` and let the test fail

```ruby
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 `assert_predicate`:

```ruby
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 `assert_predicate`
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](https://github.com/rubocop/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](https://rspec.info),
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:

```yml
Minitest/AssertPredicate:
  Enabled: false

Minitest/RefutePredicate:
  Enabled: false
```

Remember to add both rules for `assert_predicate` and `refute_predicate` or
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:

```sh
rubocop -A
```

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:

```sh
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](https://rspec.info)). 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 `assert_predicate` and `refute_predicate` produce a better output
on a failed test, but check the same as a simple `assert` would do. That's why I
will use `assert_predicate` and `refute_predicate` now.
