Unfortunately not too much people (developers) adopt a sane test driven development (TDD) approach and, worse, they don’t write tests at all.

Why?

In my personal opinion there are two main cause for that:

  • test are perceived as “something to proof my code”, and it takes time to be written
  • in “always-running life” time is precious, so nobody tends to waste it (near projects deadline time gets short and pressure increases…)

Doing a correct TDD you get:

  • a regression test suite, incredibly useful when you should change something in your system and be sure you don’t break anything
  • a description of what your system does

The latter point is very importat: a test suite represents an executable documentation of what the system is intended to be, its purpose, and its boundaries.
With TDD you describe the “behaviour” of your system, exactly what should be done for your customer: the functionalities she wants.

So why not change perspective?

With BDD you describe what your system is supposed to do, and then you implement a little as possible to accomplish exactly that.
Benefits (yes, not different from a well done TDD):

  • regression test/behaviour suite to prevent you breaking things in future modification (aka refactoring, or adding some new functionality)
  • an executable documentation about what your system is intended to be
  • a “way” to define interfaces during features definition

I strongly believe that the last point is the more important. Simply put: you pay attention to your customer need, translate it into a set of functionalities and again translate it into a set of behaviours. In this way your design is really close to the reality you want to capture.

After all, in TDD there is a subtle issue: tests reflects the structural arragement of the code, not its behaviour…

Let see a simple example about that using Ruby (a language I love…).

An example

For Ruby novice (or lovers) we’ll use the “Pickaxe” book example about songs (look here for older online version):

song.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Song
  attr_reader :name, :artist, :duration, :plays
  def initialize(name, artist, duration)
    @name     = name
    @artist   = artist
    @duration = duration
    @plays    = 0
  end
 
  def play
    @plays += 1
  end
 
  def to_s
    "#{@name} (#{@duration}) - #{@artist} - #{@plays} plays."
  end
end

song_test.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require 'song'
require 'test/unit'
 
class TestSongList < Test::Unit::TestCase
  def setup
    @s = Song.new('Vivo sohnando', 'Rosalia De Souza', 153)
  end
 
  def teardown
  end
 
  # a song must have a name, an artist and a duration
  def test_attributes
    assert ! @s.name.empty?
    assert ! @s.artist.empty?
    assert @s.duration > 0
  end
 
  # we want to know how many times a song is played
  def test_num_of_plays
    @s.play
    @s.play
    assert @s.plays == 2
  end
end

Ok, we have a class and a test suite that assures us about the fact that functionalities present in the class definition are corrects.
Now change our standpoint, and try to define a priori what we want from our Soong class:

  • a song has a name, and artist and a duration
  • a song should store the number of plays, because we’ll be interested in some analysis (song ratings, and so on…)

Well, let translate these points in code using RSpec : an elegant framework that provide a DSL (Domain Specific Language) to describe behaviours with “executable examples”.
Here’s the code:

song_spec.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
require 'song'
 
describe "A song" do
 
  before :each do
    @s = Song.new('Vivo sohnando', 'Rosalia De Souza', 153)
  end
 
  it "has a name, an artist and a duration" do
    @s.name.should_not be_empty
    @s.artist.should_not be_empty
    @s.duration.should > 0
  end
 
  it "stores how many times is played" do
    @s.plays.should == 0
    @s.play
    @s.plays.should == 1
  end
 
end

In line 4 we define a method called before each example, an example is every “it…” statement and it simply describes what the system should do, with some low level details. Not too different from the song_test.rb, isn’t it?
Here, the framework applies a simple rule:

        OBJECT.should be_SOMETHING

The RSpec framework simply calls OBJECT.SOMETHING and expects it to be true.
Of course the framework is richer of functionalities (see the the documentation for more details).

Finally, let see an executable documentation about that:

$ spec  -f s  song_spec.rb
 
A song
- has a name, an artist and a duration
- stores how many times is played
 
Finished in 0.006772 seconds
 
2 examples, 0 failures

Nice! A real “test” plus a clear documentation about the sytem intents.

A final advise: RSpecs is made for Rails too ;-)!

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Spam protection by WP Captcha-Free