14.1 测试stdout输出¶
问题¶
ä½ çš„ç¨‹åº�䏿œ‰ä¸ªæ–¹æ³•ä¼šè¾“å‡ºåˆ°æ ‡å‡†è¾“å‡ºä¸ï¼ˆsys.stdout)。也就是说它会将文本打å�°åˆ°å±�幕上é�¢ã€‚ ä½ æƒ³å†™ä¸ªæµ‹è¯•æ�¥è¯�明它,给定一个输入,相应的输出能æ£å¸¸æ˜¾ç¤ºå‡ºæ�¥ã€‚
解决方案¶
使用 unittest.mock 模å�—ä¸çš„ patch() 函数,
使用起��常简�,�以为�个测试模拟 sys.stdout 然�回滚,
并且�产生大�的临时��或在测试用例直接暴露状���。
作为一个例å�,我们在 mymodule 模å�—ä¸å®šä¹‰å¦‚下一个函数:
# mymodule.py
def urlprint(protocol, host, domain):
url = '{}://{}.{}'.format(protocol, host, domain)
print(url)
默认情况下内置的 print 函数会将输出��到 sys.stdout 。
ä¸ºäº†æµ‹è¯•è¾“å‡ºçœŸçš„åœ¨é‚£é‡Œï¼Œä½ å�¯ä»¥ä½¿ç”¨ä¸€ä¸ªæ›¿èº«å¯¹è±¡æ�¥æ¨¡æ‹Ÿå®ƒï¼Œç„¶å�Žä½¿ç”¨æ–言æ�¥ç¡®è®¤ç»“果。
使用 unittest.mock 模å�—çš„ patch() 方法å�¯ä»¥å¾ˆæ–¹ä¾¿çš„在测试è¿�è¡Œçš„ä¸Šä¸‹æ–‡ä¸æ›¿æ�¢å¯¹è±¡ï¼Œ
并且当测试完æˆ�时候自动返回它们的原有状æ€�。下é�¢æ˜¯å¯¹ mymodule 模å�—的测试代ç �:
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() 函数被用作一个上下文管�器,使用 StringIO 对象�代替 sys.stdout .
fake_out å�˜é‡�是在该进程ä¸è¢«åˆ›å»ºçš„æ¨¡æ‹Ÿå¯¹è±¡ã€‚
在withè¯å�¥ä¸ä½¿ç”¨å®ƒå�¯ä»¥æ‰§è¡Œå�„ç§�检查。当withè¯å�¥ç»“æ�Ÿæ—¶ï¼Œpatch 会将所有东西æ�¢å¤�到测试开始å‰�的状æ€�。
有一点需è¦�注æ„�的是æŸ�些对Pythonçš„C扩展å�¯èƒ½ä¼šå¿½ç•¥æŽ‰ sys.stdout çš„é…�ç½®è€Œç›´æŽ¥å†™å…¥åˆ°æ ‡å‡†è¾“å‡ºä¸ã€‚
é™�于篇幅,本节ä¸�会涉å�Šåˆ°è¿™æ–¹é�¢çš„讲解,它适用于纯Python代ç �。
å¦‚æžœä½ çœŸçš„éœ€è¦�在Cæ‰©å±•ä¸æ�•获I/Oï¼Œä½ å�¯ä»¥å…ˆæ‰“开一个临时文件,然å�Žå°†æ ‡å‡†è¾“出é‡�定å�‘到该文件ä¸ã€‚
更多关于æ�•获以å—符串形å¼�æ�•获I/Oå’Œ StringIO 对象请å�‚阅5.6å°�节。