rest-assured 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/Gemfile +17 -0
- data/LICENSE +22 -0
- data/README.markdown +78 -0
- data/Rakefile +4 -0
- data/bin/console +12 -0
- data/bin/rest-assured +28 -0
- data/cucumber.yml +3 -0
- data/db/migrate/20110620161740_add_fixtures.rb +12 -0
- data/db/migrate/20110625155332_add_redirects_table.rb +12 -0
- data/db/migrate/20110709150645_add_description_to_fixtures.rb +9 -0
- data/db/migrate/20110807222522_add_active_bit_to_fixtures.rb +9 -0
- data/db/migrate/20110818155555_add_position_to_redirects.rb +9 -0
- data/db/migrate/20110823132023_add_method_to_fixtures.rb +9 -0
- data/db/migrate/20110912162948_rename_url_to_fullpath.rb +9 -0
- data/db/migrate/20110912163705_rename_fixtures_to_doubles.rb +9 -0
- data/features/doubles_via_api.feature +50 -0
- data/features/doubles_via_ui.feature +66 -0
- data/features/persistence.feature +24 -0
- data/features/redirect_rules_via_api.feature +29 -0
- data/features/redirect_rules_via_ui.feature +68 -0
- data/features/step_definitions/doubles_steps.rb +143 -0
- data/features/step_definitions/persistence_steps.rb +13 -0
- data/features/step_definitions/redirect_rules_steps.rb +64 -0
- data/features/step_definitions/support/numeric_transforms.rb +3 -0
- data/features/support/env.rb +71 -0
- data/lib/rest-assured.rb +66 -0
- data/lib/rest-assured/config.rb +11 -0
- data/lib/rest-assured/init.rb +12 -0
- data/lib/rest-assured/models/double.rb +30 -0
- data/lib/rest-assured/models/redirect.rb +37 -0
- data/lib/rest-assured/routes/double.rb +77 -0
- data/lib/rest-assured/routes/redirect.rb +71 -0
- data/lib/rest-assured/version.rb +3 -0
- data/lib/sinatra/partials.rb +18 -0
- data/public/css/grid.inuit.css +76 -0
- data/public/css/inuit.css +904 -0
- data/public/css/jquery.jgrowl.css +132 -0
- data/public/css/style.css +88 -0
- data/public/img/css/12-grid-720.png +0 -0
- data/public/img/css/12-grid.png +0 -0
- data/public/img/css/baseline.gif +0 -0
- data/public/img/css/grid-720.png +0 -0
- data/public/img/css/grid.png +0 -0
- data/public/img/css/icons/error.png +0 -0
- data/public/img/css/icons/info.png +0 -0
- data/public/img/css/icons/success.png +0 -0
- data/public/img/css/icons/warning.png +0 -0
- data/public/javascript/application.js +12 -0
- data/public/javascript/jquery.jgrowl_minimized.js +11 -0
- data/rest-assured.gemspec +36 -0
- data/spec/functional/double_routes_spec.rb +117 -0
- data/spec/functional/redirect_routes_spec.rb +108 -0
- data/spec/models/double_spec.rb +73 -0
- data/spec/models/redirect_spec.rb +38 -0
- data/spec/spec_helper.rb +47 -0
- data/views/base.scss +11 -0
- data/views/doubles/_form.haml +16 -0
- data/views/doubles/edit.haml +4 -0
- data/views/doubles/index.haml +41 -0
- data/views/doubles/new.haml +3 -0
- data/views/layout.haml +25 -0
- data/views/redirects/_form.haml +11 -0
- data/views/redirects/edit.haml +4 -0
- data/views/redirects/index.haml +33 -0
- data/views/redirects/new.haml +3 -0
- metadata +250 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in rest-assured.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'cucumber'
|
7
|
+
gem 'database_cleaner'
|
8
|
+
gem 'rspec'
|
9
|
+
gem 'shoulda-matchers'
|
10
|
+
gem 'rack-test'
|
11
|
+
gem 'capybara'
|
12
|
+
gem 'capybara-firebug'
|
13
|
+
gem RUBY_VERSION =~ /^1\.8/ ? 'ruby-debug' : 'ruby-debug19'
|
14
|
+
gem 'awesome_print'
|
15
|
+
gem 'interactive_editor'
|
16
|
+
gem 'launchy'
|
17
|
+
#gem 'akephalos', git: 'https://github.com/Nerian/akephalos.git'
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2011, Artem Avetisyan, British Broadcasting Corporation
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# REST assured
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
A tool for stubbing/mocking external http based services that app under test is talking to. This is useful for blackbox testing or in cases where it is not possible to access application objects directly from test code.
|
6
|
+
There are three main use cases:
|
7
|
+
|
8
|
+
* stubbing out external data sources with predefined data, so that test code has known data to assert against
|
9
|
+
* setting expectations on messages to external services (currently not yet implemented)
|
10
|
+
* mimic different responses from external services during development. For that purpose there is web UI
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
You are going to need ruby >= 1.8.7. Install gem and run:
|
15
|
+
|
16
|
+
sudo gem install rest-assured # omit sudo if using rvm
|
17
|
+
rest-assured &
|
18
|
+
|
19
|
+
Or clone from github and run:
|
20
|
+
|
21
|
+
git clone git@github.com:BBC/rest-assured.git
|
22
|
+
./rest-assured/bin/rest-assured &
|
23
|
+
|
24
|
+
This starts an instance of rest-assured on port 4578 (changable with --port option) and creates rest-assured.db (changable with --database option) in the current directory. You can now access it via REST or web interfaces on http://localhost:4578
|
25
|
+
|
26
|
+
### Doubles
|
27
|
+
|
28
|
+
Double is a stub/mock of a particular external call. There is the following rest API for setting up doubles:
|
29
|
+
|
30
|
+
* `POST '/doubles', { request_fullpath: path, content: content, method: method }`
|
31
|
+
Creates double with the following parameters:
|
32
|
+
|
33
|
+
- __request_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.
|
34
|
+
- __content__ - whatever you want this double to respond with. Mandatory.
|
35
|
+
- __method__ - one of http the following http verbs: GET, POST, PUT, DELETE. Optional. GET is default.
|
36
|
+
|
37
|
+
Example (using ruby RestClient):
|
38
|
+
|
39
|
+
RestClient.post 'http://localhost:4578:/doubles', { request_fullpath: '/api/v2/products?type=fresh', method: 'GET', content: 'this is list of products' }
|
40
|
+
|
41
|
+
Now GETting http://localhost:4578/api/v2/products?type=fresh (in browser for instance) should return "this is list of products".
|
42
|
+
|
43
|
+
If there is more than one double for the same request\_fullpath and method, the last created one gets served. In UI you can manually control which double is 'active' (gets served).
|
44
|
+
|
45
|
+
* `DELETE '/doubles/all'`
|
46
|
+
Deletes all doubles.
|
47
|
+
|
48
|
+
### Redirects
|
49
|
+
|
50
|
+
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. Here is the resp API for managing redirects:
|
51
|
+
|
52
|
+
* `POST '/redirects', { pattern: pattern, to: uri }` Creates redirect with the following parameters:
|
53
|
+
|
54
|
+
- __pattern__ - regex (perl5 style) tested against request fullpath. Mandatory
|
55
|
+
- __to__ - url base e.g., `https://myserver:8787/api`. Mandatory
|
56
|
+
|
57
|
+
Example (using ruby RestClient):
|
58
|
+
|
59
|
+
RestClient.post 'http://localhost:4578/redirects', { pattern: '^/auth', to: 'https://myserver.com/api' }
|
60
|
+
|
61
|
+
Now request (any method) to http://localhost:4578/auth/services/1 will get redirected to https://myserver.com/api/auth/services/1. Provided of course there is no double matched for that fullpath and method.
|
62
|
+
Much like rewrite rules, redirects are evaluated in order (of creation). In UI you can manually rearrange the order.
|
63
|
+
|
64
|
+
### Storage
|
65
|
+
|
66
|
+
By default when you start rest-assured it creates (unless already exists) sqlite database and stores it into file in the current directory. This is good for using it for development - when you want doubles/redirects to persist across restarts - but may not be so desirable for using with tests, where you want each test run to start from blank slate. For that reason, you can specify `--database :memory:` so that database is kept in memory.
|
67
|
+
|
68
|
+
## TODO
|
69
|
+
|
70
|
+
* Implement expectations
|
71
|
+
* Support headers (extends previous point)
|
72
|
+
* Ruby client library
|
73
|
+
* Support methods in UI (at the moment it is always GET)
|
74
|
+
* Don't allow to double internal routes. Just in case
|
75
|
+
|
76
|
+
## Author
|
77
|
+
|
78
|
+
[Artem Avetisyan](https://github.com/artemave)
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "irb"
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
$:.push File.expand_path('../../lib', __FILE__)
|
6
|
+
|
7
|
+
require 'rest-assured/config'
|
8
|
+
AppConfig[:database] = ENV['FRS_DB'] || File.expand_path('../../db/development.db', __FILE__)
|
9
|
+
|
10
|
+
require 'rest-assured'
|
11
|
+
|
12
|
+
IRB.start(__FILE__)
|
data/bin/rest-assured
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.push File.expand_path('../../lib', __FILE__)
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'optparse'
|
7
|
+
require 'rest-assured/config'
|
8
|
+
|
9
|
+
OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: rest-assured [options]"
|
11
|
+
|
12
|
+
opts.on('-d', '--database FILENAME', "Path to database file. Defaults to ./rest-assured.db. There is a special value ':memory:' for in memory database.") do |fname|
|
13
|
+
AppConfig[:database] = fname
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on('-p', '--port PORT', Integer, "Server port. Defaults to 4578") do |port|
|
17
|
+
AppConfig[:port] = port
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
21
|
+
puts opts
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
end.parse!
|
25
|
+
|
26
|
+
require 'rest-assured'
|
27
|
+
|
28
|
+
RestAssured::Application.run!
|
data/cucumber.yml
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
Feature: use doubles via api
|
2
|
+
In order to use double data in integration tests
|
3
|
+
As a developer
|
4
|
+
I want to mock rest services my app is consuming from
|
5
|
+
|
6
|
+
Scenario Outline: create double
|
7
|
+
When I create a double with "<fullpath>" as fullpath, "<content>" as response content and "<method>" as request method
|
8
|
+
Then there should be 1 double with "<fullpath>" as fullpath, "<content>" as response content and "<result_method>" as request method
|
9
|
+
|
10
|
+
Examples:
|
11
|
+
| fullpath | content | method | result_method |
|
12
|
+
| /api/something | created | POST | POST |
|
13
|
+
| /api/sss | changed | PUT | PUT |
|
14
|
+
| /api/asdfsf | removed | DELETE | DELETE |
|
15
|
+
| /api/some | text content | GET | GET |
|
16
|
+
| /api/some?a=3&b=dd | more content | | GET |
|
17
|
+
|
18
|
+
Scenario Outline: request fullpath that matches double
|
19
|
+
Given there is double with "<fullpath>" as fullpath, "<content>" as response content and "<method>" as request method
|
20
|
+
When I "<method>" "<fullpath>"
|
21
|
+
Then I should get "<content>" in response content
|
22
|
+
|
23
|
+
Examples:
|
24
|
+
| fullpath | content | method |
|
25
|
+
| /api/something | created | POST |
|
26
|
+
| /api/sss | changed | PUT |
|
27
|
+
| /api/asdfsf | removed | DELETE |
|
28
|
+
| /api/some?a=3&b=dd | more content | GET |
|
29
|
+
|
30
|
+
# current rule: last added double gets picked
|
31
|
+
Scenario Outline: request fullpath that matches multiple doubles
|
32
|
+
Given there is double with "<fullpath>" as fullpath and "<content>" as response content
|
33
|
+
And there is double with "<fullpath>" as fullpath and "<content2>" as response content
|
34
|
+
When I "GET" "<fullpath>"
|
35
|
+
Then I should get "<content2>" in response content
|
36
|
+
|
37
|
+
Examples:
|
38
|
+
| fullpath | content | content2 |
|
39
|
+
| /api/something | test content | another content |
|
40
|
+
| /api/some?a=3&b=dd | more content | some text |
|
41
|
+
|
42
|
+
Scenario: request fullpath that does not match any double
|
43
|
+
Given there are no doubles
|
44
|
+
When I "GET" "/api/something"
|
45
|
+
Then I should get 404 in response status
|
46
|
+
|
47
|
+
Scenario: clear doubles
|
48
|
+
Given there are some doubles
|
49
|
+
When I delete all doubles
|
50
|
+
Then there should be no doubles
|
@@ -0,0 +1,66 @@
|
|
1
|
+
@ui
|
2
|
+
Feature: manage doubles via ui
|
3
|
+
In order to use double data in development
|
4
|
+
As a developer
|
5
|
+
I want to have a manual interface for managing doubles
|
6
|
+
|
7
|
+
Scenario: view existing doubles
|
8
|
+
Given the following doubles exist:
|
9
|
+
| fullpath | description | content |
|
10
|
+
| /url1/aaa | twitter | test content |
|
11
|
+
| /url2/bbb | geo location | more content |
|
12
|
+
| /u/b?c=1 | wikipedia | article |
|
13
|
+
When I visit "doubles" page
|
14
|
+
Then I should see that I am on "doubles" page
|
15
|
+
And I should see existing doubles:
|
16
|
+
| fullpath | description |
|
17
|
+
| /url1/aaa | twitter |
|
18
|
+
| /url2/bbb | geo location |
|
19
|
+
| /u/b?c=1 | wikipedia |
|
20
|
+
|
21
|
+
Scenario: add new double
|
22
|
+
Given I am on "doubles" page
|
23
|
+
When I choose to create a double
|
24
|
+
And I enter double details:
|
25
|
+
| fullpath | description | content |
|
26
|
+
| /url2/bb?a=b5 | google api | test content |
|
27
|
+
And I save it
|
28
|
+
Then I should see "Double created"
|
29
|
+
And I should see existing doubles:
|
30
|
+
| fullpath | description |
|
31
|
+
| /url2/bb?a=b5 | google api |
|
32
|
+
|
33
|
+
@javascript
|
34
|
+
Scenario: choose active double
|
35
|
+
Given there are two doubles for the same fullpath
|
36
|
+
When I visit "doubles" page
|
37
|
+
And I make first double active
|
38
|
+
Then first double should be served
|
39
|
+
When I make second double active
|
40
|
+
Then second double should be served
|
41
|
+
|
42
|
+
Scenario: edit double
|
43
|
+
Given the following doubles exist:
|
44
|
+
| fullpath | description | content |
|
45
|
+
| /url1/aaa | twitter | test content |
|
46
|
+
And I visit "doubles" page
|
47
|
+
And I choose to edit double
|
48
|
+
When I change "double" "description" to "google"
|
49
|
+
And I save it
|
50
|
+
Then I should see that I am on "doubles" page
|
51
|
+
And I should see existing doubles:
|
52
|
+
| fullpath | description |
|
53
|
+
| /url1/aaa | google |
|
54
|
+
|
55
|
+
@javascript
|
56
|
+
Scenario: delete double
|
57
|
+
Given the following doubles exist:
|
58
|
+
| fullpath | description | content |
|
59
|
+
| /url1/aaa | twitter | test content |
|
60
|
+
| /url/cc/bb | google | other content |
|
61
|
+
And I visit "doubles" page
|
62
|
+
And I choose to delete double with fullpath "/url1/aaa"
|
63
|
+
Then I should be asked to confirm delete
|
64
|
+
And I should see "Double deleted"
|
65
|
+
And I should not see "/url1/aaa"
|
66
|
+
And I should see "/url/cc/bb"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Feature: Persistence
|
2
|
+
In order to persist fixtrures/redirects between service restarts
|
3
|
+
As a developer
|
4
|
+
I want to be able to specify persistent storage
|
5
|
+
|
6
|
+
Scenario: default storage
|
7
|
+
Given I start service without --database option
|
8
|
+
And I register "/api/something" as fullpath and "content" as response content
|
9
|
+
And I restart service without --database option
|
10
|
+
When I request "/api/something"
|
11
|
+
Then I should get 404 in response status
|
12
|
+
|
13
|
+
Scenario Outline: specify storage
|
14
|
+
Given I start service with --database "<db>" option
|
15
|
+
And I register "/api/something" as fullpath and "content" as response content
|
16
|
+
And I restart service with --database "<db2>" option
|
17
|
+
When I request "/api/something"
|
18
|
+
Then I should get <status> in response status
|
19
|
+
|
20
|
+
Examples:
|
21
|
+
| db | db2 | status |
|
22
|
+
| database.db | database.db | 200 |
|
23
|
+
| /tmp/database.db | /tmp/database.db | 200 |
|
24
|
+
| database.db | database2.db | 404 |
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Feature: manage redirect rules
|
2
|
+
In order to be able to mock only part of api
|
3
|
+
As a developer
|
4
|
+
I want to redirect to real api if there are no doubles for requested fullpath
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given there are no redirect rules
|
8
|
+
And there are no doubles
|
9
|
+
|
10
|
+
Scenario: no redirect rules
|
11
|
+
When I request "/api/something"
|
12
|
+
Then I should get 404
|
13
|
+
|
14
|
+
Scenario: add redirect rule
|
15
|
+
When I register redirect with pattern "^/api" and uri "http://real.api.co.uk"
|
16
|
+
And I request "/api/something"
|
17
|
+
Then it should redirect to "http://real.api.co.uk/api/something"
|
18
|
+
|
19
|
+
Scenario: add second redirect that match the same request
|
20
|
+
When I register redirect with pattern "/api/something" and uri "http://real.api.co.uk"
|
21
|
+
And I register redirect with pattern "/api/some.*" and uri "http://real.com"
|
22
|
+
And I request "/api/something"
|
23
|
+
Then it should redirect to "http://real.api.co.uk/api/something"
|
24
|
+
|
25
|
+
Scenario: add second redirect that does not match the same request
|
26
|
+
When I register redirect with pattern "/api/something" and uri "http://real.api.co.uk"
|
27
|
+
And I register redirect with pattern "/api/some" and uri "http://real.com"
|
28
|
+
And I request "/api/someth"
|
29
|
+
Then it should redirect to "http://real.com/api/someth"
|