reportportal 0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
@@ -0,0 +1,81 @@
1
+ # Ruby Cucumber and RSpec formatters for ReportPortal
2
+
3
+ ## Installation
4
+
5
+ Use Ruby 2.2+
6
+
7
+ Add `gem 'reportportal', git: 'https://github.com/reportportal/agent-ruby.git'` to your `Gemfile`. Run `bundle install`.
8
+
9
+ ## Usage (examples)
10
+
11
+ * With Cucumber:
12
+
13
+ ```cucumber <other options> -f ReportPortal::Cucumber::Formatter```
14
+
15
+ * With Cucumber and parallel_tests gem:
16
+
17
+ ```parallel_cucumber <some options> -o '<some other options> -f ReportPortal::Cucumber::ParallelFormatter'```
18
+
19
+ * With RSpec:
20
+
21
+ ```rspec <other options> -f ReportPortal::RSpec::Formatter```
22
+
23
+ ## Configuration
24
+ Create report_portal.yml configuration file in one of the following folders of your project: '.', './.config', './config' (see report_portal.yaml.example).
25
+ Alternatively specify path to configuration file via rp_config environment variable.
26
+
27
+ Supported settings:
28
+
29
+ - uuid - uuid of the ReportPortal user
30
+ - endpoint - URI of ReportPortal web service where requests should be sent
31
+ - launch - launch name
32
+ - description - custom launch description
33
+ - project - project name
34
+ - tags - array of tags for the launch
35
+ - formatter_modes - array of modes that modify formatter behavior, see [formatter modes](#formatter_modes)
36
+ - launch_id - id of previously created launch (to be used if formatter_modes contains attach_to_launch)
37
+ - file_with_launch_id - path to file with id of launch (to be used if formatter_modes contains attach_to_launch)
38
+ - disable_ssl_verification - set to true to disable SSL verification on connect to ReportPortal (potential security hole!). Set `disable_ssl_verification` to `true` if you see the following error:
39
+ ```
40
+ Request to https://rp.epam.com/reportportal-ws/api/v1/pass-team/launch//finish produced an exception: RestClient::SSLCertificateNotVerified: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
41
+ ```
42
+ - is_debug - set to true to mark the launch as 'DEBUG' (it will appear in Debug tab in Report Portal)
43
+ - use_standard_logger - set to true to enable logging via standard Ruby Logger class to ReportPortal. Note that log messages are transformed to strings before sending.
44
+
45
+ Each of these settings can be overridden by an environment variable with the same name and 'rp_' prefix (e.g. 'rp_uuid' for 'uuid'). Environment variables take precedence over YAML configuration.
46
+ Environment variable values are parsed as YAML entities.
47
+
48
+ ## WebMock configuration
49
+ If you use WebMock for stubbing and setting expectations on HTTP requests in Ruby,
50
+ add this to your configuration file (for RSpec it would be `rails_helper.rb` or `spec_helper.rb`)
51
+
52
+ ```ruby
53
+ WebMock.disable_net_connect!(:net_http_connect_on_start => true, :allow_localhost => true, :allow => [/rp\.epam\.com/]) # Don't break Net::HTTP
54
+ ```
55
+
56
+ <a name="formatter_modes"></a>
57
+ ## Formatter modes
58
+
59
+ The following modes are supported:
60
+
61
+ * attach_to_launch (do not create a new launch but add executing features/scenarios to an existing launch. Use launch_id or file_with_launch_id settings to configure that. If they are not present client will check rp_launch_id.tmp in `Dir.tmpdir`)
62
+ * group_by_folder (represent folders with features as nested suites in Report Portal) # TODO: not supported by new Cucumber formatter currently
63
+
64
+ ## Logging
65
+ Experimental support for three common logging frameworks was added:
66
+
67
+ - Logger (part of standard Ruby library)
68
+ - [Logging](http://rubygems.org/gems/logging)
69
+ - [Log4r](https://rubygems.org/gems/log4r)
70
+
71
+ To use Logger, set use_standard_logger parameter to true (see Configuration chapter). For the other two corresponding appenders/outputters are available under reportportal/logging.
72
+
73
+ ## Parallel formatter
74
+
75
+ ReportPortal::Cucumber::ParallelFormatter can be used for tests started via parallel_tests gem.
76
+
77
+ Note: Launch id is shared between independent processes (as is the case with parallel_tests gem) via a file in `Dir.tmpdir`.
78
+
79
+ ## Links
80
+
81
+ - [ReportPortal](https://github.com/reportportal/)
@@ -0,0 +1,67 @@
1
+ # Copyright 2015 EPAM Systems
2
+ #
3
+ #
4
+ # This file is part of Report Portal.
5
+ #
6
+ # Report Portal is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # ReportPortal is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with Report Portal. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'thread'
20
+
21
+ require_relative 'report'
22
+
23
+ module ReportPortal
24
+ module Cucumber
25
+ class Formatter
26
+ # @api private
27
+ def initialize(config)
28
+ ENV['REPORT_PORTAL_USED'] = 'true'
29
+
30
+ @queue = Queue.new
31
+ @thread = Thread.new do
32
+ @report = ReportPortal::Cucumber::Report.new
33
+ loop do
34
+ method_arr = @queue.pop
35
+ @report.public_send(*method_arr)
36
+ end
37
+ end
38
+ @thread.abort_on_exception = true
39
+
40
+ @io = config.out_stream
41
+
42
+ [:test_case_started, :test_case_finished, :test_step_started, :test_step_finished].each do |event_name|
43
+ config.on_event event_name do |event|
44
+ @queue.push([event_name, event, ReportPortal.now])
45
+ end
46
+ end
47
+ config.on_event :test_run_finished, &method(:on_test_run_finished)
48
+ end
49
+
50
+ def puts(message)
51
+ @queue.push([:puts, message, ReportPortal.now])
52
+ @io.puts(message)
53
+ @io.flush
54
+ end
55
+
56
+ def embed(*args)
57
+ @queue.push([:embed, *args, ReportPortal.now])
58
+ end
59
+
60
+ def on_test_run_finished(_event)
61
+ @queue.push([:done, ReportPortal.now])
62
+ sleep 0.03 while !@queue.empty? || @queue.num_waiting == 0 # TODO: how to interrupt launch if the user aborted execution
63
+ @thread.kill
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,177 @@
1
+ # Copyright 2015 EPAM Systems
2
+ #
3
+ #
4
+ # This file is part of Report Portal.
5
+ #
6
+ # Report Portal is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # ReportPortal is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with Report Portal. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'base64'
20
+ require 'securerandom'
21
+ require 'mime/types'
22
+
23
+ require_relative '../../reportportal'
24
+ require_relative '../settings'
25
+
26
+ module ReportPortal
27
+ module Cucumber
28
+ # Helper class to parse and post test launch data generated by Cucumber's JSON formatter
29
+ # Supports ONLY reports generated with -x switch (i.e. expanded outlines)
30
+ class JSONSlurper
31
+ def initialize(filename)
32
+ @json = JSON.parse(File.read(filename))
33
+ fail "Cannot process #{filename} because it was generated without -x/--expand Cucumber option!" unless expanded?
34
+ calculate_start_time
35
+ end
36
+
37
+ def run
38
+ ReportPortal.start_launch('', get_time)
39
+
40
+ @json.each do |feature|
41
+ current_feature = ReportPortal::TestItem.new("Feature: #{feature['name']}",
42
+ :TEST,
43
+ nil,
44
+ get_time,
45
+ feature['uri'],
46
+ nil,
47
+ tags(feature))
48
+ current_feature_node = Tree::TreeNode.new(SecureRandom.hex, current_feature)
49
+ current_feature.id = ReportPortal.start_item(current_feature_node)
50
+ current_element_name = nil
51
+ current_outline_row = 0
52
+
53
+ feature['elements'].each do |element|
54
+ type = element['type'] == 'background' ? :BEFORE_CLASS : :STEP
55
+
56
+ element_name = "#{element['keyword']}: #{element['name']}"
57
+ if element['keyword'] == 'Scenario Outline'
58
+ if element['name'] == current_element_name
59
+ current_outline_row += 1
60
+ else
61
+ current_element_name = element['name']
62
+ current_outline_row = 1
63
+ end
64
+ element_name << " [#{current_outline_row}]"
65
+ end
66
+
67
+ ReportPortal.current_scenario = ReportPortal::TestItem.new(element_name,
68
+ type,
69
+ nil,
70
+ get_time,
71
+ "#{feature['uri']}:#{element['line']}",
72
+ nil,
73
+ tags(element))
74
+ current_scenario_node = Tree::TreeNode.new(SecureRandom.hex, ReportPortal.current_scenario)
75
+ ReportPortal.current_scenario.id = ReportPortal.start_item(current_scenario_node)
76
+
77
+ statuses = report_hooks(element, 'before')
78
+ forced_issue = nil
79
+ element['steps'].each do |step|
80
+ name = decorate("#{step['keyword']}#{step['name']}")
81
+ if step['rows']
82
+ name << step['rows'].reduce("\n") { |acc, row| acc << decorate("| #{row['cells'].join(' | ')} |") << "\n" }
83
+ end
84
+ if step['doc_string']
85
+ name << %(\n"""\n#{step['doc_string']['value']}\n""")
86
+ end
87
+
88
+ ReportPortal.send_log(:passed, name, get_time)
89
+ step['output'].each { |o| ReportPortal.send_log(:passed, o, get_time) } unless step['output'].nil?
90
+ error = step['result']['error_message']
91
+ ReportPortal.send_log(:failed, error, get_time) if error
92
+ (step['embeddings'] || []).each do |embedding|
93
+ ReportPortal.send_file(:failed, embedding['data'], 'Embedding', get_time, embedding['mime_type'])
94
+ end
95
+ statuses << step['result']['status']
96
+ forced_issue ||= case step['result']['status']
97
+ when 'pending'
98
+ error
99
+ when 'undefined'
100
+ "Undefined step #{step['name']} at #{step['match']['location']}"
101
+ else
102
+ nil
103
+ end
104
+
105
+ ReportPortal.send_log(step['result']['status'].to_sym,
106
+ "STEP #{step['result']['status'].upcase}",
107
+ get_time(step['result']['duration'].to_i / 1_000_000))
108
+ end
109
+ statuses += report_hooks(element, 'after')
110
+
111
+ status = if statuses.any? { |s| %w(failed undefined pending).include? s }
112
+ :failed
113
+ elsif statuses.all? { |s| s == 'passed' }
114
+ :passed
115
+ else
116
+ :skipped
117
+ end
118
+
119
+ ReportPortal.finish_item(ReportPortal.current_scenario, status, get_time, forced_issue)
120
+ ReportPortal.current_scenario = nil
121
+ end
122
+
123
+ ReportPortal.finish_item(current_feature, nil, get_time)
124
+ end
125
+ ReportPortal.finish_item(root, nil, get_time)
126
+ ReportPortal.finish_launch(get_time)
127
+ end
128
+
129
+ private
130
+
131
+ def tags(item)
132
+ item['tags'].nil? ? [] : item['tags'].map { |h| h['name'] }
133
+ end
134
+
135
+ def decorate(str)
136
+ sep = '-' * 25
137
+ "#{sep}#{str}#{sep}"
138
+ end
139
+
140
+ def expanded?
141
+ bad_item = @json.find do |f|
142
+ so = f['elements'].find { |e| e['keyword'] == 'Scenario Outline' }
143
+ so ? so.key?('examples') : false
144
+ end
145
+ bad_item.nil?
146
+ end
147
+
148
+ def calculate_start_time
149
+ duration_nanos = 0
150
+ @json.each do |f|
151
+ f['elements'].each do |e|
152
+ items = e['steps'] + (e['before'] || []) + (e['after'] || [])
153
+ items.each do |s|
154
+ duration_nanos += s['result']['duration'].to_i
155
+ end
156
+ end
157
+ end
158
+ @now = (Time.now.to_f * 1000).to_i - (duration_nanos / 1_000_000)
159
+ end
160
+
161
+ # update current time and return
162
+ def get_time(offset = 0)
163
+ @now += offset + 1
164
+ end
165
+
166
+ # report before/after hooks and return array of their statuses
167
+ def report_hooks(element, tag)
168
+ (element[tag] || []).map do |hook|
169
+ ReportPortal.send_log(hook['result']['status'].to_sym,
170
+ "HOOK #{hook['match']['location']} #{hook['result']['status'].upcase}",
171
+ get_time(hook['result']['duration'].to_i / 1_000_000))
172
+ hook['result']['status']
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end