Cool, something that I’ve been curious about for some time. With all of this talk about Ruby being one of the cornerstones of the TDD / BDD / ATDD community, I figured Zed would at some point get into writing tests for code.
The benefit to having tests run the code is that, instead of me having to go through and test the paths my program walks down, I can have the test code walk the paths. It’s not all of the testing I would try to do, but it’s a part of the equation I’ve long wanted to get a better feeling for.
Going forward, the “What You Should See” will be replaced by “What You Should Test“. In short, TDD begins here and now, with the idea that I will be writing automated tests for all of the code I write going forward.
Zed make the following point, and I like the sentiment a great deal:
“[…] your reason for writing unit tests is to make your brain stronger. You have gone through this book writing code to do things. Now you are going to take the next leap and write code that knows about other code you have written. This process of writing a test that runs some code you have written forces you to understand clearly what you have just written. It solidifies in your brain exactly what it does and why it works and gives you a new level of attention to detail.”
Writing A Test Case
So now we are going to get a chance to use our project skeleton that we made.
– make a Ex47 project from your project skeleton.
– Make sure you do it right and rename the library and get that first ex47/test/test_ex47.rb test file going right.
– Next, create a simple file ex47/lib/ex47.rb where you can put the code to test.
– Then update the test file in the test directory with your test code.
– and while you are at it, you should update your gemspec code as well so that it reflects what you are doing with this project.
The point to this experiment is that we load the class Room, and then we can create items that help exercise the functionality that makes up Room. There are then a set of tests that are functions starting with test_. Inside each test case there’s a bit of code that makes a Room or a set of Rooms, and then makes sure the rooms work the way you expect them to work.
The key function here:
assert_equal – makes sure that variables you have set or paths you have built are actually what you think they are. If they aren’t, Ruby’s Test::Unit module prints out an error message.
The following is Zed’s suggestions verbatim (I like them, why mess with something that’s already good ;):
– Test files go in test/ and are named test_NAME.rb. This keeps your tests from clashing with your other code.
– Write one test file for each module or class you make.
– Keep your test cases (functions) short, but do not worry if they are a bit messy. Test cases are usually kind of messy.
– Even though test cases are messy, try to keep them clean and remove any repetitive code you can.
– Create helper functions that get rid of duplicate code. You will thank me later when you make a change and then have to change your tests. Duplicated code will make changing your tests more difficult.
– Finally, do not get too attached to your tests. Sometimes, the best way to redesign something is to just delete the tests, and start over.
What You Should See
– Go read about Test::Unit more, and also read about alternatives.
I found this post to be quite clever :):
– Learn about Rspec and see if you like it better.
[I actively use RSpec in my daily testing, and while I’m not sure if I can say I like it “more”, I feel like I have a slightly better understanding of it just by virtue of having used it in conjunction with Cucumber for several months. Ideally, I would have learned Test::Unit first, and then been able to see the parallels better, but I can see the benefits both have]
I quite enjoyed working with this and doing the additional reading on Test::Unit and getting a chance to compare it with Rspec, which again I will say that I do not have an extensive level of experience with, but enough to be kinda’ dangerous (so says the kid with the loaded shotgun). I like the fact that going forward I’ll be using this framework (and I can now say I like the way that the skeleton is set up; it really does help focus what you are doing and how it gets accomplished. Most of all, I’m enjoying really seeing how TDD can and should be accomplished, and I like seeing how it should fit together.