custom assertion message for unit tests

Discussion in 'Ruby' started by Will Parsons, Feb 4, 2009.

  1. Will Parsons

    Will Parsons Guest

    I'm having trouble trying to figure out how to customize an assertion
    message when running unit tests. In particular, I want to check the
    permissions on a file, so I have something like:

    assert_equal(0755, File.stat(test_file).mode & 0777)

    If it fails, I get a message like:

    <493> expected but was
    <420>.

    and of course I would like the expected and actual permissions to be
    displayed in octal rather than decimal. How can I do that?

    --
    Will
    Will Parsons, Feb 4, 2009
    #1
    1. Advertising

  2. On Feb 4, 2009, at 5:59 PM, Will Parsons wrote:

    > I'm having trouble trying to figure out how to customize an assertion
    > message when running unit tests. In particular, I want to check the
    > permissions on a file, so I have something like:
    >
    > assert_equal(0755, File.stat(test_file).mode & 0777)
    >
    > If it fails, I get a message like:
    >
    > <493> expected but was
    > <420>.
    >
    > and of course I would like the expected and actual permissions to be
    > displayed in octal rather than decimal. How can I do that?
    >
    > --
    > Will



    Perhaps something like:

    $ ruby -r'test/unit'
    class SomeTest < Test::Unit::TestCase
    def setup
    @test_file = 'some_file'
    File.open(@test_file, 'w') {|f| f.write "Hello!"}
    end
    def test_bad_file_mode
    File.chmod(0644, @test_file)

    assert_equal '0755', '%#o'%[File.stat(@test_file).mode & 0777],
    "Mode of #{@test_file}"
    end

    def test_good_file_mode
    File.chmod(0755, @test_file)

    assert_equal '0755', '%#o'%[File.stat(@test_file).mode & 0777],
    "Mode of #{@test_file}"
    end
    end
    __END__
    Loaded suite -
    Started
    F.
    Finished in 0.025823 seconds.

    1) Failure:
    test_bad_file_mode(SomeTest) [-:9]:
    Mode of some_file.
    <"0755"> expected but was
    <"0644">.

    2 tests, 2 assertions, 1 failures, 0 errors


    Note that I'm doing the conversion to octal myself with the '%#o' and
    String#%

    It would be better to pull this into a helper method:

    $ ruby -r'test/unit'
    class SomeTest < Test::Unit::TestCase
    def assert_mode(expected_mode, actual_mode, message=nil)
    assert_equal '%#o'%expected_mode, '%#o'%actual_mode, message
    end

    def setup
    @test_file = 'some_file'
    File.open(@test_file, 'w') {|f| f.write "Hello!"}
    end
    def test_bad_file_mode
    File.chmod(0644, @test_file)

    assert_mode 0755, File.stat(@test_file).mode & 0777, "Mode of
    #{@test_file}"
    end

    def test_good_file_mode
    File.chmod(0755, @test_file)

    assert_mode 0755, File.stat(@test_file).mode & 0777, "Mode of
    #{@test_file}"
    end
    end
    __END__
    Loaded suite -
    Started
    F.
    Finished in 0.0107 seconds.

    1) Failure:
    test_bad_file_mode(SomeTest)
    [-:3:in `assert_mode'
    -:13:in `test_bad_file_mode']:
    Mode of some_file.
    <"0755"> expected but was
    <"0644">.

    2 tests, 2 assertions, 1 failures, 0 errors


    Do you really want
    assert File.stat(@test_file).executable?
    instead of a specific mode?

    -Rob

    Rob Biedenharn http://agileconsultingllc.com
    Rob Biedenharn, Feb 5, 2009
    #2
    1. Advertising

  3. Will Parsons

    Will Parsons Guest

    Rob Biedenharn wrote:
    > On Feb 4, 2009, at 5:59 PM, Will Parsons wrote:
    >
    >> I'm having trouble trying to figure out how to customize an assertion
    >> message when running unit tests. In particular, I want to check the
    >> permissions on a file, so I have something like:
    >>
    >> assert_equal(0755, File.stat(test_file).mode & 0777)
    >>
    >> If it fails, I get a message like:
    >>
    >> <493> expected but was
    >> <420>.
    >>
    >> and of course I would like the expected and actual permissions to be
    >> displayed in octal rather than decimal. How can I do that?

    >
    > Perhaps something like:
    >
    > $ ruby -r'test/unit'
    > class SomeTest < Test::Unit::TestCase
    > def setup
    > @test_file = 'some_file'
    > File.open(@test_file, 'w') {|f| f.write "Hello!"}
    > end
    > def test_bad_file_mode
    > File.chmod(0644, @test_file)
    >
    > assert_equal '0755', '%#o'%[File.stat(@test_file).mode & 0777],
    > "Mode of #{@test_file}"
    > end
    >
    > def test_good_file_mode
    > File.chmod(0755, @test_file)
    >
    > assert_equal '0755', '%#o'%[File.stat(@test_file).mode & 0777],
    > "Mode of #{@test_file}"
    > end
    > end
    > __END__
    > Loaded suite -
    > Started
    > F.
    > Finished in 0.025823 seconds.
    >
    > 1) Failure:
    > test_bad_file_mode(SomeTest) [-:9]:
    > Mode of some_file.
    ><"0755"> expected but was
    ><"0644">.
    >
    > 2 tests, 2 assertions, 1 failures, 0 errors


    This is certainly an improvement on my version, but it is not completely
    satisfying - the reason being that by explicitly converting the permissions
    to a string they get displayed as strings, i.e., I would like to see:

    <755> expected

    rather than:

    <"0755"> expected

    > Note that I'm doing the conversion to octal myself with the '%#o' and
    > String#%
    >
    > It would be better to pull this into a helper method:
    >
    > $ ruby -r'test/unit'
    > class SomeTest < Test::Unit::TestCase
    > def assert_mode(expected_mode, actual_mode, message=nil)
    > assert_equal '%#o'%expected_mode, '%#o'%actual_mode, message
    > end
    >
    > def setup
    > @test_file = 'some_file'
    > File.open(@test_file, 'w') {|f| f.write "Hello!"}
    > end
    > def test_bad_file_mode
    > File.chmod(0644, @test_file)
    >
    > assert_mode 0755, File.stat(@test_file).mode & 0777, "Mode of
    > #{@test_file}"
    > end
    >
    > def test_good_file_mode
    > File.chmod(0755, @test_file)
    >
    > assert_mode 0755, File.stat(@test_file).mode & 0777, "Mode of
    > #{@test_file}"
    > end
    > end
    > __END__
    > Loaded suite -
    > Started
    > F.
    > Finished in 0.0107 seconds.
    >
    > 1) Failure:
    > test_bad_file_mode(SomeTest)
    > [-:3:in `assert_mode'
    > -:13:in `test_bad_file_mode']:
    > Mode of some_file.
    ><"0755"> expected but was
    ><"0644">.
    >
    > 2 tests, 2 assertions, 1 failures, 0 errors


    I'm not sure I understand this - what's the advantage of defining the
    assert_mode method over using the already defined methods?

    > Do you really want
    > assert File.stat(@test_file).executable?
    > instead of a specific mode?


    Yes, because I want also to check for being read-only in addition to being
    executable in the file permissions.

    --
    Will
    Will Parsons, Feb 5, 2009
    #3
  4. Will Parsons

    Phlip Guest

    Will Parsons wrote:

    > I'm having trouble trying to figure out how to customize an assertion
    > message when running unit tests. In particular, I want to check the
    > permissions on a file, so I have something like:
    >
    > assert_equal(0755, File.stat(test_file).mode & 0777)
    >
    > If it fails, I get a message like:
    >
    > <493> expected but was
    > <420>.
    >
    > and of course I would like the expected and actual permissions to be
    > displayed in octal rather than decimal. How can I do that?


    (Unless if you use Ruby 1.8.7), install gem assert2, then write:

    assert{ '755' == (File.stat(test_file).mode & 0777).to_s(8) }

    When that fails, it prints out every expression, with its intermediate value,
    including those bitfields' decimal representations, and

    1) Failure:
    test_assert_classic_message(Assert21Suite)
    [/cygdrive/c/Users/Phlip/.UNA/2/1/1/assert2/lib/assert2.rb:214:in `assert_'
    /cygdrive/c/Users/Phlip/.UNA/2/1/1/assert2/lib/assert2.rb:76:in `assert'
    test/assert2_suite.rb:403:in `test_assert_classic_message']:

    assert{ "755" == ( File.stat(test_file).mode() & 511 ).to_s(8) }
    --> false - should pass
    test_file --> "test/assert2_suite.rb"
    File.stat(test_file) --> #<File::Stat***
    File.stat(test_file).mode() --> 33216
    ( File.stat(test_file).mode() & 511 ) --> 448
    ( File.stat(test_file).mode() & 511 ).to_s(8) --> "700".

    29 tests, 115 assertions, 1 failures, 0 errors

    All assertions should reflect everything they possibly can at failure time,
    without too much excess verbiage when you write them. They should be easy to
    write and comprehensive when they fail. Assert{ 2.0 } maximizes your bang-buck
    ratio there!

    --
    Phlip
    Phlip, Feb 5, 2009
    #4
  5. On Feb 4, 2009, at 8:39 PM, Will Parsons wrote:
    > Rob Biedenharn wrote:
    >> On Feb 4, 2009, at 5:59 PM, Will Parsons wrote:
    >>
    >>> I'm having trouble trying to figure out how to customize an
    >>> assertion
    >>> message when running unit tests. In particular, I want to check the
    >>> permissions on a file, so I have something like:
    >>>
    >>> assert_equal(0755, File.stat(test_file).mode & 0777)
    >>>
    >>> If it fails, I get a message like:
    >>>
    >>> <493> expected but was
    >>> <420>.
    >>>
    >>> and of course I would like the expected and actual permissions to be
    >>> displayed in octal rather than decimal. How can I do that?

    >>
    >> Perhaps something like:

    ...
    >>
    >> 1) Failure:
    >> test_bad_file_mode(SomeTest) [-:9]:
    >> Mode of some_file.
    >> <"0755"> expected but was
    >> <"0644">.
    >>
    >> 2 tests, 2 assertions, 1 failures, 0 errors

    >
    > This is certainly an improvement on my version, but it is not
    > completely
    > satisfying - the reason being that by explicitly converting the
    > permissions
    > to a string they get displayed as strings, i.e., I would like to see:
    >
    > <755> expected
    >
    > rather than:
    >
    > <"0755"> expected
    >
    >> Note that I'm doing the conversion to octal myself with the '%#o' and
    >> String#%
    >>
    >> It would be better to pull this into a helper method:
    >>
    >> $ ruby -r'test/unit'
    >> class SomeTest < Test::Unit::TestCase
    >> def assert_mode(expected_mode, actual_mode, message=nil)
    >> assert_equal '%#o'%expected_mode, '%#o'%actual_mode, message
    >> end
    >>
    >> def setup
    >> @test_file = 'some_file'
    >> File.open(@test_file, 'w') {|f| f.write "Hello!"}
    >> end
    >> def test_bad_file_mode
    >> File.chmod(0644, @test_file)
    >>
    >> assert_mode 0755, File.stat(@test_file).mode & 0777, "Mode of
    >> #{@test_file}"
    >> end
    >>
    >> def test_good_file_mode
    >> File.chmod(0755, @test_file)
    >>
    >> assert_mode 0755, File.stat(@test_file).mode & 0777, "Mode of
    >> #{@test_file}"
    >> end
    >> end
    >> __END__
    >> Loaded suite -
    >> Started
    >> F.
    >> Finished in 0.0107 seconds.
    >>
    >> 1) Failure:
    >> test_bad_file_mode(SomeTest)
    >> [-:3:in `assert_mode'
    >> -:13:in `test_bad_file_mode']:
    >> Mode of some_file.
    >> <"0755"> expected but was
    >> <"0644">.
    >>
    >> 2 tests, 2 assertions, 1 failures, 0 errors

    >
    > I'm not sure I understand this - what's the advantage of defining the
    > assert_mode method over using the already defined methods?


    Look at the resulting test and it's failure message:
    assert_mode 0755, File.stat(@test_file).mode & 0777

    <"0755"> expected but was
    <"0644">.

    Compared to what you had to start:
    assert_equal(0755, File.stat(test_file).mode & 0777)

    <493> expected but was
    <420>.

    Pretty close, no?

    >> Do you really want
    >> assert File.stat(@test_file).executable?
    >> instead of a specific mode?

    >
    > Yes, because I want also to check for being read-only in addition to
    > being
    > executable in the file permissions.
    >
    > --
    > Will


    But you could go all the way with:

    $ cat ml_mode_test.rb
    require 'test/unit'

    module Test
    module Unit
    module Assertions
    ##
    # Asserts that the octal modes are equal.
    # If given a +:mask+ option, will only compare those bits.
    #
    # Example:
    # assert_mode 0444, File.stat(name).mode, "Always
    readable", :mask => 0777
    #
    def assert_mode(expected_mode, actual_mode,
    options_or_message=nil, options=nil)
    if options.nil? && Hash === options_or_message
    message, options = nil, options_or_message
    elsif
    message = options_or_message
    end
    full_message = message ? message.chomp+"\n" : ''
    full_message << "<%#o> expected but was\n<%#o>"%
    [expected_mode, actual_mode]
    if Hash === options && options.has_key?:)mask)
    mask = options[:mask]
    expected_mode &= mask
    actual_mode &= mask
    full_message << " (applying %#o mask)"%mask
    end
    assert_block(full_message) { expected_mode == actual_mode }
    end
    end
    end
    end

    class SomeTest < Test::Unit::TestCase

    def setup
    @test_file = 'some_file'
    File.open(@test_file, 'w') {|f| f.write "Hello!"}
    File.chmod(0644, @test_file)
    end

    def test_with_equal
    assert_equal 0755, File.stat(@test_file).mode & 0777
    end

    def test_with_equal_and_message
    assert_equal 0755, File.stat(@test_file).mode & 0777, "equal?"
    end

    def test_with_mode
    assert_mode 0755, File.stat(@test_file).mode & 0777
    end

    def test_with_mode_and_mask
    assert_mode 0755, File.stat(@test_file).mode, :mask => 0777
    end

    def test_with_mode_and_message
    assert_mode 0755, File.stat(@test_file).mode & 0777, "executable?"
    end

    def test_with_mode_big_finish
    assert_mode 0755, File.stat(@test_file).mode,
    "executable?", :mask => 0777
    end

    end
    __END__
    rab:code/ruby $ ruby ml_mode_test.rb
    Loaded suite ml_mode_test
    Started
    FFFFFF
    Finished in 0.074508 seconds.

    1) Failure:
    test_with_equal(SomeTest) [ml_mode_test.rb:42]:
    <493> expected but was
    <420>.

    2) Failure:
    test_with_equal_and_message(SomeTest) [ml_mode_test.rb:46]:
    equal?.
    <493> expected but was
    <420>.

    3) Failure:
    test_with_mode(SomeTest)
    [ml_mode_test.rb:27:in `assert_mode'
    ml_mode_test.rb:50:in `test_with_mode']:
    <0755> expected but was
    <0644>

    4) Failure:
    test_with_mode_and_mask(SomeTest)
    [ml_mode_test.rb:27:in `assert_mode'
    ml_mode_test.rb:54:in `test_with_mode_and_mask']:
    <0755> expected but was
    <0100644> (applying 0777 mask)

    5) Failure:
    test_with_mode_and_message(SomeTest)
    [ml_mode_test.rb:27:in `assert_mode'
    ml_mode_test.rb:58:in `test_with_mode_and_message']:
    executable?
    <0755> expected but was
    <0644>

    6) Failure:
    test_with_mode_big_finish(SomeTest)
    [ml_mode_test.rb:27:in `assert_mode'
    ml_mode_test.rb:62:in `test_with_mode_big_finish']:
    executable?
    <0755> expected but was
    <0100644> (applying 0777 mask)

    6 tests, 6 assertions, 6 failures, 0 errors

    It just depends on how far you want to take it.

    -Rob

    Rob Biedenharn http://agileconsultingllc.com
    Rob Biedenharn, Feb 5, 2009
    #5
  6. Will Parsons

    Phlip Guest

    Will Parsons wrote:

    > Yes, because I want also to check for being read-only in addition to being
    > executable in the file permissions.


    If I felt the request to take the "" off of "0775" sounded a little petty, this
    would probably be on account of I'm disturbed by so much effort to achieve 0775
    when "File(...).readonly? == true" is a little bit more readable!

    How about assert{ `ls -l #{filename.inspect}` =~ /-rwxr-wr-w/ } ?
    Phlip, Feb 5, 2009
    #6
  7. Maybe it is not necessary to customize the assertion so much.

    On 04.02.2009, at 23:59, Will Parsons wrote:

    > I would like the expected and actual permissions to be
    > displayed in octal rather than decimal. How can I do that?



    irb(main):005:0> "420".to_i
    =3D> 420
    irb(main):006:0> "420".to_i.to_s(8)
    =3D> "644"
    irb(main):007:0> "420".to_i.to_s(8).to_i
    =3D> 644

    regards, Sandor Sz=FCcs
    --
    Sandor Szücs, Feb 5, 2009
    #7
  8. Will Parsons

    Ken Bloom Guest

    On Wed, 04 Feb 2009 22:55:46 +0000, Will Parsons wrote:

    > I'm having trouble trying to figure out how to customize an assertion
    > message when running unit tests. In particular, I want to check the
    > permissions on a file, so I have something like:
    >
    > assert_equal(0755, File.stat(test_file).mode & 0777)
    >
    > If it fails, I get a message like:
    >
    > <493> expected but was
    > <420>.
    >
    > and of course I would like the expected and actual permissions to be
    > displayed in octal rather than decimal. How can I do that?


    All of the standard test/unit assertions let you pass a message to be
    printed to explain the error, which will print in addition to the
    automatic message. So store the mode in a local variable so you can use
    it in both places.

    acutalmode=File.stat(test_file).mode & 0777
    assert_equal 0755, actualmode, "#{test_file} should have mode 755, but
    has mode %o instead." % [actualmode]

    Or to supress the automatic message altogether and only print your custom
    message:

    acutalmode=File.stat(test_file).mode & 0777
    assert_block ("#{test_file} should have mode 755,
    but has mode %o instead." % [actualmode]) {0755 == actualmode}

    --Ken

    --
    Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.
    Department of Computer Science. Illinois Institute of Technology.
    http://www.iit.edu/~kbloom1/
    Ken Bloom, Feb 5, 2009
    #8
  9. Will Parsons

    Will Parsons Guest

    Sandor Szücs wrote:
    > Maybe it is not necessary to customize the assertion so much.
    >
    > On 04.02.2009, at 23:59, Will Parsons wrote:
    >
    >> I would like the expected and actual permissions to be
    >> displayed in octal rather than decimal. How can I do that?

    >
    > irb(main):005:0> "420".to_i
    >=> 420
    > irb(main):006:0> "420".to_i.to_s(8)
    >=> "644"
    > irb(main):007:0> "420".to_i.to_s(8).to_i
    >=> 644


    Tricky, but it works!

    --
    Will
    Will Parsons, Feb 5, 2009
    #9
  10. Will Parsons

    Will Parsons Guest

    Ken Bloom wrote:
    > On Wed, 04 Feb 2009 22:55:46 +0000, Will Parsons wrote:
    >
    >> I'm having trouble trying to figure out how to customize an assertion
    >> message when running unit tests. In particular, I want to check the
    >> permissions on a file, so I have something like:
    >>
    >> assert_equal(0755, File.stat(test_file).mode & 0777)
    >>
    >> If it fails, I get a message like:
    >>
    >> <493> expected but was
    >> <420>.
    >>
    >> and of course I would like the expected and actual permissions to be
    >> displayed in octal rather than decimal. How can I do that?

    >
    > All of the standard test/unit assertions let you pass a message to be
    > printed to explain the error, which will print in addition to the
    > automatic message. So store the mode in a local variable so you can use
    > it in both places.
    >
    > acutalmode=File.stat(test_file).mode & 0777
    > assert_equal 0755, actualmode, "#{test_file} should have mode 755, but
    > has mode %o instead." % [actualmode]
    >
    > Or to supress the automatic message altogether and only print your custom
    > message:
    >
    > acutalmode=File.stat(test_file).mode & 0777
    > assert_block ("#{test_file} should have mode 755,
    > but has mode %o instead." % [actualmode]) {0755 == actualmode}


    Thanks! This is just what I was looking for.

    --
    Will
    Will Parsons, Feb 5, 2009
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. PeterKellner

    Looking for unit tests for Custom Provider

    PeterKellner, May 25, 2006, in forum: ASP .Net Security
    Replies:
    0
    Views:
    117
    PeterKellner
    May 25, 2006
  2. Replies:
    2
    Views:
    170
    Bret Pettichord
    Oct 7, 2005
  3. aidy
    Replies:
    2
    Views:
    146
    Tim Pease
    Apr 16, 2007
  4. Curt Sampson
    Replies:
    3
    Views:
    116
    Phlip
    Aug 11, 2007
  5. Replies:
    1
    Views:
    106
Loading...

Share This Page