rest-assured 0.3.2 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/Gemfile +4 -1
- data/README.markdown +47 -25
- data/bin/rest-assured +3 -3
- data/features/command_line_options.feature +2 -2
- data/features/rest_api/redirects.feature +10 -9
- data/features/ruby_api/create_double.feature +1 -6
- data/features/ruby_api/test_server.feature +42 -0
- data/features/ruby_api/verify_requests.feature +1 -6
- data/features/ruby_api/wait_for_requests.feature +2 -5
- data/features/step_definitions/command_line_options_steps.rb +1 -1
- data/features/step_definitions/doubles_steps.rb +4 -0
- data/features/step_definitions/redirect_rules_steps.rb +2 -6
- data/features/step_definitions/ruby_api_steps.rb +45 -0
- data/features/support/env.rb +9 -14
- data/features/support/world_helpers.rb +1 -1
- data/lib/rest-assured.rb +1 -45
- data/lib/rest-assured/api.rb +3 -0
- data/lib/rest-assured/api/app_runner.rb +18 -0
- data/lib/rest-assured/api/app_session.rb +33 -0
- data/lib/rest-assured/{client → api}/resources.rb +0 -0
- data/lib/rest-assured/api/server.rb +59 -0
- data/lib/rest-assured/application.rb +46 -0
- data/lib/rest-assured/config.rb +16 -3
- data/lib/rest-assured/models/redirect.rb +6 -0
- data/lib/rest-assured/routes/double.rb +1 -1
- data/lib/rest-assured/routes/redirect.rb +1 -1
- data/lib/rest-assured/routes/response.rb +4 -4
- data/lib/rest-assured/utils/drb_sniffer.rb +11 -0
- data/lib/rest-assured/utils/port_explorer.rb +22 -0
- data/lib/rest-assured/utils/subprocess.rb +50 -0
- data/lib/rest-assured/version.rb +1 -1
- data/prof-result.html +79521 -0
- data/rest-assured.gemspec +2 -1
- data/spec/api/app_runner_spec.rb +27 -0
- data/spec/api/app_session_spec.rb +51 -0
- data/spec/{client → api}/resource_double_spec.rb +1 -14
- data/spec/api/server_spec.rb +138 -0
- data/spec/config_spec.rb +111 -93
- data/spec/functional/response_spec.rb +5 -2
- data/spec/models/redirect_spec.rb +22 -0
- data/spec/port_explorer_spec.rb +32 -0
- data/spec/spec_helper.rb +25 -18
- data/spec/subprocess_spec.rb +138 -0
- data/spec/{custom_matchers.rb → support/custom_matchers.rb} +0 -0
- data/spec/support/reset-singleton.rb +15 -0
- metadata +66 -30
- data/lib/rest-assured/client.rb +0 -17
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
CHANGED
@@ -3,6 +3,7 @@ source "http://rubygems.org"
|
|
3
3
|
# Specify your gem's dependencies in rest-assured.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
gem 'awesome_print'
|
6
7
|
gem 'cucumber'
|
7
8
|
gem 'database_cleaner'
|
8
9
|
gem 'rspec'
|
@@ -12,6 +13,7 @@ gem 'capybara'
|
|
12
13
|
gem 'capybara-firebug'
|
13
14
|
gem 'rake'
|
14
15
|
gem 'mysql2'
|
16
|
+
gem 'sqlite3'
|
15
17
|
gem 'thin'
|
16
18
|
gem 'relish'
|
17
19
|
gem "spork", "> 0.9.0.rc"
|
@@ -25,8 +27,9 @@ group :local do
|
|
25
27
|
gem 'launchy'
|
26
28
|
gem "guard-spork"
|
27
29
|
if RUBY_PLATFORM =~ /darwin/
|
28
|
-
gem '
|
30
|
+
gem 'growl'
|
29
31
|
gem 'rb-fsevent'
|
32
|
+
gem 'rb-readline'
|
30
33
|
end
|
31
34
|
gem 'sinatra-activerecord'
|
32
35
|
end
|
data/README.markdown
CHANGED
@@ -19,7 +19,7 @@ Rest-assured requires a database to run. Either sqlite or mysql. So, make sure t
|
|
19
19
|
|
20
20
|
bash$ gem install sqlite3 # or mysql2
|
21
21
|
|
22
|
-
If using mysql, rest-assured expects database
|
22
|
+
If using mysql, rest-assured expects database `rest_assured` to be accessible by user `root` with no password. Those are defaults and can be changed with cli options.
|
23
23
|
|
24
24
|
It is also recommended to have thin installed. This improves startup time (over default webrick) and also it works with in-memory sqlite (which webrick does not):
|
25
25
|
|
@@ -36,11 +36,11 @@ Or clone from github and run:
|
|
36
36
|
bash$ cd rest-assured && bundle install
|
37
37
|
bash$ ./bin/rest-assured -d :memory: & # in-memory sqlite db
|
38
38
|
|
39
|
-
This starts up an instance of rest-assured on port 4578. It is accessible via REST or web interfaces on
|
39
|
+
This starts up an instance of rest-assured on port 4578. It is accessible via REST or web interfaces on `http://localhost:4578`
|
40
40
|
|
41
41
|
Various options (such as ssl, port, db credentials, etc.) are available through command line options. Check out `rest-assured -h` to see what they are.
|
42
42
|
|
43
|
-
NOTE that although sqlite is an extremely handy option (especially with :memory
|
43
|
+
NOTE that although sqlite is an extremely handy option (especially with `-d :memory:`), I found it sometimes locking tables under non-trivial load. Hence there is a Plan B - mysql. But may be that is just me sqliting it wrong.
|
44
44
|
|
45
45
|
## Doubles
|
46
46
|
|
@@ -50,21 +50,29 @@ Double is a stub/spy of HTTP request. Create a double that has the same request
|
|
50
50
|
|
51
51
|
Rest-assured provides client library to work with doubles. Check out 'Ruby API' section in [documentation](https://www.relishapp.com/artemave/rest-assured) for full reference.
|
52
52
|
|
53
|
-
|
53
|
+
Start up the server:
|
54
54
|
|
55
55
|
```ruby
|
56
|
-
|
56
|
+
# env.rb/spec_helper.rb
|
57
|
+
require 'rest-assured'
|
57
58
|
|
58
|
-
RestAssured::
|
59
|
+
RestAssured::Server.start(database: ':memory:', port: 7899) # or any other option available on command line
|
59
60
|
```
|
61
|
+
This server will be automatically shut down when your tests are done.
|
60
62
|
|
61
|
-
|
63
|
+
Alternatively, if you want to use existing server instance:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
RestAssured::Server.address = 'http://localhost:4578' # or wherever it is
|
67
|
+
```
|
68
|
+
|
69
|
+
You can now create doubles in your tests:
|
62
70
|
|
63
71
|
```ruby
|
64
72
|
RestAssured::Double.create(fullpath: '/products', content: 'this is content')
|
65
73
|
```
|
66
74
|
|
67
|
-
Now GET
|
75
|
+
Now GET `http://localhost:4578/products` will be returning `this is content`.
|
68
76
|
|
69
77
|
You can also verify what requests happen on a double, or, in other words, spy on a double. Say this is a Given part of a test:
|
70
78
|
|
@@ -72,7 +80,7 @@ You can also verify what requests happen on a double, or, in other words, spy on
|
|
72
80
|
@double = RestAssured::Double.create(fullpath: '/products', verb: 'POST')
|
73
81
|
```
|
74
82
|
|
75
|
-
Then let us assume that
|
83
|
+
Then let us assume that `http://localhost:4578/products` got POSTed as a result of some actions in When part. Now we can examine requests happened on that double in Then part:
|
76
84
|
|
77
85
|
```ruby
|
78
86
|
@double.wait_for_requests(1, timeout: 10) # defaults to 5 seconds
|
@@ -87,8 +95,8 @@ JSON.parse(req.rack_env)['ACCEPT'].should == 'text/html'
|
|
87
95
|
Use plain rest api to clear doubles/redirects between tests:
|
88
96
|
|
89
97
|
```ruby
|
90
|
-
RestClient.delete "#{RestAssured::
|
91
|
-
RestClient.delete "#{RestAssured::
|
98
|
+
RestClient.delete "#{RestAssured::Server.address}/redirects/all"
|
99
|
+
RestClient.delete "#{RestAssured::Server.address}/doubles/all"
|
92
100
|
```
|
93
101
|
|
94
102
|
### Plain REST API
|
@@ -97,13 +105,13 @@ For those using rest-assured from non-ruby environments.
|
|
97
105
|
|
98
106
|
#### Create double
|
99
107
|
|
100
|
-
HTTP POST to
|
108
|
+
HTTP POST to `/doubles` creates a double and returns its json representation.
|
101
109
|
The following options can be passed as request parameters:
|
102
110
|
|
103
|
-
- __fullpath__ - e.g.,
|
111
|
+
- __fullpath__ - e.g., `/some/api/object`, or with parameters in query string (useful for doubling GETs) - `/some/other/api/object?a=2&b=c`. Mandatory.
|
104
112
|
- __content__ - whatever you want this double to respond with. Optional.
|
105
|
-
- __verb__ - one of http the following http verbs: GET
|
106
|
-
- __status__ - status returned when double is requested. Optional. 200 is default.
|
113
|
+
- __verb__ - one of http the following http verbs: `GET`, `POST`, `PUT`, `DELETE`. Optional. `GET` is default.
|
114
|
+
- __status__ - status returned when double is requested. Optional. `200` is default.
|
107
115
|
- __response_headers__ - key/value map of headers. Optional.
|
108
116
|
|
109
117
|
Example:
|
@@ -118,7 +126,7 @@ For those using rest-assured from non-ruby environments.
|
|
118
126
|
|
119
127
|
#### Get double state
|
120
128
|
|
121
|
-
HTTP GET to
|
129
|
+
HTTP GET to `/doubles/:id.json` returns json with double current state. Use id from create json as `:id`.
|
122
130
|
|
123
131
|
Example:
|
124
132
|
|
@@ -148,7 +156,7 @@ For those using rest-assured from non-ruby environments.
|
|
148
156
|
}
|
149
157
|
}
|
150
158
|
|
151
|
-
The above assumes that that double has been requested once. Request history is in
|
159
|
+
The above assumes that that double has been requested once. Request history is in `requests` array (in chronological order). Each element contains the following data (keys):
|
152
160
|
|
153
161
|
- __body__ - request payload
|
154
162
|
- __params__ - request parameters. json
|
@@ -157,34 +165,34 @@ For those using rest-assured from non-ruby environments.
|
|
157
165
|
|
158
166
|
#### Delete all doubles
|
159
167
|
|
160
|
-
HTTP DELETE to
|
168
|
+
HTTP DELETE to `/doubles/all` deletes all doubles. Useful for cleaning up between tests.
|
161
169
|
|
162
170
|
## Redirects
|
163
171
|
|
164
|
-
It is sometimes desirable to only double certain calls while letting others through to the
|
172
|
+
It is sometimes desirable to only double certain calls while letting others through to the "real" services. Meet Redirects. Kind of "rewrite rules" for requests that didn't match any double.
|
165
173
|
|
166
|
-
Another potential use for redirects is setting up a
|
174
|
+
Another potential use for redirects is setting up a "default" double that matches multiple fullpaths. This is of course given your app does not mind an extra redirect. Also note that such "default" double still only covers single http verb so requests with different methods won't match (hint: need an extra double).
|
167
175
|
|
168
176
|
Here is the rest API for managing redirects:
|
169
177
|
|
170
178
|
### Create redirect
|
171
179
|
|
172
|
-
HTTP POST to
|
180
|
+
HTTP POST to `/redirects` creates redirect.
|
173
181
|
The following options can be passed as request parameters:
|
174
182
|
|
175
|
-
- __pattern__ - regex (perl5 style) tested against request fullpath. Mandatory
|
176
|
-
- __to__ - url base e.g
|
183
|
+
- __pattern__ - regex (perl5 style) tested against request fullpath. e.g, `^/auth/(.*)`. Mandatory
|
184
|
+
- __to__ - url base e.g, `http://example.com/api/\1?p=1` where `\1` is a reference to captured group from the pattern. Mandatory
|
177
185
|
|
178
186
|
Example:
|
179
187
|
|
180
188
|
bash$ curl -d 'pattern=^/auth&to=https://myserver.com/api' http://localhost:4578/redirects
|
181
189
|
|
182
|
-
Now request (any verb) to
|
190
|
+
Now request (any verb) to `http://localhost:4578/auth/services/1` will get redirected to `https://myserver.com/api/`. Provided of course there is no double matched for that fullpath and verb. Captured group in pattern can be referenced from replacement e.g. `\1`, `\2`, etc.
|
183
191
|
Much like rewrite rules, redirects are evaluated in order (of creation). In UI you can manually rearrange the order.
|
184
192
|
|
185
193
|
### Delete all redirects
|
186
194
|
|
187
|
-
HTTP DELETE to
|
195
|
+
HTTP DELETE to `/redirects/all` deletes all redirects. Useful for cleaning up between tests.
|
188
196
|
|
189
197
|
## Author
|
190
198
|
|
@@ -192,6 +200,20 @@ Here is the rest API for managing redirects:
|
|
192
200
|
|
193
201
|
## Changelog
|
194
202
|
|
203
|
+
#### 1.0.0.rc1 (13 Feb 2012)
|
204
|
+
|
205
|
+
* start/stop rest-assured via api
|
206
|
+
* redirects support pattern/replacement
|
207
|
+
|
208
|
+
#### 0.3.2 (23 Jan 2012)
|
209
|
+
|
210
|
+
* double 'activeness' does not take verb into account (bugfix)
|
211
|
+
|
212
|
+
#### 0.3.1 (09 Jan 2012)
|
213
|
+
|
214
|
+
* lock rack version to <= 1.3.6 until they release fix for
|
215
|
+
https://github.com/rack/rack/issues/299
|
216
|
+
|
195
217
|
#### 0.3 (12 Dec 2011)
|
196
218
|
|
197
219
|
* you can now specify response headers for double to respond with
|
data/bin/rest-assured
CHANGED
@@ -51,8 +51,8 @@ OptionParser.new do |opts|
|
|
51
51
|
user_opts[:logfile] = logfile
|
52
52
|
end
|
53
53
|
|
54
|
-
opts.on('--ssl', "Whether or not to run on https. Defaults to false (http)") do
|
55
|
-
user_opts[:
|
54
|
+
opts.on('--ssl', "Whether or not to run on https. Defaults to false (http)") do
|
55
|
+
user_opts[:ssl] = true
|
56
56
|
end
|
57
57
|
|
58
58
|
opts.on('-c', '--ssl_cert FILENAME', "Path to ssl_cert. Defaults to self signed certificate shipped with rest-assured") do |ssl_cert|
|
@@ -71,5 +71,5 @@ end.parse!
|
|
71
71
|
|
72
72
|
RestAssured::Config.build(user_opts)
|
73
73
|
|
74
|
-
require 'rest-assured'
|
74
|
+
require 'rest-assured/application'
|
75
75
|
RestAssured::Application.run!
|
@@ -54,10 +54,10 @@ Feature: command line options
|
|
54
54
|
|
55
55
|
Scenario Outline: use ssl option
|
56
56
|
When I start rest-assured with <option>
|
57
|
-
Then rest-assured should "<
|
57
|
+
Then rest-assured should "<ssl>"
|
58
58
|
|
59
59
|
Examples:
|
60
|
-
| option |
|
60
|
+
| option | ssl |
|
61
61
|
| | false |
|
62
62
|
| --ssl | true |
|
63
63
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
@now
|
1
2
|
Feature: manage redirect rules
|
2
3
|
In order to be able to mock only part of api
|
3
4
|
As a developer
|
@@ -10,21 +11,21 @@ Feature: manage redirect rules
|
|
10
11
|
|
11
12
|
Scenario: add redirect rule
|
12
13
|
Given blank slate
|
13
|
-
When I
|
14
|
+
When I create redirect from "^/api/(.*)" to "http://example.com/\1"
|
14
15
|
And I request "/api/something"
|
15
|
-
Then it should redirect to "http://
|
16
|
+
Then it should redirect to "http://example.com/something"
|
16
17
|
|
17
18
|
Scenario: add second redirect that match the same request
|
18
|
-
Given there is redirect
|
19
|
-
When I
|
19
|
+
Given there is redirect from "/api/something" to "http://example.com"
|
20
|
+
When I create redirect from "/api/some.*" to "http://real.com"
|
20
21
|
And I request "/api/something"
|
21
|
-
Then it should redirect to "http://
|
22
|
+
Then it should redirect to "http://example.com/"
|
22
23
|
|
23
24
|
Scenario: add second redirect that does not match the same request
|
24
|
-
Given there is redirect
|
25
|
-
When I
|
26
|
-
And I request "/api/
|
27
|
-
Then it should redirect to "http://
|
25
|
+
Given there is redirect from "/api/thing" to "http://real.com"
|
26
|
+
When I create redirect from "/api/some.*" to "http://example.com"
|
27
|
+
And I request "/api/something"
|
28
|
+
Then it should redirect to "http://example.com/"
|
28
29
|
|
29
30
|
Scenario: clear redirects
|
30
31
|
Given there are some redirects
|
@@ -1,14 +1,9 @@
|
|
1
|
+
@ruby_api
|
1
2
|
Feature: create double
|
2
3
|
As ruby developer
|
3
4
|
I want to be able to create doubles via client api
|
4
5
|
So that interactions with rest-assured server are completely hidden from me
|
5
6
|
|
6
|
-
Background:
|
7
|
-
Given rest-assured is running locally:
|
8
|
-
"""
|
9
|
-
RestAssured::Client.config.server_address = 'http://localhost:9876'
|
10
|
-
"""
|
11
|
-
|
12
7
|
Scenario: default options
|
13
8
|
When I create a double:
|
14
9
|
"""
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Feature: test server
|
2
|
+
In order to have easy integration with my test code
|
3
|
+
As a ruby developer
|
4
|
+
I want to have a client library take care of starting/stopping an instance of rest-assured appropriately
|
5
|
+
|
6
|
+
Scenario: start rest-assured server
|
7
|
+
Given there is free tcp port
|
8
|
+
When I start rest-assured server via client library:
|
9
|
+
"""
|
10
|
+
RestAssured::Server.start(:port => @free_tcp_port)
|
11
|
+
"""
|
12
|
+
Then rest-assured server should be running:
|
13
|
+
"""
|
14
|
+
RestAssured::Server.should be_up
|
15
|
+
"""
|
16
|
+
|
17
|
+
Scenario: start asyncronously (so that other heavy setup - e.g. firefox startup - can be done in parallel)
|
18
|
+
Given there is free tcp port
|
19
|
+
When I start rest-assured asyncronously:
|
20
|
+
"""
|
21
|
+
RestAssured::Server.start!(:port => @free_tcp_port)
|
22
|
+
"""
|
23
|
+
Then rest-assured server should not be running:
|
24
|
+
"""
|
25
|
+
RestAssured::Server.should_not be_up
|
26
|
+
"""
|
27
|
+
When it finally comes up
|
28
|
+
Then rest-assured server should be running:
|
29
|
+
"""
|
30
|
+
RestAssured::Server.should be_up
|
31
|
+
"""
|
32
|
+
|
33
|
+
Scenario: stop rest-assured server
|
34
|
+
Given rest-assured has been started via client library
|
35
|
+
When I stop it:
|
36
|
+
"""
|
37
|
+
RestAssured::Server.stop
|
38
|
+
"""
|
39
|
+
Then it should be stopped:
|
40
|
+
"""
|
41
|
+
RestAssured::Server.should_not be_up
|
42
|
+
"""
|
@@ -1,14 +1,9 @@
|
|
1
|
+
@ruby_api
|
1
2
|
Feature: verify requests that happened on double
|
2
3
|
In order to check that my app is performing correct requests
|
3
4
|
As test developer
|
4
5
|
I want to be able to get double 'call history'
|
5
6
|
|
6
|
-
Background:
|
7
|
-
Given rest-assured is running locally:
|
8
|
-
"""
|
9
|
-
RestAssured::Client.config.server_address = 'http://localhost:9876'
|
10
|
-
"""
|
11
|
-
|
12
7
|
Scenario: no calls made to double
|
13
8
|
Given I created a double:
|
14
9
|
"""
|
@@ -1,14 +1,11 @@
|
|
1
|
+
@ruby_api
|
1
2
|
Feature: wait for requests on double to happen
|
2
3
|
In order to know when it is a good time to verify requests on a double
|
3
4
|
As test developer
|
4
5
|
I want to be able to wait until specified number of requests happen
|
5
6
|
|
6
7
|
Background:
|
7
|
-
Given
|
8
|
-
"""
|
9
|
-
RestAssured::Client.config.server_address = 'http://localhost:9876'
|
10
|
-
"""
|
11
|
-
And I created a double:
|
8
|
+
Given I created a double:
|
12
9
|
"""
|
13
10
|
@double = RestAssured::Double.create(:fullpath => '/some/api')
|
14
11
|
"""
|
@@ -2,18 +2,14 @@ Then /^I should get (\d+)$/ do |code|
|
|
2
2
|
last_response.status.should.to_s == code
|
3
3
|
end
|
4
4
|
|
5
|
-
|
5
|
+
When /^(?:I create|there is) redirect from "([^"]*)" to "([^"]*)"$/ do |pattern, url|
|
6
6
|
post '/redirects', { :pattern => pattern, :to => url }
|
7
7
|
last_response.should be_ok
|
8
8
|
end
|
9
9
|
|
10
|
-
When /^I register redirect with pattern "([^"]*)" and uri "([^"]*)"$/ do |pattern, url|
|
11
|
-
step %{there is redirect with pattern "#{pattern}" and uri "#{url}"}
|
12
|
-
end
|
13
|
-
|
14
10
|
Then /^it should redirect to "([^"]*)"$/ do |real_api_url|
|
15
11
|
follow_redirect!
|
16
|
-
|
12
|
+
last_request.url.should == real_api_url
|
17
13
|
end
|
18
14
|
|
19
15
|
Given /^the following redirects exist:$/ do |redirects|
|
@@ -66,3 +66,48 @@ end
|
|
66
66
|
Then /^the following should be true:$/ do |code|
|
67
67
|
eval code
|
68
68
|
end
|
69
|
+
|
70
|
+
Given /^there is free tcp port$/ do
|
71
|
+
@free_tcp_port = RestAssured::Utils::PortExplorer.free_port
|
72
|
+
end
|
73
|
+
|
74
|
+
When /^I start rest-assured server via client library:$/ do |code|
|
75
|
+
eval code
|
76
|
+
end
|
77
|
+
|
78
|
+
Then /^rest\-assured server should be running:$/ do |code|
|
79
|
+
eval code
|
80
|
+
end
|
81
|
+
|
82
|
+
When /^I start rest\-assured asyncronously:$/ do |code|
|
83
|
+
eval code
|
84
|
+
end
|
85
|
+
|
86
|
+
Then /^rest\-assured server should not be running:$/ do |code|
|
87
|
+
eval code
|
88
|
+
end
|
89
|
+
|
90
|
+
When /^it finally comes up$/ do
|
91
|
+
timeout(5) do
|
92
|
+
loop do
|
93
|
+
begin
|
94
|
+
Net::HTTP.new('localhost', @free_tcp_port).head('/')
|
95
|
+
break
|
96
|
+
rescue Errno::ECONNREFUSED
|
97
|
+
sleep 1
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
Given /^rest\-assured has been started via client library$/ do
|
104
|
+
RestAssured::Server.start(:port => RestAssured::Utils::PortExplorer.free_port)
|
105
|
+
end
|
106
|
+
|
107
|
+
When /^I stop it:$/ do |code|
|
108
|
+
eval code
|
109
|
+
end
|
110
|
+
|
111
|
+
Then /^it should be stopped:$/ do |code|
|
112
|
+
eval code
|
113
|
+
end
|