我安装了pytest-mock并使用了一个模拟程序,我试图像补丁一样运行,但是我得到“类型错误:需要一个有效的目标来修补。你提供了‘返回 a + b’”
# test_capitalize.py
import time
def sum(a, b):
time.sleep(10)
return a + b
def test_sum(mocker):
mocker.patch('return a + b');
assertEqual(sum(2, 3), 9)
Run Code Online (Sandbox Code Playgroud) 我有以下项目结构
base
__init.py
settings
__init__.py
settings.py
tests
pytest.ini
test_module.py
Run Code Online (Sandbox Code Playgroud)
我pytest.ini看起来像这样:
[pytest]
#DJANGO_SETTINGS_MODULE =base.settings.settings
Run Code Online (Sandbox Code Playgroud)
我test_module.py看起来像这样:
def test_django():
from base.settings import settings as base_settings
from django.conf import settings as django_settings
assert 3==5
Run Code Online (Sandbox Code Playgroud)
我现在跑的时候:
py.test
Run Code Online (Sandbox Code Playgroud)
它会毫无问题地运行导入,并会在assert 3==5(如预期的那样)引发错误.这告诉我基础已打开sys.path且base.settings.settings可以导入.
现在我test_module.py改为:
def test_django():
from base.settings import settings as base_settings
from django.conf import settings as django_settings
print django_settings.xxx
assert 3==5
Run Code Online (Sandbox Code Playgroud)
我现在跑的时候:
py.test --ds=base.settings.settings
Run Code Online (Sandbox Code Playgroud)
我收到错误:
错误:无法导入设置'base.settings.settings'(是否在sys.path上?):没有名为base.settings.settings的模块.
当我不通过命令行设置设置,但通过pytest.ini文件(通过取消注释行)时,效果相同.
看起来我想念这里的东西???
所以,我只是失去了一天试图找出为什么py.test没有执行我的autouse,会话范围的设置和拆卸灯具.最后我偶然发现了(帽子提示这个SO评论!)插件文档中的这个小小的一点:
请注意,默认情况下,子目录中的conftest.py文件不会在工具启动时加载.
在我的项目中,我将py.test文件(conftest.py和测试文件)放在一个tests/子目录中,这似乎是一个非常标准的设置.如果我py.test在tests目录中运行,一切都正常运行.如果我py.test在项目根目录中运行,测试仍然运行,但设置/拆卸例程永远不会执行.
问题:
conftest.py根目录觉得很奇怪我的,因为我觉得所有的测试相关的文件应该留在tests子目录中.conftest.py默认情况下未加载的子目录中?我发现这种行为至少可以说,考虑到默认情况下会发现子目录中的测试,所以在查找conftest文件时似乎也很少有额外的工作量.conftest.py在子目录中加载(即远离默认值)?我在文档中找不到这个.如果可能的话,我想避免使用额外的控制台参数,那么我可以在配置文件中添加任何东西吗?非常感谢任何洞察力和提示,我觉得当我可以为我的项目编写测试时,我很多时候会浪费/浪费时间来诊断这个问题.:-(
最小的例子:
# content of tests/conftest.py
# adapted from http://pytest.org/latest/example/special.html
import pytest
def tear_down():
print "\nTEARDOWN after all tests"
@pytest.fixture(scope="session", autouse=True)
def set_up(request):
print "\nSETUP before all tests"
request.addfinalizer(tear_down)
Run Code Online (Sandbox Code Playgroud)
测试文件:
# content of tests/test_module.py
class TestClassA:
def test_1(self):
print "test A1 called"
def test_2(self):
print …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建不基于单元测试的测试类.
这个类下的这个方法
class ClassUnderTestTests:
def test_something(self):
Run Code Online (Sandbox Code Playgroud)
从命令行调用py.test或在PyCharm中运行此测试时(在它自己的模块上),无法检测并运行.
这个
def test_something(self):
Run Code Online (Sandbox Code Playgroud)
可以检测并运行类外的相同方法.
我想把我的测试分组在类下,除非我遗漏了一些我正在遵循py.test规范来做到这一点.
环境:Windows 7,pyCharm,py.test设置为测试运行器.
此链接说明如何使用pytest捕获控制台输出.我尝试了以下简单的代码,但是我收到了错误
import sys
import pytest
def f(name):
print "hello "+ name
def test_add(capsys):
f("Tom")
out,err=capsys.readouterr()
assert out=="hello Tom"
test_add(sys.stdout)
Run Code Online (Sandbox Code Playgroud)
输出:
python test_pytest.py
hello Tom
Traceback (most recent call last):
File "test_pytest.py", line 12, in <module>
test_add(sys.stdout)
File "test_pytest.py", line 8, in test_add
out,err=capsys.readouterr()
AttributeError: 'file' object has no attribute 'readouterr'
Run Code Online (Sandbox Code Playgroud)
什么是错的,需要什么修复?谢谢
编辑:根据评论,我改变了capfd,但我仍然得到相同的错误
import sys
import pytest
def f(name):
print "hello "+ name
def test_add(capfd):
f("Tom")
out,err=capfd.readouterr()
assert out=="hello Tom"
test_add(sys.stdout)
Run Code Online (Sandbox Code Playgroud) 假设我有一个简单的夹具,如下所示(使用pytest-django,但它也适用于pytest):
@pytest.fixture
def my_thing(request, db):
thing = MyModel.objects.create()
request.addfinalizer(lambda: thing.delete())
return thing
Run Code Online (Sandbox Code Playgroud)
当我的测试需要单个MyModel实例时,这很有用.但是,如果我需要两个(或三个或四个)呢?我希望每个实例都是不同的,但要以相同的方式设置.
我可以复制/粘贴代码并重命名夹具功能,但这看起来不够优雅.
同样,我试过:
@pytest.fixture
def my_thing_1(my_thing):
return my_thing
@pytest.fixture
def my_thing_2(my_thing):
return my_thing
Run Code Online (Sandbox Code Playgroud)
但是,这些中的每一个似乎都返回MyModel的相同实例.
有没有办法用pytest的内置功能做我想做的事情?或者,我可以将我的装置的设置/拆卸移动到辅助函数中,因此我不会复制太多的代码.
或者我是以错误的方式处理这整件事?
我运行py.test用夹具在conftest文件.你可以看到下面的代码(一切正常):
example_test.py
import pytest
@pytest.fixture
def platform():
return "ios"
@pytest.mark.skipif("platform == 'ios'")
def test_ios(platform):
if platform != 'ios':
raise Exception('not ios')
def test_android_external(platform_external):
if platform_external != 'android':
raise Exception('not android')
Run Code Online (Sandbox Code Playgroud)
conftest.py
import pytest
@pytest.fixture
def platform_external():
return "android"
Run Code Online (Sandbox Code Playgroud)
现在我希望能够跳过一些不适用于我当前测试运行的测试.在我的例子中,我正在为iOS或Android运行测试(这仅用于演示目的,可以是任何其他表达式).
不幸的是,我无法在声明中得到(我的外部定义夹具).当我运行下面的代码时,我收到以下异常:.我不知道这是否是py.test错误,因为本地定义的灯具正在工作.platform_externalskipifNameError: name 'platform_external' is not defined
example_test.py的附加组件
@pytest.mark.skipif("platform_external == 'android'")
def test_android(platform_external):
"""This test will fail as …Run Code Online (Sandbox Code Playgroud) 我正在使用Python断言语句来匹配实际和预期的行为。我对这些没有控制权,好像有一个错误测试用例中止了一样。我想控制断言错误,并要定义是否要在失败断言时中止测试用例。
我还想添加一些类似的内容,如果存在断言错误,则应该暂停测试用例,并且用户可以随时恢复。
我不知道该怎么做
代码示例,我们在这里使用pytest
import pytest
def test_abc():
a = 10
assert a == 10, "some error message"
Run Code Online (Sandbox Code Playgroud)
Below is my expectation
当assert抛出assertionError时,我应该可以选择暂停测试用例,并且可以调试并稍后恢复。对于暂停和恢复,我将使用tkinter模块。我将做一个断言功能如下
import tkinter
import tkinter.messagebox
top = tkinter.Tk()
def _assertCustom(assert_statement, pause_on_fail = 0):
#assert_statement will be something like: assert a == 10, "Some error"
#pause_on_fail will be derived from global file where I can change it on runtime
if pause_on_fail == 1:
try:
eval(assert_statement)
except AssertionError as e:
tkinter.messagebox.showinfo(e)
eval (assert_statement)
#Above is to raise the …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个pytest插件来自定义特定异常的外观 - 更具体地说,模拟异常(预期被调用的方法没有被调用等),因为在这些异常的追溯中存在大量无用的噪声.
这是我到目前为止所做的,它有效,但非常黑客:
import pytest
import flexmock
@pytest.hookimpl()
def pytest_exception_interact(node, call, report):
exc_type = call.excinfo.type
if exc_type == flexmock.MethodCallError:
entry = report.longrepr.reprtraceback.reprentries[-1]
entry.style = 'short'
entry.lines = [entry.lines[-1]]
report.longrepr.reprtraceback.reprentries = [entry]
Run Code Online (Sandbox Code Playgroud)
我认为我正在hookimpl使用简单的if语句检查异常类型.
我尝试report.longrepr用一个简单的字符串替换,这也有效,但后来我失去了格式化(终端中的颜色).
作为我想缩短的输出类型的一个例子,这是一个模拟断言失败:
=================================== FAILURES ====================================
_______________________ test_session_calls_remote_client ________________________
def test_session_calls_remote_client():
remote_client = mock.Mock()
session = _make_session(remote_client)
session.connect()
remote_client.connect.assert_called_once_with()
session.run_action('asdf')
> remote_client.run_action.assert_called_once_with('asdff')
tests/unit/executor/remote_test.py:22:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ …Run Code Online (Sandbox Code Playgroud) 我正在尝试设置被测目标@pytest.fixture并在模块中的所有测试中使用它。我能够正确修补测试,但是在我添加@pytest.fixture返回模拟对象并在其他单元测试中调用模拟对象后,该对象开始引用回原始函数。
以下是我拥有的代码。我期望mocked_worker单元测试中的 引用返回值,但它正在调用实际os.getcwd方法。
请帮我更正代码:
import os
import pytest
from unittest.mock import patch
class Worker:
def work_on(self):
path = os.getcwd()
print(f'Working on {path}')
return path
@pytest.fixture()
def mocked_worker():
with patch('test.test_module.os.getcwd', return_value="Testing"):
result = Worker()
return result
def test_work_on(mocked_worker):
ans = mocked_worker.work_on()
assert ans == "Testing"
Run Code Online (Sandbox Code Playgroud)