Testing on the Toilet Test Behavior, Not Implementation

九 1st, 2013

        一直关注google testing,有些文章写得的确不错,但是由于每次翻墙去看真心麻烦,所以以后会把一些比较好的内容转到blog上收藏,也方便以后查阅。

Your trusty Calculator class is one of your most popular open source projects, with many happy users:

public class Calculator { 
        public int add(int a, int b) {
        return a + b; }

You also have tests to help ensure that it works properly:

public void testAdd() {
          assertEquals(3, calculator.add(2, 1)); 
          assertEquals(2, calculator.add(2, 0)); 
          assertEquals(1, calculator.add(2, -1));

However, a fancy new library promises several orders of magnitude speedup in your code if you use it in place of the addition operator. You excitedly change your code to use this library:

public class Calculator {
          private AdderFactory adderFactory;
          public Calculator(AdderFactor adderFactory) { 
                     this.adderFactory = adderFactory; 
          public int add(int a, int b) {
                     Adder adder = adderFactory.createAdder();
                    ReturnValue returnValue = adder.compute(new Number(a), new Number(b));           
                    return returnValue.convertToInteger();

That was easy, but what do you do about the tests for this code? None of the existing tests should need to change since you only changed the code’s implementation, but its user-facing behavior didn’t change. In most cases, tests should focus on testing your code’s public API, and your code’s implementation details shouldn’t need to be exposed to tests.

Tests that are independent of implementation details are easier to maintain since they don’t need to be changed each time you make a change to the implementation. They’re also easier to understand since they basically act as code samples that show all the different ways your class’s methods can be used, so even someone who’s not familiar with the implementation should usually be able to read through the tests to understand how to use the class.

There are many cases where you do want to test implementation details (e.g. you want to ensure that your implementation reads from a cache instead of from a datastore), but this should be less common since in most cases your tests should be independent of your implementation.

Note that test setup may need to change if the implementation changes (e.g. if you change your class to take a new dependency in its constructor, the test needs to pass in this dependency when it creates the class), but the actual test itself typically shouldn’t need to change if the code’s user-facing behavior doesn’t change.

More information, discussion, and archives:  http://googletesting.blogspot.com

除非注明,本站文章均为原创。本文基于 BY-NC-SA 协议进行授权,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 metaboy(包含链接).

本文链接地址: http://blog.wangyuxiong.com/archives/52056


分类: 技术尝新 测试技术         标签: