Search code examples
ruby-on-railsrubyunit-testingassertiontestunit

Does assert_not_nil foo == assert defined? foo in Ruby's Test::Unit?


I'm new to Ruby/Rails testing. It seems the Test::Unit method assert_not_nil foo is true just in case foo is defined (i.e., it is not nil). Right?

So is assert_not_nil foo equivalent to assert defined? foo?

If not, how do they differ? If so, is there any reason why I would want to prefer one of these over the other?

Maybe more generally, it seems like assert can be combined with other expressions in place of more specialized assertion methods like assert_equal and assert_not etc. But it seems that the specialized methods are more standard practice. Is that right? Why is that?


Solution

  • nil is a value, so a variable who's value is nil is defined. Here's some repl output to demonstrate:

    [1] pry(main)> a = nil
    => nil
    [2] pry(main)> defined? a
    => "local-variable"
    [3] pry(main)> defined? b
    => nil
    

    You may be confused because accessing an undefined instance variable also returns nil, but that's still not the same:

    [4] pry(main)> defined? @b
    => nil
    [5] pry(main)> @b = nil
    => nil
    [6] pry(main)> defined? @b
    => "instance-variable"
    

    Global variables ($foo) work like instance variables in this respect, but accessing an uninitialized class variable (@@bar) raises NameError.

    One last thing: local variables are declared at parse time in Ruby, so if any branch of your method sets a local, that local is defined (and initialized to nil) anywhere in the method (or block).