cucumber-testrail 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'rubocop'
5
+ gem 'cucumber'
@@ -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.
@@ -0,0 +1,60 @@
1
+ ###Status
2
+ [![Build Status](https://travis-ci.org/Findly-Inc/cucumber-testrail.png)](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.
@@ -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
@@ -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,10 @@
1
+ require 'require_all'
2
+ require 'rspec'
3
+ require 'rspec/core'
4
+ require 'rspec/expectations'
5
+ require 'rspec/mocks'
6
+ require 'rspec/support'
7
+
8
+ require_all('lib')
9
+
10
+ World(RSpec::Mocks::ExampleMethods)
@@ -0,0 +1,11 @@
1
+ Before do
2
+ RSpec::Mocks.setup
3
+ end
4
+
5
+ After do
6
+ begin
7
+ RSpec::Mocks.verify
8
+ ensure
9
+ RSpec::Mocks.teardown
10
+ end
11
+ 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: []