mrcasals / feedback

1 stars 1 forks source link

BDD and TDD on Rails #1

Open mrcasals opened 12 years ago

mrcasals commented 12 years ago

@dchelimsky, @oriolgual, @josepjaume, let's keep the discussion in here so we have >140 characters to talk about it.

dchelimsky commented 12 years ago

Hey @mrcasals thanks for setting this up. I'm about to get on a plane so I won't be able to participate much until tomorrow some time, but let me just quickly respond to your last posts. They suggested a very specific order of features, models, controllers and views. The only thing that is defined by BDD from my POV is that you work outside-in, describing application features first and then working your way down to support them. Application features should be general, like "when my account reaches 25k miles, then I earn a silver status" (as I said, about to get on a plane :) ). The spec for this feature requires setting up data (probably not through the UI), and probably doesn't need a view at all - though if you chose to express it in a view that would seem a reasonable choice to me.

Now in The RSpec Book I go through a flow where we write a cucumber feature first and then work our way down via rspec. This is a technical workflow that is a natural result of BDD, but it does not define BDD. What you posted - that there was a very specific order that works for every case - suggests that you think that BDD means going in that order, which is what I don't agree with. This all make sense?

mrcasals commented 12 years ago

What you posted - that there was a very specific order that works for every case - suggests that you think that BDD means going in that order

No, no. I say that most of the time a feature step will need interaction with templates. Imagine I want to create a task manager Rails app. This could be my first scenario:

Scenario: User creates a task
  Given I am at the task creation page
  When I fill in and submit the task form
  Then I should see the task I just created

Maybe the problem is that this is not proper BDD. Maybe I'm trying to test superfluous things, but I've done a lot of scenarios like this one where I work.

Assuming the scenario is a good example, this implies that I have to:

  1. Write the scenario
  2. Run it and watch it fail
  3. Create a test for the unexisting Task model
  4. Write the Task model from the previous test (TDD, watch it fail and so on)
  5. Write the TasksController
  6. Write the tasks views
  7. Run the scenario again and watch it pass

As I said, this is BDD on Rails to me.

My whole point was: doing all this stuff is a pain in the ass when starting a new Rails app. I'd rather work on some models, observers or helper classes first, and after than move to controllers and views.

But hey, maybe it's me and I have misunderstood BDD and TDD :(

garybernhardt commented 12 years ago

I think that your problem lies in the features themselves, not the process. Your features mention behavior, but they're also obsessed with implementation. "page" and "form" are implementation words. Here's the same thing without the implementation details hard-coded into the scenario:

Scenario: User creates a task
  When I create a task called "buy milk"
  Then "buy milk" should be in my task list

What would the steps for this look like? Well, they might use capybara to drive a web browser:

When /I create a task called "buy milk"/ do
  click_link "Create Task"
  fill_in "Task Name", :with => "buy milk"
  click_button "Create"
end

Then /"buy milk" should be in my task list/ do
  click_link "Tasks"
  page.should have_content "buy milk"
end

but they also might also run directly against the models:

When /I create a task called "buy milk"/ do
  Task.create!(:name => "buy milk")
end

Then /"buy milk" should be in my task list/ do
  Task.where(:name => "buy milk").should exist
end

The fact that both implementations are easily possible shows you that the features are sufficiently high-level. Since someone already mentioned Destroy All Software in the Twitter thread, I'll say that in the recent "Sucks/Rocks" series, I do exactly this. I start out with some features running against a lower level of the system. Then, twice during the series, I lift the features up to a higher level. This is a great way to use both TDD loops while still starting at the most abstract part of the system and moving inward. It's also a great way to use both TDD loops without ever touching Rails. ;)

mrcasals commented 12 years ago

@garybernhardt, @dchelimsky and @oriolgual: Thanks for your participation in the discussion. With those examples form Mr. Bernhardt I got your point.

As I said before, we saw Mr. Bernhardt's "Sucks/Rocks" series on DAS at Codegram offices, but I don't know why I was sure he started with specs instead of features... My bad, mea culpa.

Again, thanks everyne for driving me to the correct path :)

oriolgual commented 12 years ago

Previous responses sum it up very well, it's difficult to add more about it :) I really like the approach of start writing abstract features that talk directly to your "domain" models and then keep refactoring them and moving up to a higher level, and maybe, end up writing Capybara-only steps.

BTW, this is the tweet that originated the discussion: https://twitter.com/#!/mrcasals/status/188665261849722882