-
-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggest assert_equal
when using assert
with multiple arguments
#117
Comments
Another idea that just occurred to me would be to register a violation if assert 100, list.length This seems like a pretty obvious case where |
Probably relevant: https://gist.github.com/arthurnn/cbd4da8512e4994dd8fe719ffcbcb569 |
I audited our largest repository at my company for accidental usages of 75% of them use a literal (
Thanks, this looks super useful! |
While this cop is correct that we should be using `assert_empty(list)` over `assert([], list)`, it's right for the wrong reasons. That example is bad because it's using `assert` and not `assert_equal`. An empty list/hash is truthy so the assertion will always succeed. That is, `assert([], [1, 2, 3])` will succeed even though at a glance it looks like it shouldn't. I believe that what this cop is intending to check for is `assert_equal([], list)` instead so I've updated the references to `assert` to `assert_equal`. Issue rubocop#117 proposes that we try to detect when `assert` is used where the user likely wanted `assert_equal` so while this cop will no longer register a violation for `assert([], list)`, if that proposal is accepted then a future cop *will* register a violation.
While this cop is correct that we should be using `assert_empty(list)` over `assert([], list)`, it's right for the wrong reasons. That example is bad because it's using `assert` and not `assert_equal`. An empty list/hash is truthy so the assertion will always succeed. That is, `assert([], [1, 2, 3])` will succeed even though at a glance it looks like it shouldn't. I believe that what this cop is intending to check for is `assert_equal([], list)` instead so I've updated the references to `assert` to `assert_equal`. Issue rubocop#117 proposes that we try to detect when `assert` is used where the user likely wanted `assert_equal` so while this cop will no longer register a violation for `assert([], list)`, if that proposal is accepted then a future cop *will* register a violation.
It is a common mistake to use `assert` instead of `assert_equal`. This is dangerous because minitest will treat the second argument to `assert` as the `msg` parameter and, as long as the first argument is truthy, the test will always pass. This false negative gives the user a sense of security even though they're not actually testing what they think they are. This commit introduces a new cop which will register a violation if `assert` is called with two arguments and the second argument isn't a `String`. If the second argument *is* a `String`, then the user is likely using `assert` as intended. If it's not, most of the time it means a mistake has been made.
It is a common mistake to use `assert` instead of `assert_equal`. This is dangerous because minitest will treat the second argument to `assert` as the `msg` parameter and, as long as the first argument is truthy, the test will always pass. This false negative gives the user a sense of security even though they're not actually testing what they think they are. This commit introduces a new cop which will register a violation if `assert` is called with two arguments and the second argument isn't a `String`. If the second argument *is* a `String`, then the user is likely using `assert` as intended. If it's not, most of the time it means a mistake has been made.
While this cop is correct that we should be using `assert_empty(list)` over `assert([], list)`, it's right for the wrong reasons. That example is bad because it's using `assert` and not `assert_equal`. An empty list/hash is truthy so the assertion will always succeed. That is, `assert([], [1, 2, 3])` will succeed even though at a glance it looks like it shouldn't. I believe that what this cop is intending to check for is `assert_equal([], list)` instead so I've updated the references to `assert` to `assert_equal`. Issue rubocop#117 proposes that we try to detect when `assert` is used where the user likely wanted `assert_equal` so while this cop will no longer register a violation for `assert([], list)`, if that proposal is accepted then a future cop *will* register a violation.
It is a common mistake to use `assert` instead of `assert_equal`. This is dangerous because minitest will treat the second argument to `assert` as the `msg` parameter and, as long as the first argument is truthy, the test will always pass. This false negative gives the user a sense of security even though they're not actually testing what they think they are. This commit introduces a new cop which will register a violation if `assert` is called with two arguments and the second argument isn't a `String`. If the second argument *is* a `String`, then the user is likely using `assert` as intended. If it's not, most of the time it means a mistake has been made.
It is a common mistake to use `assert` instead of `assert_equal`. This is dangerous because minitest will treat the second argument to `assert` as the `msg` parameter and, as long as the first argument is truthy, the test will always pass. This false negative gives the user a sense of security even though they're not actually testing what they think they are. This commit introduces a new cop which will register a violation if `assert` is called with two arguments and the second argument isn't a `String`. If the second argument *is* a `String`, then the user is likely using `assert` as intended. If it's not, most of the time it means a mistake has been made.
Is your feature request related to a problem? Please describe.
We recently caught an issue where we accidentally used the following code...
...when we really wanted this:
The first example will always pass, effectively making the test useless. This has happened a number of times before (someone even previously reported it in #32) and the only way I know of to prevent it is to hope that someone catches it in code review.
Describe the solution you'd like
The most obvious solution is to register a violation when two arguments are passed to
assert
and to suggestassert_equal
in that case. However,assert
does accept a second argument – a custom message to be displayed if the test fails:https://github.com/seattlerb/minitest/blob/b8fb1014ad1932eddefb5107c0f6504ba45e0cbc/lib/minitest/assertions.rb#L178
It would be annoying to get a violation every time the user actually wanted to use
msg
. A simple improvement would be to not register a violation if the second argument is a literalString
.I poked around using grep.app and found that most usages of the
msg
argument were using a literalString
:https://github.com/thoughtbot/paperclip/blob/e3f7493b4cc954405a0209d26933830333ae2869/spec/paperclip/validators/attachment_file_name_validator_spec.rb#L37
https://github.com/theforeman/foreman/blob/46fcf9361e2d8c6cb89af2c3f8b9be60365fdd21/test/models/orchestration/dhcp_test.rb#L12
https://github.com/faker-ruby/faker/blob/664cbafe9d15bddb97843dcbe107204e6e7291cb/test/test_locale.rb#L75
https://github.com/Linuxbrew/legacy-linuxbrew/blob/532040391bb984e410b7ad73bdd0c518f945cc0b/Library/Formula/lcm.rb#L62
https://github.com/rails/rails/blob/da418dc2508eb8af94ba88b70034021cd17b1abd/activerecord/test/cases/validations/uniqueness_validation_test.rb#L80
Most of the instances I could find where
msg
wasn't a literalString
were in custom assertion code like the following:https://github.com/thoughtbot/shoulda-context/blob/970d3d57a584ecb2652f0bc7188761024de16c52/lib/shoulda/context/assertions.rb#L94
https://github.com/thoughtbot/json_matchers/blob/4644ca82adb01055528b5643df93feb1d35c8205/lib/json_matchers/minitest/assertions.rb#L14
These are legitimate usages of
assert
with two, non-literal arguments. So if the proposed solution was implemented, these cases would have to be amended with arubocop:disable
. From my experience, it's generally more likely that the user really meant to useassert_equal
but ultimately it's not my call to make. At the very least, we could add the cop but have it disabled by default.Describe alternatives you've considered
It would be nice if the
msg
parameter toassert
was instead a named parameter but I think it's far too late for such a drastically breaking change at this point.Additional context
This idea was previously suggested in #32. That issue was closed by #38 but while the change (namely, adding a cop to prefer
assert_empty X
toassert [], X
) is desirable, it didn't address the actual issue as I understand it. I figured it was better to open a new issue than to revive a dead one.The text was updated successfully, but these errors were encountered: