Copyright © 2010 The G String. All Rights Reserved. Snowblind by Themes by bavotasan.com. Powered by WordPress.
Archive for June, 2009
In my last contract role, I encountered the ruby-based RSpec testing framework for the first time. For those who haven’t looked into it yet, it provides a testing framework for unit, functional, integration and view tests, using a nearly plain English style of test definitions. The title of this blog entry borrows from the typical usage: rather than writing assertions, as with traditional testing frameworks, RSpec steers towards specific expectations for methods, such as
response.should have_tag(‘div’)
As far as I can tell, this code is rather like a wrapper around assert statements and spec tests inherit from the Test::Unit class, allowing traditional assert statements in tests. However, to follow the fanatic principles of BDD (Behavioural Driven Development), we should write tests using the RSpec format.
Why Test-Driven?
I’m a Java developer to begin with. I was drawn into the world of Rails because I was impressed with the ease of obtaining a working website in moments: the scaffold. I liked the fact that you didn’t need to know in advance every little detail about your system, because it was easy to change things afterwards. I liked the fact you could alter the code, press a refresh button on your browser, and instantly see your changes (you can’t do that with servlets, you have to re-start the container). This approach, known as agile programming, depends on this ease of changing your mind after you’ve built something. Writing tests is a very important part of agile programming, because tests are what tell us when we inadvertantly break something when making these ‘agile’ changes. Eventually, someone pointed out that the most correct way of programming therefore was starting with your test, and then implementing the code. That practice is undeniably the best way forward, but it tends to a pedantic style of Rails programming; the idea that there is a ‘correct’ way of testing that we ‘should’ adopt.
With TDD, it feels like I’ve lost a little bit of that nice, agile approach, for in order to write the test for some code I need to know what the code does first, rather like a return to up-front designs. That’s OK- because I ought to know enough about what I want to write anyway: but in practice I’m never going to write tests in advance for anything that Rails generates. I’m probably only going to test things that I wrote, which are over a few lines of code long. In RSpec, I can write tests that check for elements of a certain ID or CSS class: I’d much rather create the page first and then test it afterwards: otherwise I have to decide these things in advance: rather than being able to change my mind easily afterward.
When deadlines are tight, or there isn’t some test manager watching you, tests are the first thing to go, because programmers don’t like writing tests, and writing tests is not as expressive or as fun as working with the real code and seeing it work in the browser.
But then comes along a crowd talking about BDD: behavourial-driven development.
Not TDD; We Need BDD: Behavioural-Driven Development
I’ve tried to see a practical different between TDD and BDD, but its essentially the same idea: writing tests against your code, ideally before you start. If you know the difference, please tell me. For someone or the other, the difference was so profound that another test framework was needed seperate from the Rails test framework: RSpec.
RSpec (and BDD) move away from assertion-led tests such as
assert_equal 50, my_variable
to a programming syntax that is closer to English, focussing on the expectation of that code:
my_variable.should == 50
If I had to say which was easier to read: I’d probably say that the RSpec version is marginally easier; but as I programmer I can read both and I’m used to the first one. Rather than writing real code and adding value to the project, I’m fishing around the appaulingly-designed RSpec website, looking for documentation on how to write something equivalent to a test I could have otherwise written in a few seconds.
The test definition is also different, allowing arbitary phrases as part of the test block, to try and be more readable:
it ‘should complete the order and then deliver an e-mail’ do
Inevitably, all of this plain-English code, while a nice idea, makes the tests verbose and longer to type. If I change the test expectation, I have to change the definition too, if I want to keep it accurate. Yet I don’t really see what benefit it brings: non-technical people are never going to read it, and apart from sticking in fancy HTML reports, again which no-one will read, the programmer is doing extra typing for no return.
Should Do More Work!
RSpec doesn’t just provide changes in syntax. The BDD crowd deem the rails functional test inadequate, for it invokes both controller and view code in order to create the response. From my perspective, the rails approach is just fine: I want to know that when you are routed to a controller action, that action runs successfully, things happen in the database and something is rendered down to the client. BDD says we’re skimping off work doing that; we should test controllers and views seperately. That is, your view should work even if your controller doesn’t and vice versa. Once you know you have a working view and a working controller, you can run integration tests to make sure they work together. However, I think this is overkill. If I can see my view working in a browser, and the test says that under this or that circumstance I get a HTTP 200, 404 or 500, I’m done. I’m never going to switch database engines or run my controllers separately from my views.
Furthermore, RSpec introduces mock objects to abstract-away from the database. As test concepts go, I’ve looked at several frameworks for mocking objects and the concept just seems crazy to me. If I’m writing a database-driven website, why do I want to abstract away from the database? Its database-driven! Why write complex, badly-documented, boring code that isn’t the actual thing? Its doubling the work, and is probably not worth it. If you’re getting a nice daily rate to write this stuff, fine; but I wouldn’t bother with it on my projects, and I can’t see how it delivers business value in the long-term.
Should be_easier
All of these opinions come back to this point: that test code should support the development process, not supplant nor hinder it. All the time spent on writing mocks, seperate tests, getting code coverage up to 100% has its value, but it certainly has a diminishing return. The first few tests that are written, covering the critical part of the codebase, are the most valuable and the easiest to do. Debugging a view test when you can see it working fine in the browser is frustrating and unhelpful.
I think my dislike also stems from the word ‘should’; an interesting word, meaning something that isn’t, but we want or expect. Everywhere we say ‘it should be this way’, we implicity say ‘it should be this way, but it is not that way’. For example, how many records will be in the database after some action? It should be 5- so let’s assert that we have 5. As a friend of mine is fond of saying, “a should is a shit”, I’d rather assert something than bang on about what ought to be this and what ought to be that.
Continue Reading »