The unit test that won't


#1

Aspiring to be a good programmer, I’m using Test::Unit for ClothRed,
writing the test before I write the code, even.

Which is all well and good, but I have a test, that produces an error
while it is executed and not in the error report:

test_textformatting(TestClothRedFormatting):
TypeError: can’t convert nil into String
…/test/…/lib/clothred.rb:22:in gsub!' ../test/../lib/clothred.rb:22:into_textile’
…/test/…/lib/clothred.rb:21:in collect!' ../test/../lib/clothred.rb:21:into_textile’
…/test/test_formatting.rb:43:in test_textformatting' ../test/test_formatting.rb:41:ineach’
…/test/test_formatting.rb:41:in `test_textformatting’

2 tests, 1 assertions, 0 failures, 1 errors

My tests look like this:

#Works:
def test_tags
assert_equal(“bold”, ClothRed.new(“bold”).to_textile)
end

#Doesn’t work:
def test_textformatting
FORMATTING_STRINGS.each do |html, textile|
test_html = ClothRed.new(html)
test_html.to_textile
assert_equal(textile,test_html)
end
end

The Array is as follows:

FORMATTING_STRINGS = [
[“bold”,“bold”], [“strong”,
strong”],
[“emphasized”, “emphasized”],
[“italics”, “italics”],
[“citation”, “??citation??”],
[“ClothRed#to_textile”, “@ClothRed#to_textile@”],
[“delete”, “-delete-”],
[“underline”, “+underline+”],
[“superscript”,"^superscript^"],
[“subscript”,"~subscript~"]
]

An improvised test run produces this:

c:\test.rb
bold
emphasized
italics

c:\cat test.rb

test.rb

11. April 2007

require ‘clothred’

TEST = ‘bold
emphasized
italics

test = ClothRed.new(TEST)

puts test.to_textile

My Ruby version:
c:\ruby -v
ruby 1.8.5 (2006-12-25 patchlevel 12) [i386-mswin32]

The output of the test suggests, that I’m doing something wrong in my
test, that my test is buggy, and not my code.

Can somebody enlighten me?


Phillip “CynicalRyan” Gawlowski
http://cynicalryan.110mb.com/

Rule of Open-Source Programming #6:

The user is always right unless proven otherwise by the developer.


#2

On Wed, Apr 11, 2007 at 02:24:37PM +0900, Phillip G. wrote:

def test_textformatting
FORMATTING_STRINGS.each do |html, textile|
test_html = ClothRed.new(html)
test_html.to_textile
assert_equal(textile,test_html)

Hmm, it looks like test_html is not a string here, but some other sort
of
object, so did you mean

    assert_equal(textfile, test_html.to_s) ?

or else

    result = test_html.to_textile
    assert_equal(textile, result)  ?

It depends whether your ‘to_textile’ method really changes the internal
state of your ClothRed object, or whether its return value is the thing
you’re interested in checking.

B.


#3

On 4/11/07, Phillip G. removed_email_address@domain.invalid wrote:

#Doesn’t work:
def test_textformatting
FORMATTING_STRINGS.each do |html, textile|
test_html = ClothRed.new(html)
test_html.to_textile
assert_equal(textile,test_html)
end
end

As Brian says, I’m not really sure what test_html.to_textile leaves
test_html as but why not go back to what works for you. It seems
simpler to
me also.

def test_textformatting
   FORMATTING_STRINGS.each do |html, textile|
     assert_equal(textile, ClothRed.new(html).to_textile )
   end
end

also a failing message wouldn’t go astray. Something like

def test_textformatting
   FORMATTING_STRINGS.each do |html, textile|
     transformed = ClothRed.new(html).to_textile
     assert_equal(textile, transformed ), "\"#{html}\" should have

transformed to “#{textile}\¨ but was “#{transformed}””
end
end

just my 0.02


#4

Daniel N wrote:

As Brian says, I’m not really sure what test_html.to_textile leaves
also a failing message wouldn’t go astray. Something like

Thanks for the input guys, looks like the error was in my code after
all.
Here’s the why:

ClothRed#to_textile used Array#collect! to iterate over the string that
was to be transformed, which let the first test complete successfully as
it was only testing for one condition. As soon as I change #collect!
to #each, the code behaved as the test expected. Although why this
happens, I’m not sure (I guess the receiver of the block is the “count”
for the block, and not the elements in the Array).

Which leads to the discovery of another bug now, which is in my regex.


Phillip “CynicalRyan” Gawlowski
http://cynicalryan.110mb.com/

Eek! That was supposed to be My Special Law, MY special law, I tell
you!

T/


#5

On Wed, Apr 11, 2007 at 03:23:52PM +0900, Phillip G. wrote:

ClothRed#to_textile used Array#collect! to iterate over the string that
was to be transformed, which let the first test complete successfully as
it was only testing for one condition. As soon as I change #collect!
to #each, the code behaved as the test expected. Although why this
happens, I’m not sure (I guess the receiver of the block is the “count”
for the block, and not the elements in the Array).

I don’t understand what you’ve written above - you might want to paste
an
example. For both Array#each and Array#collect!, the values passed to
the
block are the elements of the array. The difference is in what happens
to
the value returned by the block; #each ignores it, #collect! replaces
the
original array element with it.

As a separate point though: if to_textile changes the state of your
ClothRed
object, you might want to consider calling it something else.

Normally, a to_foo method returns an object of type foo, and does not
change
the state of the receiver. Compare Object#to_yaml, Method#to_proc,
Object#to_enum and so on.

Personally I would be surprised to find a Ruby library with a
“to_textile”
method, where the main purpose of the function was to change the state
of
the receiver, and not to return a textile object.

Regards,

Brian.


#6

Brian C. wrote:

I don’t understand what you’ve written above - you might want to paste an
example. For both Array#each and Array#collect!, the values passed to the
block are the elements of the array. The difference is in what happens to
the value returned by the block; #each ignores it, #collect! replaces the
original array element with it.

Ah, that cleared up my confusion. I wanted #each in the first place,
but made mistakes in writing my code.

Well, the learning never stops.

As a separate point though: if to_textile changes the state of your ClothRed
object, you might want to consider calling it something else.

I have changed that behavior. #to_textile is non-destructive (at least
it should be, I have to add a test for that).

Personally I would be surprised to find a Ruby library with a “to_textile”
method, where the main purpose of the function was to change the state of
the receiver, and not to return a textile object.

Yes, I’d expect that from #to-textile!, too, which was my intention in
the first place.


Phillip “CynicalRyan” Gawlowski
http://cynicalryan.110mb.com/

Rule of Open-Source Programming #48:

The number of items on a project’s to-do list always grows or remains
constant.