evolving to the tdd mindset

while reading through Beginning Ruby on Rails E-Commerce, my eyes have been really opened up to test driven development and how important it is.

i have a problem though. i don’t think like a test driven developer… i see these tests, and while they’re very insightful on how to write test code, what i’m really looking for are testing guidelines. what should i test? what should i just assume works, because the code i’ve used 100 times before has always worked?

while going through the book, i’m thinking thins like “i wouldn’t have that to test and see if the h1 tag was on the page”. or then there are things that i wouldn’t even know how to test because examples weren’t given in the book :wink:

i realize that it’s a different mindset, and i also realize that it won’t happen overnight. but what are things that other developers use as a rule of thumb in order to decide how their tests should run? what questions can i ask myself as i’m writing each action that can help me make decisions or at least help train my mind to start thinking about my tests.

Joshua Kieschnick wrote:

while reading through Beginning Ruby on Rails E-Commerce, my eyes have been really opened up to test driven development and how important it is.

i have a problem though. i don't think like a test driven developer... i see these tests, and while they're very insightful on how to write test code, what i'm really looking for are testing guidelines. what should i test? what should i just assume works, because the code i've used 100 times before has always worked?

Try never writing (or changing) a line of code until you first have a failing test case, requesting it to exist.

I'm aware that's really hard. (For example, how in Hell do you write a test case which checks your onclick contains an Ajax.Request call that will send the correct parameters to the server? In such situations, let testing slide.)

If you start that cycle of adding a little test, and adding a little code, , you will feel more secure about the code, and you will feel insecure when doing things the old way. And you will debug less, and manually test the website less.

while going through the book, i'm thinking thins like "i wouldn't have that to test and see if the h1 tag was on the page".

assert_select 'h1', /my title fragment/

Test things that could break invisibly. If that title comes from simple RHTML, don't bother to test it. If it comes from deep below the Controllers, test it.

or then there are things that i wouldn't even know _how_ to test because examples weren't given in the book :wink:

That is the coal-face of TDD research...

Here's a few of my thoughts on testing.

* Nothing works As far as I care no piece of code works unless I have a test showing that it is actually performing in the way I expect it to. That means that I will test both code I write myself but also stuff I use from Rails, like f.ex. an AR might have some "validate_uniqueness_of" I would test those validations too. I know Rails is a pretty well tested piece of software, so what I'm really testing is my understanding and usage of Rails.

* Coverage Use rcov to get an idea of how far you are from base 1. For me base 1 is 100% coverage with rcov. That is, 100% is a minimum. It just tells me that I have the basics covered. It's not really a measure of the quality of your tests, but you know that if you're not at 100% somethings missing.

* Write tests first I'm unfortunately not very good at doing this myself. But my experience tells me that writing my tests first gets me much better quality than writing tests after. Additionally writing tests first is a good way to "design" the interface to your code as a result code written test first tends to be clearer and more loosely coupled in my experience.

* Test what matters I'm not a big fan of testing what is actually in the views of pages. As far as I'm concerned the views are the place where you get the least "bang for the buck" testingwise. If there's a problem in a view chances are that it'll be noticed immediately anyways. As such I tend to focus my testing on the unit and functional level. Unittests are good for ensuring that your whole model works as intended. With unittests you can easily get into all the corner cases and obscure situations of your model. I like thin controllers so functional testing is mostly a matter of testing that the controller is actually passing stuff on correctly to the model and redirecting users as expected.

* Continous integration If possible one should setup a CI system for running tests automatically on each commit (you are using version control right? ;-)). This is beneficial in at least two ways. First it's sometimes easy to forget to run the tests, with continous integration you'll be notified immediately if you break something. The second reason is to have a clean slate environment, perhaps even using another database. Sometimes you might forget to commit a file or something else machinespecific on your development machine keeps the tests running when in reality they should fail. In this case CI will make sure you get notified of this. Right now Cerberus seems to be a good candidate for easy-to-use CI for Ruby and Rails.

* Testing is a safety net One of the big wins of testing and the first time you'll really appreciate all your hard work is when you one day make a minor change somewhere which really shouldn't have any impact at all and your tests fail. I've heard this over and over as the big aha-experience for people new to testing. Additionally as you tests grow better and better you'll become more and more confident in reworking your code and doing massive changes without worrying what you might have broken. The days of "if it ain't broken, don't fix it" are over, with testing you get the power to improve your code even when it's working. And this is probably the biggest advantage of testing, the ability to rely in your code and change it without hesitation.

* Bugs be gone Whenever a bug is reported the first thing to do is to write a test exposing the bug. Once you have this you can fix it and be sure it will stay gone forever. Over time you might even come to appreciate bugs as they make your tests even better than they were.

* The flipside Of course testing is not all fun. It's actually a lot of work to write tests and being forces to think about the problem before going on a hack'n'slash in codeland. Additionally tests may make one reluctant to perform major refactorings as a lot of test code will need to be altered at the same time. This is actually a major issue which I don't really know the solution for. When going on a major code rework how to ensure that tests are still as good as possible.

* Heckle Recently some of the good chaps over at Seattle.rb released Heckle which will try to mess with your code to expose weaknesses in your tests. This might be worth looking but will probably not be worth it until you're pretty confident in your tests.

I hope this was what you are looking for and gave you some inspiration.

Don't worry too much, getting into the TDD/BDD mindset isn't easy if you've already been a coder for a while. However, read Test-Driven Development by Kent Beck. After reading it, if you still don't understand, then you should start to worry :slight_smile:

Sam Aaron

Jacob Atzen wrote:

Here's a few of my thoughts on testing.

* Nothing works

I never worked on public websites before Rails. I understand one common Best Practice is to set the website up on a test server and mess with it before rolling the code to live servers.

We don't do that with the Rails projects. The tests all pass, we commit, deploy with Capistrano, and the live site has the latest version of the code.

Rails and testing makes us competitive with the non-Lean shops that take forever to deploy their new versions...