I don’t know what a number is anymore!

One, Two, Three, Four. I thought I understood the damn things. And then it turns outthey have ‘lifestyle choices’ and Mr. One says ‘you know, I just don’t FEEL like anInteger’ and suddenly they are making ‘changes’ and you’re alone with the Xbox, apound of bacon, and nothing but tears.

Floating Point Numbers

I’m talking numbers in Ruby right now, but I’m shaken to the core. Floating numbersare numbers! They should work right! They should ADD UP! Now, a floatingpoint number is at least equal to itself. This passes:

assert_equal(0.1, 0.1)

But this doesn’t:

assert_not_equal(0.1, 0.4-0.3)

You’d think 0.1 == 0.1 but you’d be wrong! You see, 0.1 is only an approximation ofthe value stored by the floating point system in binary. 0.3 is an approximation,and 0.4 is an approximation. And when they are mathed, they don’t approximate outequally. There’s a loss of precision. It’s pretty close. This passes:

expected_float = 0.1
actual_float = 0.4-0.3
assert ( (expected_float - actual_float).abs <= 0.00000005 )

…it’s just not exact. It’s wrong over in C# too.

[Test]
public void FloatTests()
{
Assert.AreEqual(0.1f, 0.3f - 0.2f);
}

Goes boom:

Modulus

What’s a modulus? First off, I thought it was the number you get when you use themod operator in a language…but it’s not. The modulus is actually the numberyou ‘divide’ by in a mod operation. The result is technically called the remainder.

Now the way I learned it, the mod operation is a lot like making change. If I have1453 copper pieces (cp) and one silver piece (sp) is 100 coppers, then I find outhow many silvers I have with simple division. This passes in C#:

int copper= 1453;
int silver= copper / 100;
int change= copper % 100;
Assert.AreEqual(14, silver);
Assert.AreEqual(53, change);

And in Ruby:

copper = 1453
silver = copper / 100
change = copper % 100
assert_equal 14, silver
assert_equal 53, change

It’s all good so far, right? But what if I owe money? What if my initial total is–1453 ? I owe 14 silvers and 53 coppers, right? Well, yes. And that’s what C# shows.–14 silver and –53 coppers. But not Ruby:

copper = -1453
silver = copper / 100
change = copper % 100
assert_equal -15, silver
assert_equal 47, change

You owe 15 silver. And when you pay…you’ll get 47 copper back. If you want the C#(C++, C, etc) results, you’ll need to use positive numbers and handle the negativeyourself.

I’ve been scratching my head around this, and it really seems like it’s an equallyvalid way of the numbers. The math people have both definitions lying around. Andsome cases have this method make more sense. Imagine you’re trying to find out whatO’Clock it is. You have your hours variable and you use the mod operator. HOURS %12. That works just fine, until you go negative. What if you wanted to know what O’Clockit was 143 hours ago? If it’s noon, and you’re using Ruby, –143 % 12 gives you theright answer.

I guess the accountants are right. “What do you want the numbers to be?”

Test-Driven Learning Games and Tests

In my first and second poston the idea of learning Ruby through writing tests, I showed the basics of learninga language using the TDD tools. Since that start, I’ve found some great work othershave done along these lines that you can use to play with the skills you’re learningand test yourself against some real problems.

First, the Ruby Koans byJim Weirich are a comprehensive set of ‘learning tests’ that can teach you or quizyou on what you’ve learned of Ruby so far. Each time you pass a test, it points youto the next thing you need to fix. Truly TDD learning!

I was a bit put off when I first found this set, since it seems so much like a shortcut,but there’s no reason I can’t play with Jim’s tests as well as writemy own, now is there?

Second, there’s the Ruby Quiz, whichlooks to be a great place to get a graduate education in your Ruby skills. The quizisn’t being added to anymore, but the challenges are just awesome and they have referencesolutions from people who have solved them before you. Once you’ve solved one, youcan find so many ways of learning a better way. Talk about erudition!

A Testy Way of Learning Ruby

In my recentpost, I started sharing some of the fun of learning Ruby using Test-Driven techniquesto learn the language features and document what you are learning as you go.

There are several advantages of learning the language this way. It flexes your brainin ways that just reading the book or typing in the sample code doesn’t. Once you’redone, you have some running, organized code that you can refer back to. Also, whenyou upgrade your language, or change which platform you run it on, you can run yoursuite of learning tests. Find out if Ruby 1.9 is different from 1.8…and how. Are thereimplementation differences between linux Ruby and Iron Ruby? You’ll know.

Today, I’d like to cover the additional assert variants available in the Test::Unitmodule, and talk about using an IDE.

Lasttime, we covered the assert method for testing truth. But there are lot more thingsyou can test!

  • assert – Tests the truth of an expression
  • assert_block – Tests that the return value of a code block is true
  • assert_equal – Tests that two values are equal
  • assert_in_delta – Tests two floats with tolerance for floating point error (read upon this one! it’s a doozy)
  • assert_instance_of – Tests that an object is an instance of a class
  • assert_kind_of – Tests that an object is of a class, or a subclass, or implementsthe kind
  • assert_match – Test using a regular expression
  • assert_nil – Tests the nil-ness of the expression
  • assert_no_match – A not test
  • assert_not_equal – A not test
  • assert_not_nil – A not test
  • assert_not_same – A not test
  • assert_nothing_raised – A not test
  • assert_nothing_thrown – Not a test. Just kidding.
  • assert_operator – I don’t get this one. Well, I’m still learning!
  • assert_raise – Tests that the code block raises a given exception
  • assert_respond_to – Tests that an object has a named method defined
  • assert_same – Tests that both values are the same object instance
  • assert_send – Another one to learn on. Looks like it tests a method call?
  • assert_throws – Looks like another type of exception handling.

With this group of methods, it should be rather easy for you to write some nice, readabletests as you learn things up. One interesting one is assert_same, which can provethat all values of True are really the same instance. Also, when you write a testthat fails by raising an exception, use assert_raise to document that. You shouldhave a test that shows what happens when you divide by zero, and one that shows whathappens when you use an uninitialized variable.

Using an IDE

Most of the ‘True Ruby Folk’ believe with all their flinty hearts that you shouldn’tneed anything more than a charred and pointed stick to write excellent Ruby. Theyare probably right. On the other hand, a good IDE can be like a coding video gameand make the process so much more colorful and fun. I’ve sure found that JetBrains’new RubyMine IDE has made myearly Ruby coding a bit of clicky goodness.

Creating a new test class is really easy. You just add the file to your project:

You get a fully fleshed and voluptuous test class ready for you to have your way withit.

And while you’re learning the language, it’s really nice to have some code completionfeatures so that you can figure out the rest of what you’re typing without going madswitching between windows.

All that and it’s not going to break the bank. Just $99! Give it a try.

I hope you’re keeping up with your test writing. I’ve got 168 assertions testing languagefeatures and I’m just through the primitives and variable types.

How many tests can you write?

Test-Driven Learning

You may not have realized it, but learning Ruby is like being attacked by a bunchof ADD Buddhist Monks. They’ll jump into your living room, raving and excited, anddo back flips while telling you how Zen and relaxing development should be. It’s weird.

Once we’ve medicated the frenetic relaxation, though, it’s really evident that therea lot of good ideas to be found in this community. The latest that I’ve discoveredis Test-Driven Learning.

What this means to me is that I can FINALLY stop writing ‘Hello World’ programs. Languageshave print or printf or puts commands—we can stop being thrilled by that now. Ok?Let’s just write Tests! If we can make test Assertions, we can kick the tires of eachnew piece of language syntax we learn as we learn it without creating silly, baroqueprograms to host them.

Lets start out by discovering the shortest syntax to use the language’s testing framework.The one built into Ruby is Test::Unit. This is easy in Ruby. You need a ‘require’line and to subclass the test fixture class.

require "test/unit"
class TestTest< Test::Unit::TestCase
def test_tests
assert true
end
end

That’s easy. And now you can assert things. Like ‘true’. Save that in a file, like‘test.rb’ then execute it with the ruby command line.

C:UsersjoshDesktop> ruby test.rb
Loaded suite test_test
Started
.
Finished in 0.001seconds.
??
1 tests, 1 assertions, 0 failures, 0 errors

From here on out, just start adding ‘assert’ lines as you discover things about Ruby.Since we started with ‘true’, maybe some asserts on Truth would be a good start. Iwonder which of these will pass and which will fail? If you know Perl, Javascript,or C# your preconceptions will be different.

assert true
assert false
assert 'True'
assert ""
assert 0
assert 1

So little code, and now you can curl up with your favorite Ruby howto book and spenda warm afternoon pondering the nature of Truth. Exciting eh? Well calm down! You don’tneed to be a crazy Zen guy. Just do some learning.

Resources:

Learn a Language Each Year

There’s a piece of advice that floats around,apparently from the PragmaticProgrammer, which goes like this:

Learn One New Language Each Year

I made a good start at Ruby last year, but got derailed by new exciting things overin the .NET world. This year is definitely the one.

I’ve got two reasons:

First, I’m really excited about programming phone systems with Adhearsion.

Second, I’ve realized that all the cool kids over at Microsoft spent the last 3 yearsgetting excited about Ruby. Not only are they developing their own Ruby runtime, butthe dynamicfeatures of C# 4.0 coming in VS2010 are obviously being designed to keep developersfrom jumping ship. We need to learn to think like Ruby coders toadapt to the new problems coming down the line.

One more thing…

Ruby is becoming a first-class citizen for Macintosh GUI application development.If you can write cross-platform libraries that work on the first-class frameworkson Windows, Linux, and the Mac…soon life will be nothing but champagne and swimsuitmodels!