Should I test private methods or only public ones?

2018-12-31 06:13发布

I have read this post about how to test private methods. I usually do not test them, because I always thought it's faster to test only public methods that will be called from outside the object. Do you test private methods? Should I always test them?

27条回答
人间绝色
2楼-- · 2018-12-31 06:55

You should not. If your private methods have enough complexity that must be tested, you should put them on another class. Keep high cohesion, a class should have only one purpose. The class public interface should be enough.

查看更多
还给你的自由
3楼-- · 2018-12-31 06:56

What is the purpose of testing?

The majority of the answers so far are saying that private methods are implementation details which don't (or at least shouldn't) matter so long as the public interface is well-tested and working. That's absolutely correct if your only purpose for testing is to guarantee that the public interface works.

Personally, my primary use for code tests is to ensure that future code changes don't cause problems and to aid my debugging efforts if they do. I find that testing the private methods just as thoroughly as the public interface (if not more so!) furthers that purpose.

Consider: You have public method A which calls private method B. A and B both make use of method C. C is changed (perhaps by you, perhaps by a vendor), causing A to start failing its tests. Wouldn't it be useful to have tests for B also, even though it's private, so that you know whether the problem is in A's use of C, B's use of C, or both?

Testing private methods also adds value in cases where test coverage of the public interface is incomplete. While this is a situation we generally want to avoid, the efficiency unit testing depends both on the tests finding bugs and the associated development and maintenance costs of those tests. In some cases, the benefits of 100% test coverage may be judged insufficient to warrant the costs of those tests, producing gaps in the public interface's test coverage. In such cases, a well-targeted test of a private method can be a very effective addition to the code base.

查看更多
爱死公子算了
4楼-- · 2018-12-31 06:56

If I find that the private method is huge or complex or important enough to require its own tests, I just put it in another class and make it public there (Method Object). Then I can easily test the previously private but now public method that now lives on its own class.

查看更多
笑指拈花
5楼-- · 2018-12-31 06:56

The answer to "Should I test private methods?" is ".......sometimes". Typically you should be testing against the interface of your classes.

  • One of the reasons is because you do not need double coverage for a feature.
  • Another reason is that if you change private methods, you will have to update each test for them, even if the interface of your object hasn't changed at all.

Here is an example:

class Thing
  def some_string
    one + two
  end

  private 

  def one
    'aaaa'
  end

  def two
    'bbbb'
  end

end


class RefactoredThing
def some_string
    one + one_a + two + two_b
  end

  private 

  def one
    'aa'
  end

  def one_a
    'aa'
  end

  def two
    'bb'
  end

  def two_b
    'bb'
  end
end

In RefactoredThing you now have 5 tests, 2 of which you had to update for refactoring, but your object's functionality really hasn't changed. So let's say that things are more complex than that and you have some method that defines the order of the output such as:

def some_string_positioner
  if some case
  elsif other case
  elsif other case
  elsif other case
  else one more case
  end
end

This shouldn't be run by an outside user, but your encapsulating class may be to heavy to run that much logic through it over and over again. In this case maybe you would rather extract this into a seperate class, give that class an interface and test against it.

And finally, let's say that your main object is super heavy, and the method is quite small and you really need to ensure that the output is correct. You are thinking, "I have to test this private method!". Have you that maybe you can make your object lighter by passing in some of the heavy work as an initialization parameter? Then you can pass something lighter in and test against that.

查看更多
倾城一夜雪
6楼-- · 2018-12-31 06:57

I tend to follow the advice of Dave Thomas and Andy Hunt in their book Pragmatic Unit Testing:

In general, you don't want to break any encapsulation for the sake of testing (or as Mom used to say, "don't expose your privates!"). Most of the time, you should be able to test a class by exercising its public methods. If there is significant functionality that is hidden behind private or protected access, that might be a warning sign that there's another class in there struggling to get out.

But sometimes I can't stop myself from testing private methods because it gives me that sense of reassurance that I'm building a completely robust program.

查看更多
若你有天会懂
7楼-- · 2018-12-31 06:58

I do not unit test private methods. A private method is an implementation detail that should be hidden to the users of the class. Testing private methods breaks encapsulation.

If I find that the private method is huge or complex or important enough to require its own tests, I just put it in another class and make it public there (Method Object). Then I can easily test the previously-private-but-now-public method that now lives on its own class.

查看更多
登录 后发表回答