我有一个python模块/脚本,可以完成其中的一些
以上只是两个例子。我试图找出测试这个的最佳“策略”。我所做的是我在我的模块中围绕raw_input
和os.path.exists
构建了包装函数,然后在我的测试中我覆盖这两个函数以从我的数组列表中获取输入或者做一些 mocked 行为。这种方法有以下缺点
os.path.exists
或raw_input
有什么好的建议吗?
答案 0 :(得分:2)
解决方案1:我会做这样的事情,因为它有效:
def setUp(self):
self._os_path_exists = os.path.exists
os.path.exists = self.myTestExists # mock
def tearDown(self):
os.path.exists = self._os_path_exists
不太好。
解决方案2:正如你所说,重组代码不是一个选项,对吧? 理解和不直观会使情况变得更糟。
答案 1 :(得分:2)
简短的回答是monkey patch这些系统调用。
How to display the redirected stdin in Python?
的答案中有一些很好的例子以下是raw_input()
使用lambda
的一个简单示例,该示例会抛弃提示并返回我们想要的内容。
$ cat ./name_getter.py
#!/usr/bin/env python
class NameGetter(object):
def get_name(self):
self.name = raw_input('What is your name? ')
def greet(self):
print 'Hello, ', self.name, '!'
def run(self):
self.get_name()
self.greet()
if __name__ == '__main__':
ng = NameGetter()
ng.run()
$ echo Derek | ./name_getter.py
What is your name? Hello, Derek !
$ cat ./t_name_getter.py
#!/usr/bin/env python
import unittest
import name_getter
class TestNameGetter(unittest.TestCase):
def test_get_alice(self):
name_getter.raw_input = lambda _: 'Alice'
ng = name_getter.NameGetter()
ng.get_name()
self.assertEquals(ng.name, 'Alice')
def test_get_bob(self):
name_getter.raw_input = lambda _: 'Bob'
ng = name_getter.NameGetter()
ng.get_name()
self.assertEquals(ng.name, 'Bob')
if __name__ == '__main__':
unittest.main()
$ ./t_name_getter.py -v
test_get_alice (__main__.TestNameGetter) ... ok
test_get_bob (__main__.TestNameGetter) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
答案 2 :(得分:1)
Johnnysweb充分利用您需要做的事情,但您可以导入并使用mock,而不是自己动手。 Mock专为单元测试而设计,可以非常简单地完成您正在尝试的操作。它内置于Python 3.3。
例如,如果要运行替换os.path.isfile的单元测试并始终返回True:
try:
from unittest.mock import patch
except ImportError:
from mock import patch
class SomeTest(TestCase):
def test_blah():
with patch("os.path.isfile", lambda x: True):
self.assertTrue(some_function("input"))
这可以为您节省大量的样板代码,而且它非常易读。
如果您需要更复杂的东西,例如,替换supbroccess.check_output,您可以创建一个简单的辅助函数:
def _my_monkeypatch_function(li):
x,y = li[0], li[1]
if x == "Reavers":
return "Gorram"
if x == "Inora":
return "Shiny!"
if x == y:
return "The Ballad of Jayne"
def test_monkey():
with patch("subprocess.check_output", _my_monkeypatch_function):
assertEquals(subprocess.check_output(["Mudder","Mudder"]),
"The Ballad of Jayne")