代码之家  ›  专栏  ›  技术社区  ›  dlanod

单元测试过程代码时移除依赖项

  •  0
  • dlanod  · 技术社区  · 16 年前

    在具有继承和虚拟函数的面向对象语言中,从单元测试代码中删除依赖项(如数据库、API调用等)可以简单到将这些依赖项封装到它们自己的方法中,然后在继承要测试的类的测试类中重写这些方法。

    但是,我在尝试为过程代码(C具体来说)做类似的事情时遇到了一个问题。如果没有继承,我就不能重写这些调用,那么在单元测试过程代码时,如何提供类似的依赖项移除呢?

    一种选择是提供调用这些依赖项的替代方法,并用 #ifdef 但是理想的方法是将单元测试应用于与最终构建相同的代码。这有可能吗?

    3 回复  |  直到 11 年前
        1
  •  7
  •   Joe Schneider    16 年前

    得到 Working Effectively with Legacy Code 阅读标题为“我的应用程序是所有API调用”的章节。

    基本上,Feathers描述了两种选择:

    “linker seam”:您可以在一组不同的实现中编译您试图存根的API调用,而不必更改代码——基本上,将makefile/.sln更改为在不同的函数实现中编译。

    如果这不起作用,他谈到了“皮肤和包装”,在这里基本上将所有的API函数移动到一个抽象的基类中,创建两个派生类——一个生产类和一个单元测试实现,并将调用转发到适当的方法中,然后使用依赖注入来传递适当的函数集。

        2
  •  0
  •   Rodyland    16 年前

    条件编译可以工作,我以前自己也做过。不过,需要遵守纪律,因为说“这一点太难测试”,然后就不去测试,这很有诱惑力。

    另一种选择,如我所见,是为这些库构建包含您的DB/API调用的特殊测试版本(它们在库中,不是吗?)。测试版本可以维护相同的接口(显然是一个手动过程,因为您没有要从中继承的对象/接口),但可以调用单元测试框架,并可以通过单元测试框架进行查询。我为创建库的fitness版本做了类似的工作,我认为没有任何理由它不能用于单元测试。

    缺点是,您将需要一个单独的可执行文件和每个被测试对象的编译,但这取决于您的测试框架(无论如何都可能是这样)。

    祝你好运!

        3
  •  0
  •   Tim Post Samir J M Araujo    16 年前

    我经常遇到这种情况,这是我在编写/维护测试套件方面远远落后的最大原因之一。有些情况下条件编译会有所帮助,但并非总是如此。

    例如,如果该套件应该在较低级别的接口周围测试包装器以与管理程序通信,则需要在管理程序下测试该套件。或者编写一组聪明的宏/内联函数来“伪造”管理程序,实际上根本不测试任何东西。

    在使用传统DBMS API或典型的ACME小部件API时,这样做要容易一些。

    对于传统测试,我 强烈地 建议从下载TAP(测试任何协议) ccan 把这些测试隔离起来。

    通常,我80%的测试必须像这样包装 非常 冗长而令人沮丧的维护。希望你只有几个怪人可以对付。

    直到有人写了一些魔术棒,从评论中提取测试条件和参数,保持清醒,你就会陷入同样的困境。

    祝你好运,我真的很同情你。