apirunner 0.1.5 → 0.1.6

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.
data/Gemfile CHANGED
@@ -7,7 +7,8 @@ source "http://rubygems.org"
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
 
9
9
  gem 'nokogiri', '~> 1.4.3.1'
10
- gem 'httparty', '~> 0.6.1'
10
+ #gem 'httparty', '~> 0.6.1'
11
+ gem 'rest-client', '>= 1.6.1'
11
12
 
12
13
  group :development do
13
14
  gem "rspec", ">= 2.0.0.beta.19"
data/Gemfile.lock CHANGED
@@ -2,7 +2,6 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  builder (2.1.2)
5
- crack (0.1.8)
6
5
  cucumber (0.8.5)
7
6
  builder (~> 2.1.2)
8
7
  diff-lcs (~> 1.1.2)
@@ -13,18 +12,19 @@ GEM
13
12
  gherkin (2.1.5)
14
13
  trollop (~> 1.16.2)
15
14
  git (1.2.5)
16
- httparty (0.6.1)
17
- crack (= 0.1.8)
18
15
  jeweler (1.5.0.pre3)
19
16
  bundler (~> 1.0.0)
20
17
  git (>= 1.2.5)
21
18
  rake
22
19
  json_pure (1.4.6)
20
+ mime-types (1.16)
23
21
  mocha (0.9.8)
24
22
  rake
25
23
  nokogiri (1.4.3.1)
26
24
  rake (0.8.7)
27
25
  rcov (0.9.9)
26
+ rest-client (1.6.1)
27
+ mime-types (>= 1.16)
28
28
  rspec (2.0.0.beta.22)
29
29
  rspec-core (= 2.0.0.beta.22)
30
30
  rspec-expectations (= 2.0.0.beta.22)
@@ -44,9 +44,9 @@ PLATFORMS
44
44
  DEPENDENCIES
45
45
  bundler (~> 1.0.0)
46
46
  cucumber
47
- httparty (~> 0.6.1)
48
47
  jeweler (~> 1.5.0.pre3)
49
48
  mocha (>= 0.9.8)
50
49
  nokogiri (~> 1.4.3.1)
51
50
  rcov
51
+ rest-client (>= 1.6.1)
52
52
  rspec (>= 2.0.0.beta.19)
data/README.rdoc CHANGED
@@ -26,6 +26,7 @@ apirunner was initially developed for testing of the mighty (m8ty) i18n recommen
26
26
  * print out a nice error report (that you as a awesome ruby coder will never see)
27
27
  * be invoked from within rake to generate some example configuration and testcase files
28
28
  * be invoked also from within rake to run your test's
29
+ * not travel to Ibiza
29
30
 
30
31
  == Installation
31
32
 
@@ -45,6 +46,44 @@ Additionally there will be some example testcases which can be found in:
45
46
  test/apirunner/002_delete_ressource.yml
46
47
  test/apirunner/excludes.yml
47
48
 
49
+ At first take some time and change config/api_runner.yml to your needs. You might for example want to test your app locally on localhost:3000, on staging machine and on production environment too. So your api_runner.yml could look like that:
50
+
51
+ local:
52
+ protocol: http
53
+ host: localhost
54
+ port: 3000
55
+ namespace: api
56
+ staging:
57
+ protocol: http
58
+ host: staging.yourstagingdomain.dom
59
+ port: 80
60
+ namespace: api
61
+ production:
62
+ protocol: https
63
+ host: www.yourproductiondomain.dom
64
+ port: 80
65
+ namespace: prod_api
66
+
67
+ Take a look at "namespace" here. It makes the expectation matcher build ressource URI's like so:
68
+
69
+ http://localhost:3000/api
70
+ http://staging.yourstagingdomain.dom/api
71
+ http://www.yourproductiondomain.dom/prod_api
72
+
73
+ The ressource pathes are simply appended before the request is sent.
74
+
75
+ The file also generates your rake tasks dynamically. The above config will generate 3 new tasks:
76
+
77
+ api:run:local
78
+ api:run:staging
79
+ api:run:production
80
+
81
+ == Excludes
82
+
83
+ You may also want to define some excludes for some of your environment. Imageine on your localhost's server there is no "Last-Modified" present in the header, but you would like to check that on staging and production boxes.
84
+
85
+ Simply define your story to check "Last-Modified" generally and exclude it for
86
+
48
87
  == Invocation
49
88
 
50
89
  Assuming you defined an environment "local" and "staging" you can invoke your masterpiece with:
@@ -68,6 +107,18 @@ apirunner heavily depends on the following great GEM's:
68
107
  1) nokogiri
69
108
  2) httparty
70
109
 
110
+ == Examples
111
+
112
+ After invoking:
113
+
114
+ rake api:scaffold
115
+
116
+ you will find some YAML example files for request and expectation generation in test/api_runner. You can create as many story files here as you like, they are executed in the order they are read from the filesystem, so you should name them like 000_create_some_ressource.yml, 001_read_some_ressource.yml and so on.
117
+
118
+ Alternatively you can place all your stories into one single file.
119
+
120
+ Addition
121
+
71
122
  == Authors
72
123
 
73
124
  apirunner was written by:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.5
1
+ 0.1.6
data/apirunner.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{apirunner}
8
- s.version = "0.1.5"
8
+ s.version = "0.1.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["jan@moviepilot.com"]
12
- s.date = %q{2010-09-22}
12
+ s.date = %q{2010-09-23}
13
13
  s.description = %q{apirunner is a testsuite to query your RESTful JSON API and match response with your defined expectations}
14
14
  s.email = %q{developers@moviepilot.com}
15
15
  s.extra_rdoc_files = [
@@ -63,7 +63,7 @@ Gem::Specification.new do |s|
63
63
 
64
64
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
65
65
  s.add_runtime_dependency(%q<nokogiri>, ["~> 1.4.3.1"])
66
- s.add_runtime_dependency(%q<httparty>, ["~> 0.6.1"])
66
+ s.add_runtime_dependency(%q<rest-client>, [">= 1.6.1"])
67
67
  s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
68
68
  s.add_development_dependency(%q<cucumber>, [">= 0"])
69
69
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
@@ -77,7 +77,7 @@ Gem::Specification.new do |s|
77
77
  s.add_development_dependency(%q<rcov>, [">= 0"])
78
78
  else
79
79
  s.add_dependency(%q<nokogiri>, ["~> 1.4.3.1"])
80
- s.add_dependency(%q<httparty>, ["~> 0.6.1"])
80
+ s.add_dependency(%q<rest-client>, [">= 1.6.1"])
81
81
  s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
82
82
  s.add_dependency(%q<cucumber>, [">= 0"])
83
83
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
@@ -92,7 +92,7 @@ Gem::Specification.new do |s|
92
92
  end
93
93
  else
94
94
  s.add_dependency(%q<nokogiri>, ["~> 1.4.3.1"])
95
- s.add_dependency(%q<httparty>, ["~> 0.6.1"])
95
+ s.add_dependency(%q<rest-client>, [">= 1.6.1"])
96
96
  s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
97
97
  s.add_dependency(%q<cucumber>, [">= 0"])
98
98
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
@@ -5,13 +5,42 @@
5
5
  method: 'PUT'
6
6
  body:
7
7
  username: 'duffyduck'
8
+ watchlist:
9
+ - m333
10
+ - m79
11
+ blacklist:
12
+ - m334
13
+ - m77
14
+ skiplist:
15
+ - m335
16
+ - m78
17
+ ratings:
18
+ m336: 4
19
+ m79: 2.5
20
+ m777: 3.0
21
+ m567: 4.0
22
+ m354: 5.0
23
+ expires_at: 2011-09-09T22:41:50+00:00
8
24
  response_expectation:
9
25
  status_code: 201
10
26
  headers:
11
27
  Last-Modified: /.*/
12
28
  body:
13
29
  username: 'duffyduck'
14
- fsk: "17"
30
+ watchlist:
31
+ - m333
32
+ - m79
33
+ blacklist:
34
+ - m334
35
+ - m77
36
+ skiplist:
37
+ - m335
38
+ - m78
39
+ ratings:
40
+ m336: 4.0
41
+ m79: 2.5
42
+ fsk: "18"
43
+ expires_at: Fri, 09 Sep 2011 22:41:50 +0000
15
44
  - name: 'Update existing User - Update watchlist'
16
45
  request:
17
46
  path: '/users/duffyduck/watchlist'
@@ -22,4 +51,75 @@
22
51
  response_expectation:
23
52
  status_code: 204
24
53
  body:
25
-
54
+ - name: 'Check User FSK,Watchlist'
55
+ request:
56
+ path: '/users/duffyduck'
57
+ method: 'GET'
58
+ response_expectation:
59
+ status_code: 200
60
+ headers:
61
+ Last-Modified: /.*/
62
+ body:
63
+ username: 'duffyduck'
64
+ fsk: "18"
65
+ watchlist:
66
+ - m367
67
+ - m73
68
+ blacklist:
69
+ - m334
70
+ - m77
71
+ skiplist:
72
+ - m335
73
+ - m78
74
+ ratings:
75
+ m336: 4.0
76
+ m79: 2.5
77
+ - name: 'Set 10 Ratings'
78
+ request:
79
+ path: '/users/duffyduck/ratings'
80
+ method: 'PUT'
81
+ body:
82
+ "m1035": 4
83
+ "m2087": 3
84
+ "m1554": 2
85
+ "m2981": 1
86
+ "m1590": 2
87
+ "m1056": 3
88
+ "m12493": 4
89
+ "m1875": 5
90
+ "m7258": 2.5
91
+ "m7339": 3.5
92
+ response_expectation:
93
+ status_code: 204
94
+ headers:
95
+ Last-Modified: /.*/
96
+ - name: 'Check User Ratings Update'
97
+ request:
98
+ path: '/users/duffyduck'
99
+ method: 'GET'
100
+ response_expectation:
101
+ status_code: 200
102
+ headers:
103
+ Last-Modified: /.*/
104
+ body:
105
+ username: 'duffyduck'
106
+ fsk: "18"
107
+ watchlist:
108
+ - m367
109
+ - m73
110
+ blacklist:
111
+ - m334
112
+ - m77
113
+ skiplist:
114
+ - m335
115
+ - m78
116
+ ratings:
117
+ "m1035": "1.0"
118
+ "m2087": "3.0"
119
+ "m1554": "2.0"
120
+ "m1590": "2.0"
121
+ "m1056": "3.0"
122
+ "m12493": "4.0"
123
+ "m1875": "5.0"
124
+ "m7258": "2.5"
125
+ "m7339": "3.5"
data/lib/api_runner.rb CHANGED
@@ -10,13 +10,13 @@ class ApiRunner
10
10
 
11
11
  # initializes the object, loads environment, build base_uri
12
12
  def initialize(env)
13
- @http_client = HttpClient.new
14
13
  @spec = []
15
14
  @errors = []
16
15
  @excludes = []
17
16
  load_config(env)
18
17
  load_excludes(env)
19
18
  load_url_spec
19
+ @http_client = HttpClient.new(@host, @port, @namespace)
20
20
  @expectation = ExpectationMatcher.new(@excludes)
21
21
  end
22
22
 
@@ -37,7 +37,7 @@ class ApiRunner
37
37
  # runs all testcases that are provided by the testclass an fills errors if there are any
38
38
  def run_tests
39
39
  @spec.each do |test_case|
40
- response = send_request(test_case['request']['method'].downcase.to_sym, target_uri(test_case['request']['path']), {:body => test_case['request']['body'].to_json})
40
+ response = send_request(test_case['request']['method'].downcase.to_sym, test_case['request']['path'], test_case['request']['body'])
41
41
  @expectation.test_types.each do |test_type|
42
42
  test = @expectation.check(test_type, response, test_case)
43
43
  if not test.succeeded
@@ -57,12 +57,13 @@ class ApiRunner
57
57
  end
58
58
 
59
59
  # builds target uri from base uri generated of host port and namespace as well as the ressource path
60
- def target_uri(ressource_path)
61
- "#{@protocol}://#{@host}:#{@port}/#{@namespace}" + ressource_path
60
+ def target_uri
61
+ "#{@protocol}://#{@host}"
62
62
  end
63
63
 
64
64
  # returns true if server is available
65
65
  def server_is_available?
66
+ return true
66
67
  !@http_client.send_request(:get, "#{@protocol}://#{@host}:#{@port}", {:timeout => 5}).nil?
67
68
  end
68
69
 
@@ -83,7 +84,7 @@ class ApiRunner
83
84
  # loads and parses items that need to be excluded from the checks in certain environments
84
85
  def load_excludes(env)
85
86
  excludes_file = self.class.excludes_file
86
- @excludes = YAML.load_file(excludes_file).detect{ |a| a.first == env.to_s }[1]["excludes"]
87
+ @excludes = YAML.load_file(excludes_file).detect{ |a| a.first == env.to_s }[1]["excludes"] rescue nil
87
88
  end
88
89
 
89
90
  # returns config files path and can be stubbed this way
@@ -22,7 +22,7 @@ class ExpectationMatcher
22
22
  def response_code(response, testcase)
23
23
  result_struct = Struct.new(:succeeded, :error)
24
24
  results = result_struct.new(:succeeded => true, :error => nil)
25
- if not testcase['response_expectation']['status_code'] == response.code
25
+ if not testcase['response_expectation']['status_code'].to_s == response.code.to_s
26
26
  results.succeeded = false
27
27
  results.error = "testcase '#{testcase['name']}'\n expected response code --#{testcase['response_expectation']['status_code']}--\n got response code --#{response.code}--"
28
28
  end
@@ -64,6 +64,10 @@ class ExpectationMatcher
64
64
 
65
65
  # matches the given attributes and values against the ones from the response body
66
66
  def response_body(response, testcase)
67
+ puts("Testcase #{testcase['name']}\n")
68
+ puts("got response --#{response.body}--\n\n")
69
+ puts("exp response --#{testcase['response_expectation']['body']}--\n")
70
+ puts("___________________________\n\n\n")
67
71
  result_struct = Struct.new(:succeeded, :error)
68
72
  results = result_struct.new(:succeeded => true, :error => nil)
69
73
 
data/lib/http_client.rb CHANGED
@@ -1,10 +1,70 @@
1
1
  class HttpClient
2
+ require 'net/http'
3
+ require 'JSON'
4
+
5
+ def initialize(host, port, namespace)
6
+ @http = Net::HTTP.new(host, port)
7
+ @host = host
8
+ @port = port
9
+ @namespace = namespace
10
+ end
11
+
12
+ def send_request(method, resource, data=nil)
13
+ build_response(self.send(method.to_s.downcase, resource, data))
14
+ end
15
+
16
+ protected
17
+
18
+ # returns struct containing response.code, headers, body and message
19
+ # this is only for easily interfaceing another http client
20
+ def build_response(raw_response)
21
+ response_struct = Struct.new(:code, :message, :headers, :body)
22
+ response = response_struct.new
23
+ response.code = raw_response.code
24
+ response.message = raw_response.message
25
+ response.body = raw_response.body
26
+ response.headers = raw_response.header
27
+ response
28
+ end
29
+
30
+ def get(resource, params)
31
+ request = Net::HTTP::Get.new(resource_path(resource), initheader = {'Content-Type' =>'application/json'})
32
+ response = @http.request(request)
33
+ return response
34
+ end
35
+
36
+ def put(resource, data)
37
+ request = Net::HTTP::Put.new(resource_path(resource), initheader = {'Content-Type' =>'application/json'})
38
+ request.body = data.to_json
39
+ response = @http.request(request)
40
+ end
41
+
42
+ def post(resource, data)
43
+ request = Net::HTTP::Post.new(resource_path(resource), initheader = {'Content-Type' =>'application/json'})
44
+ request.body = data.to_json
45
+ response = @http.request(request)
46
+ end
47
+
48
+
49
+ def delete(resource, params)
50
+ request = Net::HTTP::Delete.new(resource_path(resource), initheader = {'Content-Type' =>'application/json'})
51
+ response = @http.request(request)
52
+ end
53
+
54
+ def resource_path(resource)
55
+ "/" + @namespace + resource
56
+ end
57
+ end
58
+
59
+
60
+ class HttPartyClient
2
61
  require 'httparty'
3
62
  include HTTParty
4
63
 
5
64
  # sends http request with given method, uri and data and returns servers response
6
65
  def send_request(method, uri, data=nil)
7
- build_response(self.class.send(method, uri, data ||= {}))
66
+ options = { :body => data.to_json, :format => :json }
67
+ build_response(self.class.send(method, uri, options))
8
68
  end
9
69
 
10
70
  protected
data/lib/tasks/api.rake CHANGED
@@ -1,5 +1,7 @@
1
- config = YAML.load_file("#{Rails.root}/vendor/plugins/telekom_api/config/api_runner.yaml")
2
-
1
+ begin
2
+ config = YAML.load_file("#{Rails.root}/config/api_runner.yml")
3
+ rescue
4
+ end
3
5
  namespace :api do
4
6
  namespace :run do
5
7
  config.each_key do |env|
@@ -10,7 +12,7 @@ namespace :api do
10
12
  api_runner.run
11
13
  puts "\nTestrun finished\n\n"
12
14
  end
13
- end
15
+ end unless config.nil?
14
16
  end
15
17
  desc "generates configuration and a skeleton for apirunner tests as well as excludes"
16
18
  task :scaffold do
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 5
9
- version: 0.1.5
8
+ - 6
9
+ version: 0.1.6
10
10
  platform: ruby
11
11
  authors:
12
12
  - jan@moviepilot.com
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-22 00:00:00 +02:00
17
+ date: 2010-09-23 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -34,17 +34,17 @@ dependencies:
34
34
  prerelease: false
35
35
  version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency
37
- name: httparty
37
+ name: rest-client
38
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
- - - ~>
41
+ - - ">="
42
42
  - !ruby/object:Gem::Version
43
43
  segments:
44
- - 0
44
+ - 1
45
45
  - 6
46
46
  - 1
47
- version: 0.6.1
47
+ version: 1.6.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: *id002
@@ -263,7 +263,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
263
263
  requirements:
264
264
  - - ">="
265
265
  - !ruby/object:Gem::Version
266
- hash: -2331822948028323562
266
+ hash: -4500206872193641389
267
267
  segments:
268
268
  - 0
269
269
  version: "0"