# Visibility in tests

**URL:** <https://www.ruby-forum.com/t/visibility-in-tests/186429>\
**Category:** Ruby\
**Created:** [April 7, 2010, 2:26am UTC](https://www.ruby-forum.com/t/visibility-in-tests/186429 "2010-04-07T02:26:17Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![lykos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/b5e925/32.png) [@lykos](https://www.ruby-forum.com/u/lykos)\
**Post date:** [April 7, 2010, 2:26am UTC](https://www.ruby-forum.com/t/visibility-in-tests/186429/1 "2010-04-07T02:26:17Z")

</div>

Hi, I’m new to this, forum, but I really love Ruby and I hope this is  
the right place to discuss problems and questions I have. I learned Ruby  
when I was twelve, so I know Ruby for more than one third of my life and  
I now call it my “mother tongue” of programming languages, but I mostly  
programmed rather childish stuff and for a long time, I was not  
interested in learning more than the basic stuff, since I could just do  
everything I wanted with that already.

However, in the last few months, my Ruby programming has grown a little  
more serious, and (among other things) I started for example to write  
tests for all of my programs that included more than 100 lines, even for  
private purposes. Usually that went quite well, but there stumbling  
block in my way that annoyed me multiple times, so I decided to ask some  
people who maybe know a little more about Ruby.

I don’t know how to apply unit tests to private methods. Usually, I only  
use very few private methods and for my small private purposes, it was  
okay to just set those few to public, too, but how do you do that in a  
good way, if you really do have good reasons for making the methods  
private?

Another small question: Do you know where I can find Ruby style  
guidelines or something like that?

---

<div class="post-metadata">

**Author:** ![lykos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/b5e925/32.png) [@lykos](https://www.ruby-forum.com/u/lykos)\
**Post date:** [April 7, 2010, 2:43am UTC](https://www.ruby-forum.com/t/visibility-in-tests/186429/2 "2010-04-07T02:43:28Z")

</div>

On Apr 6, 2010, at 17:26 , Bernhard B. wrote:

> I don’t know how to apply unit tests to private methods. Usually, I only  
> use very few private methods and for my small private purposes, it was  
> okay to just set those few to public, too, but how do you do that in a  
> good way, if you really do have good reasons for making the methods  
> private?

easy! make them public!

Either don’t make them private in the first place (my preference) or  
make them public in your tests (second choice… usually when I’m  
working with inherited code):

class X  
public :previously\_private\_method  
end

class TestX \< MiniTest::Unit::TestCase  
def test\_previously\_private\_method  
…  
end  
end

---

<div class="post-metadata">

**Author:** ![lykos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/b5e925/32.png) [@lykos](https://www.ruby-forum.com/u/lykos)\
**Post date:** [April 7, 2010, 11:11am UTC](https://www.ruby-forum.com/t/visibility-in-tests/186429/3 "2010-04-07T11:11:49Z")

</div>

Ryan D. wrote:

> On Apr 6, 2010, at 17:26 , Bernhard B. wrote:
> 
> > I don’t know how to apply unit tests to private methods. Usually, I only  
> > use very few private methods and for my small private purposes, it was  
> > okay to just set those few to public, too, but how do you do that in a  
> > good way, if you really do have good reasons for making the methods  
> > private?
> 
> easy! make them public!

Or use one of:

obj.send(:private\_method\_name, args…)

obj.instance\_eval { private\_method\_name args… }

Note that the latter also switches the object context so that ‘@foo’  
inside the block means the @foo instance variable inside obj. That can  
be useful too.

---

<div class="post-metadata">

**Author:** ![lykos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/b5e925/32.png) [@lykos](https://www.ruby-forum.com/u/lykos)\
**Post date:** [April 7, 2010, 12:54pm UTC](https://www.ruby-forum.com/t/visibility-in-tests/186429/4 "2010-04-07T12:54:00Z")

</div>

Ryan D. wrote:

> On Apr 6, 2010, at 17:26 , Bernhard B. wrote:
> 
> > I don’t know how to apply unit tests to private methods. Usually, I only  
> > use very few private methods and for my small private purposes, it was  
> > okay to just set those few to public, too, but how do you do that in a  
> > good way, if you really do have good reasons for making the methods  
> > private?
> 
> easy! make them public!
> 
> Either don’t make them private in the first place (my preference) or  
> make them public in your tests (second choice… usually when I’m  
> working with inherited code):
> 
> class X  
> public :previously\_private\_method  
> end
> 
> class TestX \< MiniTest::Unit::TestCase  
> def test\_previously\_private\_method  
> …  
> end  
> end

Okay, thanks, a lot, nice and easy idea, I should have seen that. 🙂

Brian C. wrote:

> Ryan D. wrote:
> 
> > On Apr 6, 2010, at 17:26 , Bernhard B. wrote:
> > 
> > > I don’t know how to apply unit tests to private methods. Usually, I only  
> > > use very few private methods and for my small private purposes, it was  
> > > okay to just set those few to public, too, but how do you do that in a  
> > > good way, if you really do have good reasons for making the methods  
> > > private?
> > 
> > easy! make them public!
> 
> Or use one of:
> 
> obj.send(:private\_method\_name, args…)
> 
> obj.instance\_eval { private\_method\_name args… }
> 
> Note that the latter also switches the object context so that ‘@foo’  
> inside the block means the @foo instance variable inside obj. That can  
> be useful too.

Thanks a lot, I think the possibility to access instance variables from  
outside will also be very useful for other purposes. Okay, now I will  
have no problems anymore to write tests for private methods.^^

---

<div class="post-metadata">

**Author:** ![lykos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/b5e925/32.png) [@lykos](https://www.ruby-forum.com/u/lykos)\
**Post date:** [April 8, 2010, 2:33am UTC](https://www.ruby-forum.com/t/visibility-in-tests/186429/5 "2010-04-08T02:33:32Z")

</div>

I’m going to guess that I’m the odd one out here, but…

On Tuesday 06 April 2010 07:26:20 pm Bernhard B. wrote:

> I don’t know how to apply unit tests to private methods. Usually, I only  
> use very few private methods and for my small private purposes, it was  
> okay to just set those few to public, too, but how do you do that in a  
> good way, if you really do have good reasons for making the methods  
> private?

Don’t test them directly.

Well, alright, let me take a step back: I agree with Ryan here that they  
shouldn’t be private at all. In a language like Java, I can understand,  
but in  
Ruby, your users will have the source code, and even if they don’t,  
they’ll  
have Object#send and instance\_variable\_get/set.

Your best bet is to explicitly document your public API. If people use  
methods  
that aren’t documented, they get to keep both pieces.

However, there are exceptions – if I recall, Rails will automatically  
make  
certain methods inaccessible to mass assignment if they’re private or  
protected.

Anyway…

Presuming you really do have a good reason for making them private, you  
probably have an even better reason to not unit test them directly, and  
certainly not to rely on the state of instance variables in your unit  
tests.

Your tests should verify _behavior_, not the minute details of _state_.

As an example: I realize this is about the worst way to do things, but  
let’s  
pretend you have the following methods on Integers:

public  
def is\_prime?  
factors.empty?  
end  
private  
def factors

# …

end

Now, your tests should be testing _what_ you actually care about, not  
_how_  
it’s implemented. So, instead of testing factors directly, you would  
test  
is\_prime. Your tests would look something like this:

it ‘should believe 4 is prime’  
5.should be\_prime  
4.should\_not be\_prime  
…  
end

I realize this makes them more integration tests than unit tests, and  
maybe  
I’m missing the point, but I just don’t see the use of such fine-grained  
tests. You want them fine-grained enough to actually catch bugs, but  
coarse  
enough that they’re actually worth writing.
