small medium large xlarge

Back to: All Forums  PragPub
Gravatar_pragsmall
05 Aug 2010, 17:33
James Mead (3 posts)

Errata :-

In the first Ruby example, if Items.abc returns [(“a”, 0.7), (“b”, 0.2), (“c”, 0.1)], then items.collect(&:weight) will not return [0.7, 0.2, 0.1] as the author seems to expect. I suspect that he modified some of the code at some point, but forgot to update all of it.

Notes :-

Ruby has Enumerable#map [1] as well as Enumberable#collect.

Ruby’s Expectation gem [2] seems to do something very similar to Scala’s “expect” method.

While the general concept of custom assertions is sensible, this example doesn’t seem very sensible to me. At the very least, I think the assert_items method name should make mention of weight order e.g. assert_items_in_weight_order. I would also probably only have a few tests that compare arrays of items that would care about the weight ordering - I wouldn’t want all tests that compare arrays of items to be so strict otherwise you end up with very brittle tests.

[1] http://ruby-doc.org/core/classes/Enumerable.html#M003128 [2] http://expectations.rubyforge.org/

Icon_pragsmall
09 Aug 2010, 17:44
Paul Butcher (38 posts)

James - please forgive the delayed reply, I only just noticed your message.

Regarding your first point about @items.collect@, please see the following irb session. What am I missing?:

pauls-macbook-pro:TouchType-Build paul$ irb
>> Item = Struct.new(:name, :weight)
=> Item
>> items = [Item.new("a", 0.7), Item.new("b", 0.2), Item.new("c", 0.1)]
=> [#<struct Item name="a", weight=0.7>, #<struct Item name="b", weight=0.2>, #<struct Item name="c", weight=0.1>]
>> items.collect(&:weight)
=> [0.7, 0.2, 0.1]

Note that the full code can be downloaded from http://www.paulbutcher.com/2010/07/great-expectations/

Regarding the naming and the brittle nature of tests, my guess is that this depends upon context. In the particular codebase that I was working on that inspired this example, a weighted list was the key abstraction. We had many (many) tests that work on weighted lists, and any weighted list that wasn’t ordered correctly would definitely be an error, so a failure wouldn’t be a brittle test, it would be a failed test. The frequency with which it was called also lead me to choose the succinct name (although I accept that I should have made this reasoning clearer in the article). Clearly on a different codebase, a different set of tradeoffs might make sense.

But in a way, that’s the point that I was trying to illustrate - by collecting the particular peculiarities of your codebase into custom expectations, you can make your tests much more concise and expressive.

Gravatar_pragsmall
12 Aug 2010, 13:40
James Mead (3 posts)

There doesn’t appear to be anything wrong with your irb session, but what you have in there doesn’t match what you had in the article i.e. it wasn’t obvious to me that :-

  [(“a”, 0.7), (“b”, 0.2), (“c”, 0.1)]

Actually meant :-

  [Item.new("a", 0.7), Item.new("b", 0.2), Item.new("c", 0.1)]

It’s helpful that you’ve now published the full code - it’s difficult to abbreviate code without making it confusing.

Regarding my comment about “brittle tests” - I think I may have been a bit hasty and may not have explained my concerns very well. I think what I was getting at was that if there is one place in the code which is concerned with ordering, I would only expect a small number of tests to be checking that the ordering is done correctly, otherwise when you make a change to that single bit of code, lots of tests are going to break. However, if you have lots of places in the code which do different types of ordering then a custom assertion like this makes a lot more sense.

You must be logged in to comment