test_linker 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.infinity_test +7 -0
- data/.rspec +1 -1
- data/ChangeLog.rdoc +26 -0
- data/Gemfile +4 -6
- data/README.rdoc +35 -34
- data/Rakefile +39 -36
- data/features/step_definitions/get_info_steps.rb +12 -12
- data/features/support/env.rb +8 -4
- data/lib/core_ext/hash_patch.rb +24 -0
- data/lib/core_ext/xmlrpc_client_patch.rb +7 -0
- data/lib/test_linker.rb +42 -9
- data/lib/test_linker/helpers.rb +68 -81
- data/lib/test_linker/version.rb +1 -1
- data/lib/test_linker/wrapper.rb +147 -158
- data/spec/core_ext/xmlrpc_client_patch_spec.rb +16 -0
- data/spec/spec_helper.rb +23 -5
- data/spec/test_linker/wrapper_spec.rb +168 -0
- data/spec/test_linker_spec.rb +26 -0
- data/test_linker.gemspec +32 -43
- metadata +148 -119
- data/gemspec.yml +0 -25
data/.infinity_test
ADDED
data/.rspec
CHANGED
@@ -1 +1 @@
|
|
1
|
-
--colour --format documentation
|
1
|
+
--colour --format documentation --tty
|
data/ChangeLog.rdoc
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
=== 1.0.0 / 2011-05-08
|
2
|
+
|
3
|
+
* Added support for new (old) Rubies:
|
4
|
+
* 1.8.7
|
5
|
+
* jruby 1.6.1
|
6
|
+
* ree 1.8.7
|
7
|
+
* Hash keys are all now symbols.
|
8
|
+
* Renamed methods:
|
9
|
+
* Wrapper#project_test_plans to Wrapper#test_plans.
|
10
|
+
* Wrapper#create_test_project to Wrapper#create_project.
|
11
|
+
* Wrapper#upload_test_project_attachment to Wrapper#upload_project_attachment.
|
12
|
+
* Wrapper#first_level_test_suites_for_test_project to Wrapper#first_level_test_suites_for_project.
|
13
|
+
* Helpers#test_project_id to Helpers#project_id.
|
14
|
+
* Helpers#test_project_by_name to Helpers#project_by_name.
|
15
|
+
* New Helper method:
|
16
|
+
* #find_projects
|
17
|
+
* Helper#find_projects and Helper#find_test_plans take a trailing parameter that
|
18
|
+
let's you specify which attribute to match on--that defaults to :name.
|
19
|
+
* Added ability to log XMLRPC calls that go through Net::HTTP.
|
20
|
+
* Development stuff:
|
21
|
+
* Stopped using ore for gem bundling; just use Jeweler now.
|
22
|
+
|
23
|
+
=== 0.1.1 / 2011-03-24
|
24
|
+
|
25
|
+
* Fixed dumb dependency on self to install.
|
26
|
+
|
1
27
|
=== 0.1.0 / 2011-03-24
|
2
28
|
|
3
29
|
* Initial release:
|
data/Gemfile
CHANGED
@@ -4,13 +4,11 @@ source :rubygems
|
|
4
4
|
gem 'versionomy', '~> 0.4.0'
|
5
5
|
|
6
6
|
group :development do
|
7
|
+
gem 'bundler', '~> 1.0.0'
|
7
8
|
gem 'cucumber', '~> 0.10.0'
|
8
|
-
gem '
|
9
|
-
gem '
|
10
|
-
gem 'ore-core', '~> 0.1.4'
|
11
|
-
gem 'ore-tasks', '~> 0.5.0'
|
9
|
+
gem 'fakeweb', '~> 1.3.0'
|
10
|
+
gem 'jeweler', '~> 1.6.0'
|
12
11
|
gem 'rspec', '~> 2.5'
|
13
|
-
gem 'simplecov', '>= 0.4.0', :require => false
|
14
|
-
gem 'jeweler', '~> 1.5.0'
|
12
|
+
gem 'simplecov', '>= 0.4.0', :require => false if RUBY_VERSION >= "1.9"
|
15
13
|
gem 'yard', '~> 0.6.0'
|
16
14
|
end
|
data/README.rdoc
CHANGED
@@ -15,32 +15,37 @@ easier. This supports TestLink APIs 1.0 Beta 5 (from TestLink 1.8.x) and 1.0
|
|
15
15
|
== Features
|
16
16
|
|
17
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
|
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
22
|
|
23
23
|
== Examples
|
24
24
|
|
25
|
+
Get results to a CSV file:
|
26
|
+
|
25
27
|
require 'test_linker'
|
28
|
+
require 'pp'
|
26
29
|
|
27
|
-
server = 'http://testlink
|
30
|
+
server = 'http://testlink'
|
28
31
|
dev_key = "90b7941411928ae0a84d19f365a01a63"
|
29
|
-
tl_project = "
|
32
|
+
tl_project = "My nifty project"
|
33
|
+
tl = TestLinker.new(server, dev_key)
|
30
34
|
|
31
|
-
|
35
|
+
# Write out the CSV headers
|
36
|
+
csv_file_name = "report.csv"
|
32
37
|
csv_file = File.new(csv_file_name, "w")
|
33
|
-
csv_file.write "Build,Passed,Failed,Blocked,
|
34
|
-
|
35
|
-
tl = TestLinker.new(server, dev_key)
|
38
|
+
csv_file.write "Build,Passed,Failed,Blocked,TOTAL,Overall %,Overall % (+B)\n"
|
36
39
|
|
37
|
-
|
38
|
-
|
40
|
+
# Get the list of test plans that I want to report on
|
41
|
+
project_id = tl.project_id tl_project
|
42
|
+
test_plans = tl.find_test_plans(project_id, /^Component.+1.0/)
|
39
43
|
puts "All test plans for project #{project_id}"
|
40
|
-
|
44
|
+
pp test_plans
|
41
45
|
|
46
|
+
# Get a list of all builds from those test plans
|
42
47
|
builds = test_plans.collect do |test_plan|
|
43
|
-
tl.builds_for_test_plan(test_plan[
|
48
|
+
tl.builds_for_test_plan(test_plan[:id])
|
44
49
|
end
|
45
50
|
builds.flatten!
|
46
51
|
|
@@ -48,66 +53,62 @@ easier. This supports TestLink APIs 1.0 Beta 5 (from TestLink 1.8.x) and 1.0
|
|
48
53
|
overall[:pass] = 0
|
49
54
|
overall[:failed] = 0
|
50
55
|
overall[:blocked] = 0
|
51
|
-
overall[:pass_rates] =
|
52
56
|
results = {}
|
53
57
|
|
58
|
+
# Total up results for each build and write to the CSV file
|
54
59
|
builds.each do |build|
|
55
60
|
results[:pass] = 0
|
56
61
|
results[:failed] = 0
|
57
62
|
results[:blocked] = 0
|
58
|
-
results[:skipped] = 0
|
59
63
|
|
60
|
-
test_cases = tl.test_cases_for_test_plan(build[
|
61
|
-
{
|
64
|
+
test_cases = tl.test_cases_for_test_plan(build[:testplan_id],
|
65
|
+
{ :buildid => build[:id] })
|
62
66
|
|
63
67
|
test_cases.each_value do |test_case|
|
64
|
-
case test_case[
|
68
|
+
case test_case[:exec_status]
|
65
69
|
when "p"
|
66
70
|
results[:pass] += 1
|
67
71
|
when "f"
|
68
72
|
results[:failed] += 1
|
69
73
|
when "b"
|
70
74
|
results[:blocked] += 1
|
71
|
-
when "s"
|
72
|
-
results[:skipped] += 1
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
76
78
|
overall[:pass] += results[:pass]
|
77
79
|
overall[:failed] += results[:failed]
|
78
80
|
overall[:blocked] += results[:blocked]
|
79
|
-
build_total = results[:pass] + results[:failed] + results[:blocked]
|
80
|
-
|
81
|
+
build_total = results[:pass] + results[:failed] + results[:blocked]
|
82
|
+
|
81
83
|
overall_rate = "%2.2f" % (overall[:pass] * 100 / (overall[:pass] +
|
82
84
|
overall[:failed]).to_f)
|
83
|
-
overall[:pass_rates] << overall_rate.to_f
|
84
85
|
overall_rate_plus_blocked = "%2.2f" % (overall[:pass] * 100 / (overall[:pass] +
|
85
86
|
overall[:failed] + overall[:blocked]).to_f)
|
86
87
|
|
87
|
-
|
88
|
-
|
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"
|
88
|
+
csv_line = "#{build[:name]},#{results[:pass]},#{results[:failed]},#{results[:blocked]},"
|
89
|
+
csv_line << "#{build_total},#{overall_rate},#{overall_rate_plus_blocked}\n"
|
95
90
|
csv_file.write csv_line
|
96
91
|
end
|
92
|
+
|
93
|
+
csv_file.close
|
94
|
+
|
97
95
|
|
98
96
|
== Requirements
|
99
97
|
|
100
98
|
* Rubies (tested)
|
99
|
+
* 1.8.7
|
101
100
|
* 1.9.2
|
101
|
+
* jruby 1.6.1
|
102
|
+
* ree 1.8.7
|
102
103
|
* Gems
|
103
104
|
* versionomy, ~> 0.4.0
|
104
105
|
* Gems (development)
|
105
106
|
* bundler, ~> 1.0.0
|
106
107
|
* cucumber, ~> 0.10.0
|
108
|
+
* fakeweb, ~> 1.3.0
|
107
109
|
* jeweler, ~> 1.5.0
|
108
|
-
* ore, ~> 0.7.2
|
109
|
-
* ore-core, ~> 0.1.4
|
110
110
|
* rspec, ~> 2.5.0
|
111
|
+
* simplecov, >= 0.4.0
|
111
112
|
* yard, ~> 0.6.0
|
112
113
|
|
113
114
|
Getting it all running (on the TestLink side):
|
data/Rakefile
CHANGED
@@ -1,48 +1,51 @@
|
|
1
|
-
require '
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
2
3
|
|
3
4
|
begin
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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."
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
17
9
|
exit e.status_code
|
18
10
|
end
|
19
11
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
$:.unshift Dir.pwd + "/lib"
|
15
|
+
require 'test_linker'
|
16
|
+
require 'jeweler'
|
17
|
+
Jeweler::Tasks.new do |gem|
|
18
|
+
gem.name = "test_linker"
|
19
|
+
gem.version = TestLinker::VERSION
|
20
|
+
gem.homepage = "http://github.com/turboladen/test_linker"
|
21
|
+
gem.license = "MIT"
|
22
|
+
gem.summary = %Q{An interface to the TestLink XMLRPC API}
|
23
|
+
gem.description = %Q{This is a Ruby wrapper around the TestLink XMLRPC API, thus allowing access to
|
24
|
+
your TestLink test projects, plans, cases, and results using Ruby. We've added
|
25
|
+
a few helper methods as well to allow for getting at more of your data a little
|
26
|
+
easier. This supports TestLink APIs 1.0 Beta 5 (from TestLink 1.8.x) and 1.0
|
27
|
+
(from TestLink 1.9.x)..}
|
28
|
+
gem.email = "steve.loveless@gmail.com"
|
29
|
+
gem.authors = ["turboladen"]
|
30
|
+
gem.add_bundler_dependencies
|
26
31
|
end
|
32
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
34
|
+
require 'rspec/core'
|
35
|
+
require 'rspec/core/rake_task'
|
36
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
37
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
39
38
|
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
41
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
42
|
+
spec.rcov = true
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'cucumber/rake/task'
|
46
|
+
Cucumber::Rake::Task.new(:features)
|
47
|
+
|
48
|
+
task :default => :spec
|
44
49
|
|
45
50
|
require 'yard'
|
46
51
|
YARD::Rake::YardocTask.new
|
47
|
-
task :doc => :yard
|
48
|
-
|
@@ -1,10 +1,10 @@
|
|
1
1
|
Given /^I know the name of a project$/ do
|
2
|
-
@test_project_name = @server.projects.last[
|
2
|
+
@test_project_name = @server.projects.last[:name]
|
3
3
|
@test_project_name.should_not be_nil
|
4
4
|
end
|
5
5
|
|
6
6
|
Given /^I know the name of a test plan in that project$/ do
|
7
|
-
@original_test_plan_name = @test_plans.last[
|
7
|
+
@original_test_plan_name = @test_plans.last[:name]
|
8
8
|
@original_test_plan_name.should_not be_nil
|
9
9
|
end
|
10
10
|
|
@@ -15,7 +15,7 @@ end
|
|
15
15
|
|
16
16
|
Given /^I have a list of test plans$/ do
|
17
17
|
#When "I ask for the list of test plans"
|
18
|
-
@test_plans = @server.
|
18
|
+
@test_plans = @server.test_plans(@project_list.last[:id])
|
19
19
|
end
|
20
20
|
|
21
21
|
When /^I ask for the list of projects$/ do
|
@@ -23,16 +23,16 @@ When /^I ask for the list of projects$/ do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
When /^I ask for the list of test plans$/ do
|
26
|
-
@test_plans = @server.
|
26
|
+
@test_plans = @server.test_plans(@project_list.last[:id])
|
27
27
|
end
|
28
28
|
|
29
29
|
When /^I ask for that project by name$/ do
|
30
|
-
@requested_test_project_name = @server.
|
30
|
+
@requested_test_project_name = @server.project_by_name(@test_project_name)
|
31
31
|
end
|
32
32
|
|
33
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
|
-
|
34
|
+
@requested_test_plan_name = @server.test_plan_by_name(@project_list.last[:name], @original_test_plan_name)
|
35
|
+
|
36
36
|
end
|
37
37
|
|
38
38
|
Then /^I get a list of projects$/ do
|
@@ -46,16 +46,16 @@ Then /^I get a list of test plans$/ do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
Then /^I get that project$/ do
|
49
|
-
@requested_test_project_name.last[
|
49
|
+
@requested_test_project_name.last[:name].should == @test_project_name
|
50
50
|
end
|
51
51
|
|
52
52
|
Then /^I get that test plan$/ do
|
53
|
-
@requested_test_plan_name.first[
|
53
|
+
@requested_test_plan_name.first[:name].should == @original_test_plan_name
|
54
54
|
end
|
55
55
|
|
56
56
|
Given /^I know the ID of a test case in that project$/ do
|
57
57
|
pending
|
58
|
-
@test_cases = @server.test_cases_for_test_plan(@test_plans.last[
|
58
|
+
@test_cases = @server.test_cases_for_test_plan(@test_plans.last[:id])
|
59
59
|
end
|
60
60
|
|
61
61
|
When /^I ask for that test case by ID$/ do
|
@@ -68,11 +68,11 @@ end
|
|
68
68
|
|
69
69
|
When /^I ask for the list of test cases in that test plan$/ do
|
70
70
|
@test_cases = @server.test_cases_for_test_plan(
|
71
|
-
@test_plans.last.values.last[
|
71
|
+
@test_plans.last.values.last[:id])
|
72
72
|
end
|
73
73
|
|
74
74
|
Then /^I get a list of test cases in that test plan$/ do
|
75
75
|
@test_cases.should_not be_nil
|
76
76
|
@test_cases.class.should == Hash
|
77
|
-
@test_cases.each_value {|v| v[
|
77
|
+
@test_cases.each_value {|v| v[:name].class.should == String }
|
78
78
|
end
|
data/features/support/env.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
if RUBY_VERSION > '1.9'
|
2
|
+
require 'simplecov'
|
3
|
+
|
4
|
+
SimpleCov.start do
|
5
|
+
add_group "Library", "lib/"
|
6
|
+
end
|
4
7
|
end
|
5
|
-
|
8
|
+
|
9
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/test_linker')
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Hash
|
2
|
+
def symbolize_keys
|
3
|
+
inject({ }) do |options, (key, value)|
|
4
|
+
new_key = case key
|
5
|
+
when String
|
6
|
+
Integer(key) rescue key.to_sym
|
7
|
+
end
|
8
|
+
|
9
|
+
new_value = case value
|
10
|
+
when Hash then value.symbolize_keys
|
11
|
+
when String
|
12
|
+
Integer(value) rescue value
|
13
|
+
else value
|
14
|
+
end
|
15
|
+
|
16
|
+
options[new_key] = new_value
|
17
|
+
options
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def symbolize_keys!
|
22
|
+
self.replace(self.symbolize_keys)
|
23
|
+
end
|
24
|
+
end
|
data/lib/test_linker.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
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
1
|
require 'logger'
|
2
|
+
require 'rubygems'
|
7
3
|
require 'versionomy'
|
8
4
|
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/core_ext/hash_patch')
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_linker/wrapper')
|
7
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_linker/version')
|
8
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_linker/error')
|
9
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_linker/helpers')
|
10
|
+
require File.expand_path(File.dirname(__FILE__) + '/core_ext/xmlrpc_client_patch')
|
11
|
+
|
9
12
|
class TestLinker
|
10
13
|
include TestLinker::Wrapper
|
11
14
|
include TestLinker::Helpers
|
@@ -77,6 +80,25 @@ class TestLinker
|
|
77
80
|
@version = Versionomy.parse(options[:version] || api_version)
|
78
81
|
end
|
79
82
|
|
83
|
+
# @return [Boolean] Returns if logging of XMLRPC requests/responses is
|
84
|
+
# enabled or not.
|
85
|
+
def log_xml?
|
86
|
+
@log_xml ||= false
|
87
|
+
end
|
88
|
+
|
89
|
+
# @param [Boolean] do_logging false to turn XMLRPC logging off; true to
|
90
|
+
# turn it back on.
|
91
|
+
def log_xml=(do_logging)
|
92
|
+
if do_logging == true
|
93
|
+
puts "WARNING: Net::HTTP warns against using this in production, so you probably shouldn't!!"
|
94
|
+
@server.set_debug(TestLinker.logger)
|
95
|
+
elsif do_logging == false
|
96
|
+
@server.set_debug(nil)
|
97
|
+
end
|
98
|
+
|
99
|
+
@log_xml = do_logging
|
100
|
+
end
|
101
|
+
|
80
102
|
# Makes the call to the server with the given arguments. Note that this also
|
81
103
|
# allows for calling XMLRPC methods on the server that haven't yet been
|
82
104
|
# implemented as Ruby methods here.
|
@@ -92,18 +114,29 @@ class TestLinker
|
|
92
114
|
# @return The return type depends on the method call.
|
93
115
|
def make_call(method_name, arguments, method_supported_in_version)
|
94
116
|
ensure_version_is :greater_than_or_equal_to, method_supported_in_version
|
117
|
+
|
118
|
+
arguments.merge!({ :devKey => @dev_key }) unless arguments.has_key? :devKey
|
119
|
+
|
95
120
|
TestLinker.log "API Version: #{method_supported_in_version}"
|
96
|
-
TestLinker.log "Calling method: '#{method_name}' with args '#{arguments}'"
|
121
|
+
TestLinker.log "Calling method: '#{method_name}' with args '#{arguments.inspect}'"
|
97
122
|
response = @server.call(method_name, arguments)
|
123
|
+
|
124
|
+
TestLinker.log "response class: #{response.class}"
|
125
|
+
if response.is_a?(Array) && response.first.is_a?(Hash)
|
126
|
+
response.each { |r| r.symbolize_keys! }
|
127
|
+
elsif response.is_a? Hash
|
128
|
+
response.symbolize_keys!
|
129
|
+
end
|
130
|
+
|
98
131
|
TestLinker.log "Received response:"
|
99
132
|
TestLinker.log response
|
100
133
|
|
101
134
|
if @version.nil?
|
102
135
|
return response
|
103
|
-
elsif response.is_a?(Array) && response.first[
|
104
|
-
raise TestLinker::Error, "#{response.first[
|
136
|
+
elsif response.is_a?(Array) && response.first[:code]
|
137
|
+
raise TestLinker::Error, "#{response.first[:code]}: #{response.first[:message]}"
|
105
138
|
end
|
106
|
-
|
139
|
+
|
107
140
|
response
|
108
141
|
end
|
109
142
|
|