Home > Development > Testing rubys initialize

Testing rubys initialize

October 6th, 2014

In /ruby you have a lot of flexibility in writing code, this includes possibility to not initialize an object.
I use this for testing my initializers, here are some examples how to do it.

Lets start with ruby class:

class TestMe
  attr_reader :value
  def initialize(value = nil)
    @value = value
  end
end

It’s a simple example where only initialize can set a value, usually you use more advanced code, but this is just a minimal example.

Now lets test it:

describe TestMe do
  subject do
    TestMe.allocate
  end

  it "has default value" do
    subject.send :initialize
    subject.value.must_equal nil
  end

  it "sets value" do
    subject.send :initialize, 3
    subject.value.must_equal 3
  end

end

For more real live examples of allocate check

  1. December 17th, 2014 at 13:44 | #1

    @Nando Vieira Exactly!
    @Michal That’s extremely bad practice to allocate then initialize, the sole reason being to make it clear you’re testing #initialize. Your client code will never look like this (hopefully) so why should your specs? Any Ruby dev knows that Class#new calls allocate and initialize, no need to decompose it in your specs. Here’s how I would do it:

    https://gist.github.com/Roman2K/c72060a19161ae077b78

    This simple. Yes, Ruby is flexible, so much so that people make contrived uses of all these tools, losing sight of simplicity and the principle of least surprise (the very one embraced by Matz originally).

  2. October 7th, 2014 at 05:58 | #2

    @Jeremy
    i do not need it, I more feel like it is the right way, getting the object before initialize and testing the initialize – because it’s what I’m testing here.

  3. Jeremy
    October 7th, 2014 at 04:38 | #3

    There are very few situations where you’d want to test in this way. Initializers have no output. Perhaps it’d be useful to detail why you need to test like this? I have done it, but not to test the initializer, instead to setup an object whose initialize method had been made private.

  4. October 7th, 2014 at 02:47 | #4

    @Nando Vieira
    I have to agree your counter examples look good, but it’s still for simple example code, and lets agree, we break encapsulation in tests all the time … I know you can avoid that, but it’s like with this old databases saying “Normalize until it hurts, denormalize until it works.”

  5. October 7th, 2014 at 01:57 | #5

    @Michal Papis
    It makes no sense calling a private method (TestMe#initialize) to test something that you can do without breaking encapsulation.

  6. October 6th, 2014 at 19:29 | #6

    @Nando Vieira
    Can you elaborate on why not? any documentation/examples why my example would be wrong/bad? For me it looks cleaner, you see the method that is tested.

  7. October 6th, 2014 at 17:34 | #7

    Please, don’t. Just assert the behavior of your initialize method. Instead of doing what you suggested, just do something like TestMe.new.value.must_equal nil and TestMe.new(3).value.must_equal 3.

Comments are closed.