标签: pytest

使用 mocker 修补 pytest

我安装了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)

python mocking pytest

19
推荐指数
1
解决办法
4万
查看次数

Django py.test找不到设置模块

我有以下项目结构

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.pathbase.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文件(通过取消注释行)时,效果相同.

看起来我想念这里的东西???

python django pytest

18
推荐指数
1
解决办法
7845
查看次数

如何让py.test识别子目录中的conftest.py?

所以,我只是失去了一天试图找出为什么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)

python pytest

18
推荐指数
1
解决办法
9232
查看次数

py.test在类下没有找到测试

我正在尝试创建不基于单元测试的测试类.

这个类下的这个方法

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设置为测试运行器.

python unit-testing pytest pycharm

18
推荐指数
2
解决办法
1万
查看次数

编写pytest函数来检查python中控制台(stdout)的输出?

此链接说明如何使用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)

python printing stdout pytest

18
推荐指数
2
解决办法
8518
查看次数

pytest夹具的多个副本

假设我有一个简单的夹具,如下所示(使用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的内置功能做我想做的事情?或者,我可以将我的装置的设置/拆卸移动到辅助函数中,因此我不会复制太多的代码.

或者我是以错误的方式处理这整件事?

python testing django pytest

18
推荐指数
1
解决办法
3850
查看次数

如何使用外部夹具跳过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)

问题

现在我希望能够跳过一些不适用于我当前测试运行的测试.在我的例子中,我正在为iOSAndroid运行测试(这仅用于演示目的,可以是任何其他表达式).

不幸的是,我无法在声明中得到(我的外部定义夹具).当我运行下面的代码时,我收到以下异常:.我不知道这是否是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 decorator pytest python-decorators

18
推荐指数
3
解决办法
8067
查看次数

是否可以在Python中更改PyTest的assert语句行为

我正在使用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)

python testing assert pytest

18
推荐指数
3
解决办法
466
查看次数

自定义pytest中特定异常的错误消息

我正在尝试编写一个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)

python pytest

17
推荐指数
1
解决办法
984
查看次数

使用 pytest.fixture 返回模拟对象的正确方法

我正在尝试设置被测目标@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)

python unit-testing pytest python-3.x python-unittest

17
推荐指数
2
解决办法
1万
查看次数