Python|测试输出到标准输出
测试是开发的关键部分,因为在Python执行代码之前没有编译器来分析代码。
给定一个程序,该程序具有一个输出到标准输出 (sys.stdout)的方法。这几乎总是意味着它将文本发送到屏幕。人们喜欢为代码编写一个测试,以证明在给定正确输入的情况下,会显示正确的输出。
使用unittest.mock 模块的patch()
函数,可以很简单地模拟出sys.stdout以进行单个测试,然后再将其放回去,而不会出现混乱的临时变量或在测试用例之间泄漏模拟状态。
代码 #1:示例
def urlprint(protocol, host, domain):
url = '{}://{}.{}'.format(protocol, host, domain)
print(url)
默认情况下,内置print
函数将输出发送到sys.stdout
。为了测试输出是否真正到达那里,将使用替代对象对其进行模拟,然后对发生的情况进行断言。
使用unittest.mock
模块的patch()
方法可以方便地仅在运行测试的上下文中替换对象,在测试完成后立即将对象恢复到原始状态。
代码#2:上述代码的测试代码
from io import StringIO
from unittest import TestCase
from unittest.mock import patch
import mymodule
class TestURLPrint(TestCase):
def test_url_gets_to_stdout(self):
protocol = 'http'
host = 'www'
domain = 'example.com'
expected_url = '{}://{}.{}\n'.format(protocol, host, domain)
with patch('sys.stdout', new = StringIO()) as fake_out:
mymodule.urlprint(protocol, host, domain)
self.assertEqual(fake_out.getvalue(), expected_url)
-
urlprint()
函数接受三个参数,测试从为每个参数设置虚拟参数开始。 expected_url 变量设置为包含预期输出的字符串。 - 为了运行测试,
unittest.mock.patch()
函数被用作上下文管理器,将sys.stdout
的值替换为 StringIO 对象作为替代。 - fake_out变量是在这个过程中创建的模拟对象。这可以在 with 语句的主体内使用来执行各种检查。当 with 语句完成时,patch 可以方便地将所有内容恢复到测试运行之前的状态。
- 值得注意的是, Python的某些 C 扩展可能会绕过 sys.stdout 的设置直接写入标准输出。