TDD - 重构成黑盒子?

Kon*_*rus 6 language-agnostic testing tdd

我有一个用TDD开发的非常重要的服务对象.它从一个简单的任务开始:对于队列中的对象,构造异步处理的尝试.所以我围绕我的constructAttempt()方法编写了一个测试:

void constructAttempt() {...}
Run Code Online (Sandbox Code Playgroud)

有许多可能需要考虑的场景,所以我对这种方法进行了十几次测试.


然后我实现了我真正需要它做的事情:扫描整个队列并构建一批尝试.所以代码看起来更像:

public void go() {
    for (QueuedItem item : getQueuedItems()) {
        constructAttempt(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我为这个go()方法添加了一两个新测试.


最后我发现我需要一些有时可能影响的预处理constructAttempt().现在代码看起来更像:

public void go() {
    preprocess();
    for (QueuedItem item : getQueuedItems()) {
        constructAttempt(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

我对现在应该做些什么有些怀疑.

我应该按原样保存代码constructAttempt(),preprocess()go()独立测试吗?为什么不是/为什么不呢?我冒险不承担预处理和破坏封装的副作用.

或者我应该重构整个测试套件只调用go()(这是唯一的公共方法)?为什么不是/为什么不呢?这会使测试更加模糊,但另一方面,它会考虑所有可能的相互作用.事实上,它将成为仅使用公共API的黑盒测试,这可能与TDD不符.

Jef*_*nal 6

go方法实际上只是编排了几个交互,并且本身并不是很有趣.如果你编写测试go而不是你的从属方法,那么测试可能会非常复杂,因为你必须考虑到preprocess和之间相互作用的组合爆炸constructAttempt(甚至可能getQueuedItems,虽然听起来相对简单).

相反,您应该为下级方法编写测试 - 以及constructAttempt需要考虑所有预处理'潜在影响的测试.如果您无法模拟这些副作用(通过操纵底层队列或测试双重),那么重构您的课程直到可以.