cucumber-testrail 0.0.6
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/.rubocop.yml +56 -0
- data/.travis.yml +16 -0
- data/Dockerfile +16 -0
- data/Gemfile +5 -0
- data/LICENSE.md +13 -0
- data/README.md +60 -0
- data/TESTRAIL_LICENSE.md +23 -0
- data/cucumber_testrail.gemspec +19 -0
- data/deploy.sh +44 -0
- data/features/docs/testrail/adaptor.feature +39 -0
- data/features/lib/step_definitions/testrail/adaptor.rb +127 -0
- data/features/lib/support/env.rb +10 -0
- data/features/lib/support/hooks.rb +11 -0
- data/lib/testrail/adaptor.rb +94 -0
- data/lib/testrail/api_client.rb +119 -0
- data/lib/testrail/test_case.rb +24 -0
- data/lib/testrail/test_result.rb +32 -0
- data/lib/testrail/test_run.rb +32 -0
- data/lib/testrail/test_section.rb +21 -0
- data/lib/testrail/test_suite.rb +84 -0
- data/lib/testrail/testrail_client.rb +58 -0
- metadata +164 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0409c7f705e1d7bde8a6a11a10ec36244a7b42e2
|
4
|
+
data.tar.gz: f15eee126647e95096b269dd2ab54da02e1007ec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b32360e83cb242813920e0bbd73e7742aa0706e982f9ab41180c0e3b5e4c0fa37d63f9df9de07944e58b5c7dbf1ecaa0fc836c6b96f3b43aea48e700d839dea2
|
7
|
+
data.tar.gz: 6ae9b3aee409643232e7e27b2491a4c89b7309c7d09c7d89bd10a8624bc6d3763e599ba209d40ce0a18df9ac01a84587d9ab6ec32eb4ee0907a4a43adea5c91a
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.2
|
3
|
+
|
4
|
+
Lint/UnusedBlockArgument:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Metrics/AbcSize:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Metrics/LineLength:
|
11
|
+
Max: 120
|
12
|
+
|
13
|
+
Metrics/MethodLength:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Metrics/ParameterLists:
|
17
|
+
Max: 7
|
18
|
+
|
19
|
+
Metrics/ClassLength:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Style/AccessorMethodName:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Style/BracesAroundHashParameters:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/ClassAndModuleChildren:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/ClassVars:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/Documentation:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Style/EmptyLinesAroundBlockBody:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Style/EmptyLinesAroundClassBody:
|
41
|
+
EnforcedStyle: empty_lines
|
42
|
+
|
43
|
+
Style/EmptyLinesAroundModuleBody:
|
44
|
+
EnforcedStyle: empty_lines
|
45
|
+
|
46
|
+
Style/IndentationWidth:
|
47
|
+
Width: 2
|
48
|
+
|
49
|
+
Style/IndentHash:
|
50
|
+
Enabled: false
|
51
|
+
|
52
|
+
Style/WordArray:
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
Lint/HandleExceptions:
|
56
|
+
Enabled: false
|
data/.travis.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.2
|
4
|
+
before_install: gem update --remote bundler
|
5
|
+
install:
|
6
|
+
- bundle install --retry=3
|
7
|
+
script:
|
8
|
+
- bundle exec rubocop features lib
|
9
|
+
- bundle exec cucumber features
|
10
|
+
- gem build cucumber_testrail.gemspec
|
11
|
+
deploy:
|
12
|
+
provider: rubygems
|
13
|
+
api_key:
|
14
|
+
secure: DcF9uIbKdFzbKdz6xbYBbauG0dBV90i+HQRxpl41sz9hua/tfEkNtWCKa1A15xD4MhSkeKNkwwM3Axm/OA8Fp63nc9dHPTd3mcWwL0CmmKVAlolgbdHvTr04Vz0s1M9dV4w0XBhX/M/Vezi23MoHT2Z3B0YvYnbBVQEtIH+t5CPcY5tWXm/Dyz3J8CGhuO4oboW906K3MVBRqclz/njM3PXezNwOXrNGVyOnr94WTDXG857qzZnr2p1U1gRVCX7eyHIY6/pgxuejfcIkXS8c7WZ8tYuyc4xfcHGMdpHdFRRXuf7anpGikFPz2Qw2r2uaDhVAUzRgXjTF9JfYPPyDP3iZHVXa+G+jMHhXCCNPX85D4mfQz87okNH1PelRv2U9kZv3sxxtuIuOAwuKS+fWAc/dmhf7Q5PWROxGLzkwjbzqfQGz6Ia2jTvv+c4/1hyZLLctwf6Mq4E/XOqiU0ebjY77xhuMghtEscCp6D+HfD0p2GXiNbUfIPpczNZYZ2mv/kova7hExaldcrV0hE3y2OhxmxPEishjWm43wtoPXbpyK3w7Rm2mJXQk8OhwYpOh+OKg33GOBzI221KLnPvnip0vQ5Zw8FZuVH3ygyX4JA2WiqM2JKaqFTGzcNwMJdL6rDG61jKpVv7Hb8mO8zGWtew5FEwjdD6ypVtx5h4LqE4=
|
15
|
+
on:
|
16
|
+
tags: true
|
data/Dockerfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
FROM dockerfile/ubuntu
|
2
|
+
|
3
|
+
# Install Ruby
|
4
|
+
RUN apt-add-repository ppa:brightbox/ruby-ng && apt-get update && apt-get install -y ruby2.2
|
5
|
+
|
6
|
+
WORKDIR /workspace
|
7
|
+
|
8
|
+
RUN gem install nexus
|
9
|
+
|
10
|
+
ADD ./Gemfile Gemfile
|
11
|
+
ADD ./lib lib
|
12
|
+
ADD ./cucumber_testrail.gemspec cucumber_testrail.gemspec
|
13
|
+
ADD ./deploy.sh deploy.sh
|
14
|
+
|
15
|
+
ENTRYPOINT ["./deploy.sh"]
|
16
|
+
CMD ["--help"]
|
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2016 Findly Inc. NZ
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
###Status
|
2
|
+
[](https://travis-ci.org/Findly-Inc/cucumber-testrail)
|
3
|
+
|
4
|
+
TestRail Integration Adaptor
|
5
|
+
============================
|
6
|
+
|
7
|
+
The tool provides a way to integrate Cucumber/RSpec test suites with
|
8
|
+
TestRail using it's API.
|
9
|
+
|
10
|
+
The adaptor gets all the tests results in a cache so it doesn't make
|
11
|
+
https for each test. Instead, it sends a single API call with all the
|
12
|
+
results together. This avoid problems with the server throttling enforced
|
13
|
+
by the server.
|
14
|
+
|
15
|
+
### Installation
|
16
|
+
|
17
|
+
Just include the gem in your Gemfile
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'testrail-integration'
|
21
|
+
```
|
22
|
+
|
23
|
+
### Usage
|
24
|
+
|
25
|
+
Create a Test Adaptor with the required configuration
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
testrail_adaptor = TestRail::Adaptor.new(
|
29
|
+
enabled: flag, # Enable or Disable the TestRail runner(default: false)
|
30
|
+
url: url, # URL for custom TestRail Integration
|
31
|
+
username: username, # Authentication Username
|
32
|
+
password: password, # Authentication Password
|
33
|
+
project_id: project_id, # TestRail Project ID
|
34
|
+
suite_id: suite_id # TestRail Suite ID
|
35
|
+
)
|
36
|
+
```
|
37
|
+
|
38
|
+
When the test suite is ready, start a test run
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
testrail_adaptor.start_test_run
|
42
|
+
```
|
43
|
+
|
44
|
+
As an example, a Cucumber test suite is used to send results to the adaptor
|
45
|
+
Each scenario is being sent using the **submit** method:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
After do |scenario|
|
49
|
+
...
|
50
|
+
testrail_adaptor.submit(scenario)
|
51
|
+
...
|
52
|
+
end
|
53
|
+
|
54
|
+
at_exit do
|
55
|
+
testrail_adaptor.end_test_run
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
At the end of the test suite the adaptor needs to be finished to send the results
|
60
|
+
to TestRail. This is done with the **end_test_run** method.
|
data/TESTRAIL_LICENSE.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
License
|
2
|
+
-------
|
3
|
+
|
4
|
+
Copyright (c) 2010-2014 Gurock Software GmbH
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = 'cucumber-testrail'
|
3
|
+
spec.version = '0.0.6'
|
4
|
+
spec.date = '2016-04-26'
|
5
|
+
spec.summary = 'Cucumber TestRail integration'
|
6
|
+
spec.description = 'Library to integrate Test Suite with TestRail'
|
7
|
+
spec.authors = ['Javier Durante', 'Will Gauvin', 'Nathan Jones']
|
8
|
+
spec.email = 'mercury@findly.com'
|
9
|
+
spec.license = 'Apache-2.0'
|
10
|
+
spec.files = `git ls-files`.split("\n").reject {|path| path =~ /\.gitignore$/ }
|
11
|
+
spec.homepage = 'https://github.com/Findly-Inc/cucumber-testrail'
|
12
|
+
spec.add_development_dependency 'rspec', '>= 3.0'
|
13
|
+
spec.add_development_dependency 'pry'
|
14
|
+
spec.add_development_dependency 'rspec-core'
|
15
|
+
spec.add_development_dependency 'rspec-expectations'
|
16
|
+
spec.add_development_dependency 'rspec-mocks'
|
17
|
+
spec.add_development_dependency 'rspec-support'
|
18
|
+
spec.add_development_dependency 'require_all'
|
19
|
+
end
|
data/deploy.sh
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
script=$0
|
6
|
+
script_dir=$(cd "$(dirname "$0")" && pwd)
|
7
|
+
|
8
|
+
spec_file=$1
|
9
|
+
|
10
|
+
fatal() {
|
11
|
+
if [ "${1}" != "" ]; then
|
12
|
+
echo "Error: ${1}"
|
13
|
+
fi
|
14
|
+
usage
|
15
|
+
exit 1
|
16
|
+
}
|
17
|
+
|
18
|
+
param_exists() {
|
19
|
+
if [ "${1}" = "" ]; then
|
20
|
+
fatal "${2}"
|
21
|
+
fi
|
22
|
+
}
|
23
|
+
|
24
|
+
build() {
|
25
|
+
echo "Building $spec_file"
|
26
|
+
gem_file=`gem build $spec_file | grep File | awk '{split($0, output,":"); print output[2] }'`
|
27
|
+
}
|
28
|
+
|
29
|
+
deploy() {
|
30
|
+
echo "Deploying $gem_file"
|
31
|
+
result=`gem push $gem_file`
|
32
|
+
if [[ $result == *"Created"* ]]
|
33
|
+
then
|
34
|
+
echo "Gem $gem_file deployed to $nexus_url"
|
35
|
+
else
|
36
|
+
echo "Error uploading Gem"
|
37
|
+
exit 1
|
38
|
+
fi
|
39
|
+
}
|
40
|
+
|
41
|
+
param_exists "${spec_file}" "Gem spec file not specified"
|
42
|
+
|
43
|
+
build
|
44
|
+
deploy
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Feature: Test suite adaptor
|
2
|
+
|
3
|
+
Scenario: Start test run actually starts a test suite run
|
4
|
+
Given an Adaptor
|
5
|
+
When a test run is started
|
6
|
+
Then the test suite starts a test run
|
7
|
+
|
8
|
+
Scenario: End test run finishes a successful run
|
9
|
+
Given an Adaptor
|
10
|
+
And a test run is started
|
11
|
+
When the rest run is ended
|
12
|
+
Then the test suite submit the results
|
13
|
+
And the test suite is closed
|
14
|
+
|
15
|
+
Scenario: End test run doesn't close a run with failures
|
16
|
+
Given an Adaptor
|
17
|
+
And a test run is started
|
18
|
+
And an invalid test result is submitted
|
19
|
+
When the rest run is ended
|
20
|
+
Then the test suite submit the results
|
21
|
+
And the test suite is not closed
|
22
|
+
|
23
|
+
Scenario: Disabled adaptor does not perform any operations
|
24
|
+
Given a disabled Adaptor
|
25
|
+
And a test run is started
|
26
|
+
When the rest run is ended
|
27
|
+
Then no interactions are made to the test suite
|
28
|
+
|
29
|
+
Scenario Outline: Submit supports multiple scenarios
|
30
|
+
Given an Adaptor
|
31
|
+
And a test run is started
|
32
|
+
When a result of type "<Result Type>" is submitted
|
33
|
+
And the rest run is ended
|
34
|
+
Then the submitted results contains the provided details
|
35
|
+
Examples:
|
36
|
+
| Result Type |
|
37
|
+
| Cucumber Scenario Outline |
|
38
|
+
| Cucumber Simple Scenario |
|
39
|
+
| RSpec Example |
|
@@ -0,0 +1,127 @@
|
|
1
|
+
def setup_adaptor(enabled: true)
|
2
|
+
@test_suite = spy('test_suite')
|
3
|
+
@enabled = enabled
|
4
|
+
@adaptor = TestRail::Adaptor.new(
|
5
|
+
enabled: @enabled,
|
6
|
+
url: 'fakeurl',
|
7
|
+
username: 'username',
|
8
|
+
password: 'password',
|
9
|
+
project_id: 'project_id',
|
10
|
+
suite_id: 'suite_id',
|
11
|
+
test_suite: @test_suite
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_test_result(type, test_case_result: true)
|
16
|
+
result_class = double('result_class')
|
17
|
+
test_result = double('test_result')
|
18
|
+
|
19
|
+
@test_case_section = 'test_case_section'
|
20
|
+
@test_case_name = 'test_case_name'
|
21
|
+
@test_case_comment = 'test_case_comment'
|
22
|
+
|
23
|
+
case type
|
24
|
+
when 'Cucumber Scenario Outline'
|
25
|
+
class_name = 'Cucumber::RunningTestCase::ScenarioOutlineExample'
|
26
|
+
scenario_outline = double('scenario_outline')
|
27
|
+
feature = double('feature')
|
28
|
+
|
29
|
+
allow(test_result).to receive(:scenario_outline) { scenario_outline }
|
30
|
+
allow(test_result).to receive(:failed?) { !test_case_result }
|
31
|
+
allow(test_result).to receive(:exception) { @test_case_comment }
|
32
|
+
allow(scenario_outline).to receive(:feature) { feature }
|
33
|
+
allow(scenario_outline).to receive(:name) { @test_case_name }
|
34
|
+
allow(feature).to receive(:name) { @test_case_section }
|
35
|
+
when 'Cucumber Simple Scenario'
|
36
|
+
class_name = 'Cucumber::RunningTestCase::Scenario'
|
37
|
+
feature = double('feature')
|
38
|
+
|
39
|
+
allow(test_result).to receive(:feature) { feature }
|
40
|
+
allow(test_result).to receive(:name) { @test_case_name }
|
41
|
+
allow(test_result).to receive(:failed?) { !test_case_result }
|
42
|
+
allow(test_result).to receive(:exception) { @test_case_comment }
|
43
|
+
allow(feature).to receive(:name) { @test_case_section }
|
44
|
+
when 'RSpec Example'
|
45
|
+
class_name = 'RSpec::Core::Example'
|
46
|
+
example_group = double('example_group')
|
47
|
+
|
48
|
+
allow(test_result).to receive(:example_group) { example_group }
|
49
|
+
allow(test_result).to receive(:description) { @test_case_name }
|
50
|
+
if test_case_result
|
51
|
+
allow(test_result).to receive(:exception) { nil }
|
52
|
+
@test_case_comment = nil
|
53
|
+
else
|
54
|
+
allow(test_result).to receive(:exception) { @test_case_comment }
|
55
|
+
end
|
56
|
+
allow(example_group).to receive(:description) { @test_case_section }
|
57
|
+
end
|
58
|
+
|
59
|
+
allow(test_result).to receive(:class) { result_class }
|
60
|
+
allow(result_class).to receive(:name) { class_name }
|
61
|
+
test_result
|
62
|
+
end
|
63
|
+
|
64
|
+
Given(/^an Adaptor$/) do
|
65
|
+
setup_adaptor
|
66
|
+
end
|
67
|
+
|
68
|
+
When(/^a test run is started$/) do
|
69
|
+
@test_run = spy('test_run')
|
70
|
+
allow(@test_suite).to receive(:start_test_run) { @test_run } if @enabled
|
71
|
+
@adaptor.start_test_run
|
72
|
+
end
|
73
|
+
|
74
|
+
Then(/^the test suite starts a test run$/) do
|
75
|
+
expect(@test_suite).to have_received(:start_test_run) if @enabled
|
76
|
+
end
|
77
|
+
|
78
|
+
When(/^the rest run is ended$/) do
|
79
|
+
if @enabled
|
80
|
+
@failure_count = @failure_count ||= 0
|
81
|
+
allow(@test_run).to receive(:submit_results)
|
82
|
+
allow(@test_run).to receive(:failure_count) { @failure_count }
|
83
|
+
end
|
84
|
+
@adaptor.end_test_run
|
85
|
+
end
|
86
|
+
|
87
|
+
Then(/^the test suite submit the results$/) do
|
88
|
+
expect(@test_run).to have_received(:submit_results)
|
89
|
+
end
|
90
|
+
|
91
|
+
Then(/^the test suite is closed$/) do
|
92
|
+
expect(@test_run).to have_received(:close)
|
93
|
+
end
|
94
|
+
|
95
|
+
Given(/^an invalid test result is submitted$/) do
|
96
|
+
@failure_count = 1
|
97
|
+
end
|
98
|
+
|
99
|
+
Then(/^the test suite is not closed$/) do
|
100
|
+
expect(@test_run).to_not have_received(:close)
|
101
|
+
end
|
102
|
+
|
103
|
+
Given(/^a disabled Adaptor$/) do
|
104
|
+
setup_adaptor(enabled: false)
|
105
|
+
end
|
106
|
+
|
107
|
+
Then(/^no interactions are made to the test suite$/) do
|
108
|
+
expect(@test_run).to_not have_received(:submit_results)
|
109
|
+
expect(@test_run).to_not have_received(:failure_count)
|
110
|
+
expect(@test_run).to_not have_received(:close)
|
111
|
+
end
|
112
|
+
|
113
|
+
When(/^a result of type "([^"]*)" is submitted$/) do |result_type|
|
114
|
+
@test_result = create_test_result(result_type)
|
115
|
+
allow(@test_run).to receive(:add_test_result)
|
116
|
+
@adaptor.submit(@test_result)
|
117
|
+
end
|
118
|
+
|
119
|
+
Then(/^the submitted results contains the provided details/) do
|
120
|
+
expect(@test_run).to have_received(:submit_results)
|
121
|
+
expect(@test_run).to have_received(:add_test_result).with({
|
122
|
+
section_name: @test_case_section,
|
123
|
+
test_name: @test_case_name,
|
124
|
+
success: true,
|
125
|
+
comment: @test_case_comment
|
126
|
+
})
|
127
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'testrail/api_client'
|
2
|
+
require 'testrail/testrail_client'
|
3
|
+
|
4
|
+
module TestRail
|
5
|
+
|
6
|
+
class Adaptor
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
enabled: false,
|
10
|
+
test_suite: nil,
|
11
|
+
url:,
|
12
|
+
username:,
|
13
|
+
password:,
|
14
|
+
project_id:,
|
15
|
+
suite_id:
|
16
|
+
)
|
17
|
+
@enabled = enabled
|
18
|
+
return unless @enabled
|
19
|
+
if test_suite.nil?
|
20
|
+
testrail_client = TestRail::APIClient.new(url)
|
21
|
+
testrail_client.user = username
|
22
|
+
testrail_client.password = password
|
23
|
+
@test_suite = TestRail::TestRailClient.new(testrail_client).get_suite(
|
24
|
+
project_id: project_id,
|
25
|
+
suite_id: suite_id
|
26
|
+
)
|
27
|
+
else
|
28
|
+
@test_suite = test_suite
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Submits an example test results
|
33
|
+
# If the test case exists, it will reuse the id, otherwise it will create a new Test Case in TestRails
|
34
|
+
# @param example [Example] A test case example after execution
|
35
|
+
def submit(example)
|
36
|
+
return unless @enabled
|
37
|
+
case example.class.name
|
38
|
+
when 'Cucumber::RunningTestCase::ScenarioOutlineExample'
|
39
|
+
test_case_section = example.scenario_outline.feature.name
|
40
|
+
test_case_section.strip!
|
41
|
+
|
42
|
+
test_case_name = example.scenario_outline.name
|
43
|
+
test_case_name.strip!
|
44
|
+
|
45
|
+
test_result = !example.failed?
|
46
|
+
test_comment = example.exception
|
47
|
+
when 'Cucumber::RunningTestCase::Scenario'
|
48
|
+
test_case_section = example.feature.name
|
49
|
+
test_case_section.strip!
|
50
|
+
|
51
|
+
test_case_name = example.name
|
52
|
+
test_case_name.strip!
|
53
|
+
|
54
|
+
test_result = !example.failed?
|
55
|
+
test_comment = example.exception
|
56
|
+
when 'RSpec::Core::Example'
|
57
|
+
test_case_section = example.example_group.description
|
58
|
+
test_case_section.strip!
|
59
|
+
|
60
|
+
test_case_name = example.description
|
61
|
+
test_case_name.strip!
|
62
|
+
|
63
|
+
test_result = example.exception.nil?
|
64
|
+
test_comment = example.exception
|
65
|
+
end
|
66
|
+
|
67
|
+
@test_run.add_test_result(
|
68
|
+
section_name: test_case_section,
|
69
|
+
test_name: test_case_name,
|
70
|
+
success: test_result,
|
71
|
+
comment: test_comment)
|
72
|
+
end
|
73
|
+
|
74
|
+
# This method initiates a test run against a project, and specified testsuite.
|
75
|
+
# ruby functional test file (.rb) containing a range of rspec test cases.
|
76
|
+
# Each rspec test case (in the ruby functional test file) will have a corresponding Test Case in TestRail.
|
77
|
+
# These Test Rail test cases will belong to a test suite that has the title of the corresponding
|
78
|
+
# ruby functional test file.
|
79
|
+
def start_test_run
|
80
|
+
return unless @enabled
|
81
|
+
@test_run = @test_suite.start_test_run
|
82
|
+
end
|
83
|
+
|
84
|
+
# Checks to see if any of the tests in a particular test run have failed, if they have then the
|
85
|
+
# it will leave the run opened. If there are no failed tests then it will call close the particular run.
|
86
|
+
def end_test_run
|
87
|
+
return if !@enabled || @test_run.nil?
|
88
|
+
@test_run.submit_results
|
89
|
+
@test_run.close unless @test_run.failure_count > 0
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
#
|
2
|
+
# TestRail API binding for Ruby (API v2, available since TestRail 3.0)
|
3
|
+
#
|
4
|
+
# Learn more:
|
5
|
+
#
|
6
|
+
# http://docs.gurock.com/testrail-api2/start
|
7
|
+
# http://docs.gurock.com/testrail-api2/accessing
|
8
|
+
#
|
9
|
+
# Copyright Gurock Software GmbH. See TESTRAIL_LICENSE.md for details.
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'net/http'
|
13
|
+
require 'net/https'
|
14
|
+
require 'uri'
|
15
|
+
require 'json'
|
16
|
+
|
17
|
+
module TestRail
|
18
|
+
|
19
|
+
class APIClient
|
20
|
+
|
21
|
+
@url = ''
|
22
|
+
@user = ''
|
23
|
+
@password = ''
|
24
|
+
|
25
|
+
attr_accessor :user
|
26
|
+
attr_accessor :password
|
27
|
+
|
28
|
+
def initialize(base_url)
|
29
|
+
base_url += base_url =~ %r{/$} ? '/' : ''
|
30
|
+
@url = base_url + 'index.php?/api/v2/'
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Send Get
|
35
|
+
#
|
36
|
+
# Issues a GET request (read) against the API and returns the result
|
37
|
+
# (as Ruby hash).
|
38
|
+
#
|
39
|
+
# Arguments:
|
40
|
+
#
|
41
|
+
# uri The API method to call including parameters
|
42
|
+
# (e.g. get_case/1)
|
43
|
+
#
|
44
|
+
def send_get(uri)
|
45
|
+
_send_request('GET', uri, nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Send POST
|
50
|
+
#
|
51
|
+
# Issues a POST request (write) against the API and returns the result
|
52
|
+
# (as Ruby hash).
|
53
|
+
#
|
54
|
+
# Arguments:
|
55
|
+
#
|
56
|
+
# uri The API method to call including parameters
|
57
|
+
# (e.g. add_case/1)
|
58
|
+
# data The data to submit as part of the request (as
|
59
|
+
# Ruby hash, strings must be UTF-8 encoded)
|
60
|
+
#
|
61
|
+
def send_post(uri, data)
|
62
|
+
_send_request('POST', uri, data)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def _secure_channel(conn, url)
|
68
|
+
return unless url.scheme == 'https'
|
69
|
+
conn.use_ssl = true
|
70
|
+
conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
71
|
+
end
|
72
|
+
|
73
|
+
def _get_result(response)
|
74
|
+
result = if response.body && !response.body.empty?
|
75
|
+
JSON.parse(response.body)
|
76
|
+
else
|
77
|
+
{}
|
78
|
+
end
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def _send_request(method, uri, data)
|
83
|
+
url = URI.parse(@url + uri)
|
84
|
+
if method == 'POST'
|
85
|
+
request = Net::HTTP::Post.new(url.path + '?' + url.query)
|
86
|
+
request.body = JSON.dump(data)
|
87
|
+
else
|
88
|
+
request = Net::HTTP::Get.new(url.path + '?' + url.query)
|
89
|
+
end
|
90
|
+
|
91
|
+
request.basic_auth(@user, @password)
|
92
|
+
request.add_field('Content-Type', 'application/json')
|
93
|
+
|
94
|
+
conn = Net::HTTP.new(url.host, url.port)
|
95
|
+
_secure_channel(conn, url)
|
96
|
+
|
97
|
+
response = conn.request(request)
|
98
|
+
|
99
|
+
result = _get_result(response)
|
100
|
+
|
101
|
+
if response.code != '200'
|
102
|
+
error = if result && result.key?('error')
|
103
|
+
'"' + result['error'] + '"'
|
104
|
+
else
|
105
|
+
'No additional error message received'
|
106
|
+
end
|
107
|
+
raise APIError.new, "TestRail API returned HTTP #{response.code} (#{error})"
|
108
|
+
end
|
109
|
+
|
110
|
+
result
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
class APIError < StandardError
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'testrail/test_result'
|
2
|
+
|
3
|
+
module TestRail
|
4
|
+
|
5
|
+
class TestCase
|
6
|
+
|
7
|
+
attr_reader :id, :name, :section
|
8
|
+
|
9
|
+
def initialize(id:, name:, section:, testrail_client:)
|
10
|
+
raise(ArgumentError, 'test case id nil') if id.nil?
|
11
|
+
raise(ArgumentError, 'test case name nil') if name.nil?
|
12
|
+
@id = id
|
13
|
+
@name = name
|
14
|
+
@section = section
|
15
|
+
@testrail_client = testrail_client
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_result(success:, comment:)
|
19
|
+
TestResult.new(test_case: self, success: success, comment: comment)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module TestRail
|
2
|
+
|
3
|
+
class TestResult
|
4
|
+
|
5
|
+
STATUS_SUCCESS = 1
|
6
|
+
STATUS_ERROR = 5
|
7
|
+
|
8
|
+
attr_reader :comment
|
9
|
+
attr_reader :success
|
10
|
+
alias success? success
|
11
|
+
|
12
|
+
def initialize(test_case:, success:, comment:)
|
13
|
+
@test_case = test_case
|
14
|
+
@success = success
|
15
|
+
@comment = comment
|
16
|
+
end
|
17
|
+
|
18
|
+
def status_id
|
19
|
+
success? ? STATUS_SUCCESS : STATUS_ERROR
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
{
|
24
|
+
'case_id': @test_case.id,
|
25
|
+
'status_id': status_id,
|
26
|
+
'comment': comment
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module TestRail
|
2
|
+
|
3
|
+
class TestRun
|
4
|
+
|
5
|
+
def initialize(suite:, id:)
|
6
|
+
@suite = suite
|
7
|
+
@id = id
|
8
|
+
@results = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_test_result(section_name:, test_name:, success:, comment: nil)
|
12
|
+
@results << @suite
|
13
|
+
.get_or_create_section(section_name)
|
14
|
+
.get_or_create_test_case(test_name)
|
15
|
+
.create_result(success: success, comment: comment)
|
16
|
+
end
|
17
|
+
|
18
|
+
def submit_results
|
19
|
+
@suite.submit_test_results(run_id: @id, results: @results)
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
@suite.close_test_run(@id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def failure_count
|
27
|
+
@results.count { |r| !r.success? }
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module TestRail
|
2
|
+
|
3
|
+
class TestSection
|
4
|
+
|
5
|
+
attr_reader :id, :name
|
6
|
+
|
7
|
+
def initialize(id:, name:, test_suite:)
|
8
|
+
raise(ArgumentError, 'section id nil') if id.nil?
|
9
|
+
raise(ArgumentError, 'section name nil') if name.nil?
|
10
|
+
@id = id
|
11
|
+
@name = name
|
12
|
+
@test_suite = test_suite
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_or_create_test_case(name)
|
16
|
+
@test_suite.get_or_create_test_case(section_id: @id, name: name)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'testrail/test_run'
|
2
|
+
require 'testrail/test_section'
|
3
|
+
require 'testrail/test_case'
|
4
|
+
|
5
|
+
module TestRail
|
6
|
+
|
7
|
+
class TestSuite
|
8
|
+
|
9
|
+
def initialize(project_id:, suite_id:, testrail_client:)
|
10
|
+
@project_id = project_id
|
11
|
+
@suite_id = suite_id
|
12
|
+
@testrail_client = testrail_client
|
13
|
+
sections = testrail_client.get_sections(project_id: project_id, suite_id: suite_id)
|
14
|
+
.map { |s| new_test_section(s) }
|
15
|
+
@sections_by_name = Hash[sections.map { |s| [s.name, s] }]
|
16
|
+
@sections_by_id = Hash[sections.map { |s| [s.id, s] }]
|
17
|
+
@test_cases = Hash[testrail_client.get_test_cases(project_id: project_id, suite_id: suite_id)
|
18
|
+
.lazy
|
19
|
+
.map { |t| new_test_case(t) }
|
20
|
+
.map { |t| [test_case_key(t.section.id, t.name), t] }
|
21
|
+
.to_a]
|
22
|
+
end
|
23
|
+
|
24
|
+
def start_test_run
|
25
|
+
run = @testrail_client.start_test_run(project_id: @project_id, suite_id: @suite_id)
|
26
|
+
TestRun.new(suite: self, id: run['id'])
|
27
|
+
end
|
28
|
+
|
29
|
+
def submit_test_results(run_id:, results:)
|
30
|
+
@testrail_client.submit_test_results(run_id: run_id, results: results.map(&:to_hash))
|
31
|
+
end
|
32
|
+
|
33
|
+
def close_test_run(run_id)
|
34
|
+
@testrail_client.close_test_run(run_id)
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_or_create_section(section_name)
|
38
|
+
@sections_by_name[section_name] || create_section(section_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_or_create_test_case(section_id:, name:)
|
42
|
+
@test_cases[test_case_key(section_id, name)] || create_test_case(section_id: section_id, name: name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_section(section_name)
|
46
|
+
section = new_test_section(@testrail_client.create_section(
|
47
|
+
project_id: @project_id,
|
48
|
+
suite_id: @suite_id,
|
49
|
+
section_name: section_name))
|
50
|
+
@sections_by_name[section_name] = section
|
51
|
+
@sections_by_id[section.id] = section
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_test_case(section_id:, name:)
|
55
|
+
test_case = new_test_case(@testrail_client.create_test_case(
|
56
|
+
section_id: section_id,
|
57
|
+
name: name))
|
58
|
+
@test_cases[test_case_key(test_case.section.id, test_case.name)] = test_case
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def test_case_key(section_id, name)
|
64
|
+
{ s: section_id, n: name }
|
65
|
+
end
|
66
|
+
|
67
|
+
def new_test_section(section)
|
68
|
+
TestSection.new(
|
69
|
+
id: section['id'],
|
70
|
+
name: section['name'],
|
71
|
+
test_suite: self)
|
72
|
+
end
|
73
|
+
|
74
|
+
def new_test_case(test_case)
|
75
|
+
TestCase.new(
|
76
|
+
id: test_case['id'],
|
77
|
+
name: test_case['title'],
|
78
|
+
section: @sections_by_id[test_case['section_id']],
|
79
|
+
testrail_client: @testrail_client)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'testrail/test_suite'
|
2
|
+
|
3
|
+
module TestRail
|
4
|
+
|
5
|
+
class TestRailClient
|
6
|
+
|
7
|
+
def initialize(testrail_http_client)
|
8
|
+
@testrail_http_client = testrail_http_client
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_suite(project_id:, suite_id:)
|
12
|
+
TestSuite.new(
|
13
|
+
project_id: project_id,
|
14
|
+
suite_id: suite_id,
|
15
|
+
testrail_client: self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def start_test_run(project_id:, suite_id:)
|
19
|
+
@testrail_http_client.send_post("add_run/#{project_id}",
|
20
|
+
suite_id: suite_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
def close_test_run(run_id)
|
24
|
+
@testrail_http_client.send_post("close_run/#{run_id}", {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_test_case(section_id:, name:)
|
28
|
+
@testrail_http_client.send_post("add_case/#{section_id}",
|
29
|
+
title: name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_section(project_id:, suite_id:, section_name:)
|
33
|
+
@testrail_http_client.send_post("add_section/#{project_id}",
|
34
|
+
suite_id: suite_id,
|
35
|
+
name: section_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_sections(project_id:, suite_id:)
|
39
|
+
@testrail_http_client.send_get("get_sections/#{project_id}\&suite_id=#{suite_id}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_test_cases(project_id:, suite_id:)
|
43
|
+
@testrail_http_client.send_get("get_cases/#{project_id}&suite_id=#{suite_id}")
|
44
|
+
end
|
45
|
+
|
46
|
+
def submit_test_result(run_id:, test_case_id:, status_id:, comment: nil)
|
47
|
+
@testrail_http_client.send_post("add_result_for_case/#{run_id}/#{test_case_id}",
|
48
|
+
status_id: status_id,
|
49
|
+
comment: comment)
|
50
|
+
end
|
51
|
+
|
52
|
+
def submit_test_results(run_id:, results:)
|
53
|
+
@testrail_http_client.send_post("add_results_for_cases/#{run_id}", { results: results })
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cucumber-testrail
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Javier Durante
|
8
|
+
- Will Gauvin
|
9
|
+
- Nathan Jones
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2016-04-26 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '3.0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: pry
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
type: :development
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: rspec-core
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: rspec-expectations
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rspec-mocks
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rspec-support
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: require_all
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
description: Library to integrate Test Suite with TestRail
|
114
|
+
email: mercury@findly.com
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".rubocop.yml"
|
120
|
+
- ".travis.yml"
|
121
|
+
- Dockerfile
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE.md
|
124
|
+
- README.md
|
125
|
+
- TESTRAIL_LICENSE.md
|
126
|
+
- cucumber_testrail.gemspec
|
127
|
+
- deploy.sh
|
128
|
+
- features/docs/testrail/adaptor.feature
|
129
|
+
- features/lib/step_definitions/testrail/adaptor.rb
|
130
|
+
- features/lib/support/env.rb
|
131
|
+
- features/lib/support/hooks.rb
|
132
|
+
- lib/testrail/adaptor.rb
|
133
|
+
- lib/testrail/api_client.rb
|
134
|
+
- lib/testrail/test_case.rb
|
135
|
+
- lib/testrail/test_result.rb
|
136
|
+
- lib/testrail/test_run.rb
|
137
|
+
- lib/testrail/test_section.rb
|
138
|
+
- lib/testrail/test_suite.rb
|
139
|
+
- lib/testrail/testrail_client.rb
|
140
|
+
homepage: https://github.com/Findly-Inc/cucumber-testrail
|
141
|
+
licenses:
|
142
|
+
- Apache-2.0
|
143
|
+
metadata: {}
|
144
|
+
post_install_message:
|
145
|
+
rdoc_options: []
|
146
|
+
require_paths:
|
147
|
+
- lib
|
148
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
requirements: []
|
159
|
+
rubyforge_project:
|
160
|
+
rubygems_version: 2.4.5
|
161
|
+
signing_key:
|
162
|
+
specification_version: 4
|
163
|
+
summary: Cucumber TestRail integration
|
164
|
+
test_files: []
|