Forum: Ruby The unit test that won't.

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Phillip G. (Guest)
on 2007-04-11 09:24
(Received via mailing list)
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:in `to_textile'
     ../test/../lib/clothred.rb:21:in `collect!'
     ../test/../lib/clothred.rb:21:in `to_textile'
     ../test/test_formatting.rb:43:in `test_textformatting'
     ../test/test_formatting.rb:41:in `each'
     ../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("<b>bold</b>").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 = [
     ["<b>bold</b>","**bold**"], ["<strong>strong</strong>",
"*strong*"],
     ["<em>emphasized</em>", "_emphasized_"],
     ["<i>italics</i>", "__italics__"],
     ["<cite>citation</cite>", "??citation??"],
     ["<code>ClothRed#to_textile</code>", "@ClothRed#to_textile@"],
     ["<del>delete</del>", "-delete-"],
     ["<ins>underline</ins>", "+underline+"],
     ["<sup>superscript</sup>","^superscript^"],
     ["<sub>subscript</sub>","~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 = '<b>bold</b>
<em>emphasized</em>
<i>italics</i>'

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.
Brian C. (Guest)
on 2007-04-11 09:50
(Received via mailing list)
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.
Daniel -. (Guest)
on 2007-04-11 10:04
(Received via mailing list)
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
Phillip G. (Guest)
on 2007-04-11 10:24
(Received via mailing list)
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/
Brian C. (Guest)
on 2007-04-11 11:35
(Received via mailing list)
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.
Phillip G. (Guest)
on 2007-04-11 12:23
(Received via mailing list)
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.
This topic is locked and can not be replied to.