Monday, November 12, 2007
Ruby: Testing Private Methods
Jason Rudolph recently wrote about Testing Private Methods in Ruby. Before I continue, it's probably a good idea to note that I rarely test private methods. I prefer to test through the public API. However, there are times when life is easier if you write a few tests for a private method or two.
The solution highlighted by Jason (original implementation from Evan Phoenix) is nice from a maintainability perspective since it encapsulates changing the behavior of the class within the test. However, it's a bit verbose for my taste.
Reading the entry I couldn't help but think that gaining temporary access to a private method for testing seems like something that can be handled by a general solution instead.
Here's how I would have solved the problem.
The solution highlighted by Jason (original implementation from Evan Phoenix) is nice from a maintainability perspective since it encapsulates changing the behavior of the class within the test. However, it's a bit verbose for my taste.
Reading the entry I couldn't help but think that gaining temporary access to a private method for testing seems like something that can be handled by a general solution instead.
Here's how I would have solved the problem.
private
" victims are no longer with us."
end
end
saved_private_instance_methods = self.private_instance_methods
self.class_eval {public *saved_private_instance_methods }
yield
self.class_eval {private *saved_private_instance_methods }
end
end
unit_tests do
test "kill returns a murder string" do
Ninja.publicize_methods do
assert_equal '3 victims are no longer with us.', Ninja.new.kill(3)
end
end
endLabels: ruby, testing private methods
Comments:
<< Home
I believe the context of the conversation was how would you test in Ruby 1.9 since send will no longer allow you to call private methods.
Hi Jay,
I was wondering, where would you put the publicize_methods class? Is it wise to have this in your normal code or should this be for testing only?
Also, your way is very slick and is less verbose. To me though, the other technique makes it a bit easier at a glance what it going on with the test. I will have to use both techniques to see which ends up winning.
Thanks!
I was wondering, where would you put the publicize_methods class? Is it wise to have this in your normal code or should this be for testing only?
Also, your way is very slick and is less verbose. To me though, the other technique makes it a bit easier at a glance what it going on with the test. I will have to use both techniques to see which ends up winning.
Thanks!
DrMark,
Lately I've been putting these type of methods in a *_extensions files (class_extensions for this example). You can put these files in an extension folder under the test directory.
Cheers, Jay
Lately I've been putting these type of methods in a *_extensions files (class_extensions for this example). You can put these files in an extension folder under the test directory.
Cheers, Jay
Just enclose the argument in parenthesis.
class Class
def publicize_methods
saved_private_instance_methods = self.private_instance_methods
self.class_eval { public(*saved_private_instance_methods) }
yield
self.class_eval { private(*saved_private_instance_methods) }
end
end
Post a Comment
class Class
def publicize_methods
saved_private_instance_methods = self.private_instance_methods
self.class_eval { public(*saved_private_instance_methods) }
yield
self.class_eval { private(*saved_private_instance_methods) }
end
end
<< Home




