test_linker 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ infinity_test do
2
+ notifications :growl do
3
+ show_images :mode => :mario_bros
4
+ end
5
+
6
+ use :rubies => %w(1.8.7 jruby 1.9.2 ree), :test_framework => :rspec
7
+ end
data/.rspec CHANGED
@@ -1 +1 @@
1
- --colour --format documentation
1
+ --colour --format documentation --tty
@@ -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 'rake', '~> 0.8.7'
9
- gem 'ore', '~> 0.7.2'
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
@@ -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.pelco.org'
30
+ server = 'http://testlink'
28
31
  dev_key = "90b7941411928ae0a84d19f365a01a63"
29
- tl_project = "!SSW Auto-Smoke Testing"
32
+ tl_project = "My nifty project"
33
+ tl = TestLinker.new(server, dev_key)
30
34
 
31
- csv_file_name = "mtrx_report.csv"
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,Skipped,TOTAL,Overall %,Overall % (+B)\n"
34
-
35
- tl = TestLinker.new(server, dev_key)
38
+ csv_file.write "Build,Passed,Failed,Blocked,TOTAL,Overall %,Overall % (+B)\n"
36
39
 
37
- project_id = tl.test_project_id tl_project
38
- test_plans = tl.find_test_plans(project_id, /NSM5200.+ISC West/)
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
- puts test_plans
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["id"])
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["testplan_id"],
61
- { "buildid" => build["id"] })
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["exec_status"]
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
- results[:skipped]
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
- 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"
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 'rake'
1
+ require 'rubygems'
2
+ require 'bundler'
2
3
 
3
4
  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."
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
- 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
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
- 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
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
- require 'ore/specification'
42
- require 'jeweler'
43
- Jeweler::Tasks.new(Ore::Specification.new)
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["name"]
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["name"]
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.project_test_plans(@project_list.last["id"])
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.project_test_plans(@project_list.last["id"])
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.test_project_by_name(@test_project_name)
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
- @project_list.last["name"])
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["name"].should == @test_project_name
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["name"].should == @original_test_plan_name
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["id"])
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["id"])
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["name"].class.should == String }
77
+ @test_cases.each_value {|v| v[:name].class.should == String }
78
78
  end
@@ -1,5 +1,9 @@
1
- require 'simplecov'
2
- SimpleCov.start do
3
- add_group "Library", "lib/"
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
- require_relative '../../lib/test_linker'
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
@@ -0,0 +1,7 @@
1
+ require 'xmlrpc/client'
2
+
3
+ class XMLRPC::Client
4
+ def set_debug(new_logger=$stderr)
5
+ @http.set_debug_output(new_logger)
6
+ end
7
+ end
@@ -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['code']
104
- raise TestLinker::Error, "#{response.first['code']}: #{response.first['message']}"
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