Workflow for TDD/BDD on Rails ?
Hi, I'd like some feedback if possible about the workflow of TDD/BDD on a Rails app. I was doing a research the whole weekend trying to find some good examples on how to do porperly TDD on my Rails apps, but most of the resources (especially with Rspec) seemed a bit outdated as they were using older versions or I wasn't happy enough with the content of the resource.
However I think I've manage to come up with how TDD is done in Rails and I'd like to try and describe it to you with a simple example and then if you could tell me if I have understand it correct or not. Lets go to my example:
Lets assume that we want to build a simple blog and for the tests want to use Rspec, Capybara, FactoryGirl etc etc (I picked these gems as an example, but I assume same thing would apply if we used minitest instead of rspec or with any other gem). In most examples I've seen they start testing by writing a first test (as TDD suggests) like this:
// visit the root page
// click the link "New Post"
// submit the form (eg title and body fields)
// expect the page to display the new post
And with a combination of Rspec and Capybara we write a test like this and we run it every single time in order to write the minimum required code until the test pass. And then we keep going to the next one, and the next one etc etc, until we come up with a completelly restfull PostsController.
Ok, this seems quite nice, but what if we know right from the begining that we need to create this restfull PostsController? Wouldn't make more sence to generate a scaffold Posts and then do the tests? So the steps would be
- rails g scaffold Post title:string body:text
- write a test like the one above to see if we can create a post etc etc
So, I think we are not doing exactlly TDD in this case, but still we do testing.
Regarding organizing our tests, I've seen in a few resources doing something like this:
- have /spec/features directory where we can write tests that are related with the "user interactivity", so tests that cover things like click this link, submit this form, expect to see this content on my webpage etc
- have the /spec/models for testing the models, like validation rules, scopes, methods etc etc
- have the /spec/cotrollers for testing controllers in the same way as we do for models
So,
Is this how TDD is supposed to be done? and is this the proper way to organize our tests then ?
I'd appreciate if you could give me your feedback on this.
I just want to throw in my 2 cents with regards to TDD and the workflow/practices of a development team. You're correct that "textbook TDD" states you first write specs that don't pass, then you implement them feature-by-feature following a red-green refactoring process. That sounds great, and it's a good tool to teach others.
However, the real world is hardly that simple. For example, out of the last 3 Rails projects I've built in the last 2 years, all of them had features that we didn't know the final specification until we first built versions that didn't work and our clients had a chance to review it and give us further guidance on what they really wanted.
Here's a real-world example from my current project. I have a task system that assigns tasks to users, and they can complete a task or reopen it. My first pass was to have completed_at
and reopened_at
columns that tracked when these 2 states changed and to base my logic off of them.
But then I talked to my client, and they also told me they need an inbetween state when a task was "submitted" and needed to be reviewed, but wasn't technically complete.
If I followed TDD, I would have written a bunch of specs that would have been fairly useless and have to be refactored constantly. And the reason they would have to be changed constantly is because I didn't know what the final core architecture or features of the project was going to be.
Thus, in my opinion, pure TDD only makes good sense if you have a clear understanding of what the final product needs to do. In cases where you have a general idea but are refining it constantly, I recommend holding off on the specs until you've solidified on key design. Some projects gather all the product specifications ahead of time and TDD works out great; other projects have general ideas and but the key architecture is figured out at "run-time" so to speak, when your development team actually implements the features and finds all the "gotchas" (most projects are like this for me).
I say this because specs are nothing more than code that also has to be maintained and refactored as time goes on. When you view your specs this way, you realize there is a cost involved with writing and maintaining good specs.
View specs as a guarantee that future code doesn't break existing features. So don't worry as much about having specs while you're building out features, but when you ship that feature to your production system, at that time I strongly recommend you have specs that ensure it all works.
As a final word, don't go crazy testing everything. Much of the core Rails code is already tested, you don't need to repeat what they're already doing. Test your logic and your projects unique features, don't worry as much about "does this core Ruby/Rails method actually do what it says it does?" Chances are it probably does.