我有一个入口点函数main在一个对象上调用它,我想保持未被模拟,因为它在对象上调用了几个其他方法:
class Thing(object):
def main(self):
self.alpha()
self.bravo()
def alpha(self):
self.charlie()
def bravo(self):
raise TypeError("Requires Internet connection!")
def charlie(self):
raise Exception("Bad stuff happens here!")
Run Code Online (Sandbox Code Playgroud)
这很简单,可以手动模拟:
thing = Thing()
thing.alpha = MagicMock()
thing.bravo = MagicMock()
Run Code Online (Sandbox Code Playgroud)
我可以测试以确保alpha和bravo都被调用一次,我可以在alpha和bravo中设置副作用以确保它们被处理等等.
我担心的是,如果代码定义发生变化并且有人添加了一个charlie调用main.它没有被嘲笑,所以现在会感觉到副作用(而且它们就像写入文件,连接到数据库,从Internet上获取东西,因此这个简单的异常不会提醒我现在的测试坏).
我的计划是验证我的模拟对象不会调用其他方法而不是我应该说的方法(或者引发测试异常).但是,如果我做这样的事情:
MockThing = create_autospec(Thing)
thing = Thing()
thing.main()
print thing.method_calls
# [calls.main()]
Run Code Online (Sandbox Code Playgroud)
然后main也被嘲笑,所以它没有其他方法.我怎么能模仿每个方法但主要的方法呢?(我想要method_calls [calls.alpha(), calls.bravo()]).
编辑:用于黑客答案
好吧,我有一个非常hacky解决方案,但我希望有一个比这更好的答案.基本上我从原始类重新绑定方法(Python绑定一个未绑定的方法)
MockThing = create_autospec(Thing)
thing = MockThing()
thing.main = Thing.ingest.__get__(thing, Thing)
thing.main()
print thing.method_calls
# [calls.alpha(), …Run Code Online (Sandbox Code Playgroud) 我想迭代一个项目列表,并对每个项目运行一个断言.一个例子可能是检查列表中的每个数字是否为奇数.
TestCase:
class TestOdd(unittest.TestCase):
def runTest(self):
"""Assert that the item is odd"""
self.assertTrue( NUMBER %2==1, "Number should be odd")
Run Code Online (Sandbox Code Playgroud)
测试suite:
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(TestOdd())
# I would like to have:
# suite.addTest(TestOdd(1))
# suite.addTest(TestOdd(2))
# suite.addTest(TestOdd(3))
# ...
unittest.main()
Run Code Online (Sandbox Code Playgroud)
如何TestOdd使用参数实例化对象 - 例如,要测试的数字?
更新:根据2011年的博客文章(发布为答案),没有内置的参数化测试机制.我很乐意接受任何更清洁的解决方案.
我有这个测试
import unittest
class TestName(unittest.TestCase):
def setUp(self):
self.name = "Bob"
self.expected_name = "Bob"
def test_name(self):
# ... some operation over self.name
print self.name
self.assertEquals(self.name, self.expected_name)
if __name__ == '__main__':
unittest.main(verbosity=2)
Run Code Online (Sandbox Code Playgroud)
我如何运行测试实例?
为输入和输出列表运行相同的测试(["Bob", "Alice", ...]),也许就像
TestName(name="Bob", expected_name="Bob")
TestName(name="Alice", expected_name="Alice")
Run Code Online (Sandbox Code Playgroud) 下面是一个示例脚本,它在第一个测试用例中检查前置条件,如果不满足前置条件,我的目的是中止脚本.
#!/usr/bin/python
import unittest
import sys
class TestMyScript(unittest.TestCase):
def test_000_prerequisite(self):
a = 0
if not a:
sys.exit()
return
def test_001_test1(self):
print "Inside test 1"
return
def test_002_test2(self):
print "Inside test 2"
return
if __name__ == "__main__":
unittest.main()
Run Code Online (Sandbox Code Playgroud)
但是,sys.exit()仅退出套件的单个测试用例.它不会退出整个脚本.
我理解unittest对每个测试用例进行单独处理,这就是为什么测试用例处理由任何测试用例引起的任何异常并进入下一个测试用例的原因.
但是我想要脚本自杀,我该怎么做?
这是我的脚本的输出:
./temp.py
EInside test 1
.Inside test 2
.
======================================================================
ERROR: test_000_prerequisite (__main__.TestMyScript)
----------------------------------------------------------------------
Traceback (most recent call last):
File "./temp.py", line 9, in test_000_prerequisite
sys.exit()
SystemExit
----------------------------------------------------------------------
Ran 3 tests in 0.000s
FAILED (errors=1)
Run Code Online (Sandbox Code Playgroud)
我的猜测是,如果测试用例返回一些信号,我必须乱用TestRunner并终止脚本.但不确定如何真正实现它.
解:
我给出了一个在ipython/jupyter笔记本中抛出错误的示例,但作为单个脚本运行正常.
import unittest
class Samples(unittest.TestCase):
def testToPow(self):
pow3 = 3**3
assert pow3==27
if __name__ == '__main__':
unittest.main()
Run Code Online (Sandbox Code Playgroud)
错误如下:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-7-232db94ae8b2> in <module>()
8
9 if __name__ == '__main__':
---> 10 unittest.main()
/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/main.pyc in __init__(self, module, defaultTest, argv, testRunner, testLoader, exit, verbosity, failfast, catchbreak, buffer)
92 self.testLoader = testLoader
93 self.progName = os.path.basename(argv[0])
---> 94 self.parseArgs(argv)
95 self.runTests()
96
/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/main.pyc in parseArgs(self, argv)
147 else:
148 self.testNames = (self.defaultTest,)
--> 149 self.createTests()
150 except getopt.error, …Run Code Online (Sandbox Code Playgroud) python python-2.7 ipython-notebook python-unittest jupyter-notebook
给定这样的文件夹结构:
dags/
**/
code.py
tests/
dags/
**/
test_code.py
conftest.py
Run Code Online (Sandbox Code Playgroud)
其中 dags 作为 src 文件的根,“dags/a/b/c.py”导入为“abc”。
我想在code.py中测试以下函数:
dags/
**/
code.py
tests/
dags/
**/
test_code.py
conftest.py
Run Code Online (Sandbox Code Playgroud)
但我面临的问题是我无法找到修补get_connfrom的方法dag_common.connections。我尝试了以下操作:
import os
import sys
# adds dags to sys.path for tests/*.py files to be able to import them
sys.path.append(os.path.join(os.path.dirname(__file__), "..", "dags"))
{{fixtures}}
Run Code Online (Sandbox Code Playgroud)
我测试了以下替代品{{fixtures}}:
(1.a) - 默认
from dag_common.connections import get_conn
from utils.database import dbtypes
def select_records(
conn_id: str,
sql: str,
bindings,
):
conn: dbtypes.Connection = get_conn(conn_id)
with conn.cursor() …Run Code Online (Sandbox Code Playgroud) 我过去几周一直在研究一个Django项目,而且一帆风顺.我使用Django的unittest库来测试所有内容,结果显示在控制台中.
然而,经过一些研究,看起来像pydev提供了设施PyUnit.我使用Eclipse,我认为我只是能够将单元测试传输到PyUnit中,但我没有任何运气,或者找到文档来做到这一点.
如何在eclipse中的PyUnit视图中运行我的单元测试?
目前,我使用以下方法在eclipse中运行我的所有测试:
manage.py test
Run Code Online (Sandbox Code Playgroud)
谢谢!
我正在测试一个Flask应用程序(Flask 0.9),特别是我有一个会话夹具,我想以文档化的方式运行,就像这样(我理解):
from flask import Flask, session
app = Flask(__name__)
@app.route('/', methods=['POST'])
def m():
logging.error(session) # expect {'x': 1}
return ""
with app.test_request_context() as trc:
with app.test_client() as c:
with c.session_transaction() as sess:
sess['x'] = 1
c.post()
Run Code Online (Sandbox Code Playgroud)
这按预期工作,输出如下:
ERROR:root:<SecureCookieSession {'x': 1}>
Run Code Online (Sandbox Code Playgroud)
不幸的是我遇到了意外的结果,其中会话数据没有在端点函数中设置,即输出是这样的:
ERROR:root:<SecureCookieSession {}>
Run Code Online (Sandbox Code Playgroud)
只有从我的单元测试框架运行时才会出现此问题.就目前情况而言,我无法用堕落的情况重现这个问题,尽管我已经做了相当大的努力,其中有一些努力.重要的是我已经包括在内,itsdangerous并Google App Engine testbed期待其中一个可能是原因.
在我自己的系统上,我已经超越了要点,几乎完全复制了我的单元测试框架,试图将其隔离开来.同样,我从测试框架中删除了越来越多的相关代码.到目前为止,我无法想到退化案例与我可能影响结果的精简框架之间的差异.我已经遍历了c.post()pdb中的调用来尝试找出这种恶意的原因,但还没有收集任何有用的见解.
这就是说,我会对这个问题可能存在的方向或建议表示感谢.什么可能影响Werkzeug的背景,以至于session_transaction没有被尊重?
我有一个接受默认参数的方法:
def build_url(endpoint, host=settings.DEFAULT_HOST):
return '{}{}'.format(host, endpoint)
Run Code Online (Sandbox Code Playgroud)
我有一个运行此方法的测试用例:
class BuildUrlTestCase(TestCase):
def test_build_url(self):
""" If host and endpoint are supplied result should be 'host/endpoint' """
result = build_url('/end', 'host')
expected = 'host/end'
self.assertEqual(result,expected)
@patch('myapp.settings')
def test_build_url_with_default(self, mock_settings):
""" If only endpoint is supplied should default to settings"""
mock_settings.DEFAULT_HOST = 'domain'
result = build_url('/end')
expected = 'domain/end'
self.assertEqual(result,expected)
Run Code Online (Sandbox Code Playgroud)
如果我删除调试点build_url并检查此属性settings.DEFAULT_HOST将返回模拟值.但是测试继续失败,断言指示host从我的实际值中分配值settings.py.我知道这是因为host关键字参数是在导入时设置的,我的模拟不被考虑.
调试器
(Pdb) settings
<MagicMock name='settings' id='85761744'>
(Pdb) settings.DEFAULT_HOST
'domain'
(Pdb) host
'host-from-settings.com'
Run Code Online (Sandbox Code Playgroud)
有没有办法在测试时覆盖此值,以便我可以使用模拟 …
有人可以帮我解决这个错误信息:
Could not find a version that satisfies the requirement unittest
Run Code Online (Sandbox Code Playgroud)
我安装了最新的Python和PyCharm并尝试安装包单元测试但是出现上述错误.到目前为止,我使用Python的经历有点像dll地狱......
python-unittest ×10
python ×7
mocking ×2
python-2.7 ×2
arguments ×1
django ×1
eclipse ×1
flask ×1
pydev ×1
pytest ×1
python-mock ×1
test-suite ×1
unit-testing ×1