There is a long history of postings and even books written about this topic. Most of the time it is called test-driven development (or design resp.) or behavior-driven development, what doesn't matter now. The important thing about it is that you do it first, before writing a single line of code.
Why should I do that?
Most important, it helps you to look at your application from a different point of view. You just concentrate on the desired behavior, and don't think about the how (you would do it), just the what (to do). Next, when writing the tests after your code, you simply test too much or too less, and are too close to the implementation details. And finally, it's best practice to write a test first for every bug you encounter, just to reproduce the error and make sure that it will never ever happen again!
Are there any problems?
One might say your tests are too integrative, meaning that you focus on more than the unit to test, and you probably and simply test too much. But I think it's just a matter of experience, and at the end you can optimize your tests just like the application code later on.
A simple example
You start by describing what your application, method or class should behave like. The user model in this case:
1 2 describe "A user's display name" do
3
4 it "should equal his/her login if no other name is available"
5
6 it "should equal his/her full name if available"
7
8 end
9
What do we have here? First, at line 1 we defined a context for our test, using RSpec's describe block (have a look at
RSpec documentation for details). Furthermore we have two behaviors (it-blocks), defining what we expect our system to behave like. Let's go a step further and fill these up a bit:
1 2 describe "A user's display name" do
3 it "should equal his/her login name if no other is available" do
4 user = User.new(:login => 'dude')
5 user.display_name.should eql('dude')
6 end
7 it "should equal his/her full name if available" do
8 user = User.new(:login => 'dude', :name => 'Thorsten Böttger')
9 user.display_name.should eql('Thorsten Böttger')
10 end
11 end
12
At the very end, you write the application code, and fire up the tests to check, if it behaves
the way you wanted while writing the tests:
1 2 class User < ActiveRecord::Base
3 def display_name
4 name.blank? ? login : name
5 end
6 end
7