Skip to content
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

Add new RSpec/EmptyOutput cop #1854

Merged
merged 1 commit into from Apr 4, 2024
Merged

Add new RSpec/EmptyOutput cop #1854

merged 1 commit into from Apr 4, 2024

Conversation

bquorning
Copy link
Collaborator

Instead of calling output with an empty string, you should use the inverse runner and call output without an argument. E.g. instead of

expect { foo }.to output('').to_stdout

you should call

expect { foo }.not_to output.to_stdout

Before submitting the PR make sure the following are checked:

  • Feature branch is up-to-date with master (if not - rebase it).
  • Squashed related commits together.
  • Added tests.
  • Updated documentation.
  • Added an entry to the CHANGELOG.md if the new code introduces user-observable changes.
  • The build (bundle exec rake) passes (be sure to run this locally, since it may produce updated documentation that you will need to commit).

If you have created a new cop:

  • Added the new cop to config/default.yml.
  • The cop is configured as Enabled: pending in config/default.yml.
  • The cop is configured as Enabled: true in .rubocop.yml.
  • The cop documents examples of good and bad code.
  • The tests assert both that bad code is reported and that good code is not reported.
  • Set VersionAdded: "<<next>>" in default/config.yml.

@bquorning bquorning marked this pull request as ready for review March 30, 2024 23:28
@bquorning bquorning requested a review from a team as a code owner March 30, 2024 23:28
CHANGELOG.md Outdated Show resolved Hide resolved
@bquorning bquorning force-pushed the empty-output branch 3 times, most recently from 471010f to 4c96fce Compare April 1, 2024 10:37
@bquorning
Copy link
Collaborator Author

cc @pirj

@pirj
Copy link
Member

pirj commented Apr 1, 2024

One exception I can think of is a compund expectation like output(‘’).to_stdout.and output(‘’).to_stderr.
We had a cop that suggested using a custom negation matcher for compound expectations. Was that not_change?

Otherwise - looks good, thanks!

@bquorning
Copy link
Collaborator Author

I actually did look into the compound marchers, and I thinkto_stderr and to_stdout both return true so they cannot be chained. I may be wrong of course.

@pirj
Copy link
Member

pirj commented Apr 1, 2024

At a glance, it returns self, and the vase class does include Composable that defines and/or.

Not a big deal, just an edge case. But since to_std… is mandatory, it’s not unrealistic.

@bquorning
Copy link
Collaborator Author

bquorning commented Apr 1, 2024

I’ll have a look.

Actually what should we recommend if someone matches e.g.

expect {}.to output("foo").to_stdout.and output("").to_stderr

I don’t think there’s a way to do e.g.

expect {}.to output("foo").to_stdout.and not output.to_stderr
# or
expect {}.to_not output.to_stderr.and output("foo").to_stdout

The last code tells me that

expect(...).not_to matcher.and matcher is not supported, since it creates a bit of an ambiguity. Instead, define negated versions of whatever matchers you wish to negate with RSpec::Matchers.define_negated_matcher and use expect(...).to matcher.and matcher.

Maybe in that case it’s fine that we don’t detect an offense on compound expectations.

Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you!

@pirj
Copy link
Member

pirj commented Apr 1, 2024

For the other cop, we register an offence, but don’t autocorrect, since it’s not guaranteed that the negated matcher (not_change) is defined in the user’s codebase.

expect { :nop }
  .to not_output.to_stdout
  .and not_output.to_stderr

should work, just like a combination of output.to_stderr with eg not_output.to_stdout

@bquorning
Copy link
Collaborator Author

Yeah, I think it’s too much if we ask the user to implement a #not_output method when output("") works fine.

Instead of calling `output` with an empty string, you should use the
inverse runner and call `output` without an argument. E.g. instead of

    expect { foo }.to output('').to_stdout

you should call

    expect { foo }.not_to output.to_stdout
@bquorning
Copy link
Collaborator Author

Just to be sure, the all matcher cannot be used together with output, right? E.g. expect([proc_1, proc_2]).to all(output("").to_stderr)

@pirj pirj requested a review from ydah April 2, 2024 06:19
@ydah
Copy link
Member

ydah commented Apr 2, 2024

I checked with real-world-rspec. There seems to be no errors or false positives ✅

Offenses:

/ydah/real-world-rspec/rubocop/spec/rubocop/config_loader_spec.rb:1016:74: C: [Correctable] RSpec/EmptyOutput: Use not_to instead of matching on an empty output.
        expect { expect(configuration_from_file.to_h).to eq(config) }.to output('').to_stderr
                                                                         ^^^^^^^^^^
/ydah/real-world-rspec/rubocop/spec/rubocop/config_loader_spec.rb:1213:18: C: [Correctable] RSpec/EmptyOutput: Use not_to instead of matching on an empty output.
          end.to output('').to_stderr
                 ^^^^^^^^^^
/ydah/real-world-rspec/rubocop/spec/rubocop/config_loader_spec.rb:1249:18: C: [Correctable] RSpec/EmptyOutput: Use not_to instead of matching on an empty output.
          end.to output('').to_stderr
                 ^^^^^^^^^^
/ydah/real-world-rspec/rubocop/spec/rubocop/config_loader_spec.rb:1317:47: C: [Correctable] RSpec/EmptyOutput: Use not_to instead of matching on an empty output.
        expect { configuration_from_file }.to output('').to_stderr
                                              ^^^^^^^^^^

22407 files inspected, 4 offenses detected, 4 offenses autocorrectable

@bquorning bquorning mentioned this pull request Apr 4, 2024
6 tasks
Copy link
Member

@ydah ydah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@ydah ydah merged commit 5113a9b into master Apr 4, 2024
24 checks passed
@ydah ydah deleted the empty-output branch April 4, 2024 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants