Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Making feature specs fun again

275 views

Published on

With the right mindset and tools, feature specs (automated acceptance tests) are fun to write.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Making feature specs fun again

  1. 1. Phillip Oertel, Ruby User Group Munich, 2016-10-12 Making feature specs fun again With the right mindset and tools, feature specs are fun to write.
  2. 2. Test types Unit API Integration Component GUI
  3. 3. Test types Unit API Integration Component GUI user acceptance tests »feature specs«
  4. 4. Kudos to lale.help ❖ see most of this in action at lale.help (Open Source, MIT license)
 https://github.com/lale-help/lale-help
 

  5. 5. #1: Mindset #2: Tools #3: Pareto
  6. 6. #1: Mindset change.
 Unit and feature specs are 
 very different kinds of beasts.
  7. 7. bunnies vs. elephants controlability high low size S XXL value (tamed) $ $$$$$
  8. 8. bunnies vs. elephants unit feature controlability high low size S XXL value (tamed) $ $$$$$
  9. 9. Size (stack trace) E, [2016-10-10T22:17:56.431204 #14091] ERROR -- : /Users/phillip/Code/_all/lale/app/models/user.rb:60:in `name' E, [2016-10-10T22:17:56.431275 #14091] ERROR -- : /Users/phillip/Code/_all/lale/app/views/files/_list.slim:25:in `block in _app_views_files__list_slim___261366778297433219_70263351087480' E, [2016-10-10T22:17:56.431342 #14091] ERROR -- : /Users/phillip/Code/_all/lale/app/views/files/_list.slim:18:in `each' E, [2016-10-10T22:17:56.431422 #14091] ERROR -- : /Users/phillip/Code/_all/lale/app/views/files/_list.slim:18:in `_app_views_files__list_slim___261366778297433219_70263351087480' E, [2016-10-10T22:17:56.431499 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:145:in `block in render' E, [2016-10-10T22:17:56.431571 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:166:in `instrument' E, [2016-10-10T22:17:56.431641 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:333:in `instrument' E, [2016-10-10T22:17:56.431707 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:143:in `render' E, [2016-10-10T22:17:56.431772 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/partial_renderer.rb:339:in `render_partial' E, [2016-10-10T22:17:56.431833 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/partial_renderer.rb:310:in `block in render' E, [2016-10-10T22:17:56.431893 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/abstract_renderer.rb:39:in `block in instrument' E, [2016-10-10T22:17:56.431954 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `block in instrument' E, [2016-10-10T22:17:56.432021 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument' E, [2016-10-10T22:17:56.432086 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `instrument' E, [2016-10-10T22:17:56.432147 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/abstract_renderer.rb:39:in `instrument' E, [2016-10-10T22:17:56.432207 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/partial_renderer.rb:309:in `render' E, [2016-10-10T22:17:56.432268 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/renderer.rb:47:in `render_partial' E, [2016-10-10T22:17:56.432329 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/helpers/rendering_helper.rb:35:in `render' E, [2016-10-10T22:17:56.432397 #14091] ERROR -- : /Users/phillip/Code/_all/lale/app/views/dashboards/_resources.slim:35:in `_app_views_dashboards__resources_slim___579668583005552750_70263385315780' E, [2016-10-10T22:17:56.432469 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:145:in `block in render' E, [2016-10-10T22:17:56.432532 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:166:in `instrument' E, [2016-10-10T22:17:56.432608 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:333:in `instrument' E, [2016-10-10T22:17:56.432679 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:143:in `render' E, [2016-10-10T22:17:56.432757 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/partial_renderer.rb:339:in `render_partial' E, [2016-10-10T22:17:56.432823 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/partial_renderer.rb:310:in `block in render' E, [2016-10-10T22:17:56.432906 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/abstract_renderer.rb:39:in `block in instrument' E, [2016-10-10T22:17:56.432975 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `block in instrument' E, [2016-10-10T22:17:56.433045 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument' E, [2016-10-10T22:17:56.433122 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `instrument' E, [2016-10-10T22:17:56.433186 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/abstract_renderer.rb:39:in `instrument' E, [2016-10-10T22:17:56.433247 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/partial_renderer.rb:309:in `render' E, [2016-10-10T22:17:56.433318 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/renderer.rb:47:in `render_partial' E, [2016-10-10T22:17:56.433402 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/helpers/rendering_helper.rb:35:in `render' E, [2016-10-10T22:17:56.433473 #14091] ERROR -- : /Users/phillip/Code/_all/lale/app/views/circles/show.slim:16:in `_app_views_circles_show_slim__1918807562146475508_70263361984140' E, [2016-10-10T22:17:56.433538 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:145:in `block in render' E, [2016-10-10T22:17:56.433610 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:166:in `instrument' E, [2016-10-10T22:17:56.433682 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:333:in `instrument' E, [2016-10-10T22:17:56.433745 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/template.rb:143:in `render' E, [2016-10-10T22:17:56.433812 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/template_renderer.rb:54:in `block (2 levels) in render_template' E, [2016-10-10T22:17:56.433878 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/abstract_renderer.rb:39:in `block in instrument' E, [2016-10-10T22:17:56.433946 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `block in instrument' E, [2016-10-10T22:17:56.434025 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument' E, [2016-10-10T22:17:56.434100 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `instrument' E, [2016-10-10T22:17:56.434174 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/abstract_renderer.rb:39:in `instrument' E, [2016-10-10T22:17:56.434245 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/template_renderer.rb:53:in `block in render_template' E, [2016-10-10T22:17:56.434330 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/template_renderer.rb:61:in `render_with_layout' E, [2016-10-10T22:17:56.434395 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/template_renderer.rb:52:in `render_template' E, [2016-10-10T22:17:56.434456 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/template_renderer.rb:14:in `render' E, [2016-10-10T22:17:56.434530 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/renderer.rb:42:in `render_template' E, [2016-10-10T22:17:56.434606 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/renderer/renderer.rb:23:in `render' E, [2016-10-10T22:17:56.434664 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/rendering.rb:100:in `_render_template' E, [2016-10-10T22:17:56.434726 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/streaming.rb:217:in `_render_template' E, [2016-10-10T22:17:56.434784 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/rendering.rb:83:in `render_to_body' E, [2016-10-10T22:17:56.434845 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/rendering.rb:32:in `render_to_body' E, [2016-10-10T22:17:56.434903 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/renderers.rb:37:in `render_to_body' E, [2016-10-10T22:17:56.434965 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/abstract_controller/rendering.rb:25:in `render' E, [2016-10-10T22:17:56.435037 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/rendering.rb:16:in `render' E, [2016-10-10T22:17:56.435101 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/instrumentation.rb:44:in `block (2 levels) in render' E, [2016-10-10T22:17:56.435165 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/core_ext/benchmark.rb:12:in `block in ms' E, [2016-10-10T22:17:56.435237 #14091] ERROR -- : /Users/phillip/.rvm/rubies/ruby-2.2.3/lib/ruby/2.2.0/benchmark.rb:303:in `realtime' E, [2016-10-10T22:17:56.435295 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/core_ext/benchmark.rb:12:in `ms' E, [2016-10-10T22:17:56.435355 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/instrumentation.rb:44:in `block in render' E, [2016-10-10T22:17:56.435651 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/instrumentation.rb:87:in `cleanup_view_runtime' E, [2016-10-10T22:17:56.435708 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/railties/controller_runtime.rb:25:in `cleanup_view_runtime' E, [2016-10-10T22:17:56.435770 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/instrumentation.rb:43:in `render' E, [2016-10-10T22:17:56.435836 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/implicit_render.rb:10:in `default_render' E, [2016-10-10T22:17:56.435899 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/implicit_render.rb:5:in `send_action' E, [2016-10-10T22:17:56.435972 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/abstract_controller/base.rb:198:in `process_action' E, [2016-10-10T22:17:56.436037 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/rendering.rb:10:in `process_action' E, [2016-10-10T22:17:56.436096 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/abstract_controller/callbacks.rb:20:in `block in process_action' E, [2016-10-10T22:17:56.436157 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:117:in `call' E, [2016-10-10T22:17:56.436215 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:117:in `call' E, [2016-10-10T22:17:56.436276 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile' E, [2016-10-10T22:17:56.436340 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call' E, [2016-10-10T22:17:56.436399 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call' E, [2016-10-10T22:17:56.436463 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:498:in `block (2 levels) in around' E, [2016-10-10T22:17:56.436518 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:298:in `call' E, [2016-10-10T22:17:56.436573 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:298:in `block in halting_and_conditional' E, [2016-10-10T22:17:56.436633 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:497:in `call' E, [2016-10-10T22:17:56.436701 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:497:in `block in around' E, [2016-10-10T22:17:56.436770 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call' E, [2016-10-10T22:17:56.436834 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:505:in `call' E, [2016-10-10T22:17:56.436892 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:92:in `__run_callbacks__' E, [2016-10-10T22:17:56.436947 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:778:in `_run_process_action_callbacks' E, [2016-10-10T22:17:56.437008 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:81:in `run_callbacks' E, [2016-10-10T22:17:56.437072 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/abstract_controller/callbacks.rb:19:in `process_action' E, [2016-10-10T22:17:56.437136 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/rescue.rb:29:in `process_action' E, [2016-10-10T22:17:56.437194 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action' E, [2016-10-10T22:17:56.437249 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `block in instrument' E, [2016-10-10T22:17:56.437314 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument' E, [2016-10-10T22:17:56.437375 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications.rb:164:in `instrument' E, [2016-10-10T22:17:56.437440 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/instrumentation.rb:30:in `process_action' E, [2016-10-10T22:17:56.437497 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/params_wrapper.rb:250:in `process_action' E, [2016-10-10T22:17:56.437559 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/railties/controller_runtime.rb:18:in `process_action' E, [2016-10-10T22:17:56.437616 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/abstract_controller/base.rb:137:in `process' E, [2016-10-10T22:17:56.437677 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.4/lib/action_view/rendering.rb:30:in `process' E, [2016-10-10T22:17:56.437735 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal.rb:196:in `dispatch' E, [2016-10-10T22:17:56.437838 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal/rack_delegation.rb:13:in `dispatch' E, [2016-10-10T22:17:56.437903 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_controller/metal.rb:237:in `block in action' E, [2016-10-10T22:17:56.437967 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/routing/route_set.rb:76:in `call' E, [2016-10-10T22:17:56.438025 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/routing/route_set.rb:76:in `dispatch' E, [2016-10-10T22:17:56.438088 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/routing/route_set.rb:45:in `serve' E, [2016-10-10T22:17:56.438150 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/journey/router.rb:43:in `block in serve' E, [2016-10-10T22:17:56.438208 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/journey/router.rb:30:in `each' E, [2016-10-10T22:17:56.438273 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/journey/router.rb:30:in `serve' E, [2016-10-10T22:17:56.438331 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/routing/route_set.rb:821:in `call' E, [2016-10-10T22:17:56.438392 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/omniauth-1.2.2/lib/omniauth/strategy.rb:404:in `call_app!' E, [2016-10-10T22:17:56.438456 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/omniauth-identity-1.1.1/lib/omniauth/strategies/identity.rb:43:in `other_phase' E, [2016-10-10T22:17:56.438520 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/omniauth-1.2.2/lib/omniauth/strategy.rb:185:in `call!' E, [2016-10-10T22:17:56.438584 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/omniauth-1.2.2/lib/omniauth/strategy.rb:164:in `call' E, [2016-10-10T22:17:56.438657 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/omniauth-1.2.2/lib/omniauth/builder.rb:59:in `call' E, [2016-10-10T22:17:56.438722 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/http_accept_language-2.0.5/lib/http_accept_language/middleware.rb:14:in `call' E, [2016-10-10T22:17:56.438786 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/etag.rb:24:in `call' E, [2016-10-10T22:17:56.438842 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/conditionalget.rb:25:in `call' E, [2016-10-10T22:17:56.438902 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/head.rb:13:in `call' E, [2016-10-10T22:17:56.438960 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/params_parser.rb:27:in `call' E, [2016-10-10T22:17:56.439023 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/flash.rb:260:in `call' E, [2016-10-10T22:17:56.439079 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/query_cache.rb:36:in `call' E, [2016-10-10T22:17:56.439139 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract/connection_pool.rb:653:in `call' E, [2016-10-10T22:17:56.439203 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/callbacks.rb:29:in `block in call' E, [2016-10-10T22:17:56.439268 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:88:in `__run_callbacks__' E, [2016-10-10T22:17:56.439514 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:778:in `_run_call_callbacks' E, [2016-10-10T22:17:56.439581 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:81:in `run_callbacks' E, [2016-10-10T22:17:56.439644 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/callbacks.rb:27:in `call' E, [2016-10-10T22:17:56.439715 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/remote_ip.rb:78:in `call' E, [2016-10-10T22:17:56.439778 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rollbar-2.12.0/lib/rollbar/middleware/rails/rollbar.rb:24:in `block in call' E, [2016-10-10T22:17:56.439843 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rollbar-2.12.0/lib/rollbar.rb:735:in `scoped' E, [2016-10-10T22:17:56.439907 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rollbar-2.12.0/lib/rollbar/middleware/rails/rollbar.rb:22:in `call' E, [2016-10-10T22:17:56.439973 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call' E, [2016-10-10T22:17:56.440035 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rollbar-2.12.0/lib/rollbar/middleware/rails/show_exceptions.rb:22:in `call_with_rollbar' E, [2016-10-10T22:17:56.440105 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/show_exceptions.rb:30:in `call' E, [2016-10-10T22:17:56.440165 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/rack/logger.rb:38:in `call_app' E, [2016-10-10T22:17:56.440227 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/rack/logger.rb:20:in `block in call' E, [2016-10-10T22:17:56.440290 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:68:in `block in tagged' E, [2016-10-10T22:17:56.440354 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:26:in `tagged' E, [2016-10-10T22:17:56.440419 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:68:in `tagged' E, [2016-10-10T22:17:56.440482 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/rack/logger.rb:20:in `call' E, [2016-10-10T22:17:56.440546 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:225:in `context' E, [2016-10-10T22:17:56.440615 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:220:in `call' E, [2016-10-10T22:17:56.440673 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/cookies.rb:560:in `call' E, [2016-10-10T22:17:56.440741 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/request_id.rb:21:in `call' E, [2016-10-10T22:17:56.440805 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/methodoverride.rb:22:in `call' E, [2016-10-10T22:17:56.440863 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/runtime.rb:18:in `call' E, [2016-10-10T22:17:56.440924 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/lock.rb:17:in `call' E, [2016-10-10T22:17:56.440990 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.4/lib/action_dispatch/middleware/static.rb:116:in `call' E, [2016-10-10T22:17:56.441060 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/sendfile.rb:113:in `call' E, [2016-10-10T22:17:56.441124 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/engine.rb:518:in `call' E, [2016-10-10T22:17:56.441188 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/application.rb:165:in `call' E, [2016-10-10T22:17:56.441259 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/urlmap.rb:66:in `block in call' E, [2016-10-10T22:17:56.441325 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/urlmap.rb:50:in `each' E, [2016-10-10T22:17:56.441389 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/urlmap.rb:50:in `call' E, [2016-10-10T22:17:56.441447 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/capybara-2.6.2/lib/capybara/server.rb:19:in `call' E, [2016-10-10T22:17:56.441502 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/unicorn-5.1.0/lib/unicorn/http_server.rb:562:in `process_client' E, [2016-10-10T22:17:56.441557 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/unicorn-5.1.0/lib/unicorn/http_server.rb:658:in `worker_loop' E, [2016-10-10T22:17:56.441626 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/unicorn-5.1.0/lib/unicorn/http_server.rb:508:in `spawn_missing_workers' E, [2016-10-10T22:17:56.441688 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/unicorn-5.1.0/lib/unicorn/http_server.rb:132:in `start' E, [2016-10-10T22:17:56.441761 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/bundler/gems/rbsavvy_commons-ba9044e1bafd/lib/rack/handler/unicorn.rb:33:in `run' E, [2016-10-10T22:17:56.441820 #14091] ERROR -- : /Users/phillip/Code/_all/lale/spec/support/capybara.rb:28:in `block in <top (required)>' E, [2016-10-10T22:17:56.441879 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/capybara-2.6.2/lib/capybara/server.rb:70:in `call' E, [2016-10-10T22:17:56.441934 #14091] ERROR -- : /Users/phillip/.rvm/gems/ruby-2.2.3/gems/capybara-2.6.2/lib/capybara/server.rb:70:in `block in boot' feature spec fail: 160 lines 3 threads/
 processes 1. test runner 2. browser 3. Rails app # ./app/models/user.rb:60:in `name' # ./spec/models/user_spec.rb:14:in `block (3 levels) in <top (required)>' # ./spec/rails_helper.rb:55:in `block (4 levels) in <top (required)>' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/database_cleaner-1.5.1/lib/database_cleaner/generic/base.rb:16:in `cleaning' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/database_cleaner-1.5.1/lib/database_cleaner/base.rb:92:in `cleaning' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/database_cleaner-1.5.1/lib/database_cleaner/configuration.rb:86:in `block (2 levels) in cleaning' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/database_cleaner-1.5.1/lib/database_cleaner/configuration.rb:87:in `call' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/database_cleaner-1.5.1/lib/database_cleaner/configuration.rb:87:in `cleaning' # ./spec/rails_helper.rb:54:in `block (3 levels) in <top (required)>' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:68:in `block in tagged' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:26:in `tagged' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/tagged_logging.rb:68:in `tagged' # ./spec/rails_helper.rb:50:in `block (2 levels) in <top (required)>' # ./spec/rails_helper.rb:41:in `block (3 levels) in <top (required)>' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/vcr-2.9.3/lib/vcr/util/variable_args_block_caller.rb:9:in `call' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/vcr-2.9.3/lib/vcr/util/variable_args_block_caller.rb:9:in `call_block' # /Users/phillip/.rvm/gems/ruby-2.2.3/gems/vcr-2.9.3/lib/vcr.rb:182:in `use_cassette' # ./spec/rails_helper.rb:40:in `block (2 levels) in <top (required)>' # ./spec/support/cached_emails.rb:29:in `block (2 levels) in <top (required)>' unit test fail: 13 lines
 
 1 process
  10. 10. Avg. runtime [one test; ms] unit test feature spec 0 250 500 750 1000
  11. 11. Value (feature spec) ❖ Only way to automatically ensure your application works for real users, since they use the application through the web browser, like real users. ❖ low coupling to the actual source code (black box test). This enables large refactorings. Rails version upgrade without tests, anyone? ❖ serve as application specification if written correctly.
  12. 12. https://blog.smartive.ch/postman-integrationtests
  13. 13. Learning ❖ feature specs are more complex but more valuable than unit type tests. ❖ expect more effort to write & tame them.
  14. 14. #2: Tools. Use them.
  15. 15. The »old« way ❖ several factories in each spec to set up test data ❖ CSS selectors inline in spec ❖ global, custom helper methods (#fill_form, anyone?) ❖ some custom RSpec matchers ❖ one assertion per test (being a good TDD citizen) ❖ many tests in one spec file ❖ sleep …
  16. 16. Pain points ❖ maintainability: 
 duplication of CSS selectors, test setup
 no order to test files & helper code ❖ test stability: test sometimes fails even though feature OK ❖ runtime: test suite takes a long time to complete ❖ => slow to write, hard to debug & maintain
  17. 17. »Object graph« factories
  18. 18. »Object graph« factories ❖ one-liner to create all test data ❖ reusable across specs ❖ DRY ❖ reliable (if tested) ❖ uses regular factory_girl features
  19. 19. Example create(:circle, :with_admin_and_working_group) => create(:circle) => create(:user) => create(:circle_admin_role) => create(:circle_volunteer_role, ...) => create(:working_group) => create(:working_group_volunteer_role, ...)
  20. 20. In action describe "Update project" do let(:circle) { create(:circle, :with_admin_and_working_group) } let(:admin) { circle.admins.first } let(:working_group) { circle.working_groups.first } [...] end
  21. 21. before describe "Update project" do let(:circle) { create(:circle) } let(:user) { create(:user) } let(:circle_role) { create(:circle_admin_role, ...) } let(:circle_v_role) { create(:circle_volunteer_role, ...) } let(:working_group) { create(:working_group, ...) } let(:working_group_role) { create(:working_group_volunteer_role, ..) } [...] end
  22. 22. Factory tests describe "the :with_admin_and_working_group trait" do it "assigns a new user as admin" do circle = create(:circle, :with_admin_and_working_group) expect(circle.admins.size).to eq(1) expect(circle.admins.first).to be_a(User) end [...] end
  23. 23. Implementation factory :circle do trait :with_admin_and_working_group do with_admin after(:create) do |circle, evaluator| create(:working_group, circle: circle, member: circle.admin) end end [...] end
  24. 24. More examples # combining traits create(:circle, :with_admin, :with_volunteer) # passing in a user for more control create(:circle, admin: my_user) # project with two tasks create(:project, tasks: 2)
  25. 25. Page objects
  26. 26. Definition »A page object wraps an HTML page, or fragment, with an application-specific API, allowing you to manipulate page elements without digging around in the HTML.« Martin Fowler
 http://martinfowler.com/bliki/PageObject.html
  27. 27. Examples task_page.helpers => expect(task_page.helpers).to include(user_1.name) task_form.visit(task: my_task) task_form.fill_form(title: 'My Task’, …) task_form.fill_date(due_date: Date.today)
  28. 28. Rspec predicate matchers expect(task_form).to have_validation_error("Please enter a name") # calls: task_form.has_validation_error?("Please enter a name") expect(task_page).to be_completed # calls: task_page.completed? Documentation: https://goo.gl/znGT6
  29. 29. SitePrism: element class TaskPage < SitePrism::Page element :volunteer_button, '.button-primary', text: "I'll help" end task_page = TaskPage.new task_page.volunteer_button.click task_page.has_volunteer_button? task_page.wait_for_volunteer_button task_page.wait_for_volunteer_button(10)
  30. 30. SitePrism: section class WorkingGroupDashboard < SitePrism::Page section :tab_nav, TabNav, '.tab-nav' end class TabNav < SitePrism::Section element :tasks, 'a', text: /Tasks/ element :supplies, 'a', text: /Supplies/ end page = WorkingGroupDashboard.new page.tab_nav.tasks.click => section is scoped to parent
  31. 31. more SitePrism features ❖ element & section collections ❖ page navigation & verification (matching URLs) ❖ https://github.com/natritmeyer/site_prism
  32. 32. SitePrism summary ❖ correspond to your application’s pages ❖ DRY up and encapsulate your CSS selectors ❖ hold your helper methods ❖ perfect to reuse
  33. 33. Organizing specs
  34. 34. Organizing specs (1) spec/features !"" circle #   !"" add_and_remove_circle_admins_spec.rb #   !"" block_and_unblock_circle_member_spec.rb #   !"" edit_circle_spec.rb #   !"" show_circle_dashboard_spec.rb #   !"" show_circle_documents_spec.rb #   $"" show_my_activities_spec.rb !"" members #   !"" edit_member_profile_spec.rb #   !"" show_member_profile_spec.rb
  35. 35. Organizing specs (2) describe "Add and remove circle admins" do describe "add" do context "circle has a member that's not admin yet" do it "can be added" ... end end describe "remove" do context "circle has a member that's not admin yet" do it "can be removed" ... end end end
  36. 36. Tools for speed & debugging
  37. 37. Tools for speed & debugging # create a screenshot save_and_open_page # shorten to #show! # open a console in the scope of the HTML page Capybara.pry # run some JS code in the scope of the page evaluate_script(’some js code’)
  38. 38. Tools for speed & debugging (2) ❖ spring gem ❖ poltergeist gem, uses PhantomJS (headless Webkit) ❖ capybara-screenshot gem ❖ browser developer console => test CSS selectors ❖ parallelize (at your own risk, can increase timing issues)
  39. 39. Handling unstable tests
  40. 40. Handling unstable tests ❖ use smart waits (#wait_for_element) ❖ increase default timeout to > 2 seconds ❖ run specs on dedicated hardware ❖ rspec/retry gem ❖ use poltergeist in debug mode ❖ :ci_ignore: https://goo.gl/4ZpYhu
  41. 41. Use smart objects to make the view dumb.
  42. 42. Identify view components
  43. 43. Identify view components
  44. 44. Identify view components
  45. 45. describe CalendarLeafCell, type: :cell do include RSpecHtmlMatchers let(:date) { Date.parse("2016-12-24") } let(:html) { cell(:calendar_leaf, date).call } it "renders month" do expect(html).to have_tag('.calendar-leaf .month', text: 'DEC') end it "renders week" do expect(html).to have_tag('.calendar-leaf .day_number', text: '24') end it "renders weekday" do expect(html).to have_tag('.calendar-leaf .day-of-week', text: 'Sat') end end
  46. 46. class CalendarLeafCell < ::ViewModel def month I18n.l(date, format: "%b").upcase end def day date.day end def week I18n.l(date, format: '%a') end end # app/cells/calendar_leaf/show.slim .calendar-leaf *attributes .month = month .day span.day_number = day span.day-of-week = week https://github.com/apotonick/cells
  47. 47. #3: The Pareto principle.
 Apply the 80/20 rule.
  48. 48. 100% perfection?
  49. 49. The Pareto principle 80% value 20% time 80% time 20% value
  50. 50. Questions to ask ❖ what is the system under test? ❖ which features do I care most about? (login, registration, payment) ❖ which scenarios are most important? (»happy path«) ❖ what is likely to break?
  51. 51. Take shortcuts ❖ Stub APIs (vcr gem) ❖ login »backdoor« ❖ don’t navigate to pages ❖ don’t assert every detail of a page ❖ a hackish test is always better than no test at all
  52. 52. Recap
  53. 53. #1: Mindset #2: Tools #3: Pareto
  54. 54. Happy coding :-)
  55. 55. Image credits ❖ bunny: https://goo.gl/KzXYVX ❖ elephant: https://goo.gl/iqU33k
  56. 56. lale.help introduction
  57. 57. Ralf Schroeder ralf@lale.help https://github.com/lale- help/lale-help
  58. 58. Who needs Lale? 120+ refugees in 2016 3 camps 10+ wokring groups, 100+ helpers Thousands of tasks…
  59. 59. What is Lale? Volunteers Helper circle Refugees 5x 6x 3x @ Many phone calls, emails, meetings, etc until a task is properly assigned to a volunteer
  60. 60. Administrators • System admin • Member management • Data privacy Group organizers • Define and manage groups • Create tasks and supplies; source volunteers Helpers • Register • Task & Supplies • Communicate Roles

×