给定软件...
- 该系统由几个子系统组成
- 每个子系统由几个组件组成
- 每个组件都使用许多类来实现
...我喜欢为每个子系统或组件编写自动化测试。
我不会为组件的每个内部类编写测试(除非每个类都有助于组件的公共功能,因此可以通过组件的公共 API 从外部进行测试/测试)。
当我重构组件的实现时(我经常这样做,作为添加新功能的一部分),因此我不需要更改任何现有的自动化测试:因为测试只依赖于组件的公共 API 和公共 API通常是扩大而不是改变。
我认为该政策与Refactoring Test Code 之类的文档形成鲜明对比,该文档说...
- “……单元测试……”
- “......系统中每个班级的测试班......”
- “......测试代码/生产代码比率......理想情况下被认为接近1:1的比率......”
...我想我不同意所有这些(或者至少不练习)。
我的问题是,如果您不同意我的政策,您能解释一下原因吗?这种程度的测试在什么场景下是不够的?
总之:
- 公共接口经过测试(和重新测试),很少更改(它们被添加但很少更改)
- 内部 API 隐藏在公共 API 之后,无需重写测试公共 API 的测试用例即可更改
脚注:我的一些“测试用例”实际上是作为数据实现的。例如,UI 的测试用例由包含各种用户输入和相应的预期系统输出的数据文件组成。测试系统意味着拥有读取每个数据文件的测试代码,将输入重放到系统中,并断言它获得了相应的预期输出。
虽然我很少需要更改测试代码(因为通常会添加而不是更改公共 API),但我确实发现有时(例如每周两次)需要更改一些现有的数据文件。当我将系统输出更改为更好(即新功能改进现有输出)时,可能会发生这种情况,这可能会导致现有测试“失败”(因为测试代码仅尝试断言输出未更改)。为了处理这些情况,我执行以下操作:
- 重新运行自动化测试套件,其中有一个特殊的运行时标志,告诉它不要断言输出,而是将新输出捕获到新目录中
- 使用可视化差异工具查看哪些输出数据文件(即哪些测试用例)已更改,并验证这些更改是否良好且符合新功能的预期
- 通过将新输出文件从新目录复制到运行测试用例的目录来更新现有测试(覆盖旧测试)
脚注:“组件”是指“一个 DLL”或“一个程序集”之类的东西……大到足以在体系结构或系统部署图中可见的东西,通常使用数十个或 100 个类来实现,并且使用仅由大约 1 个或少数几个接口组成的公共 API……可以分配给一个开发团队的东西(其中不同的组件被分配给不同的团队),因此根据康威定律有一个相对稳定的公共 API。
脚注:文章面向对象测试:神话与现实说,
误区:黑盒测试就足够了。 如果您使用类接口或规范仔细地进行测试用例设计,您可以确信该类已被充分执行。白盒测试(查看方法的实现以设计测试)违反了封装的概念。
现实:OO 结构很重要,第二部分。许多研究表明,被开发人员认为极其彻底的黑盒测试套件仅在被测实现中执行了三分之一到一半的语句(更不用说路径或状态)了。这有三个原因。首先,选择的输入或状态通常使用正常路径,但不会强制所有可能的路径/状态。其次,仅靠黑盒测试无法揭示惊喜。假设我们已经测试了被测系统的所有指定行为。为了确保没有未指定的行为,我们需要知道系统的任何部分是否没有被黑盒测试套件执行过。获取此信息的唯一方法是通过代码检测。第三,
我应该补充一点,我正在做白盒功能测试:我看到代码(在实现中)并编写功能测试(驱动公共 API)来练习各种代码分支(功能实现的细节)。