SuperPumpup (dot com)
General awesomeness may be found here.

06 February 2013

Cucumber vs Capybara/Selenium

At the beginning of the project I'm currently on (Nov 2012), I had a disagreement with the (then) lead dev on the project regarding using Cucumber for acceptance testing. He was a big proponent of the "mythical customer who reads and writes specs for you", which, to be fair, has not been even close to happening on this project, while I argued that "Cucumber just puts a DSL between you and your RSpec code. You have to interpret it all yourself, and it's not worth the double-effort there."

Rank was pulled and I grudgingly set up the application using Cucumber for integration testing. However, the other dev left the company about 3 days later and before the proverbial chair was cold, I had torn it out and have been happily writing Capybara/Selenium testing since.

Well, Maybe Happily Is Too Strong A Statement

You see, when I was doing my acceptance testing of the boring "scaffold"-type pages - the CRUD in this application, I was able to quickly write stuff like:

it "allows a dispatcher to create a vendor" do
  sign_in(:dispatcher)
  visit vendors_path
  expect(page).to have_content("New Vendor")
  visit new_vendor_path
  expect(page).to have_content("Name")
  fill_in 'Name', with: "SUPERVENDOR"
  fill_in 'Description', with: "DESCRIPTION"
  click_button 'Save'
  expect(page).to have_content("SUPERVENDOR")
end

Wonderful, right? It is totally readable code, and didn't have to go through YA-DSL. However, over the past few weeks, as I 'polish' the UI elements (by adding lots of fancy schmancy javascript), I find myself writing test cases like this:

it "- can be hauled by a DRH employee using DRH equipment" do
  pending
  customer = create(:customer)
  equipment_mover = create(:haul_truck)
  equipment_to_move = create(:equipment_item)
  employee = create(:employee)

  to_job = create(:job, customer: customer)
  from_job = create(:job, customer: customer)
  sign_in(:dispatcher)
  visit purchase_orders_path
  click_link "new_PurchaseOrder_link"
  select to_job.to_s
  fill_in "Description", with: "SUPERDESCRIPTION"
  click_link "add_equipment_haul_link"
  within ".new_equipment_haul" do
    select equipment_to_move
    select_job(from_job, "$('.jobpicker').first()")
    select_job(to_job, "$('.jobpicker').last()")
    within ".inhouse_move" do
      select_datetime("Jan 10th, 7AM", label: "Start time")
      select_datetime("Jan 10th, 9AM", label: "End time")
      select employee.full_name
      select equipment_mover
    end
  end
  click_button "Save"
  page.should have_content "SUPERDESCRIPTION"
  page.should have_content to_job.name
  page.should have_content from_job.name
  page.should have_content equipment_to_move.number
  page.should have_content employee.full_name
  visit equipment_item_path(equipment_to_move.id)
  within ".current_location" do
    page.should have_content to_job.name
  end
end

Gross, right? And that's even after I've done some work to refactor out some commonly-used patterns like

def select_job(job, finder = "$('.jobpicker').first()")
  token_info = "{'id': #{job.id}, 'name': '#{job.to_s}'}"
  script = finder + ".tokenInput('add', #{token_info})"
  page.execute_script(script)
end

Wait, what? Now I'm WRITING MY OWN DSL to make my Capybara tests readable so that they tell a story? Crap.

So then I watch Build An App With Corey Haines and I remember, "Oh yeah, Cucumber." Cucumber forces you to do that work up front. It ENFORCES the good policy of "Make your acceptance tests readable" - or really, "Make your tests readable".

Is it too late to switch back?