Why test Rails, itself?

I'm trying to learn the habit of writing tests, but now that I'm
getting into it, I'm starting to realize that many potential tests --
including some described in Agile Web Development w/Rails -- don't
test the application. Instead, they test Rails itself.

For example, what is the point of writing a unit test that simply
tests a validate statement in the model? Yes, it's interesting (the
first time, at least) that the test works and that, golly-gee, Rails
works as advertised, as well, but is there any real use in doing this?

I can imagine a scenario where a I update Rails and suddenly a unit
test that tests a Rails validator fails, but I expect the Rails
development team would find this before me. Or is that too naive?

The reason I ask is that I'm starting to realize how time consuming it
is to write tests... it could easily double the amount of work. I
can't afford that, so am trying to focus tests on my application code.
I just want to make sure I'm not missing some obvious benefit of
testing the whole Framework.

-- John

Hi --

I'm trying to learn the habit of writing tests, but now that I'm
getting into it, I'm starting to realize that many potential tests --
including some described in Agile Web Development w/Rails -- don't
test the application. Instead, they test Rails itself.

For example, what is the point of writing a unit test that simply
tests a validate statement in the model? Yes, it's interesting (the
first time, at least) that the test works and that, golly-gee, Rails
works as advertised, as well, but is there any real use in doing this?

I can imagine a scenario where a I update Rails and suddenly a unit
test that tests a Rails validator fails, but I expect the Rails
development team would find this before me. Or is that too naive?

The reason I ask is that I'm starting to realize how time consuming it
is to write tests... it could easily double the amount of work. I
can't afford that, so am trying to focus tests on my application code.
I just want to make sure I'm not missing some obvious benefit of
testing the whole Framework.

It's a very interesting question. There really is no point testing
validates_format_of itself, since there's already a test suite for it.
I'd say, though, that it's good to have tests that walk your models
through everything they're supposed to do. Among other things that
will come in handy if you accidentally comment out or alter the
validation. So you can think of your test suite as a kind of
documentation or mega-assertion pertaining to your whole application.

David

I would add to that:

1) If you do not test it, you do not know if it works. Yes there are
tests of Rails itself, but not of your use of Rails.
2) The comment I have seen and come to believe is that if it is not
tested then it is not guaranteed to work. The tests define what
"work" is.

On a small project the programmer may know all the requirements and
remember them at all times, and always get it right. :slight_smile:

But, even on a 2 man project it helps to build tests for what you
expect the software to do.

The application tests will only test the cases that matter to the
applicaiton, while the Rails tests test all the cases the framwork
supports. But, you never know if the Rails tests cover the one case
you care about.

Michael

For example, what is the point of writing a unit test that simply
tests a validate statement in the model? Yes, it's interesting (the
first time, at least) that the test works and that, golly-gee, Rails
works as advertised, as well, but is there any real use in doing this?

+1

The reason I ask is that I'm starting to realize how time consuming it
is to write tests... it could easily double the amount of work. I
can't afford that, so am trying to focus tests on my application code.
I just want to make sure I'm not missing some obvious benefit of
testing the whole Framework.

+1. Actually, *it* doubles the amount of work. Imagine you want to test
you method Father.add_kid. You'll need to 'manually' add a kid to your
@father and then call your method add_kid and assert equality. You
simply rewrite your code! That really annoys me.

However, testing is *really* useful, but not for testing if rake
test:units passes: I have discovered 'bugs' (logic problems) when I
was writing tests.
You know, you're beginning to write your
test_father_add_kid method with weird @father and suddently a
flash[:warning] rings in your head: 'Hey! What about if @father has
already 12 kids? It can't work because... blablabla'. So you
correct your 'real method' and cut/paste in your test just for 'fun'
and be proud to see that it passes.

My $0.02.

Hi --

I would add to that:

1) If you do not test it, you do not know if it works. Yes there are
tests of Rails itself, but not of your use of Rails.

Yes -- that's what I mean about not testing validates_format_of
itself, but testing what you want your application to do, and if what
you want it to do involves calling validates_format_of, then the test
will fail if v_f_of is broken.

2) The comment I have seen and come to believe is that if it is not
tested then it is not guaranteed to work. The tests define what
"work" is.

That still leaves the question: at what point can we consider x to
have been tested?

On a small project the programmer may know all the requirements and
remember them at all times, and always get it right. :slight_smile:

But, even on a 2 man project it helps to build tests for what you
expect the software to do.

I think testing is good even if you're working alone on a project. But
that's for another discussion :slight_smile:

The application tests will only test the cases that matter to the
applicaiton, while the Rails tests test all the cases the framwork
supports. But, you never know if the Rails tests cover the one case
you care about.

I think you can usually assume it doesn't. But it's still a question
of what point you hand off the responsibility to the framework -- or
the language. I don't have any code that specifically tests
String#capitalize, even though I use it and Rails uses it, because I
assume that there are tests in place that test it, in both the Ruby
and the Rails test suites. But if I have a method called title_case,
or something, I'll test *that*, and if it fails then I can investigate
where it went wrong.

All of this relates, also, to the use of tests as an anchor for
refactoring. The fact that my title_case method uses capitalize is
incidental, just as it's incidental that I prevent people from having
too-short passwords by using validates_size_of. There are other ways
to do these things, so it's really a matter of testing for
functionality (I'll let someone else be the one to introduce the word
'behavior' into the thread :slight_smile: rather than implementation.

David

I find that kind of estimations hard to believe, because they sort of assume the alternative amount of work equals development minus tests.

But that is not the case, you need to sum all the bug fixing that comes afterwards, normally in production, and normally accompained by stress, and the uncertainty to deploy yet again without the safety net of a test suite, heh, perhaps you broke some other part of the system, and sometime you do.

Now, in frameworks or libraries you just can't afford publishing something without tests. People are relying on your work, they are using your software in _their_ production systems. So extra care is needed.

I got accostumed to the idea using (and humbly writing) Perl modules from CPAN. As you probably know, CPAN modules are expected to have a test suite. That test suite is run when the module is installed in _your_ machine, locally, which is even better because all I know as an author is they pass in my computer (and the ones volunteered by CPAN testers). If the test suite does not pass module managers won't install them unless forced.

-- fxn

> +1. Actually, *it* doubles the amount of work.

I find that kind of estimations hard to believe, because they sort of
assume the alternative amount of work equals development minus tests.

But that is not the case, you need to sum all the bug fixing that
comes afterwards, normally in production, and normally accompained by
stress, and the uncertainty to deploy yet again without the safety
net of a test suite, heh, perhaps you broke some other part of the
system, and sometime you do.

You're right. But if you want to test your code on boundaries conditions
(which are the ones which most of time break your code), you'll need to
imagine them first and then write your methods. It's just like the writing of
your app's core. For your project, you have (let's assume you're not the
project leader and you don't have to mess^W^understand what your
customers really want) a pretty precise idea of what your code should
do, and you spend time thinking how to implement it. For testing
purposes, you already know how to implement tests since it's just like
the code in your app's core, but you need to imagine all sort of
conditions: normal cases, boundaries, weirdy, etc.

Actually, I didn't meant to say that's development process and testing
require EXACTLY the same time, but testing process requires a lot of
time.

Now, in frameworks or libraries you just can't afford publishing
something without tests. People are relying on your work, they are
using your software in _their_ production systems. So extra care is
needed.

I completly agree. I am really surprised whenever I read on blogs: 'hey!
checkout my acts_as_hibernate plugin. INSTALL: svn co http://svn. &
script/generate hibernate_plugin lots_of_messy_xml etc.'. What about
rake test:plugins?

I got accostumed to the idea using (and humbly writing) Perl modules
from CPAN. As you probably know, CPAN modules are expected to have a
test suite. That test suite is run when the module is installed in
_your_ machine, locally, which is even better because all I know as
an author is they pass in my computer (and the ones volunteered by
CPAN testers). If the test suite does not pass module managers won't
install them unless forced.

'perl is dead' (© my algorithmic teacher)

> +1. Actually, *it* doubles the amount of work.

Based on the test writing that I've been doing the last few days, I'd
say that writing tests turns a 'N' job into a '2N' job... possibly a
'3N' job...

Perhaps I'm just new at it and will get faster with practice, but
taking the time to think up tests takes at least as much time as it
does to write the code. And then you have to debug the tests, because
they are no more likely to work the first time than any other code.
I've just spent a couple hours writing Unit tests for a handful of
functions.

However...

But that is not the case, you need to sum all the bug fixing that
comes afterwards, normally in production, and normally accompained by
stress, and the uncertainty to deploy yet again without the safety
net of a test suite, heh, perhaps you broke some other part of the
system, and sometime you do.

I guess this is the point. An investment now will pay off in the
future.

Additionally, in writing a bunch of 'pointless' model tests, I did
find a bug in a migration... that is the model, and my tests, expected
the database to be set up one way, but the test failed and thereby
uncovered a bug that had been lurking in the database.

So testing the connection between the model code and the database is
one use of validating things that you already "know" are correct.

-- John

Maybe just some viewpoint shift is needed?
Take look at BDD and RSpec, write executable specification *before*
code, so first you state:

context "Data Model " do
   specify "should not allow blank names" do
      @model.name = ''
      @model.should_not be_valid
   end
end

and only then implement the spec:

class Model < ActiveRecord::Base
   validates_presence_of :name
end

Don't look it as testing Rails. You are testing your model on testing
validates. Let's say you write this class:

class Person < ActiveRecord::Base
  validates_length_of :phone_number, :within => 7..10
  ...
end

So you write a test:

def test_phone_number_length_correct
  person = Person.new(:phone_number => '1234567')
  person.valid?
  assert !person.errors.invalid?(:phone_number), 'Valid Phone Number
Coming Back as Invalid'
end

I think we would all agree that this test makes sure that a valid
phone number passes.

Now not thinking you do a find and replace and replace all 7s with 8s
or maybe number with numbers is more likely. So you have:

class Person < ActiveRecord::Base
  validates_length_of :phone_numbers, :within => 7..10
  ...
end

Now you can place :phone_number => '12' into your database because you
are now validating :phone_numbers.

If you have a test you run tests after you completed the find and
replace, and this error would be caught right away. That is why you
'test Rails.'

Amos King
Ramped Media Inc./US Postal Service
Programmer Analyst
dirtyInformation.com

Amos.L.King wrote:

  person = Person.new(:phone_number => '1234567')
  person.valid?

Now not thinking you do a find and replace and replace all 7s with 8s
or maybe number with numbers is more likely.

Or you internationalize. :slight_smile:

(Good sample BTW!)

To me it seems like testing is duplicating (some times 3-4 times) you
work; but in a good way.

So if I have the following:

class Person < ActiveRecord::Base
  validates_length_of :phone_number, :within => 7..10
  ...
end

And the test:

def test_phone_number_length_correct
  person = Person.new(:phone_number => '1234567')
  person.valid?
  assert !person.errors.invalid?(:phone_number), 'Valid Phone Number
Coming Back as Invalid'
end

I am basically saying in two separate places that my application
requires phone numbers to be in a certain format. By putting this in
two or more separate places (and using different syntax) I find myself
significantly less likely to make a mistake (because I have to think
about it in more than one way) and I find myself significantly more
likely to find the errors.

If the odds of coding something wrong (i.e. differently than I think I
am coding) are 20%. Then the odds of coding the same thing wrong twice
are about 4% (0.2 * 0.2). Writing tests has made me go from writing
code that does what I want 80% of the time to doing what I want 96% of
the time.

I'm sure real life difference isn't as simple as that math, but I have
found the concept to be true.

PS. I'm not saying that repetition within you application code is
good. DRY is still the best way to go!!!!

Hi, it's simply about testing your application. I tend to have
business login in the models. Thus, I don't really expect this to
have been done by the core team because they do not know anything
about login with my modules. I also I tend to perform both functional
and integration testing as well.

Rails makes it very easy to perform testing at very levels of your
application. If you think that it's pointless, then you should try
testing J2EE and/or PHP application. When I wrote code in these
technologies, I wished that there was a testing infrastructure like
Rails.

Next, I tend to write my tests first. Then I write the code for my
Rails application so that the tests pass. I'm still getting use to
doing things this way as well as writing tests in general.

Finally, if your client knows enough about Rails, you may be require
to provide these tests as part of the projtect.

-Conrad