Download - TDD with Rails
TDD with RailsAndrzejKrzywda.com
RuPy 2008Poznan, Poland
Who am I?
Andrzej Krzywda
• Developing software since 2000
• Java/.NET/PHP/Python/Rails
Now mostly Rails
First Rails app in November 2004
I started doing TDD in 2001
Also involved in a project called Resolver
One, written in IronPython
Started a Rails company in 2007
Test Driven Development
The goals in a software project
Requirements are goals
What helps in achieving goals?
Goal visualization
Software requirements
TDD (in a high level) is about visualizing goals.
Software developers are responsible
for visualization of other people goals
What is TDD?
TDD is about writing tests BEFORE writing
production code.
What kind of tests?
Be pragmatic.
TDD definitions
TDD is like politics or religion
Everyone thinks he’s right
I think they are wrong...
My TDD
Acceptance tests
+Unit tests
Acceptance tests + Unit tests
Definitions
Acceptance test is a test from the user’s
perspective.
Unit test is a test for a class.
Which are more important?
It depends.
0
25
50
75
100
2001 2003 2006 2008
Unit tests Acceptance tests
The level of test coverage
Java IronPython Rails
Why?
Why
• Rails is a more mature community (in the TDD aspect)
• So many great tools
• REST! - almost no need to test controllers
• Almost only model unit tests
• Acceptance tests, trivial with RSpec Stories + Webrat
Acceptance tests
Doing TDD means to have many tests.
TDD is a good requirements
management technique
TDD
• 3 x D rule
• Defense (Tests)
• Design
• Documentation
???
Let’s take an example.
A blog application
We are about to add a ‘commenting’ feature.
How can we visualize it?
As a Rails developer?
> script/generate migration CreateCommentsTable content:text
class Post < ActiveRecord::Base has_many :commentsend
class Comment < ActiveRecord::Base belongs_to :postend
<%= render_collection @post.comments %>
As a software developer?
$$$$
Someone pays for your work, right?
What users are involved in the blog commenting
feature?
A blog reader
As a blog reader
I want to comment on a blog post
So that I can share my thoughts on the topic
A blog owner / author
As a blog ownerI want to display
commentsSo that other people can see how cool my
blog is.
As a blog ownerI want to moderate
commentsSo that there is no spam
As a blog ownerI want to display captcha
imagesSo that there is no spam
Another blog reader
As another blog readerI want to reply to other
commentsSo that I can prove they
are wrong
As an RSS subscriber...
As a bad person...
As a bad personI want to use SQL InjectionSo that I can break your blog and become famous.
The structure
Spikes / prototyping
User stories
Show your customer the user stories.
Discuss it.
Estimate it.
Prioritize.
Implement it.
Split it into tasks which are usually related to
scenarios.
TDD helps you focusing on one task at a time.
There’s always exactly one test failing.
Tools
RSpec storiesWebrat
Selenium RCWatir
RSpec / BDD
RSpec stories != RSpec examples
RSpec stories is for acceptance tests
‘RSpec examples’ is a unit testing tool.
The process
List the scenarios.
RSpec storyStory: Commenting on a blog
As a blog reader I want to comment So that I can share my thoughts about the article Scenario: Simple adding of a comment
Given an existing blog post And a blog reader writing a comment When he submits it Then it appears below the blog post
stories/comments
require File.join('stories', 'helper')
steps_for :comments doend
with_steps_for :comments do run 'stories/comments', :type => RailsStoryend
require File.join('stories', 'helper')
steps_for :comments do Given "an existing blog post" do @post = Post.create(:title => 'title', :body => 'body') endend
with_steps_for :comments do run 'stories/comments', :type => RailsStoryend
require File.join('stories', 'helper')
steps_for :comments do Given "an existing blog post" do @post = Post.create(:title => 'title', :body => 'body') end Given "a blog reader writing a comment" do visits '/' clicks_link 'Read more...' fills_in 'comment[content]', :with => 'First!' endend
RSpec story runnerrequire File.join('stories', 'helper')
steps_for :comments do Given "an existing blog post" do @post = Post.create(:title => 'title', :body => 'body') end Given "a blog reader writing a comment" do visits '/' clicks_link 'Read more...' fills_in 'comment[content]', :with => 'First!' end
stories/comments.rb
RSpec story runner When "he submits it" do clicks_button "Add" end Then "it appears below the blog post" do visits '/' clicks_link 'Read more...' response.body.should have_text 'First!' end
end with_steps_for :comments, :posts do run 'stories/comments', :type => RailsStoryend
stories/comments.rb
Run the test
It fails
Implement one step at a time
If it’s not trivial start with a spec first.
RSpec example
• Bryan Helmkamp
• github.com/brynary/webrat
• manipulates DOM
• builds POST from DOM
Webrat
Problems?
Slow builds
Fragile, unreliable tests
What about the scientists opinions?
Thirumalesh Bhat and Nachiappan Nagappan. Evaluating the efficacy of test- driven development: industrial case studies. In ISESE ’06: Proceedings of the 2006 ACM/IEEE international symposium on Empirical software engineering, pa- ges 356–363, New York, NY, USA, 2006. ACM.
Gerardo Canfora, Aniello Cimitile, Felix Garcia, Mario Piattini, and Corrado Aaron Visaggio. Evaluating advantages of test driven development: a controlled experi- ment with professionals. In ISESE ’06: Proceedings of the 2006 ACM/IEEE inter- national symposium on Empirical software engineering, pages 364–371, New York, NY, USA, 2006. ACM.
Steven Fraser, Dave Astels, Kent Beck, Barry Boehm, John McGregor, James New- kirk, and Charlie Poole. Discipline and practices of tdd: (test driven development). In OOPSLA ’03: Companion of the 18th annual ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications, pages 268–270, New York, NY, USA, 2003. ACM.
Ivana Turnu, Marco Melis, Alessandra Cau, Michele Marchesi, and Alessio Setzu. Introducing tdd on a free libre open source software pro ject: a simulation expe- riment. In QUTE-SWAP ’04: Proceedings of the 2004 workshop on Quantitative techniques for software agile process, pages 59–65, New York, NY, USA, 2004. ACM.
What are the consequences of doing
TDD?
I don’t use debuggers.
Simpler, thus better design
Frequently asking the question:
“How would I test it?”
After many years of doing TDD, I find it
VERY difficult to work with untested code.
Unit testing tips
• One assertion per test method
• Write the assertion first
• Thin controllers, fat models
• REST
• Fixtures, it’s easier without them
• Specs output as a documentation
Quotes
“TDD was the single most effective software
development habit I adopted”
“My impression is that it's intuitive the way riding a bicycle is intuitive. Extremely UN-intuitive for the child who is learning, but to the adult hardly anything but common sense and difficult to unlearn.
That said, as a developer who's fallen down and scraped his knee... since I need to get from point A to point B fast, I know how to run already so I still do that.”
“TDD doesn't work very well when you're
trying to work on something new - try a
spike instead, and follow with test-driven coding
later”
“It’s not clear how to split tests into suites”
“TDD is intuitive once you start doing it”
“You have to start thinking in a different
way”
“TDD is only one thing, don’t forget about the
others: refactoring, code quality”
“Writing good tests may be difficult for
beginners”
“I can’t achieve a 100% code coverage”
My thoughts
A different way of thinking
I always think “How can I test that” instead of
“how do I implement it”
Live coding
Thank you!
• http://AndrzejKrzywda.com
• Rails consulting, training
• Feel free to email/IM me with TDD questions