[QUIZ] DayRange (#92)

quoth the David Vallner:

darren kirby wrote:
> My messages aren't appearing as HTML to you all are they? My settings say
> not...

Nope. But they are encoded in iso-8859-6, which I haven't covered in
Thunderbird font settings and the default Courier New ticks me off. What
language set is that anyway? (I should send a hint to Mozilla people
that font substitution is a Good Thing, and that some people just want
to use one font for everything without clicking through all 20 language
groups, thankyouverymuch, since they can't read one bit Chinese or
Indian anyway.)

Hmm. In my Kmail settings I have this:

"This list is checked for every outgoing message from the top to the bottom
for a charset that contains all required characters"
us-ascii
iso-8859-1
utf-8

So where the heck is iso-8859-6 coming from. I have explicitly sent this as
us-ascii, and if it seems to work I will send my ruby-quiz solutions the same
way.

David Vallner

Thanks for the hints guys,
-d

···

--
darren kirby :: Part of the problem since 1976 :: http://badcomputer.org
"...the number of UNIX installations has grown to 10, with more expected..."
- Dennis Ritchie and Ken Thompson, June 1972

Thanks for trying to help, but if I understand how setup functions, your modification defeats my requirement that the test objects be created once and once only. As I understand it, setup will run before EACH test and the test objects will be created over and over again, even for test_bad_args where they are not needed at all.

My opinion is that this is a very good thing. Tests should work in isolation as much as possible.

You are testing one small part of the whole, to verify correctness. When you start sharing details between the tests you tie them right back into a complete system again and that's what unit testing is trying to avoid. Requiring that tests be run in a given order is just too fragile.

I appreciate the point you are making here. My concept, and I admit it is the concept of a complete Test::Unit newbie, was that the test case class was the unit of test, not the individual tests defined in the class. I guess I need to read up on the philosophy behind unit testing. Know any good references?

Also, I still don't like the idea of creating test objects over and over again, especially for tests that don't use them at all. Maybe my old (and now bad) habits formed over years of working on machines with limited resources are leading me astray, but -- at least for now -- I can't overcome my distaste for such extravagance.

When I do require that some tests work sequentially, I do it like this:

  def test_me_first
    # ...
  end

  def test_me_second
    test_me_first

    # ...
  end

I only feel safe counting on the order when I get to say what the order is, using the above.

This is good advice. I'll try to heed it.

This does extra work, as you complained about with my implementation of setup(). Ruby doesn't mind the exercise though and as long as she can do it quickly, I don't either. Besides, it shoots that test counter right on up! (Makes me feel great, "These tests are just flying by...")

Renaming test_valid_args to test_args is not only simpler, it meets the requirement of parsimony of test objects.

I'm very convinced this is the wrong way to go. You are relying on an implementation detail of Test::Unit here, that could change at anytime. That could cause your tests to start magically failing at some point down the road.

You've almost convinced me, too :wink:

I also don't believe you have the order correct. Your tests run as expected on my box with no modification to the method names. I haven't gone into the source of Test::Unit to determine why this is, but it could be that the methods are hashed in which case you can't count on any order at all.

I'm not sure what you mean by not correct. My results printout speaks for itself, doesn't it?
I agree that its being different on your box is troubling. It makes, as you point out, relying on any particular order indefensible.

One thing is for sure -- your comments are sending me back to redo my test case class. I'm not sure where I will take it (I'm still resisting you approach using setup), but I will change it so it doesn't rely on the order in which the tests are run. Oh well, I wanted to learn about Test::Unit and I'm certainly doing that :slight_smile:

Regards, Morton

···

On Aug 30, 2006, at 4:00 PM, James Edward Gray II wrote:

On Aug 30, 2006, at 2:40 PM, Morton Goldberg wrote:

I guess I need to read up on the philosophy behind unit testing. Know any good references?

You know, I've read a couple of books on the subject now and still have not found one I just fell in love with. Hopefully others will chime in with some good suggestions.

Also, I still don't like the idea of creating test objects over and over again, especially for tests that don't use them at all. Maybe my old (and now bad) habits formed over years of working on machines with limited resources are leading me astray, but -- at least for now -- I can't overcome my distaste for such extravagance.

Remember, these are unit tests, not nuclear missile guidance systems. The code is only run when you ask it to run as a tool to help you develop your code.

The goal is to make that testing process as painless as possible, not to win awards for speed and low memory consumption.

This is also very common in unit testing. Rails for example reloads database fixtures before every single test, whether the test uses them or not. That's a substantially higher commitment than your eight DayRange objects. :wink: (To be fair though, the Rails team has had to work hard to get that fixture load time down. Slow tests are bad!)

I also don't believe you have the order correct. Your tests run as expected on my box with no modification to the method names. I haven't gone into the source of Test::Unit to determine why this is, but it could be that the methods are hashed in which case you can't count on any order at all.

I'm not sure what you mean by not correct. My results printout speaks for itself, doesn't it?

Oops, I misunderstood them. My bad. The situation you described *is* the same on my box. Sorry to spread confusion.

James Edward Gray II

···

On Aug 30, 2006, at 3:48 PM, Morton Goldberg wrote:

Well, I understand that test/unit is patterned after JUnit, which in
turn came from SUnit, one idea would be to google for terms like

junit
sunit

and

test infected
which is kind of a cult term.

I guess one of my claims to fame was that I was there when Kent Beck
"test infected" Erich Gamma, which led to JUnit.

···

On 8/30/06, James Edward Gray II <james@grayproductions.net> wrote:

On Aug 30, 2006, at 3:48 PM, Morton Goldberg wrote:

> I guess I need to read up on the philosophy behind unit testing.
> Know any good references?

You know, I've read a couple of books on the subject now and still
have not found one I just fell in love with. Hopefully others will
chime in with some good suggestions.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Just to make sure I looked at the implementation. It does call sort on the test method names to establish the order for running the test. I can't imagine why it does this. If I were implementing something like Test::Unit, as an application of principle of least surprise, I would want to ensure Test::Unit preserved the order in which the programmer defined the tests. That doesn't mean I'm saying Nathaniel Talbott has erred; he may well have a good reason that simply escapes me.

Another thing I gleaned from the code was that it rejects any method with arity other than 0 or -1; i.e, any method that can't be called with __send__(test_name), where test_name matches /^test./. I don't think this is mentioned in the Pickaxe book and it certainly isn't mentioned in the ri documentation, but it explains something else that was niggling me: why Test::Unit was smart enough not to run my test_arg_helper method as a test method.

Regards, Morton

···

On Aug 30, 2006, at 5:03 PM, James Edward Gray II wrote:

I also don't believe you have the order correct. Your tests run as expected on my box with no modification to the method names. I haven't gone into the source of Test::Unit to determine why this is, but it could be that the methods are hashed in which case you can't count on any order at all.

I'm not sure what you mean by not correct. My results printout speaks for itself, doesn't it?

Oops, I misunderstood them. My bad. The situation you described *is* the same on my box. Sorry to spread confusion.

An object's methods don't have an order.

irb(main):001:0> class X; def y; end; end
=> nil
irb(main):002:0> X.instance_methods(false)
=> ["y"]
irb(main):003:0> class X; def z; end; end
=> nil
irb(main):004:0> X.instance_methods(false)
=> ["z", "y"]
irb(main):005:0> class X; def b; end; end
=> nil
irb(main):006:0> X.instance_methods(false)
=> ["z", "y", "b"]

···

On Aug 30, 2006, at 6:16 PM, Morton Goldberg wrote:

If I were implementing something like Test::Unit, as an application of principle of least surprise, I would want to ensure Test::Unit preserved the order in which the programmer defined the tests.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

Well, for one thing, I don't believe that it KNOWS the order in which
the methods are defined.

Second, the unit tests really should be order independent. It
shouldn't matter which order they run in. If you need to sequence code
it should be in the test methods.

I think of a test case as a bucket of tests, not any kind of ordered collection.

···

On 8/30/06, Morton Goldberg <m_goldberg@ameritech.net> wrote:

Just to make sure I looked at the implementation. It does call sort
on the test method names to establish the order for running the test.
I can't imagine why it does this. If I were implementing something
like Test::Unit, as an application of principle of least surprise, I
would want to ensure Test::Unit preserved the order in which the
programmer defined the tests. That doesn't mean I'm saying Nathaniel
Talbott has erred; he may well have a good reason that simply escapes
me.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

OK, I accept that methods aren't ordered at run time and, therefore, depending on their lexical order is wrong. I have rewritten my test case so it has no dependencies on the order of execution.
Nevertheless, Test::Unit does take the trouble to impose an order on the test methods. I wonder why?

Regards, Morton

···

On Aug 31, 2006, at 1:25 AM, Eric Hodel wrote:

On Aug 30, 2006, at 6:16 PM, Morton Goldberg wrote:

If I were implementing something like Test::Unit, as an application of principle of least surprise, I would want to ensure Test::Unit preserved the order in which the programmer defined the tests.

An object's methods don't have an order.

irb(main):001:0> class X; def y; end; end
=> nil
irb(main):002:0> X.instance_methods(false)
=> ["y"]
irb(main):003:0> class X; def z; end; end
=> nil
irb(main):004:0> X.instance_methods(false)
=> ["z", "y"]
irb(main):005:0> class X; def b; end; end
=> nil
irb(main):006:0> X.instance_methods(false)
=> ["z", "y", "b"]

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

Eric Hodel <drbrain@segment7.net> writes:

If I were implementing something like Test::Unit, as an application
of principle of least surprise, I would want to ensure Test::Unit
preserved the order in which the programmer defined the tests.

An object's methods don't have an order.

Although I agree with the principle that unit tests shouldn't depend
on the order they're executed in (I actually think that Test::Unit
should sort the methods randomly to enforce this), the order that
methods are defined can actually be recorded in Ruby:

irb(main):001:0> class Foo
irb(main):002:1> def Foo.method_added(r); @meth ||= ; @meth << r; end
irb(main):003:1> def Foo.get_meths; @meth; end
irb(main):004:1> end
=> nil
irb(main):005:0>
irb(main):006:0* class FooDescendant < Foo
irb(main):007:1> def h;1;end
irb(main):008:1> def e;1;end
irb(main):009:1> def ll;1;end
irb(main):010:1> def o;1;end
irb(main):011:1> end
=> nil
irb(main):012:0> FooDescendant.get_meths
=> [:h, :e, :ll, :o]

So if the author of Test::Unit wanted to perform tests in the order
that they were defined, it would be perfectly possible without
changing the existing interface. I just don't think it would be a
good idea.

···

On Aug 30, 2006, at 6:16 PM, Morton Goldberg wrote:

--
s=%q( Daniel Martin -- martin@snowplow.org
       puts "s=%q(#{s})",s.map{|i|i}[1] )
       puts "s=%q(#{s})",s.map{|i|i}[1]

Harder than you think:

class AbstractTestCase < Test::Unit::TestCase
   def test_one() end
end

class TestClassOne < AbstractTestCase
   def test_some_thing() end
end

class TestClassTwo < AbstractTestCase
   def test_some_other_thing() end
end

Handling this correctly will take more code than it is worth. Simple is better.

···

On Aug 31, 2006, at 4:20 PM, Daniel Martin wrote:

Eric Hodel <drbrain@segment7.net> writes:

On Aug 30, 2006, at 6:16 PM, Morton Goldberg wrote:

If I were implementing something like Test::Unit, as an application
of principle of least surprise, I would want to ensure Test::Unit
preserved the order in which the programmer defined the tests.

An object's methods don't have an order.

Although I agree with the principle that unit tests shouldn't depend
on the order they're executed in (I actually think that Test::Unit
should sort the methods randomly to enforce this), the order that
methods are defined can actually be recorded in Ruby:

irb(main):001:0> class Foo
irb(main):002:1> def Foo.method_added(r); @meth ||= ; @meth << r; end
irb(main):003:1> def Foo.get_meths; @meth; end
irb(main):004:1> end
=> nil
irb(main):005:0>
irb(main):006:0* class FooDescendant < Foo
irb(main):007:1> def h;1;end
irb(main):008:1> def e;1;end
irb(main):009:1> def ll;1;end
irb(main):010:1> def o;1;end
irb(main):011:1> end
=> nil
irb(main):012:0> FooDescendant.get_meths
=> [:h, :e, :ll, :o]

So if the author of Test::Unit wanted to perform tests in the order
that they were defined, it would be perfectly possible without
changing the existing interface. I just don't think it would be a
good idea.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com