April 21, 2008 at 07:36 PM · Posted under Misc
The 9th edition of the International Free Software Forum (FISL) conference just took place here in my city - Porto Alegre, RS, Brazil - between April 17 and 19. There were more than 7000 people in the event.
Also, there were many interesting talks going on, distributed across 8 rooms. The subject ranged from philosophical and point-of-views to the most technical ones and, of course, RubyOnRails.
Fabio Akita, a very talented and famous RoR developer and a co-worker of mine, gave a great talk about Rails Deployment. He lost the scheduled time due some weather problems in the airport but was able to give it in the day after although to a very smaller public. Anyhow, it was a great presentation and i believe everyone agrees. For those who didn’t see it, he published a screencast of the presentation (It is in brazilian portuguese).
There were other two Rails talks in the event. Sylvestre Mergulhão gave a talk about Rails 2 and Fabricio de Sousa Nascimento gave a introduction to Rails. Both had the room full.
The last talk was a really inspiring and funny one gave by no one less than Jon Maddog Hall. He talked about why having fun developing software is so important, specially for the open source community. The majority of important open source projects has been created by bored people who decided to have fun writing software. Linux is a great example of that. He thinks that open source got too serious and people should be having more fun. I think i agree with him.
Many other big figures were around, including Randal L. Schwartz who gave a talk about Seaside. Sadly, i lost it but heard really good things about it.
Other than the talks, it was great to meet many people who are involved in the community. Some of them i already knew from the internet but others i met for the first time: Vinicius Manhaes Telles, Fabio Akita, Lucas Hungaro, Luiz Vitor Martinez, Jony dos Santos, Julio Monteiro, Carlos Eduardo, and many other people who i won’t recall their names. We talked a lot about Ruby, Rails, Agile Methodologies and other interesting subjects.
It was fun.
Comments (2)
December 28, 2007 at 11:21 AM · Posted under Development, SurgeWorks
One thing that i don’t like about ActiveRecord is the way that it deals with validation messages. I don’t like the fact that it actually push a complete message into the errors stack.
Just to explain it a little better let me illustrate the situation with some code.
The current behavior is the following:
1
2
3
4
5
6
7
|
class User < ActiveRecord::Base
validates_presence_of :username
end
@user = User.new
@user.valid? # => false
@user.errors.on(:username) # => ["can't be blank"] |
I really think it would be better to store the error messages somewhere else and push only an error identifier instead of the whole error message (i.e. “can’t be blank”). Then it would be translate to a message only when needed, probably in the view.
So we would have this instead:
|
@user.errors.on(:username) # => [:blank] |
Someone might ask: what’s the difference? Well, since we would have to store the error messages somewhere it would actually be easier to support internationalization. Besides i don’t like the fact that when writing examples/tests i need to compare error messages to verify that a validation error exists.
Comparing error messages directly is bad. If you change the error message you have to change all the examples that check for that error.
A example that checks for presence of username would be something like this:
1
2
3
4
5
6
7
8
9
|
describe User do
before :each do
@user = User.new
end
it "should require a username" do
@user.errors.on(:username).should include("can't be blank")
end
end |
Now if you decide to change the default error message for validatespresenceof to “is required”, you’d have to change all the examples that check against “can’t be blank”.
While this behavior is not changed – and i tried – i’ve found a good solution to check for validations in my specs that allows me to do this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
describe User do
include Matchers::ActiveRecordMatchers
before :each do
@user = User.new
end
it "should require a username" do
@user.should have_error_on(:username, :blank)
end
it "should require a username of at least 3 characters" do
@user.username = "ab"
@user.should have_error_on(:username, :too_short, 3)
end
it "should require a username of at most 15 characters" do
@user.username = "a"*16
@user.should have_error_on(:username, :too_long, 15)
end
end |
Do you like it?
Then download this, save it as spec/matchers/activerecord_matchers.rb and put this in your spec/spec_helper.rb:
1
2
3
|
%W(matchers).each do |dir|
Dir["#{RAILS_ROOT}/spec/#{dir}/*.rb"].each {|file| require file}
end |
Enjoy!
Comments Off (2)
December 15, 2007 at 02:50 PM · Posted under Development, SurgeWorks
Test vs. Behavior
Test-Driven-Development (TDD) is an approach to software development where developers write tests before actually write code.
There are many good reasons for doing that but certainly there are a few more important:
Writing tests first allows the developer to focus only on the code that he needs to write to accomplish the involved task/feature, reducing the amount of unnecessary code.
Tests are also a documentation of the application. It contains verifications of how the application should behave in specific cases, and since tests are executable you can run the tests at any time to check if the system is behaving correctly or if any bugs has been introduced.
Writing a test first allows the developer to think on how he could implement it, which is a great way to actually design how it should work, defining it’s interface and how it would interact with it’s collaborators.
When a developer starts doing test-driven-development he easily understand the benefits of having a executable test which helps identifying bugs and check if something got broken. On the other hand, it’s not easy to actually understand why he should write test first or even realize that tests can be a really powerful design/architecture tool.
It take some time to get used to writing tests. A developer with a recent interest in the subject usually doesn’t even know what he should test for and if he is too worried about the simplest thing possible in the process he won’t note something more complex and as subtle as the benefit of using tests to drive the application design.
One of the main reason for this lack of understandment is the terminology. The first understanding of a concept directly reflects how it was presented. In other words, the word “test” doesn’t say anything more than just actually testing something, and in general you usually test something after you finished doing it. So it’s kind of hard to realize that tests are not really just tests.
This is where Behavior-Driven-Development – or simply BDD - comes in scene. The ideology and philosophy behind BDD is pretty much the same of TDD, but it has a complete different terminology.
While in TDD you’d have tests, in BDD you’ll have a specification. A executable specification where you define how your application should behave. And isn’t specification something you do first?
The important thing is that by changing the terminology, you actually change the focus on the subject and that not only helps the developers to understand the benefits of doing behavior driven development but also makes possible to have tools with a different approach and point of view.
Test::Unit vs. RSpec
I’m going to use the ruby’s core Test::Unit and RSpec as examples of differences between a TDD tool and a BDD one, they’re both written in Ruby and are the most used in the ruby community.
Let’s write some code. Take this ShoppingCart as example:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class ShoppingCart
attr_reader :total
def initialize
@total = 0
@items = []
end
def add(item)
@items << item
@total += item.price
end
end |
If you have done any unit testing before, the following will probably be really simple to understand:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Item # mock
attr_reader :price
def initialize(price)
@price = price
end
end
class ShoppingCartTest < Test::Unit::TestCase
def setup
@cart = ShoppingCart.new
end
def test_initial_total
assert_equal 0, @cart.total
end
def test_total_on_item_addition
item = Item.new(10)
old_total = @cart.total
@cart.add(item)
assert_equal old_total + item.price, @cart.total
end
end |
If we run this test, the output would be something like this:
$ ruby cart_test.rb
Loaded suite test
Started
..
Finished in 0.000867 seconds.
2 tests, 2 assertions, 0 failures, 0 errors
This tell us that both tests passed.
The equivalent RSpec code would be:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
describe ShoppingCart do
before :each do
@cart = ShoppingCart.new
end
it "should have initial total 0" do
@cart.total.should == 0
end
it "should add item price to total" do
item = mock(:item)
item.should_receive(:price).and_return(10)
old_total = @cart.total
@cart.add(item)
@cart.total.should == old_total + 10
end
end |
At first, let’s focus on the terminology. Look at the keywords: describe, it and should. This is a Specification, which describes the behavior of Cart by saying what it should do. Isn’t that easy to read and understand?
If we run this specification, the output would be:
$ spec cart_spec.rb
..
Finished in 0.017832 seconds
2 examples, 0 failures
This is pretty much the same that of Test::Unit output, and it’s really great to see if something is failing. But if we run this with a different argument we will get a more detailed documentation of the specification:
$ spec --format specdoc cart_spec.rb
Cart
- should have initial total 0
- should add item price to total
Finished in 0.017011 seconds
2 examples, 0 failures
RSpec has other different output formats, also integration with coverage tool and others. I’m not going to get into too much details, you should go and visit RSpec’s website, it is a really great tool.
Another thing you should note is the built-in mocking. That’s because BDD really enforces the use of mocks and stubs. And for who don’t know: Mocks Aren’t Stubs.
State verification vs. Interaction verification
The common approach for tests is usually to check the initial state of the object, perform some action that modify it’s state, and check the state again to see if it is what we would expect. A good example of this is where we check for the old total, add an item and check the new total:
1
2
3
4
|
item = Item.new(10)
old_total = @cart.total
@cart.add(item)
assert_equal old_total + item.price, @cart.total |
A different approach is interaction verification – or collaboration verification – where we actually check for message trading between the object and it’s collaborator. Taking a look at the shopping cart specification you’d note this:
1
2
|
item = mock(:item)
item.should_receive(:price).and_return(10) |
These lines create a mock and sets an expectation that this item should receive a message “price” and if it receive it will return 10. In other words, if the method “price” of this mock doesn’t get called it will raise an error, if it gets called it will return 10.
By setting expectations we’re verifying the interaction between the object being tested and it’s collaborators. Also, mocks are great way to isolate the object being tested from possible interferences – errors – related with any of the collaborators.
BDD encourage the use of mocks and interaction verification along with the traditional testing techniques such as stubs and state verification. When mocking and setting expectations you’ll have to think about the object interface and that bring us back to the test-as-a-designing-tool subject.
Final thoughts
Switching to BDD opened my eyes to many benefits of writing proper tests on both TDD and BDD, mostly because it allowed me to think using the right terms.
Many things here presented as BDD (such as mocking and interaction verification) are not exclusive to it, and it can be easily applied to TDD by using other libraries or even rolling your own solution. But again, the beautiful thing about BDD is the terminology and how it impacts on the way you think.
I say give BDD a try, but of course it’s up to you.
Comments Off (1)
December 07, 2007 at 04:51 PM · Posted under Development
That’s it. No more waiting. Rails 2.0 has been officially launched and it was followed by a 2.0.1 release to fix a small bug.
I’m pretty sure that this is going to be a great release since it’s mostly about polishing and making rails more mature.
So go ahead and upgrade your gems:
gem install rails -y –source http://gems.rubyonrails.org
A more detailed info about the release can be found here
Comments Off