bbq 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -0
- data/CHANGELOG +30 -7
- data/README.md +80 -19
- data/bbq.gemspec +1 -0
- data/lib/bbq.rb +9 -13
- data/lib/bbq/devise.rb +5 -0
- data/lib/bbq/rails/routes.rb +13 -0
- data/lib/bbq/railtie.rb +4 -0
- data/lib/bbq/roles.rb +12 -0
- data/lib/bbq/rspec.rb +42 -35
- data/lib/bbq/session.rb +60 -0
- data/lib/bbq/test.rb +2 -33
- data/lib/bbq/test_client.rb +94 -0
- data/lib/bbq/test_unit.rb +37 -0
- data/lib/bbq/test_user.rb +14 -33
- data/lib/bbq/test_user/capybara_dsl.rb +15 -0
- data/lib/bbq/version.rb +1 -1
- data/lib/generators/bbq/install_generator.rb +1 -1
- data/lib/generators/bbq/test_generator.rb +1 -1
- data/lib/generators/rspec/templates/test_user.rb +2 -0
- data/lib/generators/test_unit/templates/README +1 -1
- data/lib/generators/test_unit/templates/test_user.rb +2 -0
- data/test/dummy/app/controllers/home_controller.rb +11 -0
- data/test/dummy/config/routes.rb +1 -0
- data/test/support/driver_factory.rb +46 -0
- data/test/unit/bbq_rspec_test.rb +191 -53
- data/test/unit/bbq_session_pool_test.rb +42 -0
- data/test/unit/bbq_test_generator_test.rb +1 -1
- data/test/unit/bbq_test_unit_test.rb +172 -6
- metadata +147 -39
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
@@ -1,12 +1,35 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0 / 2013-01-06
|
2
|
+
==================
|
2
3
|
|
3
|
-
*
|
4
|
-
*
|
4
|
+
* Extracted Rails' URL helpers inclusion to separate module
|
5
|
+
* Include only Capybara::Session::DSL_METHODS in TestUser, not the whole Capybara::DSL
|
6
|
+
* Added Capybara sessions pool
|
7
|
+
* Moved Test::User default options to separate method
|
8
|
+
* Added Test::Client for testing REST APIs
|
9
|
+
* Renamed bbq/test.rb to bbq/test_unit.rb. You may want to fix your test_helper.
|
10
|
+
* Moved require bbq/test_user to generated test_user.rb. You may want to update your existing test_user.rb.
|
11
|
+
* Fixed Capybara 'within' scope for RSpec flavour
|
5
12
|
|
6
|
-
0.0.
|
13
|
+
0.0.4 / 2011-10-19
|
14
|
+
==================
|
7
15
|
|
8
|
-
*
|
16
|
+
* Make bbq work with capybara 1.0 and 1.1
|
17
|
+
* rails is development dependency
|
9
18
|
|
10
|
-
0.0.
|
19
|
+
0.0.3 / 2011-07-14
|
20
|
+
==================
|
11
21
|
|
12
|
-
*
|
22
|
+
* Added support and tests for Sinatra
|
23
|
+
* Added Bbq.app and Bbq.app=
|
24
|
+
|
25
|
+
0.0.2 / 2011-07-01
|
26
|
+
==================
|
27
|
+
|
28
|
+
* Extracted Bbq::TestUser::Eyes module
|
29
|
+
* Added :within option to TestUser methods
|
30
|
+
* Fix tests for ree and ruby187
|
31
|
+
|
32
|
+
0.0.1 / 2011-04-20
|
33
|
+
==================
|
34
|
+
|
35
|
+
* BBQ introduced to the wild world!
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@ Warning & disclaimer
|
|
3
3
|
|
4
4
|
This gem is currently under development. We're targeting most popular use cases - Rails & Rack applications (ex. Sinatra). However the philosophy behind it is not limited to Rails nor web applications in general. There is even example usage with EventMachine. Feel free to modify it for your own needs.
|
5
5
|
|
6
|
-
[![Build Status](https://secure.travis-ci.org/drugpl/bbq.png)](http://travis-ci.org/drugpl/bbq)
|
6
|
+
[![Build Status](https://secure.travis-ci.org/drugpl/bbq.png)](http://travis-ci.org/drugpl/bbq) [![Dependency Status](https://gemnasium.com/drugpl/bbq.png)](https://gemnasium.com/drugpl/bbq)
|
7
7
|
|
8
8
|
BBQ
|
9
9
|
===
|
@@ -42,7 +42,7 @@ First, add BBQ to your apps Gemfile:
|
|
42
42
|
|
43
43
|
```ruby
|
44
44
|
# Gemfile
|
45
|
-
gem "bbq", "
|
45
|
+
gem "bbq", :git => "git://github.com/drugpl/bbq"
|
46
46
|
```
|
47
47
|
|
48
48
|
Run install generator:
|
@@ -54,7 +54,7 @@ rails generate bbq:install
|
|
54
54
|
Require BBQ in test/test_helper.rb (in case of Test::Unit):
|
55
55
|
|
56
56
|
```ruby
|
57
|
-
require "bbq/
|
57
|
+
require "bbq/test_unit"
|
58
58
|
```
|
59
59
|
|
60
60
|
Require BBQ in spec/spec_helper.rb (in case of RSpec):
|
@@ -99,9 +99,14 @@ module Roundtrip
|
|
99
99
|
click_on "Add update"
|
100
100
|
end
|
101
101
|
|
102
|
+
def open_application
|
103
|
+
visit '/'
|
104
|
+
end
|
105
|
+
|
102
106
|
module TicketReporter
|
103
107
|
def open_tickets_listing
|
104
|
-
|
108
|
+
open_application
|
109
|
+
click_link 'Tickets'
|
105
110
|
end
|
106
111
|
|
107
112
|
def open_ticket(summary, description)
|
@@ -119,8 +124,13 @@ module Roundtrip
|
|
119
124
|
end
|
120
125
|
|
121
126
|
module TicketManager
|
127
|
+
def open_administration
|
128
|
+
visit '/admin'
|
129
|
+
end
|
130
|
+
|
122
131
|
def open_tickets_listing
|
123
|
-
|
132
|
+
open_administration
|
133
|
+
click_link 'Tickets'
|
124
134
|
end
|
125
135
|
|
126
136
|
def close_ticket(summary, comment = nil)
|
@@ -174,6 +184,67 @@ class AdminTicketsTest < Bbq::TestCase
|
|
174
184
|
end
|
175
185
|
```
|
176
186
|
|
187
|
+
Testing REST APIs
|
188
|
+
================
|
189
|
+
|
190
|
+
Bbq provides `Bbq::TestClient`, similar to `Bbq::TestUser`, but intended for testing APIs.
|
191
|
+
It's a thin wrapper around `Rack::Test` which allows you to send requests and run assertions
|
192
|
+
against responses.
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
class ApiTest < Bbq::TestCase
|
196
|
+
background do
|
197
|
+
headers = {'HTTP_ACCEPT' => 'application/json'}
|
198
|
+
@client = TestClient.new(:headers => headers)
|
199
|
+
end
|
200
|
+
|
201
|
+
scenario "admin can browse all user tickets" do
|
202
|
+
@client.get "/unicorn" do |response|
|
203
|
+
assert_equal 200, response.status
|
204
|
+
assert_equal "pink", response.body["unicorn"]["color"]
|
205
|
+
end
|
206
|
+
@client.post "/ponies", { :name => "Miracle" } do |response|
|
207
|
+
assert_equal 200, response.status
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
Rails' URL Helpers
|
214
|
+
================
|
215
|
+
|
216
|
+
Using url helpers from Rails in integration tests is not recommended.
|
217
|
+
Testing routes is part of integration test, so you should actually use only
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
visit '/'
|
221
|
+
```
|
222
|
+
|
223
|
+
in your integration test. Use links and buttons in order to get to other pages in your app.
|
224
|
+
|
225
|
+
If you really need url helpers in your test user, just include them in your TestUser class:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
require 'bbq/rails/routes'
|
229
|
+
|
230
|
+
module Roundtrip
|
231
|
+
class TestUser < Bbq::TestUser
|
232
|
+
include Bbq::Rails::Routes
|
233
|
+
end
|
234
|
+
end
|
235
|
+
```
|
236
|
+
or just
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
module Roundtrip
|
240
|
+
class TestUser < Bbq::TestUser
|
241
|
+
include ::ActionDispatch::Routing::UrlFor
|
242
|
+
include ::Rails.application.routes.url_helpers
|
243
|
+
include ::ActionDispatch::Routing::RouteSet::MountedHelpers unless ::Rails.version < "3.1"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
```
|
247
|
+
|
177
248
|
Deal with Devise
|
178
249
|
================
|
179
250
|
|
@@ -202,28 +273,18 @@ Caveats
|
|
202
273
|
<h2>Timeout::Error</h2>
|
203
274
|
|
204
275
|
If you simulate multiple users in your tests and spawn multiple browsers with selenium it might
|
205
|
-
be a good idea to use
|
206
|
-
We have experienced some problems with
|
276
|
+
be a good idea to use Thin instead of Webrick to create application server.
|
277
|
+
We have experienced some problems with Webrick that lead to `Timeout::Error` exception
|
207
278
|
when user/browser that was inactive for some time (due to other users/browsers
|
208
279
|
activities) was requested to execute an action.
|
209
280
|
|
210
|
-
|
211
|
-
`test/test_helper.rb` or `spec/spec_helper.rb`:
|
212
|
-
|
213
|
-
```ruby
|
214
|
-
Capybara.server do |app, port|
|
215
|
-
require 'rack/handler/mongrel'
|
216
|
-
Rack::Handler::Mongrel.run(app, :Port => port)
|
217
|
-
end
|
218
|
-
```
|
219
|
-
|
220
|
-
Add `mongrel` to your `Gemfile`:
|
281
|
+
Capybara will use Thin instead of Webrick when it's available, so you only need to add Thin to you Gemfile:
|
221
282
|
|
222
283
|
```ruby
|
223
284
|
# In test group if you want it to
|
224
285
|
# be used only in tests and not in your development mode
|
225
286
|
# ex. when running 'rails s'
|
226
|
-
gem '
|
287
|
+
gem 'thin', :require => false
|
227
288
|
```
|
228
289
|
|
229
290
|
Development environment
|
data/bbq.gemspec
CHANGED
data/lib/bbq.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
|
3
3
|
module Bbq
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def self.rails?
|
9
|
-
defined?(::Rails)
|
10
|
-
end
|
4
|
+
class << self
|
5
|
+
def root
|
6
|
+
@root ||= Pathname.new(File.expand_path(File.join(File.dirname(__FILE__), '..')))
|
7
|
+
end
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
def rails?
|
10
|
+
defined?(::Rails)
|
11
|
+
end
|
15
12
|
|
16
|
-
|
17
|
-
Capybara.app=(new_app)
|
13
|
+
attr_accessor :app
|
18
14
|
end
|
19
15
|
end
|
20
16
|
|
21
|
-
require 'bbq/railtie' if Bbq.rails?
|
17
|
+
require 'bbq/railtie' if Bbq.rails?
|
data/lib/bbq/devise.rb
CHANGED
@@ -5,6 +5,11 @@ if defined?(Devise)
|
|
5
5
|
module Devise
|
6
6
|
attr_accessor :devise_authentication_key, :email, :password, :scope
|
7
7
|
|
8
|
+
def self.included(klass)
|
9
|
+
require 'bbq/rails/routes'
|
10
|
+
klass.send(:include, Bbq::Rails::Routes)
|
11
|
+
end
|
12
|
+
|
8
13
|
def initialize_devise
|
9
14
|
@devise_initialized ||= begin
|
10
15
|
self.devise_authentication_key = ::Devise.authentication_keys.first
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Bbq
|
2
|
+
module Rails
|
3
|
+
module Routes
|
4
|
+
def self.included(klass)
|
5
|
+
klass.send(:include, ::ActionDispatch::Routing::UrlFor)
|
6
|
+
klass.send(:include, ::Rails.application.routes.url_helpers)
|
7
|
+
unless ::Rails.version < "3.1"
|
8
|
+
klass.send(:include, ::ActionDispatch::Routing::RouteSet::MountedHelpers)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/bbq/railtie.rb
CHANGED
data/lib/bbq/roles.rb
ADDED
data/lib/bbq/rspec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
require 'bbq'
|
2
|
+
require 'bbq/session'
|
1
3
|
require 'rspec/core'
|
2
|
-
require 'bbq/test_user'
|
3
4
|
require 'capybara/rspec/matchers'
|
4
5
|
|
5
6
|
module Bbq
|
@@ -13,45 +14,51 @@ module Bbq
|
|
13
14
|
end
|
14
15
|
|
15
16
|
module RSpecMatchers
|
16
|
-
|
17
|
-
def initialize(negative, *args)
|
18
|
-
@args, @negative = args, negative
|
19
|
-
end
|
20
|
-
|
21
|
-
def matches?(actual)
|
22
|
-
@negative ? actual.not_see?(*@args) : actual.see?(*@args)
|
23
|
-
end
|
17
|
+
extend RSpec::Matchers::DSL
|
24
18
|
|
25
|
-
|
26
|
-
|
19
|
+
matcher :see do |text|
|
20
|
+
chain :within do |locator|
|
21
|
+
@locator = locator
|
27
22
|
end
|
28
23
|
|
29
|
-
|
30
|
-
|
24
|
+
match_for_should do |page|
|
25
|
+
if @locator
|
26
|
+
page.within(@locator) do
|
27
|
+
page.see? text
|
28
|
+
end
|
29
|
+
else
|
30
|
+
page.see? text
|
31
|
+
end
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
-
@
|
34
|
+
match_for_should_not do |page|
|
35
|
+
if @locator
|
36
|
+
page.within(@locator) do
|
37
|
+
page.not_see? text
|
38
|
+
end
|
39
|
+
else
|
40
|
+
page.not_see? text
|
41
|
+
end
|
35
42
|
end
|
36
43
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
failure_message_for_should do |page|
|
45
|
+
body = if @locator
|
46
|
+
page.find(@locator).text
|
47
|
+
else
|
48
|
+
page.body
|
49
|
+
end
|
50
|
+
"expected to see #{text} in #{body}"
|
41
51
|
end
|
42
52
|
|
43
|
-
|
44
|
-
|
53
|
+
failure_message_for_should_not do |page|
|
54
|
+
body = if @locator
|
55
|
+
page.find(@locator).text
|
56
|
+
else
|
57
|
+
page.body
|
58
|
+
end
|
59
|
+
"expected not to see #{text} in #{body}"
|
45
60
|
end
|
46
61
|
end
|
47
|
-
|
48
|
-
def see(*args)
|
49
|
-
TestUserEyes.new(false, *args)
|
50
|
-
end
|
51
|
-
|
52
|
-
def not_see(*args)
|
53
|
-
TestUserEyes.new(true, *args)
|
54
|
-
end
|
55
62
|
end
|
56
63
|
|
57
64
|
class TestUser
|
@@ -60,15 +67,11 @@ module Bbq
|
|
60
67
|
include Bbq::RSpecMatchers
|
61
68
|
|
62
69
|
def see!(*args)
|
63
|
-
args.
|
64
|
-
page.should have_content(arg)
|
65
|
-
end
|
70
|
+
see?(*args).should be_true
|
66
71
|
end
|
67
72
|
|
68
73
|
def not_see!(*args)
|
69
|
-
args.
|
70
|
-
page.should have_no_content(arg)
|
71
|
-
end
|
74
|
+
not_see?(*args).should be_true
|
72
75
|
end
|
73
76
|
end
|
74
77
|
end
|
@@ -87,4 +90,8 @@ RSpec.configuration.include Bbq::RSpecFeature, :type => :acceptance
|
|
87
90
|
RSpec.configure do |config|
|
88
91
|
config.include Capybara::RSpecMatchers, :type => :acceptance
|
89
92
|
config.include Bbq::RSpecMatchers, :type => :acceptance
|
93
|
+
|
94
|
+
config.after :each, :type => :acceptance do
|
95
|
+
Bbq::Session.pool.release
|
96
|
+
end
|
90
97
|
end
|
data/lib/bbq/session.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
module Bbq
|
2
|
+
module Session
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def next(options = {})
|
6
|
+
driver = options.delete(:driver)
|
7
|
+
pool = options.delete(:pool)
|
8
|
+
|
9
|
+
if pool
|
10
|
+
pool.next(driver)
|
11
|
+
else
|
12
|
+
create(driver)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def create(driver)
|
17
|
+
Capybara::Session.new(driver, Bbq.app)
|
18
|
+
end
|
19
|
+
|
20
|
+
def pool
|
21
|
+
@pool ||= Pool.new
|
22
|
+
end
|
23
|
+
|
24
|
+
class Pool
|
25
|
+
attr_accessor :idle, :taken
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@idle = []
|
29
|
+
@taken = []
|
30
|
+
end
|
31
|
+
|
32
|
+
def next(driver)
|
33
|
+
take_idle(driver) || create(driver)
|
34
|
+
end
|
35
|
+
|
36
|
+
def release
|
37
|
+
taken.each(&:reset!)
|
38
|
+
idle.concat(taken)
|
39
|
+
taken.clear
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def take_idle(driver)
|
45
|
+
idle.find { |s| s.mode == driver }.tap do |session|
|
46
|
+
if session
|
47
|
+
idle.delete(session)
|
48
|
+
taken.push(session)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def create(driver)
|
54
|
+
Bbq::Session.create(driver).tap do |session|
|
55
|
+
taken.push(session)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|