allure-ruby-commons 2.10.0.beta2
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/README.md +67 -0
- data/lib/allure-ruby-commons.rb +168 -0
- data/lib/allure_ruby_commons/allure_lifecycle.rb +257 -0
- data/lib/allure_ruby_commons/config.rb +23 -0
- data/lib/allure_ruby_commons/file_writer.rb +46 -0
- data/lib/allure_ruby_commons/model/attachment.rb +18 -0
- data/lib/allure_ruby_commons/model/content_type.rb +21 -0
- data/lib/allure_ruby_commons/model/executable_item.rb +34 -0
- data/lib/allure_ruby_commons/model/fixture_result.rb +5 -0
- data/lib/allure_ruby_commons/model/jsonable.rb +36 -0
- data/lib/allure_ruby_commons/model/label.rb +14 -0
- data/lib/allure_ruby_commons/model/link.rb +15 -0
- data/lib/allure_ruby_commons/model/parameter.rb +14 -0
- data/lib/allure_ruby_commons/model/stage.rb +10 -0
- data/lib/allure_ruby_commons/model/status.rb +10 -0
- data/lib/allure_ruby_commons/model/status_details.rb +20 -0
- data/lib/allure_ruby_commons/model/step_result.rb +5 -0
- data/lib/allure_ruby_commons/model/test_result.rb +31 -0
- data/lib/allure_ruby_commons/model/test_result_container.rb +17 -0
- data/lib/allure_ruby_commons/result_utils.rb +151 -0
- data/lib/allure_ruby_commons/util.rb +45 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c6ec9c5dd1a69617de027bd146f0deaf35ef51a1bd8861e013c41550070020b7
|
4
|
+
data.tar.gz: e049c7285aed91e6c8aceb3185ed4a11f143aaafb5b8ae20acdf996c1239f923
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1367a4de864e0c704ac5223b626a8027bdb942aaa91ceac3e25b84ec228b86e6b4f4204c3439b55f8f8a9d5860e3b044877da910aa70270a19d1ee5a4f9be5f0
|
7
|
+
data.tar.gz: 626e8aa40a5d8f7cde655ca3b6a7f1b283a5006d80676aa86001e63986f25e674220cfabaff63d8f607a6381f9221e493cbed4d88e1f4833da6e570637b343f5
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Allure Ruby Adaptor API
|
2
|
+
|
3
|
+
This is a helper library containing the basics for any ruby-based Allure adaptor.
|
4
|
+
Using it you can easily implement the adaptor for your favorite ruby testing library or
|
5
|
+
you can just create the report of any other kind using the basic Allure terms.
|
6
|
+
|
7
|
+
## Setup
|
8
|
+
|
9
|
+
Add the dependency to your Gemfile
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'allure-ruby-commons'
|
13
|
+
```
|
14
|
+
|
15
|
+
## Configuration
|
16
|
+
|
17
|
+
Following configuration options are supported:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
Allure.configure do |c|
|
21
|
+
c.results_directory = "/whatever/you/like"
|
22
|
+
c.logging_level = Logger::INFO
|
23
|
+
# these are used for creating links to bugs or test cases where {} is replaced with keys of relevant items
|
24
|
+
c.link_tms_pattern = "http://www.jira.com/browse/{}"
|
25
|
+
c.link_issue_pattern = "http://www.jira.com/browse/{}"
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
Getting the configuration object:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
Allure.configuration
|
33
|
+
```
|
34
|
+
|
35
|
+
## Allure lifecycle
|
36
|
+
|
37
|
+
Reports are built using API defined in AllureLifecycle class and using allure specific entities defined in models.
|
38
|
+
Example of building a simple test case can be seen in [integration spec](spec/integration/full_report_spec.rb).
|
39
|
+
|
40
|
+
Convenience method `Allure.lifecycle` exists for getting thread specific allure lifecycle instance.
|
41
|
+
|
42
|
+
Additional methods in [Allure](lib/allure-ruby-commons.rb) exist to add various custom attributes to test report.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
Allure.add_attachment(name: "attachment", source: "Some string", type: Allure::ContentType::TXT, test_case: false)
|
46
|
+
Allure.add_link(name: "Custom Url", url: "http://www.github.com")
|
47
|
+
```
|
48
|
+
|
49
|
+
## Testing
|
50
|
+
|
51
|
+
Install dependencies:
|
52
|
+
|
53
|
+
```bash
|
54
|
+
bundle install
|
55
|
+
```
|
56
|
+
|
57
|
+
Run tests:
|
58
|
+
|
59
|
+
```bash
|
60
|
+
bundle exec rspec
|
61
|
+
```
|
62
|
+
|
63
|
+
## Building
|
64
|
+
|
65
|
+
```bash
|
66
|
+
gem build allure-ruby-commons.gemspec
|
67
|
+
```
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# rubocop:disable Naming/FileName
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "require_all"
|
5
|
+
require "uuid"
|
6
|
+
require_rel "allure_ruby_commons/**/*rb"
|
7
|
+
|
8
|
+
# Namespace for classes that handle allure report generation and different framework adaptors
|
9
|
+
module Allure
|
10
|
+
class << self
|
11
|
+
# Get thread specific allure lifecycle object
|
12
|
+
# @return [Allure::AllureLifecycle]
|
13
|
+
def lifecycle
|
14
|
+
Thread.current[:lifecycle] ||= AllureLifecycle.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# Set lifecycle object
|
18
|
+
# @param [Allure::AllureLifecycle] lifecycle
|
19
|
+
# @return [void]
|
20
|
+
def lifecycle=(lifecycle)
|
21
|
+
Thread.current[:lifecycle] = lifecycle
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get allure configuration
|
25
|
+
# @return [Allure::Config]
|
26
|
+
def configuration
|
27
|
+
Config
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set allure configuration
|
31
|
+
# @yieldparam [Allure::Config]
|
32
|
+
# @yieldreturn [void]
|
33
|
+
# @return [void]
|
34
|
+
def configure
|
35
|
+
yield(Config)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Add epic to current test case
|
39
|
+
# @param [String] value
|
40
|
+
# @return [void]
|
41
|
+
def epic(value)
|
42
|
+
label(ResultUtils::EPIC_LABEL_NAME, value)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Add feature to current test case
|
46
|
+
# @param [String] value
|
47
|
+
# @return [void]
|
48
|
+
def feature(value)
|
49
|
+
label(ResultUtils::FEATURE_LABEL_NAME, value)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Add story to current test case
|
53
|
+
# @param [String] value
|
54
|
+
# @return [void]
|
55
|
+
def story(value)
|
56
|
+
label(ResultUtils::STORY_LABEL_NAME, value)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Add suite to current test case
|
60
|
+
# @param [String] value
|
61
|
+
# @return [void]
|
62
|
+
def suite(value)
|
63
|
+
label(ResultUtils::SUITE_LABEL_NAME, value)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Add label to current test case
|
67
|
+
# @param [String] name
|
68
|
+
# @param [String] value
|
69
|
+
# @return [void]
|
70
|
+
def label(name, value)
|
71
|
+
lifecycle.update_test_case do |test_case|
|
72
|
+
test_case.labels.push(Label.new(name, value))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Add description to current test case
|
77
|
+
# @param [String] description
|
78
|
+
# @return [void]
|
79
|
+
def description(description)
|
80
|
+
lifecycle.update_test_case do |test_case|
|
81
|
+
test_case.description = description
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Add html description to current test case
|
86
|
+
# @param [String] description_html
|
87
|
+
# @return [void]
|
88
|
+
def description_html(description_html)
|
89
|
+
lifecycle.update_test_case do |test_case|
|
90
|
+
test_case.description_html = description_html
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Add parameter to current test case
|
95
|
+
# @param [String] name
|
96
|
+
# @param [String] value
|
97
|
+
# @return [void]
|
98
|
+
def parameter(name, value)
|
99
|
+
lifecycle.update_test_case do |test_case|
|
100
|
+
test_case.parameters.push(Parameter.new(name, value))
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Add tms link to current test case
|
105
|
+
# @param [String] name
|
106
|
+
# @param [String] url
|
107
|
+
# @return [void]
|
108
|
+
def tms(name, url)
|
109
|
+
add_link(name: name, url: url, type: ResultUtils::TMS_LINK_TYPE)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Add issue linkt to current test case
|
113
|
+
# @param [String] name
|
114
|
+
# @param [String] url
|
115
|
+
# @return [void]
|
116
|
+
def issue(name, url)
|
117
|
+
add_link(name: name, url: url, type: ResultUtils::ISSUE_LINK_TYPE)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Add link to current test case
|
121
|
+
# @param [String ] url
|
122
|
+
# @param [String] name
|
123
|
+
# @param [String] type type of the link used to display link icon
|
124
|
+
# @return [void]
|
125
|
+
def add_link(url:, name: nil, type: "custom")
|
126
|
+
lifecycle.update_test_case do |test_case|
|
127
|
+
test_case.links.push(Link.new(type, name || url, url))
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Add attachment to current test case or step
|
132
|
+
# @param [String] name Attachment name
|
133
|
+
# @param [File, String] source File or string to save as attachment
|
134
|
+
# @param [String] type attachment type defined in {Allure::ContentType}
|
135
|
+
# @param [Boolean] test_case add attachment to current test case instead of test step
|
136
|
+
# @return [void]
|
137
|
+
def add_attachment(name:, source:, type:, test_case: false)
|
138
|
+
lifecycle.add_attachment(name: name, source: source, type: type, test_case: test_case)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Add step with provided name and optional status to current test step, fixture or test case
|
142
|
+
# @param [String] name
|
143
|
+
# @param [Symbol] status <Allure::Status>, <Allure::Status::PASSED> by default
|
144
|
+
# @return [void]
|
145
|
+
def step(name:, status: nil)
|
146
|
+
lifecycle.add_test_step(StepResult.new(name: name, status: status || Status::PASSED, stage: Stage::FINISHED))
|
147
|
+
end
|
148
|
+
|
149
|
+
# Run passed block as step with given name
|
150
|
+
# @param [String] name
|
151
|
+
# @yield [] step block
|
152
|
+
# @return [void]
|
153
|
+
def run_step(name)
|
154
|
+
lifecycle.start_test_step(StepResult.new(name: name, stage: Stage::RUNNING))
|
155
|
+
yield
|
156
|
+
lifecycle.update_test_step { |step| step.status = Status::PASSED }
|
157
|
+
rescue => e
|
158
|
+
lifecycle.update_test_step do |step|
|
159
|
+
step.status = ResultUtils.status(e)
|
160
|
+
step.status_details = ResultUtils.status_details(e)
|
161
|
+
end
|
162
|
+
raise(e)
|
163
|
+
ensure
|
164
|
+
lifecycle.stop_test_step
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
# rubocop:enable Naming/FileName
|
@@ -0,0 +1,257 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Allure
|
4
|
+
# Main class for creating and writing allure results
|
5
|
+
class AllureLifecycle
|
6
|
+
def initialize
|
7
|
+
@step_context = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# Start test result container
|
11
|
+
# @param [Allure::TestResultContainer] test_result_container
|
12
|
+
# @return [Allure::TestResultContainer]
|
13
|
+
def start_test_container(test_result_container)
|
14
|
+
test_result_container.start = ResultUtils.timestamp
|
15
|
+
@current_test_result_container = test_result_container
|
16
|
+
end
|
17
|
+
|
18
|
+
# @example Update current test container
|
19
|
+
# update_test_container do |container|
|
20
|
+
# container.stage = Allure::Stage::FINISHED
|
21
|
+
# end
|
22
|
+
# @yieldparam [Allure::TestResultContainer] current test result container
|
23
|
+
# @yieldreturn [void]
|
24
|
+
# @return [void]
|
25
|
+
def update_test_container
|
26
|
+
unless @current_test_result_container
|
27
|
+
return logger.error("Could not update test container, no container is running.")
|
28
|
+
end
|
29
|
+
|
30
|
+
yield(@current_test_result_container)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Stop current test container and write result
|
34
|
+
# @return [void]
|
35
|
+
def stop_test_container
|
36
|
+
unless @current_test_result_container
|
37
|
+
return logger.error("Could not stop test container, no container is running.")
|
38
|
+
end
|
39
|
+
|
40
|
+
@current_test_result_container.stop = ResultUtils.timestamp
|
41
|
+
file_writer.write_test_result_container(@current_test_result_container)
|
42
|
+
clear_current_test_container
|
43
|
+
end
|
44
|
+
|
45
|
+
# Start test case and add to current test container
|
46
|
+
# @param [Allure::TestResult] test_result
|
47
|
+
# @return [Allure::TestResult]
|
48
|
+
def start_test_case(test_result)
|
49
|
+
clear_step_context
|
50
|
+
unless @current_test_result_container
|
51
|
+
return logger.error("Could not start test case, test container is not started")
|
52
|
+
end
|
53
|
+
|
54
|
+
test_result.start = ResultUtils.timestamp
|
55
|
+
test_result.stage = Stage::RUNNING
|
56
|
+
test_result.labels.push(ResultUtils.thread_label, ResultUtils.host_label, ResultUtils.language_label)
|
57
|
+
@current_test_result_container.children.push(test_result.uuid)
|
58
|
+
@current_test_case = test_result
|
59
|
+
end
|
60
|
+
|
61
|
+
# @example Update current test case
|
62
|
+
# update_test_container do |test_case|
|
63
|
+
# test_case.status = Allure::Status::FAILED
|
64
|
+
# end
|
65
|
+
# @yieldparam [Allure::TestResult] current test
|
66
|
+
# @yieldreturn [void]
|
67
|
+
# @return [void]
|
68
|
+
def update_test_case
|
69
|
+
return logger.error("Could not update test case, no test case running") unless @current_test_case
|
70
|
+
|
71
|
+
yield(@current_test_case)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Stop current test case and write result
|
75
|
+
# @return [void]
|
76
|
+
def stop_test_case
|
77
|
+
return logger.error("Could not stop test case, no test case is running") unless @current_test_case
|
78
|
+
|
79
|
+
@current_test_case.stop = ResultUtils.timestamp
|
80
|
+
@current_test_case.stage = Stage::FINISHED
|
81
|
+
file_writer.write_test_result(@current_test_case)
|
82
|
+
clear_current_test_case
|
83
|
+
clear_step_context
|
84
|
+
end
|
85
|
+
|
86
|
+
# Start test step and add to current test case
|
87
|
+
# @param [Allure::StepResult] step_result
|
88
|
+
# @return [Allure::StepResult]
|
89
|
+
def start_test_step(step_result)
|
90
|
+
return logger.error("Could not start test step, no test case is running") unless @current_test_case
|
91
|
+
|
92
|
+
step_result.start = ResultUtils.timestamp
|
93
|
+
step_result.stage = Stage::RUNNING
|
94
|
+
add_test_step(step_result)
|
95
|
+
step_result
|
96
|
+
end
|
97
|
+
|
98
|
+
# @example Update current test step
|
99
|
+
# update_test_container do |test_step|
|
100
|
+
# test_step.status = Allure::Status::BROKEN
|
101
|
+
# end
|
102
|
+
# @yieldparam [Allure::StepResult] current test step
|
103
|
+
# @yieldreturn [void]
|
104
|
+
# @return [void]
|
105
|
+
def update_test_step
|
106
|
+
return logger.error("Could not update test step, no step is running") unless current_test_step
|
107
|
+
|
108
|
+
yield(current_test_step)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Stop current test step
|
112
|
+
# @return [void]
|
113
|
+
def stop_test_step
|
114
|
+
return logger.error("Could not stop test step, no step is running") unless current_test_step
|
115
|
+
|
116
|
+
current_test_step.stop = ResultUtils.timestamp
|
117
|
+
current_test_step.stage = Stage::FINISHED
|
118
|
+
clear_last_test_step
|
119
|
+
end
|
120
|
+
|
121
|
+
# Start prepare fixture
|
122
|
+
# @param [Allure::FixtureResult] fixture_result
|
123
|
+
# @return [Allure::FixtureResult]
|
124
|
+
def start_prepare_fixture(fixture_result)
|
125
|
+
start_fixture(fixture_result) || return
|
126
|
+
@current_test_result_container.befores.push(fixture_result)
|
127
|
+
@current_fixture = fixture_result
|
128
|
+
end
|
129
|
+
|
130
|
+
# Start tear down fixture
|
131
|
+
# @param [Allure::FixtureResult] fixture_result
|
132
|
+
# @return [Allure::FixtureResult]
|
133
|
+
def start_tear_down_fixture(fixture_result)
|
134
|
+
start_fixture(fixture_result) || return
|
135
|
+
@current_test_result_container.afters.push(fixture_result)
|
136
|
+
@current_fixture = fixture_result
|
137
|
+
end
|
138
|
+
|
139
|
+
# Start fixture
|
140
|
+
# @param [Allure::FixtureResult] fixture_result
|
141
|
+
# @return [Allure::FixtureResult]
|
142
|
+
def start_fixture(fixture_result)
|
143
|
+
clear_step_context
|
144
|
+
unless @current_test_result_container
|
145
|
+
logger.error("Could not start fixture, test container is not started")
|
146
|
+
return false
|
147
|
+
end
|
148
|
+
|
149
|
+
fixture_result.start = ResultUtils.timestamp
|
150
|
+
fixture_result.stage = Stage::RUNNING
|
151
|
+
end
|
152
|
+
|
153
|
+
# @example Update current fixture
|
154
|
+
# update_test_container do |fixture|
|
155
|
+
# fixture.status = Allure::Status::BROKEN
|
156
|
+
# end
|
157
|
+
# @yieldparam [Allure::FixtureResult] current fixture
|
158
|
+
# @yieldreturn [void]
|
159
|
+
# @return [void]
|
160
|
+
def update_fixture
|
161
|
+
return logger.error("Could not update fixture, fixture is not started") unless @current_fixture
|
162
|
+
|
163
|
+
yield(@current_fixture)
|
164
|
+
end
|
165
|
+
|
166
|
+
def stop_fixture
|
167
|
+
return logger.error("Could not stop fixture, fixture is not started") unless @current_fixture
|
168
|
+
|
169
|
+
@current_fixture.stop = ResultUtils.timestamp
|
170
|
+
@current_fixture.stage = Stage::FINISHED
|
171
|
+
clear_current_fixture
|
172
|
+
clear_step_context
|
173
|
+
end
|
174
|
+
|
175
|
+
# Add attachment to current test or step
|
176
|
+
# @param [String] name Attachment name
|
177
|
+
# @param [File, String] source File or string to save as attachment
|
178
|
+
# @param [String] type attachment type defined in {Allure::ContentType}
|
179
|
+
# @param [Boolean] test_case add attachment to current test case
|
180
|
+
# @return [void]
|
181
|
+
def add_attachment(name:, source:, type:, test_case: false)
|
182
|
+
attachment = prepare_attachment(name, type) || begin
|
183
|
+
return logger.error("Can't add attachment, unrecognized mime type: #{type}")
|
184
|
+
end
|
185
|
+
executable_item = (test_case && @current_test_case) || current_executable
|
186
|
+
executable_item&.attachments&.push(attachment) || begin
|
187
|
+
return logger.error("Can't add attachment, no test, step or fixture is running")
|
188
|
+
end
|
189
|
+
write_attachment(source, attachment)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Create attachment object
|
193
|
+
# @param [String] name
|
194
|
+
# @param [String] type
|
195
|
+
# @return [Allure::Attachment]
|
196
|
+
def prepare_attachment(name, type)
|
197
|
+
extension = ContentType.to_extension(type) || return
|
198
|
+
file_name = "#{UUID.generate}-attachment.#{extension}"
|
199
|
+
Attachment.new(name: name, source: file_name, type: type)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Write attachment file
|
203
|
+
# @param [File, String] source
|
204
|
+
# @param [Allure::Attachment] attachment
|
205
|
+
# @return [void]
|
206
|
+
def write_attachment(source, attachment)
|
207
|
+
file_writer.write_attachment(source, attachment)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Add step to current fixture|step|test case
|
211
|
+
# @param [Allure::StepResult] step_result
|
212
|
+
# @return [Allure::StepResult]
|
213
|
+
def add_test_step(step_result)
|
214
|
+
current_executable.steps.push(step_result)
|
215
|
+
@step_context.push(step_result)
|
216
|
+
step_result
|
217
|
+
end
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
def logger
|
222
|
+
@logger ||= Logger.new(STDOUT, level: Config.logging_level)
|
223
|
+
end
|
224
|
+
|
225
|
+
def file_writer
|
226
|
+
@file_writer ||= FileWriter.new
|
227
|
+
end
|
228
|
+
|
229
|
+
def current_executable
|
230
|
+
current_test_step || @current_fixture || @current_test_case
|
231
|
+
end
|
232
|
+
|
233
|
+
def clear_current_test_container
|
234
|
+
@current_test_result_container = nil
|
235
|
+
end
|
236
|
+
|
237
|
+
def clear_current_test_case
|
238
|
+
@current_test_case = nil
|
239
|
+
end
|
240
|
+
|
241
|
+
def current_test_step
|
242
|
+
@step_context.last
|
243
|
+
end
|
244
|
+
|
245
|
+
def clear_last_test_step
|
246
|
+
@step_context.pop
|
247
|
+
end
|
248
|
+
|
249
|
+
def clear_step_context
|
250
|
+
@step_context.clear
|
251
|
+
end
|
252
|
+
|
253
|
+
def clear_current_fixture
|
254
|
+
@current_fixture = nil
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
|
5
|
+
module Allure
|
6
|
+
class Config
|
7
|
+
DEFAULT_RESULTS_DIRECTORY = "reports/allure-results"
|
8
|
+
DEFAULT_LOGGING_LEVEL = Logger::INFO
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :link_tms_pattern, :link_issue_pattern
|
12
|
+
attr_writer :results_directory, :logging_level
|
13
|
+
|
14
|
+
def results_directory
|
15
|
+
@results_directory || DEFAULT_RESULTS_DIRECTORY
|
16
|
+
end
|
17
|
+
|
18
|
+
def logging_level
|
19
|
+
@logging_level || DEFAULT_LOGGING_LEVEL
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Allure
|
4
|
+
class FileWriter
|
5
|
+
TEST_RESULT_SUFFIX = "-result.json"
|
6
|
+
TEST_RESULT_CONTAINER_SUFFIX = "-container.json"
|
7
|
+
ATTACHMENT_FILE_SUFFIX = "-attachment"
|
8
|
+
|
9
|
+
# Write test result
|
10
|
+
# @param [Allure::TestResult] test_result
|
11
|
+
# @return [void]
|
12
|
+
def write_test_result(test_result)
|
13
|
+
write("#{test_result.uuid}#{TEST_RESULT_SUFFIX}", test_result.to_json)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Write test result container
|
17
|
+
# @param [Allure::TestResultContainer] test_container_result
|
18
|
+
# @return [void]
|
19
|
+
def write_test_result_container(test_container_result)
|
20
|
+
write("#{test_container_result.uuid}#{TEST_RESULT_CONTAINER_SUFFIX}", test_container_result.to_json)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Write allure attachment file
|
24
|
+
# @param [File, String] source File or string of attachment to save
|
25
|
+
# @param [Allure::Attachment] attachment
|
26
|
+
# @return [void]
|
27
|
+
def write_attachment(source, attachment)
|
28
|
+
source.is_a?(File) ? copy(source.path, attachment.source) : write(attachment.source, source)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def output_dir
|
34
|
+
@output_dir ||= FileUtils.mkpath(Allure::Config.results_directory).first
|
35
|
+
end
|
36
|
+
|
37
|
+
def write(name, source)
|
38
|
+
filename = File.join(output_dir, name)
|
39
|
+
File.open(filename, "w") { |file| file.write(source) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def copy(from, to)
|
43
|
+
FileUtils.cp(from, File.join(output_dir, to))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "jsonable"
|
4
|
+
|
5
|
+
module Allure
|
6
|
+
class Attachment < JSONable
|
7
|
+
# @param [String] name attachment name
|
8
|
+
# @param [String] type attachment type, {Allure::ContentType}
|
9
|
+
# @param [String] source attachment file name
|
10
|
+
def initialize(name:, type:, source:)
|
11
|
+
@name = name
|
12
|
+
@type = type
|
13
|
+
@source = source
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_accessor :name, :type, :source
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Allure
|
4
|
+
class ContentType
|
5
|
+
TXT = "text/plain"
|
6
|
+
XML = "application/xml"
|
7
|
+
CSV = "text/csv"
|
8
|
+
TSV = "text/tab-separated-values"
|
9
|
+
CSS = "text/css"
|
10
|
+
URI = "text/uri-list"
|
11
|
+
SVG = "image/svg+xml"
|
12
|
+
PNG = "image/png"
|
13
|
+
JSON = "application/json"
|
14
|
+
WEBM = "video/webm"
|
15
|
+
JPG = "image/jpeg"
|
16
|
+
|
17
|
+
def self.to_extension(content_type)
|
18
|
+
constants.detect { |const| const_get(const) == content_type }&.to_s&.downcase
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "jsonable"
|
4
|
+
|
5
|
+
module Allure
|
6
|
+
class ExecutableItem < JSONable
|
7
|
+
# @param [Hash] options
|
8
|
+
# @option options [String] :name
|
9
|
+
# @option options [String] :description
|
10
|
+
# @option options [String] :description_html
|
11
|
+
# @option options [String] :stage ('scheduled'), {Allure::Stage}
|
12
|
+
# @option options [String] :status ('broken'), {Allure::Status}
|
13
|
+
# @option options [Allure::StatusDetails] :status_details
|
14
|
+
# @option options [Array<Allure::ExecutableItem>] :steps ([])
|
15
|
+
# @option options [Array<Allure::Attachment>] :attachments ([])
|
16
|
+
# @option options [Array<Allure::Parameter>] :parameters ([])
|
17
|
+
def initialize(**options)
|
18
|
+
@name = options[:name]
|
19
|
+
@description = options[:description]
|
20
|
+
@description_html = options[:description_html]
|
21
|
+
@status = options[:status] || Status::BROKEN
|
22
|
+
@status_details = options[:status_details] || StatusDetails.new
|
23
|
+
@stage = options[:stage] || Stage::SCHEDULED
|
24
|
+
@steps = options[:steps] || []
|
25
|
+
@attachments = options[:attachments] || []
|
26
|
+
@parameters = options[:parameters] || []
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_accessor(
|
30
|
+
:name, :status, :status_details, :stage, :description, :description_html,
|
31
|
+
:steps, :attachments, :parameters, :start, :stop
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module Allure
|
6
|
+
class JSONable
|
7
|
+
def as_json(_options = {})
|
8
|
+
instance_variables.each_with_object({}) do |var, map|
|
9
|
+
key = camelcase(var.to_s.delete_prefix("@"))
|
10
|
+
value = instance_variable_get(var)
|
11
|
+
map[key] = value unless value.nil?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_json(*options)
|
16
|
+
as_json(*options).to_json(*options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
self.class == other.class && state == other.state
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def state
|
26
|
+
instance_variables.map { |var| instance_variable_get(var) }
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def camelcase(str)
|
32
|
+
str = str.gsub(/(?:_+)([a-z])/) { Regexp.last_match(1).upcase }
|
33
|
+
str.gsub(/(\A|\s)([A-Z])/) { Regexp.last_match(1) + Regexp.last_match(2).downcase }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Allure
|
4
|
+
class StatusDetails < JSONable
|
5
|
+
# @param [Boolean] known
|
6
|
+
# @param [Boolean] muted
|
7
|
+
# @param [Boolean] flaky
|
8
|
+
# @param [String] message
|
9
|
+
# @param [String] trace
|
10
|
+
def initialize(known: false, muted: false, flaky: false, message: nil, trace: nil)
|
11
|
+
@known = known
|
12
|
+
@muted = muted
|
13
|
+
@flaky = flaky
|
14
|
+
@message = message
|
15
|
+
@trace = trace
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessor :known, :muted, :flaky, :message, :trace
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Allure
|
4
|
+
class TestResult < ExecutableItem
|
5
|
+
# @param [String] uuid
|
6
|
+
# @param [String] history_id
|
7
|
+
# @param [Hash] options
|
8
|
+
# @option options [String] :name
|
9
|
+
# @option options [String] :full_name
|
10
|
+
# @option options [String] :description
|
11
|
+
# @option options [String] :description_html
|
12
|
+
# @option options [String] :status ('broken')
|
13
|
+
# @option options [String] :stage ('scheduled')
|
14
|
+
# @option options [Allure::StatusDetails] :status_details
|
15
|
+
# @option options [Array<Allure::ExecutableItem>] :steps ([])
|
16
|
+
# @option options [Array<Allure::Label>] :labels ([])
|
17
|
+
# @option options [Array<Allure::Link>] :links ([])
|
18
|
+
# @option options [Array<Allure::Attachment>] :attachments ([])
|
19
|
+
# @option options [Array<Allure::Parameter>] :parameters ([])
|
20
|
+
def initialize(uuid: UUID.generate, history_id: UUID.generate, **options)
|
21
|
+
super
|
22
|
+
@uuid = uuid
|
23
|
+
@history_id = history_id
|
24
|
+
@full_name = options[:full_name] || "Unnamed"
|
25
|
+
@labels = options[:labels] || []
|
26
|
+
@links = options[:links] || []
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_accessor :uuid, :history_id, :full_name, :labels, :links
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "jsonable"
|
4
|
+
module Allure
|
5
|
+
class TestResultContainer < JSONable
|
6
|
+
def initialize(uuid: UUID.generate, name: "Unnamed")
|
7
|
+
@uuid = uuid
|
8
|
+
@name = name
|
9
|
+
@children = []
|
10
|
+
@befores = []
|
11
|
+
@afters = []
|
12
|
+
@links = []
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :uuid, :name, :description, :description_html, :start, :stop, :children, :befores, :afters, :links
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "socket"
|
4
|
+
|
5
|
+
module Allure
|
6
|
+
module ResultUtils
|
7
|
+
ISSUE_LINK_TYPE = "issue"
|
8
|
+
TMS_LINK_TYPE = "tms"
|
9
|
+
|
10
|
+
ALLURE_ID_LABEL_NAME = "AS_ID"
|
11
|
+
SUITE_LABEL_NAME = "suite"
|
12
|
+
PARENT_SUITE_LABEL_NAME = "parentSuite"
|
13
|
+
SUB_SUITE_LABEL_NAME = "subSuite"
|
14
|
+
EPIC_LABEL_NAME = "epic"
|
15
|
+
FEATURE_LABEL_NAME = "feature"
|
16
|
+
STORY_LABEL_NAME = "story"
|
17
|
+
SEVERITY_LABEL_NAME = "severity"
|
18
|
+
TAG_LABEL_NAME = "tag"
|
19
|
+
OWNER_LABEL_NAME = "owner"
|
20
|
+
LEAD_LABEL_NAME = "lead"
|
21
|
+
HOST_LABEL_NAME = "host"
|
22
|
+
THREAD_LABEL_NAME = "thread"
|
23
|
+
TEST_METHOD_LABEL_NAME = "testMethod"
|
24
|
+
TEST_CLASS_LABEL_NAME = "testClass"
|
25
|
+
PACKAGE_LABEL_NAME = "package"
|
26
|
+
FRAMEWORK_LABEL_NAME = "framework"
|
27
|
+
LANGUAGE_LABEL_NAME = "language"
|
28
|
+
|
29
|
+
class << self
|
30
|
+
# @param [Time] time
|
31
|
+
# @return [Number]
|
32
|
+
def timestamp(time = nil)
|
33
|
+
((time || Time.now).to_f * 1000).to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
# Current thread label
|
37
|
+
# @return [Allure::Label]
|
38
|
+
def thread_label
|
39
|
+
Label.new(THREAD_LABEL_NAME, Thread.current.object_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Host label
|
43
|
+
# @return [Allure::Label]
|
44
|
+
def host_label
|
45
|
+
Label.new(HOST_LABEL_NAME, Socket.gethostname)
|
46
|
+
end
|
47
|
+
|
48
|
+
def language_label
|
49
|
+
Label.new(LANGUAGE_LABEL_NAME, "ruby")
|
50
|
+
end
|
51
|
+
|
52
|
+
def framework_label(value)
|
53
|
+
Label.new(FRAMEWORK_LABEL_NAME, value)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Feature label
|
57
|
+
# @param [String] value
|
58
|
+
# @return [Allure::Label]
|
59
|
+
def feature_label(value)
|
60
|
+
Label.new(FEATURE_LABEL_NAME, value)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Package label
|
64
|
+
# @param [String] value
|
65
|
+
# @return [Allure::Label]
|
66
|
+
def package_label(value)
|
67
|
+
Label.new(PACKAGE_LABEL_NAME, value)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Suite label
|
71
|
+
# @param [String] value
|
72
|
+
# @return [Allure::Label]
|
73
|
+
def suite_label(value)
|
74
|
+
Label.new(SUITE_LABEL_NAME, value)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Story label
|
78
|
+
# @param [String] value
|
79
|
+
# @return [Allure::Label]
|
80
|
+
def story_label(value)
|
81
|
+
Label.new(STORY_LABEL_NAME, value)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Test case label
|
85
|
+
# @param [String] value
|
86
|
+
# @return [Allure::Label]
|
87
|
+
def test_class_label(value)
|
88
|
+
Label.new(TEST_CLASS_LABEL_NAME, value)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Tag label
|
92
|
+
# @param [String] value
|
93
|
+
# @return [Allure::Label]
|
94
|
+
def tag_label(value)
|
95
|
+
Label.new(TAG_LABEL_NAME, value)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Severity label
|
99
|
+
# @param [String] value
|
100
|
+
# @return [Allure::Label]
|
101
|
+
def severity_label(value)
|
102
|
+
Label.new(SEVERITY_LABEL_NAME, value)
|
103
|
+
end
|
104
|
+
|
105
|
+
# TMS link
|
106
|
+
# @param [String] value
|
107
|
+
# @return [Allure::Link]
|
108
|
+
def tms_link(value)
|
109
|
+
Link.new(TMS_LINK_TYPE, value, tms_url(value))
|
110
|
+
end
|
111
|
+
|
112
|
+
# Issue link
|
113
|
+
# @param [String] value
|
114
|
+
# @return [Allure::Link]
|
115
|
+
def issue_link(value)
|
116
|
+
Link.new(ISSUE_LINK_TYPE, value, issue_url(value))
|
117
|
+
end
|
118
|
+
|
119
|
+
# Get status based on exception type
|
120
|
+
# @param [Exception] exception
|
121
|
+
# @return [String]
|
122
|
+
def status(exception)
|
123
|
+
expectation_error?(exception) ? Status::FAILED : Status::BROKEN
|
124
|
+
end
|
125
|
+
|
126
|
+
# Get exception status detail
|
127
|
+
# @param [Exception] exception
|
128
|
+
# @return [Hash<Symbol, String>]
|
129
|
+
def status_details(exception)
|
130
|
+
StatusDetails.new(message: exception.message, trace: exception.backtrace&.join("\n"))
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def tms_url(value)
|
136
|
+
Allure.configuration.link_tms_pattern.sub("{}", value)
|
137
|
+
end
|
138
|
+
|
139
|
+
def issue_url(value)
|
140
|
+
Allure.configuration.link_issue_pattern.sub("{}", value)
|
141
|
+
end
|
142
|
+
|
143
|
+
def expectation_error?(exception)
|
144
|
+
exception.instance_of?(RSpec::Expectations::ExpectationNotMetError) ||
|
145
|
+
exception.instance_of?(RSpec::Expectations::MultipleExpectationsNotMetError)
|
146
|
+
rescue NameError
|
147
|
+
false
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "open-uri"
|
4
|
+
require "zip"
|
5
|
+
require "pathname"
|
6
|
+
|
7
|
+
module Allure
|
8
|
+
class Util
|
9
|
+
ALLURE_CLI_VERSION = "2.10.0"
|
10
|
+
ALLURE_BIN_URL = "http://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/"\
|
11
|
+
"#{ALLURE_CLI_VERSION}/allure-commandline-#{ALLURE_CLI_VERSION}.zip"
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# Download allure bin if appropriate version is not in path
|
15
|
+
# @return [String] allure executable
|
16
|
+
def allure_cli
|
17
|
+
return "allure" if ALLURE_CLI_VERSION == `allure --version`.chomp
|
18
|
+
|
19
|
+
cli_dir = File.join(".allure", "allure-#{ALLURE_CLI_VERSION}")
|
20
|
+
zip = File.join(".allure", "allure.zip")
|
21
|
+
bin = File.join(cli_dir, "bin", "allure")
|
22
|
+
|
23
|
+
FileUtils.mkpath(".allure")
|
24
|
+
download_allure(zip) unless File.exist?(zip) || File.exist?(bin)
|
25
|
+
extract_allure(zip, ".allure") unless File.exist?(bin)
|
26
|
+
|
27
|
+
bin
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def download_allure(destination)
|
33
|
+
File.open(destination, "w") { |file| file.write(open(ALLURE_BIN_URL).read) } # rubocop:disable Security/Open
|
34
|
+
end
|
35
|
+
|
36
|
+
def extract_allure(zip, destination)
|
37
|
+
Zip::File.foreach(zip) do |entry|
|
38
|
+
entry.restore_permissions = true
|
39
|
+
entry.extract(File.join(destination, entry.name))
|
40
|
+
end
|
41
|
+
FileUtils.rm(zip)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: allure-ruby-commons
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.10.0.beta2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrejs Cunskis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-06-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: uuid
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.3.9
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.3.9
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: require_all
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.8'
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '3'
|
51
|
+
type: :runtime
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1.8'
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rubyzip
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.2'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.2'
|
75
|
+
description: Utilities allowing to implement allure result generation by other test
|
76
|
+
frameworks
|
77
|
+
email: andrejs.cunskis@gmail.com
|
78
|
+
executables: []
|
79
|
+
extensions: []
|
80
|
+
extra_rdoc_files: []
|
81
|
+
files:
|
82
|
+
- README.md
|
83
|
+
- lib/allure-ruby-commons.rb
|
84
|
+
- lib/allure_ruby_commons/allure_lifecycle.rb
|
85
|
+
- lib/allure_ruby_commons/config.rb
|
86
|
+
- lib/allure_ruby_commons/file_writer.rb
|
87
|
+
- lib/allure_ruby_commons/model/attachment.rb
|
88
|
+
- lib/allure_ruby_commons/model/content_type.rb
|
89
|
+
- lib/allure_ruby_commons/model/executable_item.rb
|
90
|
+
- lib/allure_ruby_commons/model/fixture_result.rb
|
91
|
+
- lib/allure_ruby_commons/model/jsonable.rb
|
92
|
+
- lib/allure_ruby_commons/model/label.rb
|
93
|
+
- lib/allure_ruby_commons/model/link.rb
|
94
|
+
- lib/allure_ruby_commons/model/parameter.rb
|
95
|
+
- lib/allure_ruby_commons/model/stage.rb
|
96
|
+
- lib/allure_ruby_commons/model/status.rb
|
97
|
+
- lib/allure_ruby_commons/model/status_details.rb
|
98
|
+
- lib/allure_ruby_commons/model/step_result.rb
|
99
|
+
- lib/allure_ruby_commons/model/test_result.rb
|
100
|
+
- lib/allure_ruby_commons/model/test_result_container.rb
|
101
|
+
- lib/allure_ruby_commons/result_utils.rb
|
102
|
+
- lib/allure_ruby_commons/util.rb
|
103
|
+
homepage: http://allure.qatools.ru
|
104
|
+
licenses:
|
105
|
+
- Apache-2.0
|
106
|
+
metadata: {}
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: 2.5.0
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">"
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 1.3.1
|
121
|
+
requirements: []
|
122
|
+
rubygems_version: 3.0.3
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: Common library for allure results generation
|
126
|
+
test_files: []
|