python - 测试脚本输出

标签 python testing

我有一个接受一个输入(一个文本文件)的 Python 脚本:./myprog.py file.txt。该脚本根据给定的输入输出一个字符串。

我有一组测试文件,我想用它们来测试我的程序。我知道每个文件的预期输出,并希望确保我的脚本为每个文件生成正确的输出。

进行此类测试的公认方法是什么?

我在考虑使用 Python 的 unittest 模块作为测试框架,然后通过 subprocess.check_output(stderr=subprocess.STDOUT) 运行我的脚本,捕获 stdoutstderr,然后执行 unittest assertEqual 来比较实际字符串和预期字符串。我想确保我没有错过一些更好的解决方案。

最佳答案

这里有两个问题。测试一个程序,而不是函数库,测试打印的东西,而不是从函数返回的值。两者都会使测试变得更加困难,因此最好尽可能地避开这些问题。

通常的技术是创建一个函数库,然后让您的程序成为它的薄包装。这些函数返回它们的结果,只有程序进行打印。这意味着您可以对大部分代码使用普通的单元测试技术。

您可以拥有一个既是库又是程序的文件。这是一个简单的示例,如 hello.py

def hello(greeting, place):
    return greeting + ", " + place + "!"

def main():
    print(hello("Hello", "World"))

if __name__ == '__main__':
    main()

最后一点是文件如何判断它是作为程序运行还是作为库导入。它允许使用 import hello 访问各个函数,还允许文件作为程序运行。 See this answer for more information .

然后你就可以编写一个基本正常的单元测试了。

import hello
import unittest
import sys
from StringIO import StringIO
import subprocess

class TestHello(unittest.TestCase):
    def test_hello(self):
        self.assertEqual(
             hello.hello("foo", "bar"),
            "foo, bar!"
        )

    def test_main(self):
        saved_stdout = sys.stdout
        try:
            out = StringIO()
            sys.stdout = out
            hello.main()
            output = out.getvalue()
            self.assertEqual(output, "Hello, World!\n")
        finally:
            sys.stdout = saved_stdout

    def test_as_program(self):
        self.assertEqual(
            subprocess.check_output(["python", "hello.py"]),
            "Hello, World!\n"
        )

if __name__ == '__main__':
    unittest.main()

这里的test_hello是直接将hello作为一个函数进行单元测试;在更复杂的程序中,将有更多的功能需要测试。我们还有 test_main 使用 StringIOmain 进行单元测试捕获它的输出。最后,我们确保程序将作为带有 test_as_program 的程序运行。

重要的是尽可能多地测试函数返回数据的功能,并尽可能少地测试打印和格式化字符串,并且几乎不通过运行程序本身进行测试。当我们实际测试该程序时,我们需要做的就是检查它是否调用了 main

关于python - 测试脚本输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41797606/

相关文章:

python - 从 Windows 启动 spark ec2 集群

python - 使用键字符串列表作为路径添加到字典

python - crcmod 的 xorOut 参数的行为与手动异或不同

javascript - 自动化应用程序测试 (phantomjs) 和 merge 分支

Python:如何在使用正则表达式时跳过有多余字符的行?

python - 为什么索引错误: index 1 is out of bounds for axis 0 with size 1

database - 在哪些情况下,您会针对内存数据库而不是开发数据库进行测试?

ruby - 轨道测试 : Why should one use Rspec2 over Stock testing environment rails provide by default

java - 增强 hibernate IdentityGenerator 并且不破坏模式导出

java - 如何创建使用特定 JVM 参数运行的 Spring Boot 测试