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.
@@ -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