test_linker 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.*
3
+ LICENSE.rdoc
data/.gemtest ADDED
File without changes
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --markup rdoc
2
+ --title "test_linker Documentation"
3
+ --protected
4
+ --private
data/ChangeLog.rdoc ADDED
@@ -0,0 +1,8 @@
1
+ === 0.1.0 / 2011-03-24
2
+
3
+ * Initial release:
4
+ * Basic wrapper around existing XMLRPC functions.
5
+ * Allow for calling methods via Ruby style (#projects) or XMLRPC style (#getProjects)
6
+ * Support for TestLink API versions 1.0 Beta 5 and 1.0
7
+ * Only one error/exception type: TestLinkClient::Error
8
+ * Limited set of helper methods, attempting to fill in gaps from the API
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+ gem 'versionomy', '~> 0.4.0'
5
+
6
+ group :development do
7
+ gem 'cucumber', '~> 0.10.0'
8
+ gem 'rake', '~> 0.8.7'
9
+ gem 'ore', '~> 0.7.2'
10
+ gem 'ore-core', '~> 0.1.4'
11
+ gem 'ore-tasks', '~> 0.5.0'
12
+ gem 'rspec', '~> 2.5'
13
+ gem 'simplecov', '>= 0.4.0', :require => false
14
+ gem 'jeweler', '~> 1.5.0'
15
+ gem 'yard', '~> 0.6.0'
16
+ end
data/LICENSE.rdoc ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 sloveless
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,128 @@
1
+ = test_linker
2
+
3
+ * {Homepage}[http://rubygems.org/gems/test_linker]
4
+ * {Documentation}[http://rubydoc.info/gems/test_linker/frames]
5
+ * {TestLink API Documentation}[http://testlink.org/api/phpdoc_generated/TestlinkAPI/TestlinkXMLRPCServer.html]
6
+
7
+ == Description
8
+
9
+ This is a Ruby wrapper around the TestLink XMLRPC API, thus allowing access to
10
+ your TestLink test projects, plans, cases, and results using Ruby. We've added
11
+ a few helper methods as well to allow for getting at more of your data a little
12
+ easier. This supports TestLink APIs 1.0 Beta 5 (from TestLink 1.8.x) and 1.0
13
+ (from TestLink 1.9.x).
14
+
15
+ == Features
16
+
17
+ * Basic wrapper around existing XMLRPC functions.
18
+ * Allow for calling methods via Ruby style (#projects) or XMLRPC style (#getProjects)
19
+ * Support for TestLink API versions 1.0 Beta 5 and 1.0
20
+ * Only one error/exception type: TestLinker::Error
21
+ * Limited set of helper methods, attempting to fill in gaps from the API
22
+
23
+ == Examples
24
+
25
+ require 'test_linker'
26
+
27
+ server = 'http://testlink.pelco.org'
28
+ dev_key = "90b7941411928ae0a84d19f365a01a63"
29
+ tl_project = "!SSW Auto-Smoke Testing"
30
+
31
+ csv_file_name = "mtrx_report.csv"
32
+ csv_file = File.new(csv_file_name, "w")
33
+ csv_file.write "Build,Passed,Failed,Blocked,Skipped,TOTAL,Overall %,Overall % (+B)\n"
34
+
35
+ tl = TestLinker.new(server, dev_key)
36
+
37
+ project_id = tl.test_project_id tl_project
38
+ test_plans = tl.find_test_plans(project_id, /NSM5200.+ISC West/)
39
+ puts "All test plans for project #{project_id}"
40
+ puts test_plans
41
+
42
+ builds = test_plans.collect do |test_plan|
43
+ tl.builds_for_test_plan(test_plan["id"])
44
+ end
45
+ builds.flatten!
46
+
47
+ overall = {}
48
+ overall[:pass] = 0
49
+ overall[:failed] = 0
50
+ overall[:blocked] = 0
51
+ overall[:pass_rates] =
52
+ results = {}
53
+
54
+ builds.each do |build|
55
+ results[:pass] = 0
56
+ results[:failed] = 0
57
+ results[:blocked] = 0
58
+ results[:skipped] = 0
59
+
60
+ test_cases = tl.test_cases_for_test_plan(build["testplan_id"],
61
+ { "buildid" => build["id"] })
62
+
63
+ test_cases.each_value do |test_case|
64
+ case test_case["exec_status"]
65
+ when "p"
66
+ results[:pass] += 1
67
+ when "f"
68
+ results[:failed] += 1
69
+ when "b"
70
+ results[:blocked] += 1
71
+ when "s"
72
+ results[:skipped] += 1
73
+ end
74
+ end
75
+
76
+ overall[:pass] += results[:pass]
77
+ overall[:failed] += results[:failed]
78
+ overall[:blocked] += results[:blocked]
79
+ build_total = results[:pass] + results[:failed] + results[:blocked] +
80
+ results[:skipped]
81
+ overall_rate = "%2.2f" % (overall[:pass] * 100 / (overall[:pass] +
82
+ overall[:failed]).to_f)
83
+ overall[:pass_rates] << overall_rate.to_f
84
+ overall_rate_plus_blocked = "%2.2f" % (overall[:pass] * 100 / (overall[:pass] +
85
+ overall[:failed] + overall[:blocked]).to_f)
86
+
87
+ result_array = [
88
+ ['Passed', 'Failed', 'Blocked', 'Skipped', 'TOTAL', 'Overall %', 'Overall % (+B)'],
89
+ [results[:pass], results[:failed], results[:blocked], results[:skipped],
90
+ build_total, overall_rate, overall_rate_plus_blocked]
91
+ ]
92
+
93
+ csv_line = "#{build["name"]},#{results[:pass]},#{results[:failed]},#{results[:blocked]},"
94
+ csv_line << "#{results[:skipped]},#{build_total},#{overall_rate},#{overall_rate_plus_blocked}\n"
95
+ csv_file.write csv_line
96
+ end
97
+
98
+ == Requirements
99
+
100
+ * Rubies (tested)
101
+ * 1.9.2
102
+ * Gems
103
+ * versionomy, ~> 0.4.0
104
+ * Gems (development)
105
+ * bundler, ~> 1.0.0
106
+ * cucumber, ~> 0.10.0
107
+ * jeweler, ~> 1.5.0
108
+ * ore, ~> 0.7.2
109
+ * ore-core, ~> 0.1.4
110
+ * rspec, ~> 2.5.0
111
+ * yard, ~> 0.6.0
112
+
113
+ Getting it all running (on the TestLink side):
114
+ 1. Enable automation in the TestLink config file:
115
+ config.inc.php => $tlCfg->api->enabled = TRUE;
116
+ 2. The user that needs to run the automated tests needs to generate a API key
117
+ that will be used in creating the connection. This is accomplished by logging
118
+ in to TestLink and going to "Personal -> API Key -> Generate a new key".
119
+
120
+ == Install
121
+
122
+ $ gem install test_linker
123
+
124
+ == Copyright
125
+
126
+ Copyright (c) 2011 sloveless
127
+
128
+ See LICENSE.rdoc for details.
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rake'
2
+
3
+ begin
4
+ gem 'ore-tasks', '~> 0.4'
5
+ require 'ore/tasks'
6
+
7
+ Ore::Tasks.new
8
+ rescue LoadError => e
9
+ STDERR.puts e.message
10
+ STDERR.puts "Run `gem install ore-tasks` to install 'ore/tasks'."
11
+ end
12
+ begin
13
+ require 'bundler'
14
+ rescue LoadError => e
15
+ STDERR.puts e.message
16
+ STDERR.puts "Run `gem install bundler` to install Bundler."
17
+ exit e.status_code
18
+ end
19
+
20
+ begin
21
+ Bundler.setup(:development)
22
+ rescue Bundler::BundlerError => e
23
+ STDERR.puts e.message
24
+ STDERR.puts "Run `bundle install` to install missing gems."
25
+ exit e.status_code
26
+ end
27
+
28
+ begin
29
+ gem 'rspec', '~> 2.5'
30
+ require 'rspec/core/rake_task'
31
+
32
+ RSpec::Core::RakeTask.new
33
+ task :test => :spec
34
+ task :default => :spec
35
+ rescue LoadError => e
36
+ task :spec do
37
+ abort "Please run `gem install rspec` to install RSpec."
38
+ end
39
+ end
40
+
41
+ require 'ore/specification'
42
+ require 'jeweler'
43
+ Jeweler::Tasks.new(Ore::Specification.new)
44
+
45
+ require 'yard'
46
+ YARD::Rake::YardocTask.new
47
+ task :doc => :yard
48
+
@@ -0,0 +1,63 @@
1
+ Feature: Get info from TestLink
2
+ As a TestLink API user
3
+ I want to get info from the TestLink server
4
+ So that I can use the info in reports and such
5
+
6
+ Scenario Outline: Get a list of projects
7
+ Given I have a TestLink server with API version <version>
8
+ When I ask for the list of projects
9
+ Then I get a list of projects
10
+
11
+ Scenarios: Known API versions
12
+ | version |
13
+ | 1.0 Beta 5 |
14
+ | 1.0 |
15
+
16
+ Scenario Outline: Get a list of test plans
17
+ Given I have a TestLink server with API version <version>
18
+ When I ask for the list of projects
19
+ And I ask for the list of test plans
20
+ Then I get a list of test plans
21
+
22
+ Scenarios: Known API versions
23
+ | version |
24
+ | 1.0 Beta 5 |
25
+ | 1.0 |
26
+
27
+ Scenario Outline: Get a list of test cases in a test plan
28
+ Given I have a TestLink server with API version <version>
29
+ And I have the list of projects
30
+ And I know the name of a project
31
+ And I have a list of test plans
32
+ When I ask for the list of test cases in that test plan
33
+ Then I get a list of test cases in that test plan
34
+
35
+ Scenarios: Known API versions
36
+ | version |
37
+ | 1.0 Beta 5 |
38
+ | 1.0 |
39
+
40
+ Scenario: Get a test project by its name
41
+ Given I have a TestLink server with API version 1.0
42
+ And I know the name of a project
43
+ When I ask for that project by name
44
+ Then I get that project
45
+
46
+ Scenario: Get a test plan by its name
47
+ Given I have a TestLink server with API version 1.0
48
+ And I have the list of projects
49
+ And I know the name of a project
50
+ And I have a list of test plans
51
+ And I know the name of a test plan in that project
52
+ When I ask for that test plan by name
53
+ Then I get that test plan
54
+
55
+ Scenario: Get a test case by its ID
56
+ Given I have a TestLink server with API version 1.0
57
+ And I have the list of projects
58
+ And I know the name of a project
59
+ And I have a list of test plans
60
+ And I know the ID of a test case in that project
61
+ When I ask for that test case by ID
62
+ Then I get that test case
63
+
@@ -0,0 +1,78 @@
1
+ Given /^I know the name of a project$/ do
2
+ @test_project_name = @server.projects.last["name"]
3
+ @test_project_name.should_not be_nil
4
+ end
5
+
6
+ Given /^I know the name of a test plan in that project$/ do
7
+ @original_test_plan_name = @test_plans.last["name"]
8
+ @original_test_plan_name.should_not be_nil
9
+ end
10
+
11
+ Given /^I have the list of projects$/ do
12
+ #When "I ask for the list of projects"
13
+ @project_list = @server.projects
14
+ end
15
+
16
+ Given /^I have a list of test plans$/ do
17
+ #When "I ask for the list of test plans"
18
+ @test_plans = @server.project_test_plans(@project_list.last["id"])
19
+ end
20
+
21
+ When /^I ask for the list of projects$/ do
22
+ @project_list = @server.projects
23
+ end
24
+
25
+ When /^I ask for the list of test plans$/ do
26
+ @test_plans = @server.project_test_plans(@project_list.last["id"])
27
+ end
28
+
29
+ When /^I ask for that project by name$/ do
30
+ @requested_test_project_name = @server.test_project_by_name(@test_project_name)
31
+ end
32
+
33
+ When /^I ask for that test plan by name$/ do
34
+ @requested_test_plan_name = @server.test_plan_by_name(@original_test_plan_name,
35
+ @project_list.last["name"])
36
+ end
37
+
38
+ Then /^I get a list of projects$/ do
39
+ @project_list.is_a?(Array).should be_true
40
+ @project_list.last.is_a?(Hash).should be_true
41
+ end
42
+
43
+ Then /^I get a list of test plans$/ do
44
+ @test_plans.class.should == Array
45
+ @test_plans.last.class.should == Hash
46
+ end
47
+
48
+ Then /^I get that project$/ do
49
+ @requested_test_project_name.last["name"].should == @test_project_name
50
+ end
51
+
52
+ Then /^I get that test plan$/ do
53
+ @requested_test_plan_name.first["name"].should == @original_test_plan_name
54
+ end
55
+
56
+ Given /^I know the ID of a test case in that project$/ do
57
+ pending
58
+ @test_cases = @server.test_cases_for_test_plan(@test_plans.last["id"])
59
+ end
60
+
61
+ When /^I ask for that test case by ID$/ do
62
+ pending # express the regexp above with the code you wish you had
63
+ end
64
+
65
+ Then /^I get that test case$/ do
66
+ pending # express the regexp above with the code you wish you had
67
+ end
68
+
69
+ When /^I ask for the list of test cases in that test plan$/ do
70
+ @test_cases = @server.test_cases_for_test_plan(
71
+ @test_plans.last.values.last["id"])
72
+ end
73
+
74
+ Then /^I get a list of test cases in that test plan$/ do
75
+ @test_cases.should_not be_nil
76
+ @test_cases.class.should == Hash
77
+ @test_cases.each_value {|v| v["name"].class.should == String }
78
+ end
@@ -0,0 +1,13 @@
1
+ Given /^I have a TestLink server with API version (.+)$/ do |api_version|
2
+ if api_version == "1.0"
3
+ url = "http://ubuntu-desktop/testlink/"
4
+ dev_key = "b8c144a536f8233d24b04b8268bfac34"
5
+ else
6
+ url = "http://testlink/"
7
+ dev_key = "90b7941411928ae0a84d19f365a01a63"
8
+ end
9
+
10
+ @server = TestLinker.new(url, dev_key)
11
+ @server.api_version.should == api_version
12
+ @server.about.should match /#{api_version} /
13
+ end
@@ -0,0 +1,5 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_group "Library", "lib/"
4
+ end
5
+ require_relative '../../lib/test_linker'
data/gemspec.yml ADDED
@@ -0,0 +1,25 @@
1
+ name: test_linker
2
+ summary: "An interface to the TestLink XMLRPC API"
3
+ description:
4
+ This is a Ruby wrapper around the TestLink XMLRPC API, thus allowing access to
5
+ your TestLink test projects, plans, cases, and results using Ruby. We've added
6
+ a few helper methods as well to allow for getting at more of your data a little
7
+ easier. This supports TestLink APIs 1.0 Beta 5 (from TestLink 1.8.x) and 1.0
8
+ (from TestLink 1.9.x).
9
+ license: MIT
10
+ authors: Steve Loveless, Randy Stoller, Sujin Philip, Vikram Raina
11
+ email: steve.loveless@gmail.com
12
+ homepage: http://rubygems.org/gems/test_linker
13
+ has_yard: true
14
+ dependencies:
15
+ versionomy: ~> 0.4.0
16
+
17
+ development_dependencies:
18
+ bundler: ~> 1.0.0
19
+ cucumber: ~> 0.10.0
20
+ jeweler: ~> 1.5.0
21
+ ore: ~> 0.7.2
22
+ ore-core: ~> 0.1.4
23
+ rspec: ~> 2.5
24
+ simplecov: >= 0.4.0
25
+ yard: ~> 0.6.0
@@ -0,0 +1,130 @@
1
+ require_relative 'test_linker/wrapper'
2
+ require_relative 'test_linker/version'
3
+ require_relative 'test_linker/error'
4
+ require_relative 'test_linker/helpers'
5
+ require 'xmlrpc/client'
6
+ require 'logger'
7
+ require 'versionomy'
8
+
9
+ class TestLinker
10
+ include TestLinker::Wrapper
11
+ include TestLinker::Helpers
12
+
13
+ class << self
14
+
15
+ # @return [Boolean] Returns if logging is enabled or not.
16
+ def log?
17
+ @log ||= false
18
+ end
19
+
20
+ # @param [Boolean] do_logging false to turn logging off; true to turn it
21
+ # back on.
22
+ def log=(do_logging)
23
+ @log = do_logging
24
+ end
25
+
26
+ # @return [Logger,?] Returns a Logger unless you use a different type of
27
+ # logging object.
28
+ def logger
29
+ @logger ||= Logger.new STDOUT
30
+ end
31
+
32
+ # @param [?] logging_object Call this to use a different type of logger
33
+ # than Logger.
34
+ def logger=(logging_object)
35
+ @logger = logging_object
36
+ end
37
+
38
+ # @return [Symbol] The method name to send to the logging object in order to
39
+ # log messages.
40
+ def log_level
41
+ @log_level ||= :debug
42
+ end
43
+
44
+ # @param [Symbol] The method name to send to the logging object in order to
45
+ # log messages.
46
+ def log_level=(level)
47
+ @log_level = level
48
+ end
49
+
50
+ # @param [String] message The string to log.
51
+ def log message
52
+ logger.send(log_level, message) if log?
53
+ end
54
+ end
55
+
56
+ # Default value for timing out after not receiving an XMLRPC response from
57
+ # the server.
58
+ DEFAULT_TIMEOUT = 30
59
+
60
+ # Path the the XMLRPC interface (via the xmlrpc.php file) on the server.
61
+ DEFAULT_API_PATH = "/lib/api/xmlrpc.php"
62
+
63
+ # @param [String] server_url URL to access TestLink API
64
+ # @param [String] dev_key User key to access TestLink API
65
+ # @param [Hash] options
66
+ # @option options [String] api_path Alternate path to the xmlrpc.php file on
67
+ # the server.
68
+ # @option options [Fixnum] timeout Seconds to timeout after not receiving a
69
+ # response from the server.
70
+ # @option options [String] version Force a different API version.
71
+ def initialize(server_url, dev_key, options={})
72
+ api_path = options[:api_path] || DEFAULT_API_PATH
73
+ timeout = options[:timeout] || DEFAULT_TIMEOUT
74
+ @dev_key = dev_key
75
+ server_url = server_url + api_path
76
+ @server = XMLRPC::Client.new_from_uri(server_url, nil, timeout)
77
+ @version = Versionomy.parse(options[:version] || api_version)
78
+ end
79
+
80
+ # Makes the call to the server with the given arguments. Note that this also
81
+ # allows for calling XMLRPC methods on the server that haven't yet been
82
+ # implemented as Ruby methods here.
83
+ #
84
+ # @example Call a new method
85
+ # result = make_call("tl.getWidgets", { "testplanid" => 123 }, "1.5")
86
+ # raise TestLinker::Error, result["message"] if result["code"]
87
+ # return result
88
+ # @param [String] method_name The XMLRPC method to call.
89
+ # @param [Hash] arguments The arguments to send to the server.
90
+ # @param [String] method_supported_in_version The version of the API the
91
+ # method was added.
92
+ # @return The return type depends on the method call.
93
+ def make_call(method_name, arguments, method_supported_in_version)
94
+ ensure_version_is :greater_than_or_equal_to, method_supported_in_version
95
+ TestLinker.log "API Version: #{method_supported_in_version}"
96
+ TestLinker.log "Calling method: '#{method_name}' with args '#{arguments}'"
97
+ response = @server.call(method_name, arguments)
98
+ TestLinker.log "Received response:"
99
+ TestLinker.log response
100
+
101
+ if @version.nil?
102
+ return response
103
+ elsif response.is_a?(Array) && response.first['code']
104
+ raise TestLinker::Error, "#{response.first['code']}: #{response.first['message']}"
105
+ end
106
+
107
+ response
108
+ end
109
+
110
+ private
111
+
112
+ # Raises if the version set in @version doesn't meet the comparison with the
113
+ # passed-in version. Returns nil if @version isn't set, since there's
114
+ # nothing to do (and something might have called to set @version).
115
+ #
116
+ # @private
117
+ # @param [Symbol] comparison
118
+ # @param [String] version
119
+ def ensure_version_is(comparison, version)
120
+ message = "Method not supported in version #{@version}."
121
+
122
+ if @version.nil?
123
+ return
124
+ elsif comparison == :less_than && @version >= version
125
+ raise TestLinker::Error, message
126
+ elsif comparison == :greater_than_or_equal_to && @version < version
127
+ raise TestLinker::Error, message
128
+ end
129
+ end
130
+ end