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

New option --display-only-failed for junit format #8050

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,7 @@
* [#7908](https://github.com/rubocop-hq/rubocop/pull/7908): Add new `Style/RedundantRegexpEscape` cop. ([@owst][])
* [#7978](https://github.com/rubocop-hq/rubocop/pull/7978): Add new option `OnlyFor` to the `Bundler/GemComment` cop. ([@ric2b][])
* [#8063](https://github.com/rubocop-hq/rubocop/issues/8063): Add new `AllowedNames` option for `Naming/ClassAndModuleCamelCase`. ([@tejasbubane][])
* New option `--display-only-failed` that can be used with `--format junit`. Speeds up test report processing for large codebases and helps address the sorts of concerns raised at [mikian/rubocop-junit-formatter #18](https://github.com/mikian/rubocop-junit-formatter/issues/18). ([@burnettk][])

### Bug fixes

Expand Down Expand Up @@ -4558,3 +4559,4 @@
[@CvX]: https://github.com/CvX
[@jschneid]: https://github.com/jschneid
[@ric2b]: https://github.com/ric2b
[@burnettk]: https://github.com/burnettk
13 changes: 13 additions & 0 deletions docs/modules/ROOT/pages/formatters.adoc
Expand Up @@ -280,6 +280,19 @@ $ rubocop --format junit
</testsuites>
----

The `junit` style formatter is very useful for continuous integration systems
such as Jenkins, most of which support junit formatting when parsing test
results. A typical invocation in this type of scenario might look like:

[source,sh]
----
$ rubocop --format junit --out test-reports/junit.xml
----

Since there is one XML node for each cop for each file, the size of the resulting
XML can get quite large. If it is too large for you, you can restrict the output
to just failures by adding the `--display-only-failed` option.

== Offense Count Formatter

Sometimes when first applying RuboCop to a codebase, it's nice to be able to
Expand Down
14 changes: 13 additions & 1 deletion legacy-docs/formatters.md
Expand Up @@ -242,7 +242,7 @@ The JSON structure is like the following example:
**Machine-parsable**

The `junit` style formatter provides the JUnit formatting.
This formatter is based on [rubocop-junit-formatter gem](https://github.com/mikian/rubocop-junit-formatter).
This formatter is based on the [rubocop-junit-formatter gem](https://github.com/mikian/rubocop-junit-formatter).
Copy link
Collaborator

Choose a reason for hiding this comment

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

You didn't make the same edit to the actual docs. There's no need to touch the markdown files - they will be removed as soon as we setup permanent redirects between the old docs site that used them (powered by RTD) and the new one (docs.rubocop.org).


```sh
$ rubocop --format junit
Expand All @@ -268,6 +268,18 @@ $ rubocop --format junit
</testsuites>
```

The `junit` style formatter is very useful for continuous integration systems
such as Jenkins, most of which support junit formatting when parsing test
results. A typical invocation in this type of scenario might look like:

```sh
$ rubocop --format junit --out test-reports/junit.xml
```

Since there is one XML node for each cop for each file, the size of the resulting
XML can get quite large. If it is too large for you, you can restrict the output
to just failures by adding the `--display-only-failed` option.

## Offense Count Formatter

Sometimes when first applying RuboCop to a codebase, it's nice to be able to
Expand Down
18 changes: 14 additions & 4 deletions lib/rubocop/formatter/junit_formatter.rb
Expand Up @@ -35,19 +35,29 @@ def file_finished(file, offenses)
#
# In the future, it would be preferable to return only enabled cops.
Cop::Cop.all.each do |cop|
target_offenses = offenses_for_cop(offenses, cop)

next unless relevant_for_output?(options, target_offenses)

REXML::Element.new('testcase', @testsuite).tap do |testcase|
testcase.attributes['classname'] = classname_attribute_value(file)
testcase.attributes['name'] = cop.cop_name

target_offenses = offenses.select do |offense|
offense.cop_name == cop.cop_name
end

add_failure_to(testcase, target_offenses, cop.cop_name)
end
end
end

def relevant_for_output?(options, target_offenses)
!options[:display_only_failed] || target_offenses.any?
end

def offenses_for_cop(all_offenses, cop)
all_offenses.select do |offense|
offense.cop_name == cop.cop_name
end
end

def classname_attribute_value(file)
file.gsub(/\.rb\Z/, '').gsub("#{Dir.pwd}/", '').tr('/', '.')
end
Expand Down
16 changes: 14 additions & 2 deletions lib/rubocop/options.rb
Expand Up @@ -143,6 +143,8 @@ def add_formatting_options(opts)
@options[:output_path] = path
end
end

option(opts, '--display-only-failed')
end

def add_severity_option(opts)
Expand Down Expand Up @@ -286,6 +288,7 @@ def validate_compatibility # rubocop:disable Metrics/MethodLength
end
validate_auto_gen_config
validate_auto_correct
validate_display_only_failed
validate_parallel

return if incompatible_options.size <= 1
Expand All @@ -309,13 +312,20 @@ def validate_auto_gen_config
end
end

def validate_display_only_failed
return unless @options.key?(:display_only_failed)
return if @options[:format] == 'junit'

raise OptionArgumentError,
format('--display-only-failed can only be used together with --format junit.')
end

def validate_auto_correct
return if @options.key?(:auto_correct)
return unless @options.key?(:disable_uncorrectable)

raise OptionArgumentError,
format('--%<flag>s can only be used together with --auto-correct.',
flag: '--disable-uncorrectable')
format('--disable-uncorrectable can only be used together with --auto-correct.')
end

def validate_parallel
Expand Down Expand Up @@ -431,6 +441,8 @@ module OptionsHelp
'if no format is specified.'],
fail_level: ['Minimum severity (A/R/C/W/E/F) for exit',
'with error code.'],
display_only_failed: ['Only output offense messages. Omit passing',
'cops. Only valid for --format junit.'],
display_only_fail_level_offenses:
['Only output offense messages at',
'the specified --fail-level or above'],
Expand Down
14 changes: 14 additions & 0 deletions spec/rubocop/options_spec.rb
Expand Up @@ -92,6 +92,8 @@ def abs(path)
This option applies to the previously
specified --format, or the default format
if no format is specified.
--display-only-failed Only output offense messages. Omit passing
cops. Only valid for --format junit.
-r, --require FILE Require Ruby file.
--fail-level SEVERITY Minimum severity (A/R/C/W/E/F) for exit
with error code.
Expand Down Expand Up @@ -224,6 +226,18 @@ def abs(path)
end
end

describe '--display-only-failed' do
it 'fails if given without --format junit' do
expect { options.parse %w[--display-only-failed] }
.to raise_error(RuboCop::OptionArgumentError)
end

it 'works if given with --format junit' do
expect { options.parse %w[--format junit --display-only-failed] }
.not_to raise_error(RuboCop::OptionArgumentError)
end
end

describe '--fail-level' do
it 'accepts full severity names' do
%w[refactor convention warning error fatal].each do |severity|
Expand Down