应该测试内部实现,还是只测试公共行为? [英] Should one test internal implementation, or only test public behaviour?

查看:32
本文介绍了应该测试内部实现,还是只测试公共行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定软件......

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

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

... I like to write automated tests of each subsystem or component.

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

I don't write a test for each internal class of a component (except inasmuch as each class contributes to the component's public functionality and is therefore testable/tested from outside via the component's public API).

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

When I refactor the implementation of a component (which I often do, as part of adding new functionality), I therefore don't need to alter any existing automated tests: because the tests only depend on the component's public API, and the public APIs are typically being expanded rather than altered.

我认为该政策与重构测试代码,表示诸如...

I think this policy contrasts with a document like Refactoring Test Code, which says things like ...

  • ...单元测试..."
  • "...系统中每个类的测试类..."
  • ...测试代码/生产代码的比例...理想情况下被认为接近 1:1 的比例..."

...我想我不同意所有这些(或至少不实践).

... all of which I suppose I disagree with (or at least don't practice).

我的问题是,如果您不同意我的政策,您会解释原因吗?这种程度的测试在哪些情况下是不够的?

总结:

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

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

Footnote: some of my 'test cases' are actually implemented as data. For example, test cases for the UI consist of data files which contain various user inputs and the corresponding expected system outputs. Testing the system means having test code which reads each data file, replays the input into the system, and asserts that it gets the corresponding expected output.

尽管我很少需要更改测试代码(因为公共 API 通常是添加而不是更改),但我确实发现有时(例如每周两次)需要更改一些现有数据文件.当我更好地更改系统输出(即新功能改进现有输出)时,可能会发生这种情况,这可能会导致现有测试失败"(因为测试代码仅尝试断言输出未更改).为了处理这些情况,我执行以下操作:

Although I rarely need to change test code (because public APIs are usually added to rather than changed), I do find that I sometimes (e.g. twice a week) need to change some existing data files. This can happens when I change the system output for the better (i.e. new functionality improves existing output), which might cause an existing test to 'fail' (because the test code only tries to assert that output hasn't changed). To handle these cases I do the following:

  • 重新运行自动化测试套件,它有一个特殊的运行时标志,它告诉它不要断言输出,而是将新输出捕获到新目录中
  • 使用可视化差异工具查看哪些输出数据文件(即哪些测试用例)发生了更改,并验证这些更改是否良好并符合新功能的预期
  • 通过将新的输出文件从新目录复制到运行测试用例的目录来更新现有测试(覆盖旧测试)

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

Footnote: by "component", I mean something like "one DLL" or "one assembly" ... something that's big enough to be visible on an architecture or a deployment diagram of the system, often implemented using dozens or 100 classes, and with a public API that consists of only about 1 or a handful of interfaces ... something that may be assigned to one team of developers (where a different component is assigned to a different team), and which will therefore according to Conway's Law having a relatively stable public API.

脚注:文章面向对象测试:神话与现实 说,

Footnote: The article Object-Oriented Testing: Myth and Reality says,

误解:黑盒测试就足够了.如果你认真做好测试用例使用类接口设计或规格,您可以放心班级得到了充分的锻炼.白盒测试(看一个方法的实现到设计测试)违反了封装.

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.

现实:面向对象结构很重要,部分II. 许多研究表明,黑盒测试套件被认为是开发人员极其彻底只运动三分之一到一半的陈述(更不用说路径或州)在实施中测试.原因有以下三个这个.首先,输入或状态选择通常锻炼正常路径,但不要强迫所有可能的路径/状态.二、黑匣子仅靠测试无法发现惊喜.假设我们已经测试了所有系统的指定行为正在测试中.有信心有没有我们需要的未指明的行为知道系统的任何部分是否有没有被黑盒执行测试套件.唯一的办法是这个可以通过代码获取信息仪表.第三,经常难以行使例外和不检查错误处理源代码.

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.

我应该补充一点,我正在做白盒功能测试:我看到代码(在实现中)并编写功能测试(驱动公共 API)来执行各种代码分支(功能实现的详细信息).

I should add that I'm doing whitebox functional testing: I see the code (in the implementation) and I write functional tests (which drive the public API) to exercise the various code branches (details of the feature's implementation).

推荐答案

我的做法是通过公共 API/UI 来测试内部.如果某些内部代码无法从外部访问,那么我将对其进行重构以将其删除.

My practice is to test the internals through the public API/UI. If some internal code cannot be reached from the outside, then I refactor for removing it.

这篇关于应该测试内部实现,还是只测试公共行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆