tdd - 在 TDD 中,您如何为本来就有副作用的代码编写测试?

标签 tdd side-effects

如果功能的副作用是设计中固有的,我该如何开发这样的功能?

例如,如果我想实现一个类似 http.get("url") 的函数,并且我通过依赖注入(inject)将副作用作为服务 stub ,它看起来像:

var http = {
  "get": function( url, service ) {
    return promise(function( resolve ) {
      service( url ).then(function( Response ) {
        resolve( Response );
      });
    });
  }
}

...但是我需要实现与原始 http.get(url) 相同的服务,因此会产生相同的副作用,因此将我置于开发循环中。我是否必须模拟服务器来测试这样的功能?如果需要,它属于 TDD 开发周期的哪一部分?是集成测试,还是单元测试?

另一个例子是数据库模型。如果我正在开发与数据库一起使用的代码,我将设计一个接口(interface),抽象一个实现该接口(interface)的模型,然后使用依赖注入(inject)将其传递到我的代码中。只要我的模型实现了接口(interface),我就可以使用任何数据库并轻松地 stub 它的状态和响应,以便为与数据库交互的其他功能实现 TDD。但是那个模型呢?它将与数据库交互——似乎这种副作用是设计中固有的,当我去实现那个抽象时,把它抽象掉会让我进入一个开发循环。我如何实现模型的方法而不能够将它们抽象出来?

最佳答案

In the TDD how do you write tests for code that inherently have side effects?



我认为我在任何地方都没有看到特别明确的答案。最接近的可能是 GOOS ——TDD 的“伦敦”学派倾向于关注外部。

但从广义上讲,您需要了解副作用属于 imperative shell。 .它们通常在基础设施组件中实现。因此,您通常需要更高级别的抽象,您可以将其传递给系统的功能部分。

例如,读取系统时钟是一个副作用,会产生一个自纪元以来的时间值。您的大多数系统不应该关心时间来自哪里,因此读取时钟的抽象应该是系统的输入。

现在,感觉就像是“一路乌龟”——你如何测试你与基础设施的交互? Kent Beck describes停止条件

I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence....



我倾向于依靠Hoare's observation

There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies



一旦你着手实现一个明显正确的副作用,你就不再担心它了。

当你盯着一个副作用,并且实现显然不正确时,你开始寻找将硬部分拉回功能核心的方法,进一步隔离副作用。

副作用的实际测试通常发生在您开始将所有组件连接在一起时。由于副作用,这些测试通常较慢;因为它们共享可变状态,您通常需要确保它们按顺序运行。

关于tdd - 在 TDD 中,您如何为本来就有副作用的代码编写测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49418491/

相关文章:

testing - TDD/BDD 积极影响统计

node.js - 使用 gulp 仅运行一个 mocha 测试文件

python - 为什么奇怪的列表理解行为有副作用?

haskell - 函数式编程: Where does the side effect actually happen?

java - 在测试和待测方法中使用相同的值

unit-testing - 测试 BDD 中的副作用

ruby - 我如何让我的控制台以颜色(红色/绿色)显示测试结果

Java 8 Stream : Iterating,处理和计数

c - 在 C 中初始化 GtkWidget* 表

http - 懒惰地消费http请求