rspec_junit_formatter_bitbucket 0.1.0 → 0.2.0.pre.170

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 406b38492456241386e52eba83fca1ae1fe3835be224415ffc7d465d5ab5dba0
4
- data.tar.gz: 9c7b748c2d2b70a17cec376f65beb996164306926653d86a4e815fce93e8f443
3
+ metadata.gz: da625be220376cea7a09f0c1870b2bea24b5f40e825a8c7296ed76318ecf1cff
4
+ data.tar.gz: c9ae2324d2e151ee747eebd08ffa7245bec2860414392d44731a3234e4d0f797
5
5
  SHA512:
6
- metadata.gz: 2ac815d3b5d2aa7b58a73c5fec13f1675d24277663998bf3da4c07bf7ada2bd6b3b206f6693b33951ed0a81b32889e2baadfe116753459ca712632ae3d29083f
7
- data.tar.gz: 6788c28e17df99db6475ebdb4cf8dfd2072ddd3c85499fdd22a1c1356393876698c6f917d709eb1f67ed27556d5427ca991f9e503ddb32bcb803c686ccd991b4
6
+ metadata.gz: 0524b387088bbcc39230e84ac964eeef48bf77760abc9b27ff2241b7a4edc44687a7506b8755d8e260ce5bbc8b0cb75b45f3e1decc0adb268ddcbee6313d950f
7
+ data.tar.gz: 8bc904f3bdbe9d690bd1daa57151e2fd3a49b1b1de72335a8cd6e2686577a2423e1c1785006cb52555e57a1f0df775a6cf4081acc3b69f947a2105d52126810a
data/README.md CHANGED
@@ -1,42 +1,39 @@
1
- # RSpec JUnit Formatter
1
+ # RSpec JUnit Formatter | [![Build Status](https://travis-ci.org/dazzl-tv/rspec_junit_formatter.svg?branch=master)](https://travis-ci.org/dazzl-tv/rspec_junit_formatter) [![Gem Version](https://badge.fury.io/rb/rspec_junit_formatter_bitbucket.svg)](https://badge.fury.io/rb/rspec_junit_formatter_bitbucket)
2
2
 
3
3
  __FORK to project : [sj26](https://github.com/sj26/rspec_junit_formatter)__
4
4
 
5
5
  Use for pipeline bitbucket. Apply rules : http://reflex.gforge.inria.fr/xunit.html#xunitReport
6
6
 
7
- [![Build results](http://img.shields.io/travis/sj26/rspec_junit_formatter/master.svg)](https://travis-ci.org/sj26/rspec_junit_formatter)
8
- [![Gem version](http://img.shields.io/gem/v/rspec_junit_formatter.svg)](https://rubygems.org/gems/rspec_junit_formatter)
9
-
10
- [RSpec][rspec] 2 & 3 results that your CI can read. [Jenkins][jenkins-junit], [Buildkite][buildkite-junit], [CircleCI][circleci-junit], and probably more, too.
11
-
12
- [rspec]: http://rspec.info/
13
- [jenkins-junit]: https://jenkins.io/doc/pipeline/steps/junit/
14
- [buildkite-junit]: https://github.com/buildkite/rspec-junit-example
15
- [circleci-junit]: https://circleci.com/docs/2.0/collect-test-data/
7
+ Rspec 3 (remove rspec 2 compatibility) that your CI (Forked for Bitbucket pipeline).
16
8
 
17
9
  ## Usage
18
10
 
19
11
  Install the gem:
20
12
 
21
13
  ```sh
22
- gem install rspec_junit_formatter
14
+ gem install rspec_junit_formatter_bitbucket
23
15
  ```
24
16
 
25
17
  Use it:
26
18
 
27
19
  ```sh
28
- rspec --format RspecJunitFormatter --out rspec.xml
20
+ # Use RSpec directly
21
+ rspec --format JUnit --out ./tmp/test-reports/rspec/report.xml
22
+
23
+ # use with bundle
24
+ export SPEC_OPTS=" --require rspec_junit_formatter_bitbucket --format RspecJunitFormatterBitbucket::Init --out ./tmp/test-reports/rspec/report.xml"
25
+ bundle exec rake spec
29
26
  ```
30
27
 
31
- You'll get an XML file `rspec.xml` with your results in it.
28
+ You'll get an XML file `report.xml` with your results in it.
32
29
 
33
30
  You can use it in combination with other [formatters][rspec-formatters], too:
34
31
 
35
32
  ```sh
36
- rspec --format progress --format RspecJunitFormatter --out rspec.xml
33
+ rspec --format progress --format RspecJunitFormatterBitbucket::Init --out rspec.xml
37
34
  ```
38
35
 
39
- [rspec-formatters]: https://relishapp.com/rspec/rspec-core/v/3-6/docs/formatters
36
+ [rspec-formatters]: https://relishapp.com/rspec/rspec-core/v/3-8/docs/formatters/custom-formatters
40
37
 
41
38
  ### Using in your project with Bundler
42
39
 
@@ -45,14 +42,14 @@ Add it to your Gemfile if you're using [Bundler][bundler]. Put it in the same gr
45
42
  ```ruby
46
43
  group :test do
47
44
  gem "rspec"
48
- gem "rspec_junit_formatter"
45
+ gem "rspec_junit_formatter_bitbucket"
49
46
  end
50
47
  ```
51
48
 
52
49
  Put the same arguments as the commands above in [your `.rspec`][rspec-file]:
53
50
 
54
51
  ```sh
55
- --format RspecJunitFormatter
52
+ --format RspecJunitFormatterBitbucket::Init
56
53
  --out rspec.xml
57
54
  ```
58
55
  [bundler]: https://bundler.io
@@ -99,28 +96,16 @@ end
99
96
 
100
97
  [xml-charsets]: https://www.w3.org/TR/xml/#charsets
101
98
 
102
- ## Roadmap
103
-
104
- * It would be nice to split things up into individual test suites, although would this correspond to example groups? The subject? The spec file? Not sure yet.
105
-
106
99
  ## Development
107
100
 
108
101
  Run the specs with `bundle exec rake`, which uses [Appraisal][appraisal] to run the specs against all supported versions of rspec.
109
102
 
110
103
  [appraisal]: https://github.com/thoughtbot/appraisal
111
104
 
112
- ## Releasing
113
-
114
- Bump the gem version in the gemspec, and commit. Then `bundle exec rake build` to build a gem package, `bundle exec rake install` to install and test it locally, then `bundle exec rake release` to tag and push the commits and gem.
115
-
116
105
  ## License
117
106
 
118
107
  The MIT License, see [LICENSE](./LICENSE).
119
108
 
120
109
  ## Thanks
121
110
 
122
- Inspired by the work of [Diego Souza][dgvncsz0f] on [RSpec Formatters][dgvncsz0f/rspec_formatters] after frustration with [CI Reporter][ci_reporter].
123
-
124
- [dgvncsz0f]: https://github.com/dgvncsz0f
125
- [dgvncsz0f/rspec_formatters]: https://github.com/dgvncsz0f/rspec_formatters
126
- [ci_reporter]: https://github.com/nicksieger/ci_reporter
111
+ And thanks [sj26](https://github.com/sj26)
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Lint/AssignmentInCondition
4
+ module RspecJunitFormatterBitbucket
5
+ # Format attribute to xml
6
+ module Attribute
7
+ def self.classname_for(notification)
8
+ fp = example_group_file_path_for(notification)
9
+ fp.sub(%r{\.[^/]*\Z}, '').tr('/', '.').gsub(/\A\.+|\.+\Z/, '')
10
+ end
11
+
12
+ def self.description_for(notification)
13
+ notification.example.full_description
14
+ end
15
+
16
+ def self.example_group_file_path_for(notification)
17
+ metadata = notification.example.metadata[:example_group]
18
+ while parent_metadata = metadata[:parent_example_group]
19
+ metadata = parent_metadata
20
+ end
21
+ metadata[:file_path]
22
+ end
23
+
24
+ def self.duration_for(notification)
25
+ notification.example.execution_result.run_time
26
+ end
27
+ end
28
+ end
29
+ # rubocop:enable Lint/AssignmentInCondition
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: false
2
+
3
+ module RspecJunitFormatterBitbucket
4
+ # Make sure it's utf-8, replace illegal characters with
5
+ # ruby-like escapes, and replace special and discouraged
6
+ # characters with entities
7
+ module Format
8
+ # Inversion of character range from https://www.w3.org/TR/xml/#charsets
9
+ ILLEGAL_REGEXP = Regexp.new(
10
+ '\[\^' \
11
+ '\u{9}' \
12
+ '\u{a}' \
13
+ '\u{d}' \
14
+ '\u{20}-\u{d7ff}' \
15
+ '\u{e000}-\u{fffd}' \
16
+ '\u{10000}-\u{10ffff}' \
17
+ '\]'
18
+ )
19
+
20
+ # Replace illegals with a Ruby-like escape
21
+ ILLEGAL_REPLACEMENT = Hash.new do |_, c|
22
+ x = c.ord
23
+ if x <= 0xff
24
+ '\\x%02X'.freeze % x
25
+ elsif x <= 0xffff
26
+ '\\u%04X'.freeze % x
27
+ else
28
+ '\\u{%<X>}'.freeze % x
29
+ end.freeze
30
+ end.update(
31
+ "\0".freeze => '\\0'.freeze,
32
+ "\a".freeze => '\\a'.freeze,
33
+ "\b".freeze => '\\b'.freeze,
34
+ "\f".freeze => '\\f'.freeze,
35
+ "\v".freeze => '\\v'.freeze,
36
+ "\e".freeze => '\\e'.freeze
37
+ ).freeze
38
+
39
+ # Discouraged characters from https://www.w3.org/TR/xml/#charsets
40
+ # Plus special characters with well-known entity replacements
41
+ DISCOURAGED_REGEXP = Regexp.new(
42
+ '[' \
43
+ '\u{22}' \
44
+ '\u{26}' \
45
+ '\u{27}' \
46
+ '\u{3c}' \
47
+ '\u{3e}' \
48
+ '\u{7f}-\u{84}' \
49
+ '\u{86}-\u{9f}' \
50
+ '\u{fdd0}-\u{fdef}' \
51
+ '\u{1fffe}-\u{1ffff}' \
52
+ '\u{2fffe}-\u{2ffff}' \
53
+ '\u{3fffe}-\u{3ffff}' \
54
+ '\u{4fffe}-\u{4ffff}' \
55
+ '\u{5fffe}-\u{5ffff}' \
56
+ '\u{6fffe}-\u{6ffff}' \
57
+ '\u{7fffe}-\u{7ffff}' \
58
+ '\u{8fffe}-\u{8ffff}' \
59
+ '\u{9fffe}-\u{9ffff}' \
60
+ '\u{afffe}-\u{affff}' \
61
+ '\u{bfffe}-\u{bffff}' \
62
+ '\u{cfffe}-\u{cffff}' \
63
+ '\u{dfffe}-\u{dffff}' \
64
+ '\u{efffe}-\u{effff}' \
65
+ '\u{ffffe}-\u{fffff}' \
66
+ '\u{10fffe}-\u{10ffff}' \
67
+ ']'
68
+ )
69
+
70
+ # Translate well-known entities, or use generic unicode hex entity
71
+ DISCOURAGED_REPLACEMENTS = Hash.new do |_, c|
72
+ "&#x#{c.ord.to_s(16)};".freeze
73
+ end.update(
74
+ '"'.freeze => '&quot;'.freeze,
75
+ '&'.freeze => '&amp;'.freeze,
76
+ "'".freeze => '&apos;'.freeze,
77
+ '<'.freeze => '&lt;'.freeze,
78
+ '>'.freeze => '&gt;'.freeze
79
+ ).freeze
80
+
81
+ def self.escape(text)
82
+ text.to_s
83
+ .encode(Encoding::UTF_8)
84
+ .gsub(ILLEGAL_REGEXP, ILLEGAL_REPLACEMENT)
85
+ .gsub(DISCOURAGED_REGEXP, DISCOURAGED_REPLACEMENTS)
86
+ end
87
+
88
+ # rubocop:disable Metrics/LineLength
89
+ STRIP_DIFF_COLORS_BLOCK_REGEXP = /^ ( [ ]* ) Diff: (?: \e\[ 0 m )? (?: \n \1 \e\[ \d+ (?: ; \d+ )* m .* )* /x.freeze
90
+ # rubocop:enable Metrics/LineLength
91
+ STRIP_DIFF_COLORS_CODES_REGEXP = /\e\[ \d+ (?: ; \d+ )* m/x.freeze
92
+
93
+ def self.strip_diff_colors(string)
94
+ # XXX: RSpec diffs are appended to the message lines fairly early and will
95
+ # contain ANSI escape codes for colorizing terminal output if the global
96
+ # rspec configuration is turned on, regardless of which notification lines
97
+ # we ask for. We need to strip the codes from the diff part of the message
98
+ # for XML output here.
99
+ #
100
+ # We also only want to target the diff hunks because the failure message
101
+ # itself might legitimately contain ansi escape codes.
102
+ #
103
+ string.sub(STRIP_DIFF_COLORS_BLOCK_REGEXP) do |match|
104
+ match.gsub(STRIP_DIFF_COLORS_CODES_REGEXP, ''.freeze)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -4,7 +4,7 @@
4
4
  module RspecJunitFormatterBitbucket
5
5
  module Info
6
6
  # Define version
7
- VERSION = '0.1.0'
7
+ VERSION = '0.2.0'
8
8
 
9
9
  # Define Name
10
10
  GEM_NAME = 'rspec_junit_formatter_bitbucket'
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/ClassLength
4
+
5
+ # Formatter for RSpec
6
+ # Write an file xml for reporting errors.
7
+ class JUnit < RSpec::Core::Formatters::BaseFormatter
8
+ RSpec::Core::Formatters.register self,
9
+ :start,
10
+ :stop,
11
+ :dump_summary
12
+
13
+ attr_reader :started
14
+
15
+ def initialize(output)
16
+ @output = output
17
+ end
18
+
19
+ def start(notification)
20
+ @start_notification = notification
21
+ @started = Time.now
22
+ super
23
+ end
24
+
25
+ def stop(notification)
26
+ @examples_notification = notification
27
+ end
28
+
29
+ def dump_summary(notification)
30
+ @summary_notification = notification
31
+ xml = RspecJunitFormatterBitbucket::XML.new(@output, self)
32
+
33
+ without_color do
34
+ xml.dump
35
+ end
36
+ end
37
+
38
+ # private
39
+
40
+ def example_count
41
+ @summary_notification.example_count
42
+ end
43
+
44
+ def pending_count
45
+ @summary_notification.pending_count
46
+ end
47
+
48
+ def failure_count
49
+ @summary_notification.failure_count
50
+ end
51
+
52
+ def duration
53
+ @summary_notification.duration
54
+ end
55
+
56
+ def examples
57
+ @examples_notification.notifications
58
+ end
59
+
60
+ def result_of(notification)
61
+ notification.example.execution_result.status
62
+ end
63
+
64
+ def failure_type_for(example)
65
+ exception_for(example).class.name
66
+ end
67
+
68
+ def failure_message_for(example)
69
+ exception = exception_for(example).to_s
70
+ RspecJunitFormatterBitbucket::Format.strip_diff_colors(exception)
71
+ end
72
+
73
+ def failure_for(notification)
74
+ exception = notification.message_lines.join("\n")
75
+ RspecJunitFormatterBitbucket::Format.strip_diff_colors(exception) << \
76
+ "\n" << notification.formatted_backtrace.join("\n")
77
+ end
78
+
79
+ def exception_for(notification)
80
+ notification.example.execution_result.exception
81
+ end
82
+
83
+ # rspec makes it really difficult to swap in configuration temporarily due to
84
+ # the way it cascades defaults, command line arguments, and user
85
+ # configuration. This method makes sure configuration gets swapped in
86
+ # correctly, but also that the original state is definitely restored.
87
+ def swap_rspec_configuration(key, value)
88
+ unset = Object.new
89
+ force = RSpec.configuration.send(:value_for, key) { unset }
90
+ previous = check_swap(key, value, force, unset)
91
+ yield
92
+ ensure
93
+ ensure_swap(key, force, previous, unset)
94
+ end
95
+
96
+ def check_swap(key, value, force, unset)
97
+ if unset.equal?(force)
98
+ previous = RSpec.configuration.send(key)
99
+ RSpec.configuration.send(:"#{key}=", value)
100
+ else
101
+ RSpec.configuration.force(key => value)
102
+ end
103
+ previous
104
+ end
105
+
106
+ def ensure_swap(key, force, previous, unset)
107
+ if unset.equal?(force)
108
+ RSpec.configuration.send(:"#{key}=", previous)
109
+ else
110
+ RSpec.configuration.force(key => force)
111
+ end
112
+ end
113
+
114
+ # Completely gross hack for absolutely forcing off colorising for the
115
+ # duration of a block.
116
+ if RSpec.configuration.respond_to?(:color_mode=)
117
+ def without_color(&block)
118
+ swap_rspec_configuration(:color_mode, :off, &block)
119
+ end
120
+ elsif RSpec.configuration.respond_to?(:color=)
121
+ def without_color(&block)
122
+ swap_rspec_configuration(:color, false, &block)
123
+ end
124
+ else
125
+ warn 'rspec_junit_formatter cannot prevent colorising due ' \
126
+ 'to an unexpected RSpec.configuration format'
127
+ def without_color
128
+ yield
129
+ end
130
+ end
131
+
132
+ def stdout_for(example_notification)
133
+ example_notification.example.metadata[:stdout]
134
+ end
135
+
136
+ def stderr_for(example_notification)
137
+ example_notification.example.metadata[:stderr]
138
+ end
139
+ end
140
+ # rubocop:enable Metrics/ClassLength
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/LineLength
4
+ module RspecJunitFormatterBitbucket
5
+ # Write XML file
6
+ class XML
7
+ def initialize(output, example)
8
+ @test = example
9
+ @output = output
10
+ @output << first_node
11
+ end
12
+
13
+ def dump
14
+ @output << %(<test-suite #{testsuite_attr} >\n)
15
+ @output << %(<properties>\n)
16
+ @output << %(<property)
17
+ @output << %( name="seed")
18
+ @output << %( value="#{Format.escape(RSpec.configuration.seed.to_s)}")
19
+ @output << %(/>\n)
20
+ @output << %(</properties>\n)
21
+ dump_examples
22
+ @output << %(</test-suite>\n)
23
+ end
24
+
25
+ private
26
+
27
+ def first_node
28
+ %(<?xml version="1.0" encoding="UTF-8"?>\n\n)
29
+ end
30
+
31
+ def testsuite_attr
32
+ <<~TESTSUITE
33
+ name="rspec#{Format.escape(ENV['TEST_ENV_NUMBER'].to_s)}"
34
+ tests="#{@test.example_count}"
35
+ skipped="#{@test.pending_count}"
36
+ failures="#{@test.failure_count}"
37
+ errors="0"
38
+ time="#{Format.escape(format('%.6f', @test.duration))}"
39
+ timestamp="#{Format.escape(@test.started.iso8601)}"
40
+ hostname="#{Format.escape(Socket.gethostname)}"
41
+ TESTSUITE
42
+ end
43
+
44
+ def dump_examples
45
+ @test.examples.each do |example|
46
+ case @test.result_of(example)
47
+ when :pending
48
+ dump_pending(example)
49
+ when :failed
50
+ dump_failed(example)
51
+ else
52
+ dump_example(example)
53
+ end
54
+ end
55
+ end
56
+
57
+ def dump_pending(example)
58
+ dump_example(example) do
59
+ @output << %(<skipped/>)
60
+ end
61
+ end
62
+
63
+ def dump_failed(example)
64
+ dump_example(example) do
65
+ @output << %(<failure)
66
+ @output << %( message="#{Format.escape(@test.failure_message_for(example))}")
67
+ @output << %( type="#{Format.escape(@test.failure_type_for(example))}")
68
+ @output << %(>)
69
+ @output << Format.escape(@test.failure_for(example))
70
+ @output << %(</failure>)
71
+ end
72
+ end
73
+
74
+ def dump_example(example)
75
+ @output << %(<test-case )
76
+ @output << testcase_attr(example)
77
+ @output << %(>)
78
+ yield if block_given?
79
+ dump_output(example)
80
+ @output << %(</test-case>\n)
81
+ end
82
+
83
+ def testcase_attr(example)
84
+ <<~TESTCASE
85
+ classname="#{Format.escape(Attribute.classname_for(example))}"
86
+ name="#{Format.escape(Attribute.description_for(example))}"
87
+ file="#{Format.escape(Attribute.example_group_file_path_for(example))}"
88
+ time="#{Format.escape(format('%.6f', Attribute.duration_for(example)))}"
89
+ TESTCASE
90
+ end
91
+
92
+ def dump_output(example)
93
+ stdout = @test.stdout_for(example)
94
+ write_stdout(stdout) unless stdout.empty?
95
+
96
+ stderr = @test.stderr_for(example)
97
+ write_stderr(stderr) unless stderr.empty?
98
+ end
99
+
100
+ def write_stdout(stdout)
101
+ @output << %(<system-out>)
102
+ @output << Format.escape(stdout)
103
+ @output << %(</system-out>)
104
+ end
105
+
106
+ def write_stderr(stderr)
107
+ @output << %(<system-err>)
108
+ @output << Format.escape(stderr)
109
+ @output << %(</system-err>)
110
+ end
111
+ end
112
+ end
113
+ # rubocop:enable Metrics/LineLength
@@ -6,15 +6,7 @@ require 'time'
6
6
  require 'rspec/core'
7
7
  require 'rspec/core/formatters/base_formatter'
8
8
 
9
- require 'rspec_junit_formatter_bitbucket/init'
10
-
11
- =begin
12
- if Gem::Version.new(RSpec::Core::Version::STRING) >= Gem::Version.new('3')
13
- require 'rspec-junit-formatter/rspec/version-3'
14
- else
15
- require 'rspec-junit-formatter/rspec/version-2'
16
- end
17
- =end
18
-
19
- # Use alias for symplify call formatter in RSpec
20
- JUnit = RspecJunitFormatterBitbucket::Init
9
+ require 'rspec_junit_formatter_bitbucket/attribute'
10
+ require 'rspec_junit_formatter_bitbucket/format'
11
+ require 'rspec_junit_formatter_bitbucket/xml'
12
+ require 'rspec_junit_formatter_bitbucket/j_unit'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec_junit_formatter_bitbucket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0.pre.170
5
5
  platform: ruby
6
6
  authors:
7
7
  - VAILLANT Jeremy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-20 00:00:00.000000000 Z
11
+ date: 2019-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-core
@@ -36,6 +36,20 @@ dependencies:
36
36
  - - "<"
37
37
  - !ruby/object:Gem::Version
38
38
  version: '4'
39
+ - !ruby/object:Gem::Dependency
40
+ name: appraisal
41
+ requirement: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - "~>"
44
+ - !ruby/object:Gem::Version
45
+ version: '2.2'
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '2.2'
39
53
  - !ruby/object:Gem::Dependency
40
54
  name: bundler
41
55
  requirement: !ruby/object:Gem::Requirement
@@ -57,19 +71,25 @@ dependencies:
57
71
  - !ruby/object:Gem::Version
58
72
  version: 1.17.3
59
73
  - !ruby/object:Gem::Dependency
60
- name: appraisal
74
+ name: coderay
61
75
  requirement: !ruby/object:Gem::Requirement
62
76
  requirements:
63
77
  - - "~>"
64
78
  - !ruby/object:Gem::Version
65
- version: '2.2'
79
+ version: '1.1'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 1.1.2
66
83
  type: :development
67
84
  prerelease: false
68
85
  version_requirements: !ruby/object:Gem::Requirement
69
86
  requirements:
70
87
  - - "~>"
71
88
  - !ruby/object:Gem::Version
72
- version: '2.2'
89
+ version: '1.1'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.1.2
73
93
  - !ruby/object:Gem::Dependency
74
94
  name: nokogiri
75
95
  requirement: !ruby/object:Gem::Requirement
@@ -90,6 +110,20 @@ dependencies:
90
110
  - - ">="
91
111
  - !ruby/object:Gem::Version
92
112
  version: 1.8.2
113
+ - !ruby/object:Gem::Dependency
114
+ name: pry
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: 0.12.2
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - "~>"
125
+ - !ruby/object:Gem::Version
126
+ version: 0.12.2
93
127
  - !ruby/object:Gem::Dependency
94
128
  name: rake
95
129
  requirement: !ruby/object:Gem::Requirement
@@ -111,39 +145,33 @@ dependencies:
111
145
  - !ruby/object:Gem::Version
112
146
  version: 12.3.2
113
147
  - !ruby/object:Gem::Dependency
114
- name: coderay
148
+ name: rubocop
115
149
  requirement: !ruby/object:Gem::Requirement
116
150
  requirements:
117
151
  - - "~>"
118
152
  - !ruby/object:Gem::Version
119
- version: '1.1'
120
- - - ">="
121
- - !ruby/object:Gem::Version
122
- version: 1.1.2
153
+ version: 0.69.0
123
154
  type: :development
124
155
  prerelease: false
125
156
  version_requirements: !ruby/object:Gem::Requirement
126
157
  requirements:
127
158
  - - "~>"
128
159
  - !ruby/object:Gem::Version
129
- version: '1.1'
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- version: 1.1.2
160
+ version: 0.69.0
133
161
  - !ruby/object:Gem::Dependency
134
- name: pry
162
+ name: rubocop-rspec
135
163
  requirement: !ruby/object:Gem::Requirement
136
164
  requirements:
137
165
  - - "~>"
138
166
  - !ruby/object:Gem::Version
139
- version: 0.12.2
167
+ version: '1.33'
140
168
  type: :development
141
169
  prerelease: false
142
170
  version_requirements: !ruby/object:Gem::Requirement
143
171
  requirements:
144
172
  - - "~>"
145
173
  - !ruby/object:Gem::Version
146
- version: 0.12.2
174
+ version: '1.33'
147
175
  description: |2
148
176
  RSpec Junit Formatter results that your CI can read in Bitbucket Pipeline.
149
177
  Use convention http://reflex.gforge.inria.fr
@@ -156,8 +184,11 @@ files:
156
184
  - LICENSE
157
185
  - README.md
158
186
  - lib/rspec_junit_formatter_bitbucket.rb
187
+ - lib/rspec_junit_formatter_bitbucket/attribute.rb
188
+ - lib/rspec_junit_formatter_bitbucket/format.rb
159
189
  - lib/rspec_junit_formatter_bitbucket/info.rb
160
- - lib/rspec_junit_formatter_bitbucket/init.rb
190
+ - lib/rspec_junit_formatter_bitbucket/j_unit.rb
191
+ - lib/rspec_junit_formatter_bitbucket/xml.rb
161
192
  homepage: https://github.com/dazzl-tv/rspec_junit_formatter
162
193
  licenses:
163
194
  - MIT
@@ -170,7 +201,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
170
201
  requirements:
171
202
  - - ">="
172
203
  - !ruby/object:Gem::Version
173
- version: 2.0.0
204
+ version: 2.4.0
174
205
  required_rubygems_version: !ruby/object:Gem::Requirement
175
206
  requirements:
176
207
  - - ">="
@@ -1,355 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # rubocop:disable Metrics/ClassLength, Style/GuardClause, Metrics/AbcSize
4
- # rubocop:disable Metrics/MethodLength
5
-
6
- # Dumps rspec results as a JUnit XML file.
7
- # Based on XML schema: http://windyroad.org/dl/Open%20Source/JUnit.xsd
8
- module RspecJunitFormatterBitbucket
9
- class Init < RSpec::Core::Formatters::BaseFormatter
10
- RSpec::Core::Formatters.register self,
11
- :start,
12
- :stop,
13
- :dump_summary
14
-
15
- def start(notification)
16
- @start_notification = notification
17
- @started = Time.now
18
- super
19
- end
20
-
21
- def stop(notification)
22
- @examples_notification = notification
23
- end
24
-
25
- def dump_summary(notification)
26
- @summary_notification = notification
27
- without_color { xml_dump }
28
- end
29
-
30
- private
31
-
32
- attr_reader :started
33
-
34
- def example_count
35
- @summary_notification.example_count
36
- end
37
-
38
- def pending_count
39
- @summary_notification.pending_count
40
- end
41
-
42
- def failure_count
43
- @summary_notification.failure_count
44
- end
45
-
46
- def duration
47
- @summary_notification.duration
48
- end
49
-
50
- def examples
51
- @examples_notification.notifications
52
- end
53
-
54
- def result_of(notification)
55
- notification.example.execution_result.status
56
- end
57
-
58
- def example_group_file_path_for(notification)
59
- metadata = notification.example.metadata[:example_group]
60
- while parent_metadata = metadata[:parent_example_group]
61
- metadata = parent_metadata
62
- end
63
- metadata[:file_path]
64
- end
65
-
66
- def classname_for(notification)
67
- fp = example_group_file_path_for(notification)
68
- fp.sub(%r{\.[^/]*\Z}, '').tr('/', '.').gsub(/\A\.+|\.+\Z/, '')
69
- end
70
-
71
- def duration_for(notification)
72
- notification.example.execution_result.run_time
73
- end
74
-
75
- def description_for(notification)
76
- notification.example.full_description
77
- end
78
-
79
- def failure_type_for(example)
80
- exception_for(example).class.name
81
- end
82
-
83
- def failure_message_for(example)
84
- strip_diff_colors(exception_for(example).to_s)
85
- end
86
-
87
- def failure_for(notification)
88
- strip_diff_colors(notification.message_lines.join("\n")) << \
89
- "\n" << notification.formatted_backtrace.join("\n")
90
- end
91
-
92
- def exception_for(notification)
93
- notification.example.execution_result.exception
94
- end
95
-
96
- # rspec makes it really difficult to swap in configuration temporarily due to
97
- # the way it cascades defaults, command line arguments, and user
98
- # configuration. This method makes sure configuration gets swapped in
99
- # correctly, but also that the original state is definitely restored.
100
- def swap_rspec_configuration(key, value)
101
- unset = Object.new
102
- force = RSpec.configuration.send(:value_for, key) { unset }
103
- previous = check_swap(key, value, force, unset)
104
- yield
105
- ensure
106
- ensure_swap(key, force, previous, unset)
107
- end
108
-
109
- def check_swap(key, value, force, unset)
110
- if unset.equal?(force)
111
- previous = RSpec.configuration.send(key)
112
- RSpec.configuration.send(:"#{key}=", value)
113
- else
114
- RSpec.configuration.force(key => value)
115
- end
116
- previous
117
- end
118
-
119
- def ensure_swap(key, force, previous, unset)
120
- if unset.equal?(force)
121
- RSpec.configuration.send(:"#{key}=", previous)
122
- else
123
- RSpec.configuration.force(key => force)
124
- end
125
- end
126
-
127
- # Completely gross hack for absolutely forcing off colorising for the
128
- # duration of a block.
129
- if RSpec.configuration.respond_to?(:color_mode=)
130
- def without_color(&block)
131
- swap_rspec_configuration(:color_mode, :off, &block)
132
- end
133
- elsif RSpec.configuration.respond_to?(:color=)
134
- def without_color(&block)
135
- swap_rspec_configuration(:color, false, &block)
136
- end
137
- else
138
- warn 'rspec_junit_formatter cannot prevent colorising due ' \
139
- 'to an unexpected RSpec.configuration format'
140
- def without_color
141
- yield
142
- end
143
- end
144
-
145
- def stdout_for(example_notification)
146
- example_notification.example.metadata[:stdout]
147
- end
148
-
149
- def stderr_for(example_notification)
150
- example_notification.example.metadata[:stderr]
151
- end
152
-
153
- private
154
-
155
- def xml_dump
156
- output << %(<?xml version="1.0" encoding="UTF-8"?>\n)
157
- output << %(<test-suite)
158
- output << %( name="rspec#{escape(ENV['TEST_ENV_NUMBER'].to_s)}")
159
- output << %( tests="#{example_count}")
160
- output << %( skipped="#{pending_count}")
161
- output << %( failures="#{failure_count}")
162
- output << %( errors="0")
163
- output << %( time="#{escape(format('%.6f', duration))}")
164
- output << %( timestamp="#{escape(started.iso8601)}")
165
- output << %( hostname="#{escape(Socket.gethostname)}")
166
- output << %(>\n)
167
- output << %(<properties>\n)
168
- output << %(<property)
169
- output << %( name="seed")
170
- output << %( value="#{escape(RSpec.configuration.seed.to_s)}")
171
- output << %(/>\n)
172
- output << %(</properties>\n)
173
- xml_dump_examples
174
- output << %(</test-suite>\n)
175
- end
176
-
177
- def xml_dump_examples
178
- examples.each do |example|
179
- case result_of(example)
180
- when :pending
181
- xml_dump_pending(example)
182
- when :failed
183
- xml_dump_failed(example)
184
- else
185
- xml_dump_example(example)
186
- end
187
- end
188
- end
189
-
190
- def xml_dump_pending(example)
191
- xml_dump_example(example) do
192
- output << %(<skipped/>)
193
- end
194
- end
195
-
196
- def xml_dump_failed(example)
197
- xml_dump_example(example) do
198
- output << %(<failure)
199
- output << %( message="#{escape(failure_message_for(example))}")
200
- output << %( type="#{escape(failure_type_for(example))}")
201
- output << %(>)
202
- output << escape(failure_for(example))
203
- output << %(</failure>)
204
- end
205
- end
206
-
207
- def xml_dump_example(example)
208
- output << %(<test-case)
209
- output << %( classname="#{escape(classname_for(example))}")
210
- output << %( name="#{escape(description_for(example))}")
211
- output << %( file="#{escape(example_group_file_path_for(example))}")
212
- output << %( time="#{escape(format('%.6f', duration_for(example)))}")
213
- output << %(>)
214
- yield if block_given?
215
- xml_dump_output(example)
216
- output << %(</test-case>\n)
217
- end
218
-
219
- def xml_dump_output(example)
220
- if (stdout = stdout_for(example)) && !stdout.empty?
221
- output << %(<system-out>)
222
- output << escape(stdout)
223
- output << %(</system-out>)
224
- end
225
-
226
- if (stderr = stderr_for(example)) && !stderr.empty?
227
- output << %(<system-err>)
228
- output << escape(stderr)
229
- output << %(</system-err>)
230
- end
231
- end
232
-
233
- # Inversion of character range from https://www.w3.org/TR/xml/#charsets
234
- =begin
235
- ILLEGAL_REGEXP = Regexp.new(
236
- '[^' <<
237
- '\u{9}' << # => \t
238
- '\u{a}' << # => \n
239
- '\u{d}' << # => \r
240
- '\u{20}-\u{d7ff}' <<
241
- '\u{e000}-\u{fffd}' <<
242
- '\u{10000}-\u{10ffff}' <<
243
- ']'
244
- )
245
- =end
246
-
247
- # rubocop:disable Style/FormatStringToken
248
- # Replace illegals with a Ruby-like escape
249
- ILLEGAL_REPLACEMENT = Hash.new do |_, c|
250
- x = c.ord
251
- if x <= 0xff
252
- '\\x%02X'.freeze % x
253
- elsif x <= 0xffff
254
- '\\u%04X'.freeze % x
255
- else
256
- '\\u{%X}'.freeze % x
257
- end.freeze
258
- end.update(
259
- "\0".freeze => '\\0'.freeze,
260
- "\a".freeze => '\\a'.freeze,
261
- "\b".freeze => '\\b'.freeze,
262
- "\f".freeze => '\\f'.freeze,
263
- "\v".freeze => '\\v'.freeze,
264
- "\e".freeze => '\\e'.freeze
265
- ).freeze
266
- # rubocop:enable Style/FormatStringToken
267
-
268
- # Discouraged characters from https://www.w3.org/TR/xml/#charsets
269
- # Plus special characters with well-known entity replacements
270
- =begin
271
- DISCOURAGED_REGEXP = Regexp.new(
272
- '[' \
273
- "\u{22}" << # => "
274
- "\u{26}" << # => &
275
- "\u{27}" << # => '
276
- "\u{3c}" << # => <
277
- "\u{3e}" << # => >
278
- "\u{7f}-\u{84}" \
279
- "\u{86}-\u{9f}" \
280
- "\u{fdd0}-\u{fdef}" \
281
- "\u{1fffe}-\u{1ffff}" \
282
- "\u{2fffe}-\u{2ffff}" \
283
- "\u{3fffe}-\u{3ffff}" \
284
- "\u{4fffe}-\u{4ffff}" \
285
- "\u{5fffe}-\u{5ffff}" \
286
- "\u{6fffe}-\u{6ffff}" \
287
- "\u{7fffe}-\u{7ffff}" \
288
- "\u{8fffe}-\u{8ffff}" \
289
- "\u{9fffe}-\u{9ffff}" \
290
- "\u{afffe}-\u{affff}" \
291
- "\u{bfffe}-\u{bffff}" \
292
- "\u{cfffe}-\u{cffff}" \
293
- "\u{dfffe}-\u{dffff}" \
294
- "\u{efffe}-\u{effff}" \
295
- "\u{ffffe}-\u{fffff}" \
296
- "\u{10fffe}-\u{10ffff}" \
297
- ']'
298
- )
299
- =end
300
-
301
- # Translate well-known entities, or use generic unicode hex entity
302
- DISCOURAGED_REPLACEMENTS = Hash.new do |_, c|
303
- "&#x#{c.ord.to_s(16)};".freeze
304
- end.update(
305
- '"'.freeze => '&quot;'.freeze,
306
- '&'.freeze => '&amp;'.freeze,
307
- "'".freeze => '&apos;'.freeze,
308
- '<'.freeze => '&lt;'.freeze,
309
- '>'.freeze => '&gt;'.freeze
310
- ).freeze
311
-
312
- def escape(text)
313
- # Make sure it's utf-8, replace illegal characters with ruby-like escapes,
314
- # and replace special and discouraged characters with entities
315
- text.to_s.encode(Encoding::UTF_8)
316
- # .gsub(DISCOURAGED_REGEXP, DISCOURAGED_REPLACEMENTS)
317
- # .gsub(ILLEGAL_REGEXP, ILLEGAL_REPLACEMENT)
318
- end
319
-
320
- # rubocop:disable Metrics/LineLength
321
- STRIP_DIFF_COLORS_BLOCK_REGEXP = /^ ( [ ]* ) Diff: (?: \e\[ 0 m )? (?: \n \1 \e\[ \d+ (?: ; \d+ )* m .* )* /x.freeze
322
- STRIP_DIFF_COLORS_CODES_REGEXP = /\e\[ \d+ (?: ; \d+ )* m/x.freeze
323
- # rubocop:enable Metrics/LineLength
324
-
325
- def strip_diff_colors(string)
326
- # XXX: RSpec diffs are appended to the message lines fairly early and will
327
- # contain ANSI escape codes for colorizing terminal output if the global
328
- # rspec configuration is turned on, regardless of which notification lines
329
- # we ask for. We need to strip the codes from the diff part of the message
330
- # for XML output here.
331
- #
332
- # We also only want to target the diff hunks because the failure message
333
- # itself might legitimately contain ansi escape codes.
334
- #
335
- string.sub(STRIP_DIFF_COLORS_BLOCK_REGEXP) do |match|
336
- match.gsub(STRIP_DIFF_COLORS_CODES_REGEXP, ''.freeze)
337
- end
338
- end
339
- end
340
-
341
-
342
- if defined?(RSpec::Core::Notifications::NullColorizer) &&
343
- RSpec::Core::Notifications::NullColorizer.is_a?(Class) &&
344
- !RSpec::Core::Notifications::NullColorizer.respond_to?(:wrap)
345
- RSpec::Core::Notifications::NullColorizer.class_eval do
346
- def self.wrap(*args)
347
- new.wrap(*args)
348
- end
349
- end
350
- end
351
- end
352
- # Create an alias for respect case
353
- # RspecJunitFormatter = RSpecJUnitFormatter
354
- # rubocop:enable Metrics/ClassLength, Style/GuardClause, Metrics/AbcSize
355
- # rubocop:enable Metrics/MethodLength