Specs on private methods

It’s interesting that this thread has started because I just ran into
this problem.

The error I got was:

NoMethodError in ‘Signup she be a valid mac address’
protected method `normalize_mac’ called for #Signup:0x408c0434
./spec/models/signup_spec.rb:10:

Here’s the spec:

describe Signup do
before(:each) do
@signup = Signup.new
end

it “she be a valid mac address” do
@signup.mac_address = “00-11-22-33-44-55-66”
normalized = @signup.normalize_mac(@signup.mac_address)
@signup.mac_address.should == normalized
end
end

I have a model that has mac_address attribute. In the before
validation, I wanted to make the mac address have colons(:slight_smile: instead of
whatever the user typed in which could have spaces between, dashes,
nothing at all.

My thought was to just remove all of those special characters validate
it against a regex then if it passed the regex check produce the mac
address with the colons included.

And, if I understand it properly, Pat’s statement is saying that I
really shouldn’t be protecting that method…which would fix my problem.

So my question is then, how do you know when to use protected and
private or do I just do what Rick suggested and use send?

I just realized this isn’t really an rspec question…so I’ll just move
along.

Mike B.

Apart from private or public methods I see a problem in your test case.
You don’t make sure that your mac_address is returned in exactly the way
you want - you are merely saying it should look like the return value of
some (protected) method you call (normalize_mac).

Let’s assume this method was implemented wrong and just returns nil.
Let’s further assume that @signup.mac_address calls a reader method
returning nil, too. Such an implementation, though wrong, would satisfy
your spec!

A second problem is, that the parameter you are passing to the
normalize-method will already have been transformed before your method
gets its hands on it. You are not passing the init value but the value
that is returned be a read operation on the mac_address field.

What you really should specify is your concrete mac address format:

it "should return a valid mac address" do
   @signup.mac_address = "00-11-22-33-44-55"
   @signup.mac_address.should == "00:11:22:33:44:55"
end

Now you are not only implementation independent but your spec is also
saying more.

François

barsalou schrieb:

On 10.1.2008, at 22.21, Francois W. wrote:

returning nil, too. Such an implementation, though wrong, would
it “should return a valid mac address” do
@signup.mac_address = “00-11-22-33-44-55”
@signup.mac_address.should == “00:11:22:33:44:55”
end

Now you are not only implementation independent but your spec is also
saying more.

Also, this line of code is a bit smelly:

normalized = @signup.normalize_mac(@signup.mac_address)

Since normalize_mac is an instance method in the Signup class, there’s
no point passing the mac_address as a parameter; the method can simply
call the mac_address method directly. If you want to make it more
general-purpose, it doesn’t sound like it should be an instance method
anymore.

//jarkko


Jarkko L.

http://www.railsecommerce.com
http://odesign.fi

On Jan 10, 2008 12:25 PM, Jarkko L. [email protected] wrote:

Also, this line of code is a bit smelly:

normalized = @signup.normalize_mac(@signup.mac_address)

Since normalize_mac is an instance method in the Signup class, there’s
no point passing the mac_address as a parameter; the method can simply
call the mac_address method directly. If you want to make it more
general-purpose, it doesn’t sound like it should be an instance method
anymore.

Right, you could pull this into a MacAddress class, and use that:

describe MacAddress, " for 00-11-22-33-44-55" do
it “should normalize to 00:11:22:33:44:55” do
MacAddress.new(“00-11-22-33-44-55”).to_s.should ==
“00:11:22:33:44:55”
end
end

Then you can just do
@signup.mac_address = MacAddress.new “00-11-22-33-44-55”

and you don’t really need to test that, of course, since it’s just a
setter.

Pat

Even my suggestion wouldn’t be a sufficient spec. What about completely
wrong mac addresses? Empty addresses, too many characters, invalid
characters?

It is not for nothing that the rspec test cases are called examples -
you may define any number of example inputs and expected outputs that
are required to describe the behavior of the object to be specified.

barsalou schrieb:

On Jan 10, 2008 12:34 PM, Francois W. [email protected]
wrote:

Even my suggestion wouldn’t be a sufficient spec. What about completely
wrong mac addresses? Empty addresses, too many characters, invalid
characters?

I just sent a reply that crossed wires with yours…anyway,
introducing a MacAddress class here would be great for solving these
sorts of problems. Mac address validation is something that the
@signup object should not be concerned with.

Pat

Yes, you’re absolutely right. I somehow ignored the class name in my
previous answers, but that would have been the next point of attack. :wink:

Pat M. schrieb: