kookaburra 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup=markdown
data/Gemfile CHANGED
@@ -7,11 +7,11 @@ gem 'rack-test'
7
7
  # Add dependencies to develop your gem here.
8
8
  # Include everything needed to run rake, tests, features, etc.
9
9
  group :development do
10
- gem 'minitest', '>= 0'
11
- gem 'bluecloth'
12
- gem 'yard', '~> 0.6.0'
13
- gem 'bundler', '~> 1.0.0'
14
- gem 'jeweler', '~> 1.6.4'
15
- gem 'rcov', '>= 0'
16
- gem 'reek', '~> 1.2.8'
10
+ gem 'minitest'
11
+ gem 'yard'
12
+ gem 'redcarpet', '~> 1.0' # used to format documentation
13
+ gem 'bundler'
14
+ gem 'jeweler'
15
+ gem 'rcov'
16
+ gem 'reek'
17
17
  end
data/Gemfile.lock CHANGED
@@ -1,22 +1,23 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- activesupport (3.1.3)
4
+ activesupport (3.2.0)
5
+ i18n (~> 0.6)
5
6
  multi_json (~> 1.0)
6
- bluecloth (2.2.0)
7
7
  git (1.2.5)
8
8
  i18n (0.6.0)
9
9
  jeweler (1.6.4)
10
10
  bundler (~> 1.0)
11
11
  git (>= 1.2.5)
12
12
  rake
13
- minitest (2.9.0)
13
+ minitest (2.10.1)
14
14
  multi_json (1.0.4)
15
- rack (1.3.5)
15
+ rack (1.4.0)
16
16
  rack-test (0.6.1)
17
17
  rack (>= 1.0)
18
18
  rake (0.9.2.2)
19
- rcov (0.9.11)
19
+ rcov (1.0.0)
20
+ redcarpet (1.17.2)
20
21
  reek (1.2.8)
21
22
  ruby2ruby (~> 1.2)
22
23
  ruby_parser (~> 2.0)
@@ -26,20 +27,20 @@ GEM
26
27
  sexp_processor (~> 3.0)
27
28
  ruby_parser (2.3.1)
28
29
  sexp_processor (~> 3.0)
29
- sexp_processor (3.0.9)
30
- yard (0.6.8)
30
+ sexp_processor (3.0.10)
31
+ yard (0.7.4)
31
32
 
32
33
  PLATFORMS
33
34
  ruby
34
35
 
35
36
  DEPENDENCIES
36
37
  activesupport (>= 3.0)
37
- bluecloth
38
- bundler (~> 1.0.0)
38
+ bundler
39
39
  i18n
40
- jeweler (~> 1.6.4)
40
+ jeweler
41
41
  minitest
42
42
  rack-test
43
43
  rcov
44
- reek (~> 1.2.8)
45
- yard (~> 0.6.0)
44
+ redcarpet (~> 1.0)
45
+ reek
46
+ yard
data/README.markdown CHANGED
@@ -1,15 +1,29 @@
1
1
  # Kookaburra #
2
2
 
3
- Kookaburra is a framework for implementing the [Window Driver] [1] pattern in
3
+ Kookaburra is a framework for implementing the [Window Driver] [Window Driver] pattern in
4
4
  order to keep acceptance tests maintainable.
5
5
 
6
+ ## Installation ##
7
+
8
+ Kookaburra is available as a Rubygem and [published on Rubygems.org] [Kookaburra
9
+ Gem], so installation is trivial:
10
+
11
+ gem install kookaburra
12
+
13
+ If you're using [Bundler](http://gembundler.com/) for your project, just add the
14
+ following:
15
+
16
+ group :development, :test do
17
+ gem 'kookaburra'
18
+ end
19
+
6
20
  ## Setup ##
7
21
 
8
22
  Kookaburra itself abstracts some common patterns for implementing the Window
9
- Driver pattern for tests of Ruby web applications built on [Rack] [2]. You will need
23
+ Driver pattern for tests of Ruby web applications built on [Rack] [Rack]. You will need
10
24
  to tell Kookaburra which classes contain the specific Domain Driver
11
25
  implementations for your application as well as which driver to use for running
12
- the tests (currently only tested with [Capybara] [3]). The details of setting up your
26
+ the tests (currently only tested with [Capybara] [Capybara]). The details of setting up your
13
27
  Domain Driver layer are discussed below, but in general you will need the
14
28
  following in a locations such as `lib/my_application/kookaburra.rb` (replace
15
29
  `MyApplication` with a module name suitable to your actual application:
@@ -33,7 +47,7 @@ following in a locations such as `lib/my_application/kookaburra.rb` (replace
33
47
 
34
48
  ### RSpec ###
35
49
 
36
- For [RSpec] [4] integration tests, just add the following to
50
+ For [RSpec] [RSpec] integration tests, just add the following to
37
51
  `spec/support/kookaburra_setup.rb`:
38
52
 
39
53
  require 'my_application/kookaburra'
@@ -44,7 +58,7 @@ For [RSpec] [4] integration tests, just add the following to
44
58
 
45
59
  ### Cucumber ###
46
60
 
47
- For Cucumber, add the following to `features/support/kookaburra_setup.rb`:
61
+ For [Cucumber] [Cucumber], add the following to `features/support/kookaburra_setup.rb`:
48
62
 
49
63
  require 'my_application/kookaburra'
50
64
 
@@ -64,12 +78,15 @@ Cucumber step definitions.
64
78
  Kookaburra attempts to extract some common patterns that make it easier to use
65
79
  the Window Driver pattern along with various Ruby testing frameworks, but you
66
80
  still need to define your own testing DSL. An acceptance testing stack using
67
- Kookaburra has the following four layers:
81
+ Kookaburra has the following layers:
68
82
 
69
- 1. The **Business Specification Language** (Cucumber scenarios and step definitions)
70
- 2. The **Domain Driver** (Kookaburra::GivenDriver and Kookaburra::UIDriver)
71
- 3. The **Window Driver** (Kookaburra::UIDriver::UIComponent)
72
- 4. The **Application Driver** (Capybara and Rack::Test)
83
+ 1. The **Business Specification Language** (Cucumber scenarios or other
84
+ spcification documents)
85
+ 2. The **Test Implementation** (Cucumber step definitions, RSpec example blocks,
86
+ etc.)
87
+ 3. The **Domain Driver** (Kookaburra::GivenDriver and Kookaburra::UIDriver)
88
+ 4. The **Window Driver** (Kookaburra::UIDriver::UIComponent)
89
+ 5. The **Application Driver** (Capybara and Rack::Test)
73
90
 
74
91
  ### The Business Specification Language ###
75
92
 
@@ -104,18 +121,28 @@ for some reason your e-commerce system was going to be a terminal application
104
121
  rather than a web application, you would not need to change this scenario at
105
122
  all, because the actual business concepts described would not change.
106
123
 
107
- ### The Domain Driver ###
108
-
109
- The Domain Driver layer is where you build up an internal DSL that describes the
110
- business concepts of your application at a fairly high level. It consists of
111
- three top-level drivers: the `APIDriver` (available via `#api`) for interacting
112
- with your application's external API, the `GivenDriver` (available via `#given`)
113
- which really just wraps the `APIDriver` and is used to set up state for your
114
- tests, and the UIDriver (available via `#given`) for describing the tasks that a
115
- user can accomplish with the application.
116
-
117
- Given the Cucumber scenario above, the step definitions call into the Domain
118
- Driver layer to interact with your application:
124
+ ### The Test Implementation ###
125
+
126
+ The Test Implementation layer exists as the line in between the Business
127
+ Specification Language and the Domain Driver, and it includes Cucumber step
128
+ definitions, RSpec example blocks, Test::Unit tests, etc. At this layer, your
129
+ code orchestrates calls into the Domain Driver to mimic user interactions under
130
+ various conditions and make assertions about the results.
131
+
132
+ **Assertions always belong within the test implementation layer.** Some testing
133
+ frameworks such as RSpec add methods like `#should` to `Object`, which has the
134
+ effect of poisoning the entire Ruby namespace with these methods---if you are
135
+ using RSpec, you can call `#should` anywhere in your code and it will work when
136
+ RSpec is loaded. Do not be tempted to call a testing library's Object decorators
137
+ anywhere outside of your test implementation (such as within `UIDriver` or
138
+ `UIComponent` subclasses.) Doing so will tightly couple your Domain Driver
139
+ and/or Window Driver implementation to a specific testing library. If you must
140
+ make some type of assertion within the Domain Driver layer, a better approach is
141
+ to simply raise an exception with an informative error message when some desired
142
+ condition is not met.
143
+
144
+ Given the Cucumber scenario above, here is how the test implementation layer
145
+ might look:
119
146
 
120
147
  # step_definitions/various_steps.rb
121
148
 
@@ -158,6 +185,7 @@ Driver layer to interact with your application:
158
185
  The step definitions contain neither explicitly shared state (instance
159
186
  variables) nor any logic branches; they are simply wrappers around calls into
160
187
  the Domain Driver layer. There are a couple of advantages to this approach.
188
+
161
189
  First, because step definitions are so simple, it isn't necessary to force *Very
162
190
  Specific Wording* on the business analyst/product owner who is writing the
163
191
  specs. For instance, if she writes "I see a summary of my order" in another
@@ -183,8 +211,9 @@ The second advantage is that by pushing all of the complexity down into the
183
211
  Domain Driver, it's now trivial to reuse the exact same code in
184
212
  developer-centric integration tests. This ensures you have parity between the
185
213
  way the automated acceptance tests run and any additional testing that the
186
- development team needs to add in. You could write the same test using just
187
- RSpec as follows:
214
+ development team needs to add in.
215
+
216
+ Using RSpec, the test implementation would be as follows:
188
217
 
189
218
  # spec/integration/purchase_items_in_cart_spec.rb
190
219
 
@@ -204,10 +233,17 @@ RSpec as follows:
204
233
  end
205
234
  end
206
235
 
207
- Whether in Cucumber step definitions or developer integration tests, you will
208
- usually interact only with the GivenDriver and the UIDriver.
236
+ ### The Domain Driver ###
209
237
 
210
- #### TestData ####
238
+ The Domain Driver layer is where you build up an internal DSL that describes the
239
+ business concepts of your application at a fairly high level. It consists of
240
+ three top-level drivers: the `APIDriver` (available via `#api`) for interacting
241
+ with your application's external API, the `GivenDriver` (available via `#given`)
242
+ which really just wraps the `APIDriver` and is used to set up state for your
243
+ tests, and the UIDriver (available via `#ui`) for describing the tasks that a
244
+ user can accomplish with the application.
245
+
246
+ #### Test Data ####
211
247
 
212
248
  `Kookaburra::TestData` is the component via which the `GivenDriver` and the
213
249
  `UIDriver` share information. For instance, if you create a user account via the
@@ -258,7 +294,7 @@ access default data:
258
294
  end
259
295
  end
260
296
 
261
- #### APIDriver ####
297
+ #### API Driver ####
262
298
 
263
299
  The `Kookaburra::APIDriver` is used to interact with an application's external
264
300
  web services API. You tell Kookaburra about your API by creating a subclass of
@@ -273,7 +309,7 @@ web services API. You tell Kookaburra about your API by creating a subclass of
273
309
  end
274
310
  end
275
311
 
276
- #### GivenDriver ####
312
+ #### Given Driver ####
277
313
 
278
314
  The `Kookaburra::GivenDriver` is used to create a particular "preexisting"
279
315
  state within your application's data and ensure you have a handle to that data
@@ -301,7 +337,24 @@ the Domain Driver DSL for your application:
301
337
  end
302
338
  end
303
339
 
304
- #### UIDriver ####
340
+ Although there is nothing that actually *prevents* you from either interacting
341
+ with the UI or directly manipulating your application via calls into the model
342
+ from the `GivenDriver`, both things should be avoided. In the first case, the
343
+ `GivenDriver`'s purpose is to describe state that exists *before* the user
344
+ interaction that is being tested. Although this state may be the result of a
345
+ previous user interaction, your tests will generally be much, much faster if you
346
+ are able to create this state via API calls rather than driving a web browser.
347
+
348
+ In the second case, by avoiding manipulating your applications's state at the
349
+ code level and instead doing so via an external API, it is much less likely that
350
+ you will be creating a state that your application can't actually get into in a
351
+ production environment. Additionally, this opens up the possibility of running
352
+ your tests against a "remote" server where you would not have access to the
353
+ application internals. ("Remote" in the sense that it is not in the same Ruby
354
+ process as your running tests, although it may or may not be on the same
355
+ machine.)
356
+
357
+ #### UI Driver ####
305
358
 
306
359
  `Kookaburra::UIDriver` provides the necessary tools for driving your
307
360
  application's user interface using the Window Driver pattern. You will subclass
@@ -325,13 +378,14 @@ within your subclass:
325
378
  ### The Window Driver Layer ###
326
379
 
327
380
  While your `GivenDriver` and `UIDriver` provide a DSL that represents actions
328
- your users can perform in your application, the [Window Driver] [1] layer describes
329
- the individual user interface components that the user interacts with to perform
330
- these tasks. By describing each interface component using an OOP approach, it is
331
- much easier to maintain your acceptance/integration tests, because the
332
- implementation details of each component are captured in a single place. If/when
333
- that implementation changes, you can---for example---fix every single test that
334
- needs to log a user into the system just by updating the SignInScreen class.
381
+ your users can perform in your application, the [Window Driver] [Window Driver]
382
+ layer describes the individual user interface components that the user interacts
383
+ with to perform these tasks. By describing each interface component using an OOP
384
+ approach, it is much easier to maintain your acceptance/integration tests,
385
+ because the implementation details of each component are captured in a single
386
+ place. If/when that implementation changes, you can---for example---fix every
387
+ single test that needs to log a user into the system just by updating the
388
+ SignInScreen class.
335
389
 
336
390
  You describe the various user interface components by sub-classing
337
391
  `Kookaburra::UIDriver::UIComponent`:
@@ -370,22 +424,48 @@ You describe the various user interface components by sub-classing
370
424
  end
371
425
  end
372
426
 
427
+ ### The Application Driver Layer ###
428
+
429
+ `Kookaburra::APIDriver`, `Kookaburra::UIDriver` and
430
+ `Kookaburra::UIDriver::UIComponent` rely on the Application Driver layer to
431
+ interact with your application. In the case of the `APIDriver`, Kookaburra uses
432
+ `Rack::Test` to send HTTP requests to your application. The `UIDriver` and
433
+ `UIComponent` rely on whatever is configured as `Kookaburra.adapter`. Presently,
434
+ we have only used Capybara as the application driver for Kookaburra:
435
+
436
+ Kookaburra.adapter = Capybara
437
+
438
+ It's possible that something other than Capybara could be passed in, as long as
439
+ that something presented the same API. In reality, using something other than
440
+ Capybara is likely to require some changes to Kookaburra itself. If you have a
441
+ particular interest in making this work, please feel free to fork the project
442
+ and send us a [GitHub pull request] [Pull Request] with your changes.
443
+
373
444
  ## Contributing to kookaburra ##
374
445
 
375
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
376
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
446
+ * Check out the latest master to make sure the feature hasn't been implemented
447
+ or the bug hasn't been fixed yet
448
+ * Check out the issue tracker to make sure someone already hasn't requested it
449
+ and/or contributed it
377
450
  * Fork the project
378
451
  * Start a feature/bugfix branch
379
452
  * Commit and push until you are happy with your contribution
380
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
381
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
453
+ * Make sure to add tests for it. This is important so I don't break it in a
454
+ future version unintentionally.
455
+ * Please try not to mess with the Rakefile, version, or history. If you want to
456
+ have your own version, or is otherwise necessary, that is fine, but please
457
+ isolate to its own commit so I can cherry-pick around it.
458
+ * Send us a [pull request] [Pull Request]
382
459
 
383
460
  ## Copyright ##
384
461
 
385
462
  Copyright © 2011 Renewable Funding, LLC. See LICENSE.txt for
386
463
  further details.
387
464
 
388
- [1]: http://martinfowler.com/eaaDev/WindowDriver.html "Window Driver - Martin Fowler"
389
- [2]: http://rack.rubyforge.org/ "Rack: a Ruby Webserver Interface"
390
- [3]: https://github.com/jnicklas/capybara "jnicklas/capybara - GitHub"
391
- [4]: http://rspec.info "RSpec.info: home"
465
+ [Window Driver]: http://martinfowler.com/eaaDev/WindowDriver.html "Window Driver - Martin Fowler"
466
+ [Kookaburra Gem]: https://rubygems.org/gems/kookaburra "kookaburra | RubyGems.org | your community gem host"
467
+ [Rack]: http://rack.rubyforge.org/ "Rack: a Ruby Webserver Interface"
468
+ [Capybara]: https://github.com/jnicklas/capybara "jnicklas/capybara - GitHub"
469
+ [RSpec]: http://rspec.info "RSpec.info: home"
470
+ [Cucumber]: http://cukes.info/ "Cucumber - Making BDD fun"
471
+ [Pull Request]: https://github.com/projectdx/kookaburra/pull/new/master "Send a pull request - GitHub"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.2
1
+ 0.8.0
data/kookaburra.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "kookaburra"
8
- s.version = "0.7.2"
8
+ s.version = "0.8.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Renewable Funding, LLC"]
12
- s.date = "2012-01-23"
12
+ s.date = "2012-01-24"
13
13
  s.description = "Cucumber + Capybara = Kookaburra? It made sense at the time."
14
14
  s.email = "devteam@renewfund.com"
15
15
  s.extra_rdoc_files = [
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.files = [
20
20
  ".document",
21
21
  ".rvmrc",
22
+ ".yardopts",
22
23
  "Gemfile",
23
24
  "Gemfile.lock",
24
25
  "LICENSE.txt",
@@ -55,35 +56,35 @@ Gem::Specification.new do |s|
55
56
  s.add_runtime_dependency(%q<activesupport>, [">= 3.0"])
56
57
  s.add_runtime_dependency(%q<rack-test>, [">= 0"])
57
58
  s.add_development_dependency(%q<minitest>, [">= 0"])
58
- s.add_development_dependency(%q<bluecloth>, [">= 0"])
59
- s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
60
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
61
- s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
59
+ s.add_development_dependency(%q<yard>, [">= 0"])
60
+ s.add_development_dependency(%q<redcarpet>, ["~> 1.0"])
61
+ s.add_development_dependency(%q<bundler>, [">= 0"])
62
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
62
63
  s.add_development_dependency(%q<rcov>, [">= 0"])
63
- s.add_development_dependency(%q<reek>, ["~> 1.2.8"])
64
+ s.add_development_dependency(%q<reek>, [">= 0"])
64
65
  else
65
66
  s.add_dependency(%q<i18n>, [">= 0"])
66
67
  s.add_dependency(%q<activesupport>, [">= 3.0"])
67
68
  s.add_dependency(%q<rack-test>, [">= 0"])
68
69
  s.add_dependency(%q<minitest>, [">= 0"])
69
- s.add_dependency(%q<bluecloth>, [">= 0"])
70
- s.add_dependency(%q<yard>, ["~> 0.6.0"])
71
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
72
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
70
+ s.add_dependency(%q<yard>, [">= 0"])
71
+ s.add_dependency(%q<redcarpet>, ["~> 1.0"])
72
+ s.add_dependency(%q<bundler>, [">= 0"])
73
+ s.add_dependency(%q<jeweler>, [">= 0"])
73
74
  s.add_dependency(%q<rcov>, [">= 0"])
74
- s.add_dependency(%q<reek>, ["~> 1.2.8"])
75
+ s.add_dependency(%q<reek>, [">= 0"])
75
76
  end
76
77
  else
77
78
  s.add_dependency(%q<i18n>, [">= 0"])
78
79
  s.add_dependency(%q<activesupport>, [">= 3.0"])
79
80
  s.add_dependency(%q<rack-test>, [">= 0"])
80
81
  s.add_dependency(%q<minitest>, [">= 0"])
81
- s.add_dependency(%q<bluecloth>, [">= 0"])
82
- s.add_dependency(%q<yard>, ["~> 0.6.0"])
83
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
84
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
82
+ s.add_dependency(%q<yard>, [">= 0"])
83
+ s.add_dependency(%q<redcarpet>, ["~> 1.0"])
84
+ s.add_dependency(%q<bundler>, [">= 0"])
85
+ s.add_dependency(%q<jeweler>, [">= 0"])
85
86
  s.add_dependency(%q<rcov>, [">= 0"])
86
- s.add_dependency(%q<reek>, ["~> 1.2.8"])
87
+ s.add_dependency(%q<reek>, [">= 0"])
87
88
  end
88
89
  end
89
90
 
@@ -1,21 +1,16 @@
1
1
  require 'rack/test'
2
2
 
3
3
  module Kookaburra
4
- # Pattern:
5
- # - Get some data from test_data.factory
6
- # - Post it to the API
7
- # - Remember the response in test_data
8
4
  class APIDriver
9
- include Rack::Test::Methods
10
- attr_reader :app, :test_data
11
- protected :app, :test_data
12
-
13
5
  def initialize(opts)
14
- @app = opts.fetch(:app)
15
- @test_data = opts.fetch(:test_data)
6
+ @app = opts.fetch(:app)
16
7
  end
17
8
 
18
- protected
9
+ protected
10
+
11
+ include Rack::Test::Methods
12
+
13
+ attr_reader :app
19
14
 
20
15
  def raise_unless_status(expected_status, short_description)
21
16
  message = "%s failed (#{last_response.status})\n#{last_response.body}" % short_description
@@ -25,21 +20,30 @@ module Kookaburra
25
20
  ##### JSON Tools #####
26
21
 
27
22
  def post_as_json(short_description, path, data = {}, options = {})
28
- header 'Content-Type', 'application/json'
29
- header 'Accept', 'application/json'
23
+ set_json_request_headers
30
24
  post path, data.to_json
31
25
  raise_unless_status options[:expected_status] || 201, short_description
32
26
  end
33
27
 
34
28
  def put_as_json(short_description, path, data = {}, options = {})
35
- header 'Content-Type', 'application/json'
36
- header 'Accept', 'application/json'
29
+ set_json_request_headers
37
30
  put path, data.to_json
38
31
  raise_unless_status options[:expected_status] || 201, short_description
39
32
  end
40
33
 
34
+ def get_as_json(short_description, path, data = {}, options = {})
35
+ set_json_request_headers
36
+ get path, data
37
+ raise_unless_status options[:expected_status] || 200, short_description
38
+ end
39
+
41
40
  def hash_from_response_json
42
41
  HashWithIndifferentAccess.new( JSON.parse(last_response.body) )
43
42
  end
43
+
44
+ def set_json_request_headers
45
+ header 'Content-Type', 'application/json'
46
+ header 'Accept', 'application/json'
47
+ end
44
48
  end
45
49
  end
data/lib/kookaburra.rb CHANGED
@@ -3,136 +3,134 @@ require 'kookaburra/api_driver'
3
3
  require 'kookaburra/given_driver'
4
4
  require 'kookaburra/ui_driver'
5
5
 
6
- # Kookaburra is a framework for implementing the Window Driver pattern[1] in
7
- # order to keep acceptance tests maintainable.
8
- #
9
- # For RSpec integration tests, just add the following to
10
- # `spec/support/kookaburra.rb`:
11
- #
12
- # RSpec.configure do |c|
13
- # c.include(Kookaburra, :type => :request)
14
- # end
15
- #
16
- # That will make #given, #api and #ui entry-points available to your examples,
17
- # e.g.:
18
- #
19
- # describe "Widget Management" do
20
- # describe "viewing a list of widgets" do
21
- # example "when there are no widgets" do
22
- # given.there_is_a_user(:bob)
23
- # given.user_has_no_widgets(:bob)
24
- #
25
- # ui.log_in_as(:bob)
26
- # ui.navigate_to(:list_of_widgets)
27
- #
28
- # ui.list_of_widgets.should be_visible
29
- # ui.list_of_widgets.should be_empty
30
- # end
31
- # end
32
- # end
33
- #
34
- # For Cucumber, add the following to `features/support/kookaburra_setup.rb`:
35
- #
36
- # Kookaburra.adapter = Capybara
37
- # World(Kookaburra)
38
- #
39
- # Before do
40
- # kookaburra_reset!
41
- # end
42
- #
43
- # After doing to, the #api, #given and #ui methods will be available in your
44
- # Cucumber step definitions.
45
- #
46
- # (Obviously, the specific methods on #given and #ui are something that will be
47
- # unique to your application's domain.)
48
- #
49
- # [1] http://martinfowler.com/eaaDev/WindowDriver.html
6
+ # This module contains the methods for Kookaburra configuration as well as
7
+ # accessors to the `GivenDriver`, `APIDriver` and `UIDriver`. See
8
+ # {file:README.markdown README} for more information on setting up Kookaburra
9
+ # for your project.
50
10
  module Kookaburra
51
11
  class << self
52
- # Provides the default adapter for the Kookaburra library. In most cases,
53
- # this will probably be the `Capybara` class:
12
+ # Provides the default adapter for the Kookaburra library.
54
13
  #
55
- # Kookaburra.adapter = Capybara
14
+ # If not using Capybara, the Object must respond to `#app` and return a Rack
15
+ # application; and it must respond to `#current_session` and return an
16
+ # object that provides the same interface as `Capybara::Session`
56
17
  #
57
- # We allow this to be passed in, so that we can avoid a hard-coded
58
- # dependency on Capybara in this gem.
18
+ # @example using Capybara
19
+ # Kookaburra.adapter = Capybara
59
20
  attr_accessor :adapter
60
21
 
61
- # The API Driver that will be used by Kookaburra, typically a subclass of
62
- # Kookaburra::APIDriver containing the testing DSL for your app. The default
63
- # is an instance of Kookaburra::APIDriver.
22
+ # A reference to your application's subclass of `Kookaburra::APIDriver`
23
+ #
24
+ # @example setting your APIDriver
25
+ # Kookaburra.api_driver = MyApplication::Kookaburra::APIDriver
64
26
  attr_accessor :api_driver
65
27
 
66
- def api_driver
67
- @api_driver ||= Kookaburra::APIDriver
68
- end
69
-
70
- # The Given Driver that will be used by Kookaburra, typically a subclass of
71
- # Kookaburra::GivenDriver containing the testing DSL for your app. The default
72
- # is an instance of Kookaburra::GivenDriver.
28
+ # A reference to your application's subclass of `Kookaburra::GivenDriver`
29
+ #
30
+ # @example setting your GivenDriver
31
+ # Kookaburra.api_driver = MyApplication::Kookaburra::GivenDriver
73
32
  attr_accessor :given_driver
74
33
 
75
- def given_driver
76
- @given_driver ||= Kookaburra::GivenDriver
77
- end
78
-
79
- # The UI Driver that will be used by Kookaburra, typically a subclass of
80
- # Kookaburra::UIDriver containing the testing DSL for your app. The default
81
- # is an instance of Kookaburra::UIDriver.
34
+ # A reference to your application's subclass of `Kookaburra::UIDriver`
35
+ #
36
+ # @example setting your UIDriver
37
+ # Kookaburra.api_driver = MyApplication::Kookaburra::UIDriver
82
38
  attr_accessor :ui_driver
83
39
 
84
- def ui_driver
85
- @ui_driver ||= Kookaburra::UIDriver
86
- end
87
-
40
+ # Configure the test data collections and default data for your tests
41
+ #
42
+ # The passed block is evaluated in the context of the `Kookaburra::TestData`
43
+ # class and therefore has access to the
44
+ # `Kookaburra::TestData.provide_collection` and
45
+ # `Kookaburra::TestData.default` methods. Anything else in the block will
46
+ # also be evaluated in the context of the class, allowing you to further
47
+ # augment the TestData class.
48
+ #
49
+ # @param [Proc] blk the TestData configuration code
50
+ #
51
+ # @example creating a collection
52
+ # Kookaburra.test_data_setup do
53
+ # provide_collection :users
54
+ # end
55
+ #
56
+ # @example specifying default values for use in tests
57
+ # Kookaburra.test_data_setup do
58
+ # default :user,
59
+ # :first_name => 'Bob',
60
+ # :last_name => 'Jones',
61
+ # :password => 'bob_jones_password'
62
+ # end
63
+ # end
64
+ #
65
+ # @example otherwise extending TestData
66
+ # Kookaburra.test_data_setup do
67
+ # include MyApplication::Kookaburra::TestDataExtensions
68
+ # end
69
+ #
70
+ # @see Kookaburra::TestData.provide_collection
71
+ # @see Kookaburra::TestData.default
88
72
  def test_data_setup(&blk)
89
73
  Kookaburra::TestData.class_eval(&blk)
90
74
  end
91
75
  end
92
76
 
93
- # Whatever was set in `Kookaburra.adapter can be overriden in the mixin
94
- # context. For example, in an RSpec example:
77
+ # Used to override Kookaburra.adapter in Kookaburra's own tests.
95
78
  #
96
- # describe "Something" do
97
- # it "does something" do
98
- # self.kookaburra_adapter = CapybaraLikeThing
99
- # ...
100
- # end
101
- # end
79
+ # This method should not be used by applications using Kookaburra.
102
80
  #
81
+ # @private
103
82
  attr_accessor :kookaburra_adapter
104
83
 
105
84
  def kookaburra_adapter
106
85
  @kookaburra_adapter ||= Kookaburra.adapter
107
86
  end
108
87
 
109
- # Returns a configured instance of the `Kookaburra::APIDriver`
88
+ # The configured instance of the `Kookaburra::APIDriver` subclass for your
89
+ # application.
90
+ #
91
+ # Can be used in the Test Implementation layer to access the application's API
92
+ # directly, however you should probably only call this within your
93
+ # `GivenDriver`.
94
+ #
95
+ # @return [Kookaburra::APIDriver]
110
96
  def api
111
- kookaburra_drivers[:api] ||= Kookaburra.api_driver.new(
112
- :app => kookaburra_adapter.app,
113
- :test_data => kookaburra_test_data)
97
+ kookaburra_drivers[:api] ||= Kookaburra.api_driver.new(:app => kookaburra_adapter.app)
114
98
  end
115
99
 
116
- # Returns a configured instance of the `Kookaburra::GivenDriver`
100
+ # The configured instance of the `Kookaburra::GivenDriver` subclass for your
101
+ # application.
102
+ #
103
+ # Use #given inside your test implementation to call methods from your
104
+ # `GivenDriver` subclass.
105
+ #
106
+ # @return [Kookaburra::GivenDriver]
117
107
  def given
118
108
  kookaburra_drivers[:given] ||= \
119
109
  Kookaburra.given_driver.new(:api_driver => api, :test_data => kookaburra_test_data)
120
110
  end
121
111
 
122
- # Returns a configured instance of the `Kookaburra::UIDriver`
112
+ # The configured instance of the `Kookaburra::UIDriver` subclass for your
113
+ # application.
114
+ #
115
+ # Use #given inside your test implementation to call methods from your
116
+ # `UIDriver` subclass.
117
+ #
118
+ # @return [Kookaburra::UIDriver]
123
119
  def ui
124
120
  kookaburra_drivers[:ui] ||= Kookaburra.ui_driver.new(
125
121
  :browser => kookaburra_adapter.current_session,
126
122
  :test_data => kookaburra_test_data)
127
123
  end
128
124
 
125
+ # Reset the Kookaburra drivers to clear state between Cucumber scenarios
126
+ #
129
127
  # This method causes new instances of all the Kookaburra drivers to be created
130
128
  # the next time they are used, and, in particular, resets the state of any
131
129
  # test data that is shared between the various drivers. This is necessary when
132
130
  # Kookaburra is mixed in to Cucumber's World, because World does not get a new
133
- # instance for each scenario. Instead, just be sure to call this method from a
134
- # `Before` block in your cucumber setup, i.e.:
131
+ # instance for each scenario.
135
132
  #
133
+ # @example add this to `features/support/kookaburra_setup.rb`
136
134
  # Before do
137
135
  # kookaburra_reset!
138
136
  # end
@@ -142,14 +140,15 @@ module Kookaburra
142
140
 
143
141
  private
144
142
 
145
- # The Kookaburra::TestData instance should not be used directly, but all of
146
- # the drivers should reference the same instance.
143
+ # The Kookaburra::TestData instance should not be accesed directly in the test
144
+ # implementation layer, but all of the drivers should reference the same
145
+ # instance.
147
146
  def kookaburra_test_data
148
147
  kookaburra_drivers[:test_data] ||= Kookaburra::TestData.new
149
148
  end
150
149
 
151
150
  # Holds references to all drivers in a single hash, so that
152
- # Kookaburra#kookaburra_reset! can easily clear all Kookaburra state on the
151
+ # `Kookaburra#kookaburra_reset!` can clear all Kookaburra state on the
153
152
  # instance of the including class.
154
153
  def kookaburra_drivers
155
154
  @kookaburra_drivers ||= {}
@@ -1,6 +1,12 @@
1
1
  require 'helper'
2
2
 
3
3
  describe Kookaburra do
4
+ before(:each) do
5
+ Kookaburra.api_driver = Kookaburra::APIDriver
6
+ Kookaburra.given_driver = Kookaburra::GivenDriver
7
+ Kookaburra.ui_driver = Kookaburra::UIDriver
8
+ end
9
+
4
10
  describe 'as a mixin' do
5
11
  let(:mixer_class) do
6
12
  Class.new do
@@ -138,11 +144,6 @@ describe Kookaburra do
138
144
  Kookaburra.api_driver = :an_api_driver
139
145
  assert_equal :an_api_driver, Kookaburra.api_driver
140
146
  end
141
-
142
- it 'defaults to Kookaburra::APIDriver' do
143
- Kookaburra.api_driver = nil
144
- assert_equal Kookaburra::APIDriver, Kookaburra.api_driver
145
- end
146
147
  end
147
148
 
148
149
  describe '#given_driver' do
@@ -150,11 +151,6 @@ describe Kookaburra do
150
151
  Kookaburra.given_driver = :a_given_driver
151
152
  assert_equal :a_given_driver, Kookaburra.given_driver
152
153
  end
153
-
154
- it 'defaults to Kookaburra::GivenDriver' do
155
- Kookaburra.given_driver = nil
156
- assert_equal Kookaburra::GivenDriver, Kookaburra.given_driver
157
- end
158
154
  end
159
155
 
160
156
  describe '#ui_driver' do
@@ -162,11 +158,6 @@ describe Kookaburra do
162
158
  Kookaburra.ui_driver = :a_ui_driver
163
159
  assert_equal :a_ui_driver, Kookaburra.ui_driver
164
160
  end
165
-
166
- it 'defaults to Kookaburra::UIDriver' do
167
- Kookaburra.ui_driver = nil
168
- assert_equal Kookaburra::UIDriver, Kookaburra.ui_driver
169
- end
170
161
  end
171
162
 
172
163
  describe '.test_data_setup' do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kookaburra
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 63
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 7
9
- - 2
10
- version: 0.7.2
8
+ - 8
9
+ - 0
10
+ version: 0.8.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Renewable Funding, LLC
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-23 00:00:00 Z
18
+ date: 2012-01-24 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  version_requirements: &id001 !ruby/object:Gem::Requirement
@@ -84,7 +84,7 @@ dependencies:
84
84
  segments:
85
85
  - 0
86
86
  version: "0"
87
- name: bluecloth
87
+ name: yard
88
88
  prerelease: false
89
89
  type: :development
90
90
  requirement: *id005
@@ -94,13 +94,12 @@ dependencies:
94
94
  requirements:
95
95
  - - ~>
96
96
  - !ruby/object:Gem::Version
97
- hash: 7
97
+ hash: 15
98
98
  segments:
99
+ - 1
99
100
  - 0
100
- - 6
101
- - 0
102
- version: 0.6.0
103
- name: yard
101
+ version: "1.0"
102
+ name: redcarpet
104
103
  prerelease: false
105
104
  type: :development
106
105
  requirement: *id006
@@ -108,14 +107,12 @@ dependencies:
108
107
  version_requirements: &id007 !ruby/object:Gem::Requirement
109
108
  none: false
110
109
  requirements:
111
- - - ~>
110
+ - - ">="
112
111
  - !ruby/object:Gem::Version
113
- hash: 23
112
+ hash: 3
114
113
  segments:
115
- - 1
116
114
  - 0
117
- - 0
118
- version: 1.0.0
115
+ version: "0"
119
116
  name: bundler
120
117
  prerelease: false
121
118
  type: :development
@@ -124,14 +121,12 @@ dependencies:
124
121
  version_requirements: &id008 !ruby/object:Gem::Requirement
125
122
  none: false
126
123
  requirements:
127
- - - ~>
124
+ - - ">="
128
125
  - !ruby/object:Gem::Version
129
- hash: 7
126
+ hash: 3
130
127
  segments:
131
- - 1
132
- - 6
133
- - 4
134
- version: 1.6.4
128
+ - 0
129
+ version: "0"
135
130
  name: jeweler
136
131
  prerelease: false
137
132
  type: :development
@@ -154,14 +149,12 @@ dependencies:
154
149
  version_requirements: &id010 !ruby/object:Gem::Requirement
155
150
  none: false
156
151
  requirements:
157
- - - ~>
152
+ - - ">="
158
153
  - !ruby/object:Gem::Version
159
- hash: 15
154
+ hash: 3
160
155
  segments:
161
- - 1
162
- - 2
163
- - 8
164
- version: 1.2.8
156
+ - 0
157
+ version: "0"
165
158
  name: reek
166
159
  prerelease: false
167
160
  type: :development
@@ -178,6 +171,7 @@ extra_rdoc_files:
178
171
  files:
179
172
  - .document
180
173
  - .rvmrc
174
+ - .yardopts
181
175
  - Gemfile
182
176
  - Gemfile.lock
183
177
  - LICENSE.txt