标签: pytest-django

Django 测试客户端与 django-pytest

我正在使用 django-pytest 来测试 Django Rest Framework API。我有一个看起来像这样的测试模块:

class TestClass:

    def test_station_is_created(self, db, api_client):
        StationFactory(name='foo')
        response = api_client.get(reverse('api:stations'))
        assert response.status_code == 200
        ...

    def test_no_stations(self, db, api_client):
        response = api_client.get(reverse('api:stations'))
        assert response.data['data'] == []
Run Code Online (Sandbox Code Playgroud)

当我运行测试时,我得到:

________________________________ TestClass.test_no_stations________________________________
path/to/test/module.py:11: in test_no_stations

E   assert [OrderedDict(...01251d92f')])] == []
E     Left contains more items, first extra item: OrderedDict([...])
Run Code Online (Sandbox Code Playgroud)

如果我检查使用调试器返回的数据,我会看到它是在先前测试中创建的站,即使数据库似乎是空的:

ipdb> response.data['data'][0]['attributes']['name']
foo
ipdb> len(Station.objects.all())
0
Run Code Online (Sandbox Code Playgroud)

我不知道 pytest 是否在测试之间清除数据库。我怀疑正在使用多个数据库,但我的设置中只配置了一个。我虽然可能有一些缓存,但我阅读了 Django 测试客户端文档,但没有找到太多内容。我可能会错过什么?

python django pytest django-rest-framework pytest-django

3
推荐指数
1
解决办法
2265
查看次数

pytest-cov 一次涵盖许多应用程序

我构建了包含许多应用程序的 django 项目。现在我想为这些应用程序生成覆盖率报告。出于测试目的,我使用 py.test、pytest-django 和 pytest-cov。到目前为止,我只能通过在命令行上手动输入所有应用程序名称来生成报告:

py.test --cov-report html --cov=app1 --cov=app2 --cov=app3 --cov=app4 */tests.py
Run Code Online (Sandbox Code Playgroud)

pytest-cov 是否有办法用一个简单的表达式指定所有应用程序?

django coverage.py pytest pytest-django

3
推荐指数
1
解决办法
4432
查看次数

Pytest-django:设置用户权限

我使用pytest 3.0.6和pytest-django 3.1.2为Django工作.我有这个非常简单的测试失败,我不明白发生了什么:

# test_mytest.py
import pytest
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType


@pytest.mark.django_db
def test_user_has_perm(django_user_model):
    # Create a new user
    john_doe = django_user_model.objects.create_user('johndoe', email='jd@example.com', password='123456')

    # Get or create the permission to set on user
    user_ct = ContentType.objects.get(app_label='auth', model='user')
    p, _ = Permission.objects.get_or_create(content_type=user_ct, codename='delete_user', name="Can delete user")

    # User don't have the permission
    assert john_doe.has_perm(p) is False

    # Set permission to user
    john_doe.user_permissions.add(p)
    assert john_doe.has_perm(p) is True  # ---> FAIL
Run Code Online (Sandbox Code Playgroud)

以防万一,测试结果如下:

$ pytest
============================= test session starts …
Run Code Online (Sandbox Code Playgroud)

django pytest pytest-django

3
推荐指数
1
解决办法
1029
查看次数

pytest.fixture函数不能使用``yield``.而是编写并返回一个内部函数/生成器,让消费者调用并迭代它:

我正在尝试使用pytest为我的Django项目运行selenium并执行fixture fix/teardown.

我试图遵循最佳实践使用,yield但我收到一个错误:

--- ERROR at setup of test_browsing_check --- 
pytest.fixture functions cannot use ``yield``. Instead write and return an inner function/generator and let the consumer call and iterate over it.:

@pytest.fixture(scope="module")
def browser(request):
    selenium = webdriver.Firefox()
    selenium .implicitly_wait(3)
    yield selenium
    selenium.quit()
Run Code Online (Sandbox Code Playgroud)

你知道它为什么不起作用吗?

然后,我使用了另一个运行良好的代码

@pytest.fixture(scope="module")
def browser(request):
    selenium = webdriver.Firefox()
    selenium.implicitly_wait(3)
    def teardown():
        selenium.quit()
    request.addfinalizer(teardown)
    return selenium
Run Code Online (Sandbox Code Playgroud)

但不建议使用此方法:

此方法仍然完全受支持,但建议从2.10开始产量,因为它被认为更简单,更好地描述了自然代码流.

关于版本的说明:

$ python -V
$ Python 3.5.2 :: Anaconda 4.2.0 (64-bit)

$ django-admin version
$ 1.10.3

$ …
Run Code Online (Sandbox Code Playgroud)

selenium pytest-django

3
推荐指数
1
解决办法
2590
查看次数

如何使用django-pytest跟随Django重定向?

在Django中设置ArchiveIndexView时,我可以通过自己导航至页面来成功显示模型中的项目列表。

当要在pytest中编写测试以验证导航到页面“ checklist_GTD / archive /”是否成功时,测试失败并显示以下消息:

>       assert response.status_code == 200
E       assert 301 == 200
E        +  where 301 = <HttpResponsePermanentRedirect status_code=301, "text/html; charset=utf-8", url="/checklist_GTD/archive/">.status_code

test_archive.py:4: AssertionError
Run Code Online (Sandbox Code Playgroud)

我了解有一种方法可以按照请求获取最终的status_code。有人可以帮我解决这个问题,如何在pytest-django中完成吗?pytest-django上文档在重定向上没有任何内容。谢谢。

django pytest pytest-django

3
推荐指数
2
解决办法
898
查看次数

在 Django 2 中模拟一个 RelatedManager

这个问题与这个问题直接相关,但那个现在似乎已经过时了。

我正在尝试测试视图而无需访问数据库。为此,我需要对RelatedManager用户进行模拟。

我正在使用pytestpytest-mock

模型.py

# truncated for brevity, taken from django-rest-knox
class AuthToken(models.Model):
    user = models.ForeignKey(
        User, 
        null=False, 
        blank=False,
        related_name='auth_token_set', 
        on_delete=models.CASCADE
    )
Run Code Online (Sandbox Code Playgroud)

视图.py

class ChangeEmail(APIView):
    permission_classes = [permissions.IsAdmin]
    serializer_class = serializers.ChangeEmail

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        user = request.user
        user.email = request.validated_data['email']
        user.save()

        # Logout user from all devices
        user.auth_token_set.all().delete() # <--- How do I mock this?

        return Response(status=status.HTTP_200_OK)
Run Code Online (Sandbox Code Playgroud)

测试视图.py

def test_valid(mocker, user_factory):
    user = user_factory.build()
    user.id = …
Run Code Online (Sandbox Code Playgroud)

django pytest python-mock django-rest-framework pytest-django

3
推荐指数
1
解决办法
868
查看次数

需要在 pytest 工厂中覆盖 django auto_now_add

由于django 模型中的auto_now_add,sent_at在 pytest 工厂中不起作用。需要覆盖 pytest 工厂的 sent_at

class ABC(models.Model):
    x = models.ForeignKey(X, on_delete=models.CASCADE, related_name="xx")
    y = models.ForeignKey(Y, on_delete=models.CASCADE, related_name="yy")
    sent_at = models.DateTimeField(auto_now_add=True)


class ABCFactory(factory.django.DjangoModelFactory):
    x = factory.SubFactory(XFactory)
    y = factory.SubFactory(YFactory)
    sent_at = timezone.now() - timezone.timedelta(seconds=40)
Run Code Online (Sandbox Code Playgroud)

django unit-testing pytest django-rest-framework pytest-django

3
推荐指数
1
解决办法
1247
查看次数

当固定范围为“模块”时,pytest + django 给我一个数据库错误

我里面有以下内容conftest.py

@pytest.mark.django_db
@pytest.fixture(scope='module')
def thing():
    print('sleeping')  # represents a very expensive function that i want to only ever once once per module
    Thing.objects.create(thing='hello')
    Thing.objects.create(thing='hello')
    Thing.objects.create(thing='hello')
Run Code Online (Sandbox Code Playgroud)

里面tests.py

@pytest.mark.django_db
def test_thing(thing):
    assert models.Thing.objects.count() > 1

@pytest.mark.django_db
def test_thing2(thing):
    assert models.Thing.objects.count() > 1


@pytest.mark.django_db
@pytest.mark.usefixtures('thing')
def test_thing3():
    assert models.Thing.objects.count() > 1
Run Code Online (Sandbox Code Playgroud)

所有三个测试都会抛出相同的错误:RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.

我尝试过使用scope='session'///scope='class'scope='package'scope='module'唯一有效的方法是`scope='function',它违背了我想要实现的目的我希望能够为每个模块创建一次所有这些项目,而不是每次测试一次。

注意:我在大型代码库中遇到了这个问题,并使用单个应用程序创建了一个新的 django 项目来测试并查看问题是否是现有的测试代码,并且在独立测试中也失败了。使用 …

django pytest pytest-django

3
推荐指数
1
解决办法
1776
查看次数

没有创建Django测试表

我正在尝试为我的django项目编写测试用例,但是当我运行"$ ./manage.py test"命令时,它创建测试数据库,但它没有创建任何表,我收到一个错误,表不存在.欢迎任何建议.这是我通过"./manage.py inspectdb> models.py"创建的模型

class MyCustomModel(models.Model):
    name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)

    class Meta:
       managed = False
       db_table = 'MY_TABLE'
Run Code Online (Sandbox Code Playgroud)

python django django-testing python-unittest pytest-django

2
推荐指数
3
解决办法
2573
查看次数

如何使用pytest-django设置postgres数据库?

我希望pytest-django在创建测试数据库时安装Postgres扩展。我一直在弄混conftest.py尝试使其工作,但是我被卡住了。

我的conftest.py位于项目的顶层(与manage.py相同的目录),并且包含:

from django.db import connection
import pytest_django
@pytest.fixture(scope='session')
def django_db_setup(*args, **kwargs):
    pytest_django.fixtures.django_db_setup(*args, **kwargs)
    cursor = connection.cursor()
    cursor.execute("create extension pg_trgm")
Run Code Online (Sandbox Code Playgroud)

但是当我运行它时,我得到:

_pytest.vendored_packages.pluggy.PluginValidationError: unknown hook 'pytest_django' in plugin <module 'conftest' from '/path/to/my/conftest.py'>
Run Code Online (Sandbox Code Playgroud)

pytest-django

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

在 pytest-django 中每次测试后都会清理数据库

我正在努力实现什么目标。
我正在 Django 项目中测试 REST API。我想创建具有相关测试函数的测试类(以下每个测试函数都依赖于前一个测试函数) - 第一次失败意味着全部失败。在第一个测试函数中,我使用“post”请求创建了一个对象。在下一个测试用例中,我想使用“get”请求检查该对象是否确实存在。

它是如何工作的
看起来 Django-pytest 在每次测试后都会清除数据库中的所有记录。
pytest文档中提到:https://pytest-django.readthedocs.io/en/latest/helpers.html#pytest-mark-django-db-request-database-access
有什么办法可以改变这个吗?

我的代码:
我的conftest.py

import pytest


@pytest.fixture(scope='session')
def django_db_setup():
    from django.conf import settings
    settings.DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db_name.sqlite3',
    }


@pytest.fixture
def object_data():
    return {"some keys": "some values"}


@pytest.fixture
def object_name():
    return "some name"
Run Code Online (Sandbox Code Playgroud)

我的tests.py

import pytest

from rest_framework.test import APIClient
from rest_framework import status


@pytest.mark.django_db
class TestAPI:
    def setup(self):
        self.client = APIClient()

    def test_create_object(self, object_data, object_name):
        post_response = self.client.post("/api/object/", data=object_data, format="json") …
Run Code Online (Sandbox Code Playgroud)

python django-rest-framework pytest-django

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

使用特定 IP 的 Django REST 客户端测试

Django REST 文档从读取地址META。所以我必须创建Whitelist模型来存储它的 IP 地址/子网。没什么大不了的,302我的数据库中已经有了所有子网。

from rest_framework import permissions

class BlacklistPermission(permissions.BasePermission):
    """
    Global permission check for blacklisted IPs.
    """

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()
        return not blacklisted
Run Code Online (Sandbox Code Playgroud)

问题:
我想从其他 IP 地址测试白名单,而不是127.0.0.1
如何在 中做到这一点pytest

python django django-rest-framework pytest-django

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

Pytest 装置跳过测试

我有这个工厂如图:


@pytest.fixture
def user_factory(db):
    def create_app_user(
            username: str,
            password: str = None,
            first_name: str = "firstname",
            last_name: str = "lastname",
            email: str = "user@g.com",
            is_staff: str = False,
            is_superuser: str = False,
            is_active: str = True
    ):
        user_f = User.objects.create_user(
            username = username,
            password = password,
            first_name = first_name,
            last_name = last_name,
            email = email,
            is_staff = is_staff,
            is_superuser = is_superuser,
            is_active = is_active
        )
        return user_f
    return create_app_user


@pytest.fixture
def new_user(db, user_factory):
    return user_factory("myusername", "mypassword", "myfirstname")

Run Code Online (Sandbox Code Playgroud)

我尝试使用工厂来运行位于 test_name.py 文件中的测试: …

python pytest pytest-django pytest-fixtures

0
推荐指数
1
解决办法
32
查看次数