我正在使用 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 测试客户端文档,但没有找到太多内容。我可能会错过什么?
我构建了包含许多应用程序的 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 是否有办法用一个简单的表达式指定所有应用程序?
我使用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) 我正在尝试使用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) 在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上的文档在重定向上没有任何内容。谢谢。
这个问题与这个问题直接相关,但那个现在似乎已经过时了。
我正在尝试测试视图而无需访问数据库。为此,我需要对RelatedManager用户进行模拟。
我正在使用pytest和pytest-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
由于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
我里面有以下内容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项目编写测试用例,但是当我运行"$ ./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) 我希望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) 我正在努力实现什么目标。
我正在 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) 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?
我有这个工厂如图:
@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 文件中的测试: …
pytest-django ×13
django ×9
pytest ×8
python ×5
coverage.py ×1
python-mock ×1
selenium ×1
unit-testing ×1