unit-testing - 应该测试内部实现,还是只测试公共(public)行为?

标签 unit-testing refactoring automated-tests integration-testing code-coverage

给定软件...

  • 该系统由几个子系统
  • 每个子系统由几个组件组成
  • 每个组件都使用许多类来实现

  • ...我喜欢为每个子系统或组件编写自动化测试。

    我不会为组件的每个内部类编写测试(除非每个类都有助于组件的公共(public)功能,因此可以通过组件的公共(public) API 从外部进行测试/测试)。

    当我重构组件的实现时(我经常这样做,作为添加新功能的一部分),因此我不需要更改任何现有的自动化测试:因为测试仅依赖于组件的公共(public) API 和公共(public) API通常是扩大而不是改变。

    我认为这项政策与 Refactoring Test Code 之类的文件形成鲜明对比。 , 它说...
  • “...单元测试...”
  • “......系统中每个类的测试类......”
  • “......测试代码/生产代码比率......理想情况下被认为接近1:1的比率......”

  • ...我想我不同意所有这些(或者至少不练习)。

    我的问题是,如果您不同意我的政策,您能解释一下原因吗?这种程度的测试在什么场景下是不够的?

    总之:
  • 公共(public)接口(interface)经过测试(并重新测试),很少更改(添加但很少更改)
  • 内部 API 隐藏在公共(public) API 之后,无需重写测试公共(public) API 的测试用例即可更改


  • 脚注:我的一些“测试用例”实际上是作为数据实现的。例如,UI 的测试用例由包含各种用户输入和相应的预期系统输出的数据文件组成。测试系统意味着测试代码读取每个数据文件,将输入重放到系统中,并断言它得到了相应的预期输出。

    虽然我很少需要更改测试代码(因为通常会添加而不是更改公共(public) API),但我确实发现有时(例如每周两次)需要更改一些现有的数据文件。当我更好地更改系统输出(即新功能改进现有输出)时,可能会发生这种情况,这可能会导致现有测试“失败”(因为测试代码仅尝试断言输出未更改)。为了处理这些情况,我执行以下操作:
  • 重新运行自动测试套件,其中有一个特殊的运行时标志,告诉它不要断言输出,而是将新输出捕获到新目录
  • 使用可视化差异工具查看哪些输出数据文件(即哪些测试用例)已更改,并验证这些更改是否良好且符合预期
  • 通过将新输出文件从新目录复制到运行测试用例的目录来更新现有测试(覆盖旧测试)


  • 脚注:“组件”是指“一个 DLL”或“一个程序集”之类的东西……大到足以在体系结构或系统部署图上可见的东西,通常使用数十个或 100 个类来实现,并且使用仅由大约 1 个或少数几个接口(interface)组成的公共(public) API……可能分配给一个开发团队的东西(其中不同的组件分配给不同的团队),因此将根据 Conway's Law拥有相对稳定的公共(public) API。

    脚注:文章 Object-Oriented Testing: Myth and Reality说,

    Myth: Black box testing is sufficient. If you do a careful job of test case design using the class interface or specification, you can be assured that the class has been fully exercised. White-box testing (looking at a method's implementation to design tests) violates the very concept of encapsulation.

    Reality: OO structure matters, part II. Many studies have shown that black-box test suites thought to be excruciatingly thorough by developers only exercise from one-third to a half of the statements (let alone paths or states) in the implementation under test. There are three reasons for this. First, the inputs or states selected typically exercise normal paths, but don't force all possible paths/states. Second, black-box testing alone cannot reveal surprises. Suppose we've tested all of the specified behaviors of the system under test. To be confident there are no unspecified behaviors we need to know if any parts of the system have not been exercised by the black-box test suite. The only way this information can be obtained is by code instrumentation. Third, it is often difficult to exercise exception and error-handling without examination of the source code.



    我应该补充一点,我正在做白盒功能测试:我看到代码(在实现中)并编写功能测试(驱动公共(public) API)来练习各种代码分支(功能实现的细节)。

    最佳答案

    我的做法是通过公共(public) API/UI 测试内部。如果无法从外部访问某些内部代码,那么我会重构以删除它。

    关于unit-testing - 应该测试内部实现,还是只测试公共(public)行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/856115/

    相关文章:

    asp.net-mvc - 断言 Action 重定向到正确的 Action /路线?

    java - 用于泛型类扩展的 Mockito/Powermock 类构造

    c# - WPF:我应该如何重构这个 C# 项目?

    python - 长字典属性行的重构

    iphone - XCode iPhone 自动属性、合成和 delloc

    eclipse - 将 window tester 与 eclipse 集成以测试 UI

    unit-testing - 测试资源管理器未发现 Xunit 测试 [VS 15]

    unit-testing - 用于单元测试的 TestDrive.net 'Visual Studio add in' 的开源替代方案?

    javascript - 我如何从网络元素中获取文本并在控制台中打印(例如)

    user-interface - Maveryx、FitNesse、Robot 在 Mac、Windows 和 Linux 上进行桌面 GUI 测试