如何为文件转换编写适当的单元测试

时间:2016-06-21 10:30:40

标签: python unit-testing python-3.x mocking

我对单元测试不是很熟悉,我只是从学习如何做到这一步开始。也许我还没有真正理解单元测试和TDD的原理,这也是我感到困难的原因。

要测试的代码如下所示:

class DevelopingMyClass:
    def __init__(self):
        self.firstAttribute = None

    def openGivenFile(self, filename):
        f = open(filename, 'r')
        return f

    def transformInput(self, filename):
        res = self.openGivenFile(filename)
        for line in res.readlines():
            newLine = line.replace('a', 'z')
            print(newLine)

# start
myClass = DevelopingMyClass()
myClass.transformInput('testfile.txt')

当然,这个程序没有任何意义。我只想弄明白:

  • 这是可以测试的吗?如果是的话,究竟是什么让它可以测试?
  • 我是否必须编写两个测试用例,一个用于打开方法,另一个用于转换?
  • 我是否必须模拟开头,以便我独立于测试文件的存在?

1 个答案:

答案 0 :(得分:0)

单元测试在开发过程中提供帮助的原因之一是它们可以揭示您的接口是否设计正确。将单元测试视为想要使用您设计的功能的其他人的程序。

在您的情况下,我可以看到在print方法中使用transformInput时遇到的问题。此外,DevelopingMyClass是一个误导性的标识符。我不想挑剔。它只是让你的思维不那么清晰。

在进入单元测试之前,您应该选择一个不错的例子。对废话没有好的单元测试。

首先,如果您想要读取文件,修改内容并将文件写回,那么您应该从普通函数开始。这堂课不会帮到你。您可能习惯于从Java中首先创建一些对象。但它实际上并不自然。如果你需要保留一些实例变量(某些状态),对象就很好。

如果功能更通用,则不应使用print等副作用。

说,你从来没有听说过TDD,你写的代码是这样的:

#!python3

def copy_and_filter(fname_from, fname_to):
    with open(fname_from) as fin, open(fname_to, 'w') as fout:
        for line in fin:
            fout.write(line.replace('a', 'z'))


copy_and_filter('from.txt', 'to.txt')

(这实际上是您的解决方案。)对于更复杂的代码,您会发现TDD更合理。无论如何。你应该开始思考:

  • 我需要一个带有一个源文件名和一个目标文件名的函数。这两个文件都是文本文件。
  • 它复制源文件的内容,更改内容并将其写入目标。

所以你写道:

#!python3

def copy_and_filter(fname_from, fname_to):
    pass


copy_and_filter('from.txt', 'to.txt')

通过这种方式,您可以定义应该如何调用它。现在是编写单元测试的时候了。您想测试特殊情况:

  • 空档案
  • 几种具有已知内容的文件

稍后,您可能会发现源文件不存在时存在错误(实现应该反映出来),因此您添加一些测试然后修复实现。

可能出现的其他问题: - 源文件不是源文件(比如说是目录) - 目标不能开放写作 - 目标文件已存在,您不想覆盖它

当测试更多文件时,您会发现很难模拟文件,并且您可能决定更改内部结构,以便核心功能与文件类对象一起使用。