如何单元测试修改文件的功能

时间:2017-01-10 17:41:17

标签: unit-testing

自定义类具有文件写入和读取方法。如果获取文件内容的唯一方法是调用read方法,如何正确验证write的单元测试?

1 个答案:

答案 0 :(得分:3)

  1. 首先使用预先存在的测试文件测试Read()。
  2. 现在您知道它有效,请使用Read()来测试Write()。
  3. 最佳实践不是关于成为最佳实践,而是更多关于避免不良做法。糟糕的做法,例如在单个测试中将太多代码耦合在一起,这样您就无法分辨出问题所在,以及多个错误可以相互作用导致失败。除其他目的外,单元测试试图避免耦合。但是如果你试图遵循最佳实践作为教条,并且过多地关注什么类别的测试,那么你最终会做一些不好的做法,只是为了尝试遵循最佳实践。

    读取和写入文件本质上是耦合的,除非您可以阅读它,并且您将它们放在同一个类中,因此它不是一个外部依赖项。诀窍是编写测试,使得Read()和Write()错误无法进行交互以导致误报。例如,如果您执行了类似的操作:

    file = Temp.file
    content = Read(file)
    Write(file, content)
    
    assert_eq( Read(file), content )
    

    然后,如果Read(file)有一个偶尔会返回空字符串的错误,并且Write(file, content)有一个只会擦除文件的错误,那么您将从断言中获得误报。如果你这样写的话:

    file = Temp.file
    content = "The quick brown fox jumped over the lazy grey dog.\n"
    Write(file, content)
    assert_eq( Read(file), content )
    

    Read()Write()中的错误不会导致误报(除非您使用的是引用语言,在这种情况下content应声明为常量)。虽然他们可以互动,但这会引导我们走向下一步。

    你可以在不使用Write()的情况下测试Read(),所以首先要确保Read()在使用它来测试Write()之前有效。预生成一堆有趣的文件来练习Read():Unicode,空文件,大文件,特殊文件等......

    # Pardon my mish-mash prototype language
    tests = {
        empty: "",
        just_newline: "\n",
        simple: "This test is not metal.",
        simple_unicode: "†Hîß †É߆ Îß µé†å¬¡¡¡ "
    }
    
    for (file, want) in tests {
        assert_eq( Read(file), want, "Read(#{file})" )
    }
    

    如果您的测试套件具有排序功能,请确保在Write()测试之前运行Read()测试。现在,如果你运行测试并且Write()失败,你可以相当肯定它不是因为Read()失败了。

    一旦您满意Read()有效,您可以安全地使用它来测试Write()。

    你的代码和测试中总会有耦合,没有它们你就无法完成任何事情。例如,如果Temp.file有一个错误,它并不总是一个可以引入错误的空的临时文件。

    诀窍不是消除所有耦合,诀窍是尽量减少它们。关于测试,努力一次测试一件事。由于Temp类在安装时可能已经过充分测试,并且因为它是一个标准且使用得很好的类,所以在测试中依赖它是安全的。通过这种方式,您可以构建一个不断增加的经过良好测试的代码基础,以构建和测试更多代码。