ruby-testrail 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OGQ3MDc4NzM4YjdmOWRlZGY3ZjZiZjVlYjU3YzVlY2QwNTliZjUxZg==
5
+ data.tar.gz: !binary |-
6
+ MmVmOThiYzE4NWYwZTg0NDUwZDQ1ZWY0NjMzMTZiYjFkN2Y4NmVlZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MDZlNGE4ZTdlNzg1OWI4MTY3YmI5YjZlZWExZDE4MzIxZDI1MWEzNWYxM2Vj
10
+ MWUyYWM4NDE1YjQwNGU1NDkzZjg4ZWU4ZjQyMWY1M2Y3MTk4OWI1NWNkMjBh
11
+ MGJlYWZlYjk3ODA5Mjg5MTAxYzJmMzM2OWVjOGY2MTRjNGQyYTQ=
12
+ data.tar.gz: !binary |-
13
+ Y2FiMzhiZGRiOTgwZjA5MWI1MzhjMGFlYzFkNzU4ZWY3MTFmZGM2ZmEyOWJk
14
+ OTRhODBkNmJlNTNkYjljZjk0YWYxNzRkNzM4ZjdjNTg3NDdlMmEwMmRmN2U2
15
+ ZWVjNDg3NDFlOWRiYmEzODY3M2JjZDE1NDQxNGZiNTZiNjM0MzA=
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,15 @@
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
+ deploy:
11
+ provider: rubygems
12
+ api_key:
13
+ secure: DcF9uIbKdFzbKdz6xbYBbauG0dBV90i+HQRxpl41sz9hua/tfEkNtWCKa1A15xD4MhSkeKNkwwM3Axm/OA8Fp63nc9dHPTd3mcWwL0CmmKVAlolgbdHvTr04Vz0s1M9dV4w0XBhX/M/Vezi23MoHT2Z3B0YvYnbBVQEtIH+t5CPcY5tWXm/Dyz3J8CGhuO4oboW906K3MVBRqclz/njM3PXezNwOXrNGVyOnr94WTDXG857qzZnr2p1U1gRVCX7eyHIY6/pgxuejfcIkXS8c7WZ8tYuyc4xfcHGMdpHdFRRXuf7anpGikFPz2Qw2r2uaDhVAUzRgXjTF9JfYPPyDP3iZHVXa+G+jMHhXCCNPX85D4mfQz87okNH1PelRv2U9kZv3sxxtuIuOAwuKS+fWAc/dmhf7Q5PWROxGLzkwjbzqfQGz6Ia2jTvv+c4/1hyZLLctwf6Mq4E/XOqiU0ebjY77xhuMghtEscCp6D+HfD0p2GXiNbUfIPpczNZYZ2mv/kova7hExaldcrV0hE3y2OhxmxPEishjWm43wtoPXbpyK3w7Rm2mJXQk8OhwYpOh+OKg33GOBzI221KLnPvnip0vQ5Zw8FZuVH3ygyX4JA2WiqM2JKaqFTGzcNwMJdL6rDG61jKpVv7Hb8mO8zGWtew5FEwjdD6ypVtx5h4LqE4=
14
+ on:
15
+ tags: true
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'rubocop'
5
+ gem 'cucumber'
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,63 @@
1
+ ### Status
2
+ [![Build Status](https://travis-ci.org/Findly-Inc/ruby-testrail.png)](https://travis-ci.org/Findly-Inc/ruby-testrail)
3
+
4
+ ### Supported Ruby Version
5
+ 2.2
6
+
7
+ TestRail Integration Adaptor
8
+ ============================
9
+
10
+ The tool provides a way to integrate Cucumber/RSpec test suites with
11
+ TestRail using it's API.
12
+
13
+ The adaptor gets all the tests results in a cache so it doesn't make
14
+ https for each test. Instead, it sends a single API call with all the
15
+ results together. This avoid problems with the server throttling enforced
16
+ by the server.
17
+
18
+ ### Installation
19
+
20
+ Just include the gem in your Gemfile
21
+
22
+ ```ruby
23
+ gem 'ruby-testrail'
24
+ ```
25
+
26
+ ### Usage
27
+
28
+ Create a Test Adaptor with the required configuration
29
+
30
+ ```ruby
31
+ testrail_adaptor = TestRail::Adaptor.new(
32
+ enabled: flag, # Enable or Disable the TestRail runner(default: false)
33
+ url: url, # URL for custom TestRail Integration
34
+ username: username, # Authentication Username
35
+ password: password, # Authentication Password
36
+ project_id: project_id, # TestRail Project ID
37
+ suite_id: suite_id # TestRail Suite ID
38
+ )
39
+ ```
40
+
41
+ When the test suite is ready, start a test run
42
+
43
+ ```ruby
44
+ testrail_adaptor.start_test_run
45
+ ```
46
+
47
+ As an example, a Cucumber test suite is used to send results to the adaptor
48
+ Each scenario is being sent using the **submit** method:
49
+
50
+ ```ruby
51
+ After do |scenario|
52
+ ...
53
+ testrail_adaptor.submit(scenario)
54
+ ...
55
+ end
56
+
57
+ at_exit do
58
+ testrail_adaptor.end_test_run
59
+ end
60
+ ```
61
+
62
+ At the end of the test suite the adaptor needs to be finished to send the results
63
+ to TestRail. This is done with the **end_test_run** method.
@@ -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,45 @@
1
+ Feature: Test suite adaptor
2
+
3
+ Scenario: Start test run actually starts a test suite run
4
+ Given a Cucumber 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 a Cucumber 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 a Cucumber 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 Cucumber 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 Cucumber scenarios types
30
+ Given a Cucumber 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
+
40
+ Scenario: Submit supports RSpec examples
41
+ Given a RSpec Adaptor
42
+ And a test run is started
43
+ When a result of type "RSpec Example" is submitted
44
+ And the rest run is ended
45
+ Then the submitted results contains the provided details
@@ -0,0 +1,152 @@
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.
14
+
15
+ def setup_adaptor(enabled: true, type: 'Cucumber')
16
+ @test_suite = spy('test_suite')
17
+ @enabled = enabled
18
+ options = {
19
+ enabled: @enabled,
20
+ url: 'fakeurl',
21
+ username: 'username',
22
+ password: 'password',
23
+ project_id: 'project_id',
24
+ suite_id: 'suite_id',
25
+ test_suite: @test_suite
26
+ }
27
+ @adaptor = case type
28
+ when 'RSpec'
29
+ TestRail::RSpecAdaptor.new(options)
30
+ else
31
+ TestRail::CucumberAdaptor.new(options)
32
+ end
33
+ end
34
+
35
+ def create_test_result(type, test_case_result: true)
36
+ result_class = double('result_class')
37
+ test_result = double('test_result')
38
+
39
+ @test_case_section = 'test_case_section'
40
+ @test_case_name = 'test_case_name'
41
+ @test_case_comment = 'test_case_comment'
42
+
43
+ case type
44
+ when 'Cucumber Scenario Outline'
45
+ class_name = 'Cucumber::RunningTestCase::ScenarioOutlineExample'
46
+ scenario_outline = double('scenario_outline')
47
+ feature = double('feature')
48
+
49
+ allow(test_result).to receive(:scenario_outline) { scenario_outline }
50
+ allow(test_result).to receive(:failed?) { !test_case_result }
51
+ allow(test_result).to receive(:exception) { @test_case_comment }
52
+ allow(scenario_outline).to receive(:feature) { feature }
53
+ allow(scenario_outline).to receive(:name) { @test_case_name }
54
+ allow(feature).to receive(:name) { @test_case_section }
55
+ when 'Cucumber Simple Scenario'
56
+ class_name = 'Cucumber::RunningTestCase::Scenario'
57
+ feature = double('feature')
58
+
59
+ allow(test_result).to receive(:feature) { feature }
60
+ allow(test_result).to receive(:name) { @test_case_name }
61
+ allow(test_result).to receive(:failed?) { !test_case_result }
62
+ allow(test_result).to receive(:exception) { @test_case_comment }
63
+ allow(feature).to receive(:name) { @test_case_section }
64
+ when 'RSpec Example'
65
+ example_group = double('example_group')
66
+
67
+ allow(test_result).to receive(:example_group) { example_group }
68
+ allow(test_result).to receive(:description) { @test_case_name }
69
+ if test_case_result
70
+ allow(test_result).to receive(:exception) { nil }
71
+ @test_case_comment = nil
72
+ else
73
+ allow(test_result).to receive(:exception) { @test_case_comment }
74
+ end
75
+ allow(example_group).to receive(:description) { @test_case_section }
76
+ end
77
+
78
+ unless result_class.nil?
79
+ allow(test_result).to receive(:class) { result_class }
80
+ allow(result_class).to receive(:name) { class_name }
81
+ end
82
+ test_result
83
+ end
84
+
85
+ Given(/^a Cucumber Adaptor$/) do
86
+ setup_adaptor
87
+ end
88
+
89
+ Given(/^a RSpec Adaptor$/) do
90
+ setup_adaptor(type: 'RSpec')
91
+ end
92
+
93
+ When(/^a test run is started$/) do
94
+ @test_run = spy('test_run')
95
+ allow(@test_suite).to receive(:start_test_run) { @test_run } if @enabled
96
+ @adaptor.start_test_run
97
+ end
98
+
99
+ Then(/^the test suite starts a test run$/) do
100
+ expect(@test_suite).to have_received(:start_test_run) if @enabled
101
+ end
102
+
103
+ When(/^the rest run is ended$/) do
104
+ if @enabled
105
+ @failure_count = @failure_count ||= 0
106
+ allow(@test_run).to receive(:submit_results)
107
+ allow(@test_run).to receive(:failure_count) { @failure_count }
108
+ end
109
+ @adaptor.end_test_run
110
+ end
111
+
112
+ Then(/^the test suite submit the results$/) do
113
+ expect(@test_run).to have_received(:submit_results)
114
+ end
115
+
116
+ Then(/^the test suite is closed$/) do
117
+ expect(@test_run).to have_received(:close)
118
+ end
119
+
120
+ Given(/^an invalid test result is submitted$/) do
121
+ @failure_count = 1
122
+ end
123
+
124
+ Then(/^the test suite is not closed$/) do
125
+ expect(@test_run).to_not have_received(:close)
126
+ end
127
+
128
+ Given(/^a disabled Cucumber Adaptor$/) do
129
+ setup_adaptor(enabled: false)
130
+ end
131
+
132
+ Then(/^no interactions are made to the test suite$/) do
133
+ expect(@test_run).to_not have_received(:submit_results)
134
+ expect(@test_run).to_not have_received(:failure_count)
135
+ expect(@test_run).to_not have_received(:close)
136
+ end
137
+
138
+ When(/^a result of type "([^"]*)" is submitted$/) do |result_type|
139
+ @test_result = create_test_result(result_type)
140
+ allow(@test_run).to receive(:add_test_result)
141
+ @adaptor.submit(@test_result)
142
+ end
143
+
144
+ Then(/^the submitted results contains the provided details/) do
145
+ expect(@test_run).to have_received(:submit_results)
146
+ expect(@test_run).to have_received(:add_test_result).with({
147
+ section_name: @test_case_section,
148
+ test_name: @test_case_name,
149
+ success: true,
150
+ comment: @test_case_comment
151
+ })
152
+ end
@@ -0,0 +1,24 @@
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.
14
+
15
+ require 'require_all'
16
+ require 'rspec'
17
+ require 'rspec/core'
18
+ require 'rspec/expectations'
19
+ require 'rspec/mocks'
20
+ require 'rspec/support'
21
+
22
+ require_all('lib')
23
+
24
+ World(RSpec::Mocks::ExampleMethods)
@@ -0,0 +1,25 @@
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.
14
+
15
+ Before do
16
+ RSpec::Mocks.setup
17
+ end
18
+
19
+ After do
20
+ begin
21
+ RSpec::Mocks.verify
22
+ ensure
23
+ RSpec::Mocks.teardown
24
+ end
25
+ end
@@ -0,0 +1,73 @@
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.
14
+
15
+ require 'testrail/api_client'
16
+ require 'testrail/testrail_client'
17
+
18
+ module TestRail
19
+
20
+ class Adaptor
21
+
22
+ def initialize(
23
+ enabled: true,
24
+ test_suite: nil,
25
+ url:,
26
+ username:,
27
+ password:,
28
+ project_id:,
29
+ suite_id:
30
+ )
31
+ @enabled = enabled
32
+ return unless @enabled
33
+ if test_suite.nil?
34
+ testrail_client = TestRail::APIClient.new(url)
35
+ testrail_client.user = username
36
+ testrail_client.password = password
37
+ @test_suite = TestRail::TestRailClient.new(testrail_client).get_suite(
38
+ project_id: project_id,
39
+ suite_id: suite_id
40
+ )
41
+ else
42
+ @test_suite = test_suite
43
+ end
44
+ end
45
+
46
+ # A new test result is submitted to TestRails. The type of test depends on the Test Suite
47
+ # Each adaptor implementation should be able to determine the required information
48
+ # from the test provided as a parameter
49
+ def submit(_test)
50
+ raise 'submit should be overrided by Adaptor implementations'
51
+ end
52
+
53
+ # This method initiates a test run against a project, and specified testsuite.
54
+ # ruby functional test file (.rb) containing a range of test cases.
55
+ # Each test case (in the ruby functional test file) will have a corresponding Test Case in TestRail.
56
+ # These Test Rail test cases will belong to a test suite that has the title of the corresponding
57
+ # ruby functional test file.
58
+ def start_test_run
59
+ return unless @enabled
60
+ @test_run = @test_suite.start_test_run
61
+ end
62
+
63
+ # Checks to see if any of the tests in a particular test run have failed, if they have then the
64
+ # it will leave the run opened. If there are no failed tests then it will call close the particular run.
65
+ def end_test_run
66
+ return if !@enabled || @test_run.nil?
67
+ @test_run.submit_results
68
+ @test_run.close unless @test_run.failure_count > 0
69
+ end
70
+
71
+ end
72
+
73
+ 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,47 @@
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.
14
+
15
+ module TestRail
16
+
17
+ class CucumberAdaptor < Adaptor
18
+
19
+ # Submits an scenario test results
20
+ # If the test case exists, it will reuse the id, otherwise it will create a new Test Case in TestRails
21
+ # @param scenario [Cucumber::RunningTestCase::ScenarioOutlineExample|Cucumber::RunningTestCase::Scenario]
22
+ # A test case scenario after execution
23
+ def submit(scenario)
24
+ return unless @enabled
25
+ case scenario.class.name
26
+ when 'Cucumber::RunningTestCase::ScenarioOutlineExample'
27
+ test_case_section = scenario.scenario_outline.feature.name.strip
28
+ test_case_name = scenario.scenario_outline.name.strip
29
+ test_result = !scenario.failed?
30
+ test_comment = scenario.exception
31
+ when 'Cucumber::RunningTestCase::Scenario'
32
+ test_case_section = scenario.feature.name.strip
33
+ test_case_name = scenario.name.strip
34
+ test_result = !scenario.failed?
35
+ test_comment = scenario.exception
36
+ end
37
+
38
+ @test_run.add_test_result(
39
+ section_name: test_case_section,
40
+ test_name: test_case_name,
41
+ success: test_result,
42
+ comment: test_comment)
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,38 @@
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.
14
+
15
+ module TestRail
16
+
17
+ class RSpecAdaptor < Adaptor
18
+
19
+ # Submits an example test results
20
+ # If the test case exists, it will reuse the id, otherwise it will create a new Test Case in TestRails
21
+ # @param example [RSpec::Core::Example] A test case example after execution
22
+ def submit(example)
23
+ return unless @enabled
24
+ test_case_section = example.example_group.description.strip
25
+ test_case_name = example.description.strip
26
+ test_result = example.exception.nil?
27
+ test_comment = example.exception
28
+
29
+ @test_run.add_test_result(
30
+ section_name: test_case_section,
31
+ test_name: test_case_name,
32
+ success: test_result,
33
+ comment: test_comment)
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,38 @@
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.
14
+
15
+ require 'testrail/test_result'
16
+
17
+ module TestRail
18
+
19
+ class TestCase
20
+
21
+ attr_reader :id, :name, :section
22
+
23
+ def initialize(id:, name:, section:, testrail_client:)
24
+ raise(ArgumentError, 'test case id nil') if id.nil?
25
+ raise(ArgumentError, 'test case name nil') if name.nil?
26
+ @id = id
27
+ @name = name
28
+ @section = section
29
+ @testrail_client = testrail_client
30
+ end
31
+
32
+ def create_result(success:, comment:)
33
+ TestResult.new(test_case: self, success: success, comment: comment)
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,46 @@
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.
14
+
15
+ module TestRail
16
+
17
+ class TestResult
18
+
19
+ STATUS_SUCCESS = 1
20
+ STATUS_ERROR = 5
21
+
22
+ attr_reader :comment
23
+ attr_reader :success
24
+ alias success? success
25
+
26
+ def initialize(test_case:, success:, comment:)
27
+ @test_case = test_case
28
+ @success = success
29
+ @comment = comment
30
+ end
31
+
32
+ def status_id
33
+ success? ? STATUS_SUCCESS : STATUS_ERROR
34
+ end
35
+
36
+ def to_hash
37
+ {
38
+ 'case_id': @test_case.id,
39
+ 'status_id': status_id,
40
+ 'comment': comment
41
+ }
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,46 @@
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.
14
+
15
+ module TestRail
16
+
17
+ class TestRun
18
+
19
+ def initialize(suite:, id:)
20
+ @suite = suite
21
+ @id = id
22
+ @results = []
23
+ end
24
+
25
+ def add_test_result(section_name:, test_name:, success:, comment: nil)
26
+ @results << @suite
27
+ .get_or_create_section(section_name)
28
+ .get_or_create_test_case(test_name)
29
+ .create_result(success: success, comment: comment)
30
+ end
31
+
32
+ def submit_results
33
+ @suite.submit_test_results(run_id: @id, results: @results)
34
+ end
35
+
36
+ def close
37
+ @suite.close_test_run(@id)
38
+ end
39
+
40
+ def failure_count
41
+ @results.count { |r| !r.success? }
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,35 @@
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.
14
+
15
+ module TestRail
16
+
17
+ class TestSection
18
+
19
+ attr_reader :id, :name
20
+
21
+ def initialize(id:, name:, test_suite:)
22
+ raise(ArgumentError, 'section id nil') if id.nil?
23
+ raise(ArgumentError, 'section name nil') if name.nil?
24
+ @id = id
25
+ @name = name
26
+ @test_suite = test_suite
27
+ end
28
+
29
+ def get_or_create_test_case(name)
30
+ @test_suite.get_or_create_test_case(section_id: @id, name: name)
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,98 @@
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.
14
+
15
+ require 'testrail/test_run'
16
+ require 'testrail/test_section'
17
+ require 'testrail/test_case'
18
+
19
+ module TestRail
20
+
21
+ class TestSuite
22
+
23
+ def initialize(project_id:, suite_id:, testrail_client:)
24
+ @project_id = project_id
25
+ @suite_id = suite_id
26
+ @testrail_client = testrail_client
27
+ sections = testrail_client.get_sections(project_id: project_id, suite_id: suite_id)
28
+ .map { |s| new_test_section(s) }
29
+ @sections_by_name = Hash[sections.map { |s| [s.name, s] }]
30
+ @sections_by_id = Hash[sections.map { |s| [s.id, s] }]
31
+ @test_cases = Hash[testrail_client.get_test_cases(project_id: project_id, suite_id: suite_id)
32
+ .lazy
33
+ .map { |t| new_test_case(t) }
34
+ .map { |t| [test_case_key(t.section.id, t.name), t] }
35
+ .to_a]
36
+ end
37
+
38
+ def start_test_run
39
+ run = @testrail_client.start_test_run(project_id: @project_id, suite_id: @suite_id)
40
+ TestRun.new(suite: self, id: run['id'])
41
+ end
42
+
43
+ def submit_test_results(run_id:, results:)
44
+ @testrail_client.submit_test_results(run_id: run_id, results: results.map(&:to_hash))
45
+ end
46
+
47
+ def close_test_run(run_id)
48
+ @testrail_client.close_test_run(run_id)
49
+ end
50
+
51
+ def get_or_create_section(section_name)
52
+ @sections_by_name[section_name] || create_section(section_name)
53
+ end
54
+
55
+ def get_or_create_test_case(section_id:, name:)
56
+ @test_cases[test_case_key(section_id, name)] || create_test_case(section_id: section_id, name: name)
57
+ end
58
+
59
+ def create_section(section_name)
60
+ section = new_test_section(@testrail_client.create_section(
61
+ project_id: @project_id,
62
+ suite_id: @suite_id,
63
+ section_name: section_name))
64
+ @sections_by_name[section_name] = section
65
+ @sections_by_id[section.id] = section
66
+ end
67
+
68
+ def create_test_case(section_id:, name:)
69
+ test_case = new_test_case(@testrail_client.create_test_case(
70
+ section_id: section_id,
71
+ name: name))
72
+ @test_cases[test_case_key(test_case.section.id, test_case.name)] = test_case
73
+ end
74
+
75
+ private
76
+
77
+ def test_case_key(section_id, name)
78
+ { s: section_id, n: name }
79
+ end
80
+
81
+ def new_test_section(section)
82
+ TestSection.new(
83
+ id: section['id'],
84
+ name: section['name'],
85
+ test_suite: self)
86
+ end
87
+
88
+ def new_test_case(test_case)
89
+ TestCase.new(
90
+ id: test_case['id'],
91
+ name: test_case['title'],
92
+ section: @sections_by_id[test_case['section_id']],
93
+ testrail_client: @testrail_client)
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -0,0 +1,72 @@
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.
14
+
15
+ require 'testrail/test_suite'
16
+
17
+ module TestRail
18
+
19
+ class TestRailClient
20
+
21
+ def initialize(testrail_http_client)
22
+ @testrail_http_client = testrail_http_client
23
+ end
24
+
25
+ def get_suite(project_id:, suite_id:)
26
+ TestSuite.new(
27
+ project_id: project_id,
28
+ suite_id: suite_id,
29
+ testrail_client: self)
30
+ end
31
+
32
+ def start_test_run(project_id:, suite_id:)
33
+ @testrail_http_client.send_post("add_run/#{project_id}",
34
+ suite_id: suite_id)
35
+ end
36
+
37
+ def close_test_run(run_id)
38
+ @testrail_http_client.send_post("close_run/#{run_id}", {})
39
+ end
40
+
41
+ def create_test_case(section_id:, name:)
42
+ @testrail_http_client.send_post("add_case/#{section_id}",
43
+ title: name)
44
+ end
45
+
46
+ def create_section(project_id:, suite_id:, section_name:)
47
+ @testrail_http_client.send_post("add_section/#{project_id}",
48
+ suite_id: suite_id,
49
+ name: section_name)
50
+ end
51
+
52
+ def get_sections(project_id:, suite_id:)
53
+ @testrail_http_client.send_get("get_sections/#{project_id}\&suite_id=#{suite_id}")
54
+ end
55
+
56
+ def get_test_cases(project_id:, suite_id:)
57
+ @testrail_http_client.send_get("get_cases/#{project_id}&suite_id=#{suite_id}")
58
+ end
59
+
60
+ def submit_test_result(run_id:, test_case_id:, status_id:, comment: nil)
61
+ @testrail_http_client.send_post("add_result_for_case/#{run_id}/#{test_case_id}",
62
+ status_id: status_id,
63
+ comment: comment)
64
+ end
65
+
66
+ def submit_test_results(run_id:, results:)
67
+ @testrail_http_client.send_post("add_results_for_cases/#{run_id}", { results: results })
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'ruby-testrail'
3
+ spec.version = '1.1.0'
4
+ spec.date = '2016-04-26'
5
+ spec.summary = 'Ruby TestRail integration with RSpec and Cucumber Test Suites'
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/ruby-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
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-testrail
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
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
+ - Gemfile
122
+ - LICENSE.md
123
+ - README.md
124
+ - TESTRAIL_LICENSE.md
125
+ - features/docs/testrail/adaptor.feature
126
+ - features/lib/step_definitions/testrail/adaptor.rb
127
+ - features/lib/support/env.rb
128
+ - features/lib/support/hooks.rb
129
+ - lib/testrail/adaptor.rb
130
+ - lib/testrail/api_client.rb
131
+ - lib/testrail/cucumber_adaptor.rb
132
+ - lib/testrail/rspec_adaptor.rb
133
+ - lib/testrail/test_case.rb
134
+ - lib/testrail/test_result.rb
135
+ - lib/testrail/test_run.rb
136
+ - lib/testrail/test_section.rb
137
+ - lib/testrail/test_suite.rb
138
+ - lib/testrail/testrail_client.rb
139
+ - ruby-testrail.gemspec
140
+ homepage: https://github.com/Findly-Inc/ruby-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: Ruby TestRail integration with RSpec and Cucumber Test Suites
164
+ test_files: []