【问题标题】:Test composite object when components already tested -> redundant?当组件已经测试时测试复合对象 - >冗余?
【发布时间】:2012-03-04 13:36:08
【问题描述】:

我有一个用具体示例说明的一般性问题。 如果所有组件对象都已经测试过了,您建议测试复合对象的程度是多少?

作为一个具体的例子,考虑下面的 NullTerminatedStringReader。它从字节缓冲区中读取一个以空字符结尾的字符串。为此,它使用 Javas Charset 解码器。

我当然想测试我的 NullTerminatedStringReader。它应该能够读取UTF8、UTF16、ASCII等各种字符串。

想象一下,我已经编写了 CharsetDecoder 并测试了它可以从各种可能的字符集中解码字符。它确实经过了很好的测试和尝试,我毫不怀疑它有效。现在我编写了一个使用 CharsetDecoder 的 NullTerminatedStringReader。理论上,我希望 NullTerminatedStringReader 能够处理 CharsetDecoder 可以解码的所有字符集字符串。如果我使用的是 TDD,我会想推动我的设计,所以我会写很多测试来测试 NullTerminatedStringReader 的每个字符集解码:

...
void testNullTerminatedStringReaderCanDecodeUTF8String()
void testNullTerminatedStringReaderCanDecodeASCIIString()
...

但这似乎是多余的,因为在 CharsetDecoder 的测试中我有所有这些测试:

...
void testCharsetDecoderCanDecodeUTF8Char()
void testCharsetDecoderCanDecodeASCIIChar()
...

我不确定在这里做什么,因为如果没有 NullTerminatedStringReader 的测试,我如何驱动它的设计来支持所有这些解码?我是否在 NullTerminatedStringReader 的错误级别上进行测试?如果我不进行测试,它似乎也缺少一些东西,因为理论上我知道 NullTerminatedStringReader 正在使用 CharsetDecoder 并且我知道它所做的只是附加字符以形成一个字符串,所以这里不会出错。如果 CharsetDecoder 有效,NullTerminatedStringReader 也应该有效。但是如果它不使用 CharsetDecoder 怎么办 - 我认为假设不知道 NullTerminatedStringReader 的实现然后编写测试会更清楚,但这会导致看起来像冗余测试的结果.. 困境?你打赌。

class NullTerminatedStringReader
{
    private Charset charset;

    public String read(ByteBuffer buffer)
    {
        StringBuilder sb = new StringBuilder();
        while (true)
        {
            char charVal = readChar(buffer, charset.newDecoder()); // unicode char, possibly span several bytes
            if (charVal == '\0')
                break;
            sb.append(charVal);
        }

        return sb.toString();
    }

    private char readChar(ByteBuffer buffer, CharsetDecoder decoder) {...}
}

【问题讨论】:

    标签: java unit-testing tdd


    【解决方案1】:

    在测试复合对象时,我通常只测试两件事:

    • 它是否支持其设计的复合端到端用例?
    • 复合对象添加的任何增量功能是否有效?

    一般来说,我不会尝试全面测试子对象,因为它们应该有自己的测试用例来做到这一点。即你应该假设你自己的子对象工作,就像你假设 java.util.ArrayList 工作一样。

    因此,在您的 NullTerminatedStringReader 示例中,我可能只测试它是否可以与一两个替代字符集一起使用(即证明它正在调用正确的 CharsetDecoder),并相信 CharsetDecoder 经过足够的测试可以正常工作其他字符集。

    【讨论】:

      【解决方案2】:

      我认为您可以将这种情况视为某种集成测试:为了应对复杂性,您正在模块化。为此,你

      • 需要知道你重用的组件的contract(你在readChar中使用的CharsetDecoder的前置条件和后置条件),这样你的NullTerminatedStringReader就可以使用其他一些组件履行合同。但是您不需要知道您正在使用 CharsetDecoder 实现。
      • 无需重新测试您重复使用的组件的功能:只要满足前置条件,您就可以简单地假设后置条件。
      • 使用 TDD 的这些先决条件来驱动 NullTerminatedStringReader 的设计,但您可以假设后置条件成立。并使用 TDD 的后置条件来驱动您对某些实现的设计,例如CharsetDecoder,如果您仍然需要创建它。但为此,您可以假设满足先决条件。

      【讨论】:

      • 术语是值得商榷的,但我会考虑跨进程边界的集成测试——例如,与远程 Web 服务、数据库甚至本地文件系统通信。我会考虑在同一进程中测试多个类作为组件测试。
      • 是的,你是对的,bryanbcook,集成测试有这个内涵,并不真正适合。我的意思是测试两个组件的集成。不幸的是,我认为“组合测试”并不合适,因为它通常意味着单独测试每个组件就足够了,不需要测试交互。 ISTQB 将“组件测试”定义为单元测试的同义词,所以这也不是我想要表达的。任何其他术语建议表示赞赏!
      猜你喜欢
      • 1970-01-01
      • 2014-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-01
      • 2022-11-11
      • 2015-08-28
      相关资源
      最近更新 更多