views:

1346

answers:

5

I'm expanding my Ruby understanding by coding an equivalent of Kent Beck's xUnit in Ruby. Python (which Kent writes in) has an assert() method in the language which is used extensively. Ruby does not. I think it should be easy to add this but is Kernel the right place to put it?

BTW, I know of the existence of the various Unit frameworks in Ruby - this is an exercise to learn the Ruby idioms, rather than to "get something done".

All help gratefully received.

TIA

+5  A: 

What's your reason for adding the assert method to the Kernel module? Why not just use another module called Assertions or something?

Like this:

module Assertions
  def assert(param)
    # do something with param
  end

  # define more assertions here
end

If you really need your assertions to be available everywhere do something like this:

class Object
  include Assertions
end

Disclaimer: I didn't test the code but in principle I would do it like this.

Christoph Schiessl
+4  A: 

My understanding is that you're writing your own testing suite as a way of becoming more familiar with Ruby. So while Test::Unit might be useful as a guide, it's probably not what you're looking for (because it's already done the job).

That said, python's assert is (to me, at least), more analogous to C's assert(3). It's not specifically designed for unit-tests, rather to catch cases where "this should never happen".

How Ruby's built-in unit tests tend to view the problem, then, is that each individual test case class is a subclass of TestCase, and that includes an "assert" statement which checks the validity of what was passed to it and records it for reporting.

Atiaxi
A: 

I absolutely agree it would be useful [and as a default method].

rogerdpack
+5  A: 

No it's not a best practice. The best analogy to assert() in Python is just raising

 raise "This is wrong" unless expr

and you can implement your own exceptions of you want to provide for more specific exception handling

Julik
You can also use `fail if [expr]`, if you like, which throws a Runtime Error.
Xiong Chiamiov
`fail` is an alias for `raise`, isn't it? They both give `RuntimeError`. (Maybe one is more idiomatic?)
Benjamin Oakes
See "fail" here: http://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html
Benjamin Oakes
A: 

It's not especially idiomatic, but I think it's a good idea. Especially if done like this:

def assert(msg=nil)
    if DEBUG
        raise msg || "Assertion failed!" unless yield
    end
end

That way there's no impact if you decide not to run with DEBUG (or some other convenient switch, I've used Kernel.do_assert in the past) set.

regularfry