reportportal 0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/LICENSE.LESSER +165 -0
- data/README.md +81 -0
- data/lib/report_portal/cucumber/formatter.rb +67 -0
- data/lib/report_portal/cucumber/json_slurper.rb +177 -0
- data/lib/report_portal/cucumber/parallel_formatter.rb +53 -0
- data/lib/report_portal/cucumber/parallel_report.rb +69 -0
- data/lib/report_portal/cucumber/report.rb +232 -0
- data/lib/report_portal/logging/log4r_outputter.rb +34 -0
- data/lib/report_portal/logging/logger.rb +54 -0
- data/lib/report_portal/logging/logging_appender.rb +36 -0
- data/lib/report_portal/patches/rest_client.rb +63 -0
- data/lib/report_portal/rspec/formatter.rb +130 -0
- data/lib/report_portal/settings.rb +76 -0
- data/lib/report_portal/tasks.rb +44 -0
- data/lib/report_portal/version.rb +21 -0
- data/lib/reportportal.rb +208 -0
- metadata +90 -0
@@ -0,0 +1,53 @@
|
|
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_relative 'formatter'
|
20
|
+
require_relative 'parallel_report'
|
21
|
+
require 'parallel_tests/gherkin/io'
|
22
|
+
|
23
|
+
module ReportPortal
|
24
|
+
module Cucumber
|
25
|
+
class ParallelFormatter < Formatter
|
26
|
+
#include ::ParallelTests::Gherkin::Io
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def initialize(config)
|
30
|
+
ENV['REPORT_PORTAL_USED'] = 'true'
|
31
|
+
|
32
|
+
@queue = Queue.new
|
33
|
+
@thread = Thread.new do
|
34
|
+
@report = ReportPortal::Cucumber::ParallelReport.new
|
35
|
+
loop do
|
36
|
+
method_arr = @queue.pop
|
37
|
+
@report.public_send(*method_arr)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
@thread.abort_on_exception = true
|
41
|
+
|
42
|
+
@io = config.out_stream
|
43
|
+
|
44
|
+
[:test_case_started, :test_case_finished, :test_step_started, :test_step_finished].each do |event_name|
|
45
|
+
config.on_event event_name do |event|
|
46
|
+
@queue.push([event_name, event, ReportPortal.now])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
config.on_event :test_run_finished, &method(:on_test_run_finished)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,69 @@
|
|
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_relative 'report'
|
20
|
+
|
21
|
+
module ReportPortal
|
22
|
+
module Cucumber
|
23
|
+
class ParallelReport < Report
|
24
|
+
FILE_WITH_LAUNCH_ID = Pathname(Dir.tmpdir) + "parallel_launch_id_for_#{Process.ppid}.lck"
|
25
|
+
|
26
|
+
def parallel?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@root_node = Tree::TreeNode.new('')
|
32
|
+
@last_used_time ||= 0
|
33
|
+
|
34
|
+
if ParallelTests.first_process?
|
35
|
+
File.open(FILE_WITH_LAUNCH_ID, 'w') do |f|
|
36
|
+
f.flock(File::LOCK_EX)
|
37
|
+
start_launch
|
38
|
+
f.write(ReportPortal.launch_id)
|
39
|
+
f.flush
|
40
|
+
f.flock(File::LOCK_UN)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
File.open(FILE_WITH_LAUNCH_ID, 'r') do |f|
|
44
|
+
f.flock(File::LOCK_SH)
|
45
|
+
ReportPortal.launch_id = f.read
|
46
|
+
f.flock(File::LOCK_UN)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def done(desired_time = ReportPortal.now)
|
52
|
+
end_feature(desired_time) if @feature_node
|
53
|
+
|
54
|
+
if ParallelTests.first_process?
|
55
|
+
ParallelTests.wait_for_other_processes_to_finish
|
56
|
+
|
57
|
+
File.delete(FILE_WITH_LAUNCH_ID)
|
58
|
+
|
59
|
+
unless attach_to_launch?
|
60
|
+
$stdout.puts "Finishing launch #{ReportPortal.launch_id}"
|
61
|
+
ReportPortal.close_child_items(nil)
|
62
|
+
time_to_send = time_to_send(desired_time)
|
63
|
+
ReportPortal.finish_launch(time_to_send)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,232 @@
|
|
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 'cucumber/formatter/io'
|
20
|
+
require 'cucumber/formatter/hook_query_visitor'
|
21
|
+
require 'tree'
|
22
|
+
require 'securerandom'
|
23
|
+
|
24
|
+
require_relative '../../reportportal'
|
25
|
+
require_relative '../logging/logger'
|
26
|
+
|
27
|
+
module ReportPortal
|
28
|
+
module Cucumber
|
29
|
+
# @api private
|
30
|
+
class Report
|
31
|
+
def parallel?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def attach_to_launch?
|
36
|
+
ReportPortal::Settings.instance.formatter_modes.include?('attach_to_launch')
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
@last_used_time = 0
|
41
|
+
@root_node = Tree::TreeNode.new('')
|
42
|
+
start_launch
|
43
|
+
end
|
44
|
+
|
45
|
+
def start_launch(desired_time = ReportPortal.now)
|
46
|
+
if attach_to_launch?
|
47
|
+
ReportPortal.launch_id =
|
48
|
+
if ReportPortal::Settings.instance.launch_id
|
49
|
+
ReportPortal::Settings.instance.launch_id
|
50
|
+
else
|
51
|
+
file_path = ReportPortal::Settings.instance.file_with_launch_id || (Pathname(Dir.tmpdir) + 'rp_launch_id.tmp')
|
52
|
+
File.read(file_path)
|
53
|
+
end
|
54
|
+
$stdout.puts "Attaching to launch #{ReportPortal.launch_id}"
|
55
|
+
else
|
56
|
+
description = ReportPortal::Settings.instance.description
|
57
|
+
description ||= ARGV.map { |arg| arg.gsub(/rp_uuid=.+/, "rp_uuid=[FILTERED]") }.join(' ')
|
58
|
+
ReportPortal.start_launch(description, time_to_send(desired_time))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_case_started(event, desired_time = ReportPortal.now) # TODO: time should be a required argument
|
63
|
+
test_case = event.test_case
|
64
|
+
feature = test_case.feature
|
65
|
+
unless same_feature_as_previous_test_case?(feature)
|
66
|
+
end_feature(desired_time) if @feature_node
|
67
|
+
start_feature_with_parentage(feature, desired_time)
|
68
|
+
end
|
69
|
+
|
70
|
+
name = "#{test_case.keyword}: #{test_case.name}"
|
71
|
+
description = test_case.location.to_s
|
72
|
+
tags = test_case.tags.map(&:name)
|
73
|
+
type = :STEP
|
74
|
+
|
75
|
+
ReportPortal.current_scenario = ReportPortal::TestItem.new(name, type, nil, time_to_send(desired_time), description, false, tags)
|
76
|
+
scenario_node = Tree::TreeNode.new(SecureRandom.hex, ReportPortal.current_scenario)
|
77
|
+
@feature_node << scenario_node
|
78
|
+
ReportPortal.current_scenario.id = ReportPortal.start_item(scenario_node)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_case_finished(event, desired_time = ReportPortal.now)
|
82
|
+
result = event.result
|
83
|
+
status = result.to_sym
|
84
|
+
issue = nil
|
85
|
+
if [:undefined, :pending].include?(status)
|
86
|
+
status = :failed
|
87
|
+
issue = result.message
|
88
|
+
end
|
89
|
+
ReportPortal.finish_item(ReportPortal.current_scenario, status, time_to_send(desired_time), issue)
|
90
|
+
ReportPortal.current_scenario = nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_step_started(event, desired_time = ReportPortal.now)
|
94
|
+
test_step = event.test_step
|
95
|
+
if step?(test_step) # `after_test_step` is also invoked for hooks
|
96
|
+
step_source = test_step.source.last
|
97
|
+
message = "-- #{step_source.keyword}#{step_source.text} --"
|
98
|
+
if step_source.multiline_arg.doc_string?
|
99
|
+
message << %(\n"""\n#{step_source.multiline_arg.content}\n""")
|
100
|
+
elsif step_source.multiline_arg.data_table?
|
101
|
+
message << step_source.multiline_arg.raw.reduce("\n") { |acc, row| acc << "| #{row.join(' | ')} |\n" }
|
102
|
+
end
|
103
|
+
ReportPortal.send_log(:trace, message, time_to_send(desired_time))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_step_finished(event, desired_time = ReportPortal.now)
|
108
|
+
test_step = event.test_step
|
109
|
+
result = event.result
|
110
|
+
status = result.to_sym
|
111
|
+
|
112
|
+
if [:failed, :pending, :undefined].include?(status)
|
113
|
+
exception_info = if [:failed, :pending].include?(status)
|
114
|
+
ex = result.exception
|
115
|
+
sprintf("%s: %s\n %s", ex.class.name, ex.message, ex.backtrace.join("\n "))
|
116
|
+
else
|
117
|
+
sprintf("Undefined step: %s:\n%s", test_step.text, test_step.source.last.backtrace_line)
|
118
|
+
end
|
119
|
+
ReportPortal.send_log(:error, exception_info, time_to_send(desired_time))
|
120
|
+
end
|
121
|
+
|
122
|
+
if status != :passed
|
123
|
+
log_level = (status == :skipped)? :warn : :error
|
124
|
+
step_type = if step?(test_step)
|
125
|
+
'Step'
|
126
|
+
else
|
127
|
+
hook_class_name = test_step.source.last.class.name.split('::').last
|
128
|
+
location = test_step.location
|
129
|
+
"#{hook_class_name} at `#{location}`"
|
130
|
+
end
|
131
|
+
ReportPortal.send_log(log_level, "#{step_type} #{status}", time_to_send(desired_time))
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def done(desired_time = ReportPortal.now)
|
136
|
+
end_feature(desired_time) if @feature_node
|
137
|
+
|
138
|
+
unless attach_to_launch?
|
139
|
+
close_all_children_of(@root_node) # Folder items are closed here as they can't be closed after finishing a feature
|
140
|
+
time_to_send = time_to_send(desired_time)
|
141
|
+
ReportPortal.finish_launch(time_to_send)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def puts(message, desired_time = ReportPortal.now)
|
146
|
+
ReportPortal.send_log(:info, message, time_to_send(desired_time))
|
147
|
+
end
|
148
|
+
|
149
|
+
def embed(src, mime_type, label, desired_time = ReportPortal.now)
|
150
|
+
ReportPortal.send_file(:info, src, label, time_to_send(desired_time),mime_type)
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
# Report Portal sorts logs by time. However, several logs might have the same time.
|
156
|
+
# So to get Report Portal sort them properly the time should be different in all logs related to the same item.
|
157
|
+
# And thus it should be stored.
|
158
|
+
# Only the last time needs to be stored as:
|
159
|
+
# * only one test framework process/thread may send data for a single Report Portal item
|
160
|
+
# * that process/thread can't start the next test until it's done with the previous one
|
161
|
+
def time_to_send(desired_time)
|
162
|
+
time_to_send = desired_time
|
163
|
+
if time_to_send <= @last_used_time
|
164
|
+
time_to_send = @last_used_time + 1
|
165
|
+
end
|
166
|
+
@last_used_time = time_to_send
|
167
|
+
end
|
168
|
+
|
169
|
+
def same_feature_as_previous_test_case?(feature)
|
170
|
+
@feature_node && @feature_node.name == feature.location.file.split(File::SEPARATOR).last
|
171
|
+
end
|
172
|
+
|
173
|
+
def start_feature_with_parentage(feature, desired_time)
|
174
|
+
parent_node = @root_node
|
175
|
+
child_node = nil
|
176
|
+
path_components = feature.location.file.split(File::SEPARATOR)
|
177
|
+
path_components.each_with_index do |path_component, index|
|
178
|
+
child_node = parent_node[path_component]
|
179
|
+
unless child_node # if child node was not created yet
|
180
|
+
if index < path_components.size - 1
|
181
|
+
name = "Folder: #{path_component}"
|
182
|
+
description = nil
|
183
|
+
tags = []
|
184
|
+
type = :SUITE
|
185
|
+
else
|
186
|
+
name = "#{feature.keyword}: #{feature.name}"
|
187
|
+
description = feature.file # TODO: consider adding feature description and comments
|
188
|
+
tags = feature.tags.map(&:name)
|
189
|
+
type = :TEST
|
190
|
+
end
|
191
|
+
# TODO: multithreading # Parallel formatter always executes scenarios inside the same feature in the same process
|
192
|
+
if parallel? &&
|
193
|
+
index < path_components.size - 1 && # is folder?
|
194
|
+
(id_of_created_item = ReportPortal.item_id_of(name, parent_node)) # get id for folder from report portal
|
195
|
+
# get child id from other process
|
196
|
+
item = ReportPortal::TestItem.new(name, type, id_of_created_item, time_to_send(desired_time), description, false, tags)
|
197
|
+
child_node = Tree::TreeNode.new(path_component, item)
|
198
|
+
parent_node << child_node
|
199
|
+
else
|
200
|
+
item = ReportPortal::TestItem.new(name, type, nil, time_to_send(desired_time), description, false, tags)
|
201
|
+
child_node = Tree::TreeNode.new(path_component, item)
|
202
|
+
parent_node << child_node
|
203
|
+
item.id = ReportPortal.start_item(child_node) # TODO: multithreading
|
204
|
+
end
|
205
|
+
end
|
206
|
+
parent_node = child_node
|
207
|
+
end
|
208
|
+
@feature_node = child_node
|
209
|
+
end
|
210
|
+
|
211
|
+
def end_feature(desired_time)
|
212
|
+
ReportPortal.finish_item(@feature_node.content, nil, time_to_send(desired_time))
|
213
|
+
# Folder items can't be finished here because when the folder started we didn't track
|
214
|
+
# which features the folder contains.
|
215
|
+
# It's not easy to do it using Cucumber currently:
|
216
|
+
# https://github.com/cucumber/cucumber-ruby/issues/887
|
217
|
+
end
|
218
|
+
|
219
|
+
def close_all_children_of(root_node)
|
220
|
+
root_node.postordered_each do |node|
|
221
|
+
if !node.is_root? && !node.content.closed
|
222
|
+
ReportPortal.finish_item(node.content)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def step?(test_step)
|
228
|
+
!::Cucumber::Formatter::HookQueryVisitor.new(test_step).hook?
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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 'log4r/outputter/outputter'
|
20
|
+
|
21
|
+
require_relative '../../reportportal'
|
22
|
+
|
23
|
+
module ReportPortal
|
24
|
+
# Custom ReportPortal outputter for 'log4r' gem
|
25
|
+
class Log4rOutputter < Log4r::Outputter
|
26
|
+
def canonical_log(logevent)
|
27
|
+
synch { write(Log4r::LNAMES[logevent.level], format(logevent)) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(level, data)
|
31
|
+
ReportPortal.send_log(level, data, ReportPortal.now)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,54 @@
|
|
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 'logger'
|
20
|
+
|
21
|
+
module ReportPortal
|
22
|
+
class << self
|
23
|
+
# Monkey-patch for built-in Logger class
|
24
|
+
def patch_logger
|
25
|
+
Logger.class_eval do
|
26
|
+
alias_method :orig_add, :add
|
27
|
+
alias_method :orig_write, :<<
|
28
|
+
def add(severity, message = nil, progname = nil, &block)
|
29
|
+
ret = orig_add(severity, message, progname, &block)
|
30
|
+
|
31
|
+
unless severity < @level
|
32
|
+
progname ||= @progname
|
33
|
+
if message.nil?
|
34
|
+
if block_given?
|
35
|
+
message = yield
|
36
|
+
else
|
37
|
+
message = progname
|
38
|
+
progname = @progname
|
39
|
+
end
|
40
|
+
end
|
41
|
+
ReportPortal.send_log(format_severity(severity), format_message(format_severity(severity), Time.now, progname, message.to_s), ReportPortal.now)
|
42
|
+
end
|
43
|
+
ret
|
44
|
+
end
|
45
|
+
|
46
|
+
def <<(msg)
|
47
|
+
ret = orig_write(msg)
|
48
|
+
ReportPortal.send_log(ReportPortal::LOG_LEVELS[:unknown], msg.to_s, ReportPortal.now)
|
49
|
+
ret
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,36 @@
|
|
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 'logging'
|
20
|
+
|
21
|
+
require_relative '../../reportportal'
|
22
|
+
|
23
|
+
module ReportPortal
|
24
|
+
# Custom ReportPortal appender for 'logging' gem
|
25
|
+
class LoggingAppender < ::Logging::Appender
|
26
|
+
def write(event)
|
27
|
+
(str, lvl) = if event.instance_of?(::Logging::LogEvent)
|
28
|
+
[layout.format(event), event.level]
|
29
|
+
else
|
30
|
+
[event.to_s, ReportPortal::LOG_LEVELS[:unknown]]
|
31
|
+
end
|
32
|
+
|
33
|
+
ReportPortal.send_log(lvl, str, ReportPortal.now)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|