Как сохранить данные django db в середине теста плейсхолдера?

Я не могу понять, как вызвать "синхронизацию" create_user().

Сообщение об ошибке:

django.core.exceptions.SynchronousOnlyOperation: 
You cannot call this from an async context - use a thread or sync_to_async.

Однако, когда я использую sync_to_async, она не может быть ожидаемой, потому что это не асинхронная функция...

from functools import wraps

from django.test import TestCase
from playwright.sync_api import sync_playwright


def playwright_test(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        with sync_playwright() as self.p:
            self.browser = self.p.chromium.launch()
            self.page = self.browser.new_page()
            try:
                result = func(self, *args, **kwargs)
            finally:
                self.browser.close()
            return result

    return wrapper


class TC(TestCase):
    @playwright_test
    def test_login(self):
        self.page.goto(self.host)
        self.page.fill('input[type="email"]', 'my@email.com')
        self.page.fill('input[type="password"]', 'TestLogin')
        self.page.click('text="Login"')
        # expect "Incorrect Credentials" message (no user created yet)
        assert "Incorrect Credentials" in self.page.content()

        User = get_user_model()
        User.objects.create_user('my@email.com', password='TestLogin')

        # Login again, this time successfully
        self.page.fill('input[type="email"]', 'my@email.com')
        self.page.fill('input[type="password"]', 'TestLogin')
        self.page.click('text="Login"')
        assert "Login successful. Welcome back!" in self.page.content()

Если у вас есть предложение, пожалуйста, дайте мне знать, мои волосы начинают выпадать. 🙏

Вы можете избежать сообщения об ошибке следующим образом:

Возможно, этого будет достаточно, чтобы вы могли продолжить (я использую это обходное решение практически везде).


Что касается самого теста, вы можете попробовать что-то вроде этого:

Выполните два теста: один, где пользователь не был создан, и один, где он был создан (через приспособление create_user).

# conftest.py

# https://github.com/microsoft/playwright-python/issues/439
# https://github.com/microsoft/playwright-pytest/issues/29#issuecomment-731515676
os.environ.setdefault("DJANGO_ALLOW_ASYNC_UNSAFE", "true")
# test_login.py
import pytest
from django.contrib.auth import get_user_model


@pytest.fixture
def user_email():
    return "my@email.com"


@pytest.fixture
def user_password():
    return "TestLogin"


@pytest.fixture
def create_user(user_email, user_password):
    return get_user_model().objects.create_user(user_email, password=user_password)


@pytest.fixture
def host():
    return "?"


class TestLogin:
    def test_login_fail_no_user(self, page, host, user_email, user_password):
        page.goto(host)
        page.fill('input[type="email"]', user_email)
        page.fill('input[type="password"]', user_password)
        page.click('text="Login"')
        # expect "Incorrect Credentials" message (no user created yet)
        assert "Incorrect Credentials" in page.content()

    def test_login_success(self, create_user, page, host, user_email, user_password):
        page.goto(host)
        page.fill('input[type="email"]', user_email)
        page.fill('input[type="password"]', user_password)
        page.click('text="Login"')
        # Login again, this time successfully
        assert "Login successful. Welcome back!" in page.content()

Или немного больше DRY:

@pytest.fixture
def try_login(page, host, user_email, user_password):
    page.goto(host)
    page.fill('input[type="email"]', user_email)
    page.fill('input[type="password"]', user_password)
    page.click('text="Login"')
    return page


class TestLogin:
    def test_login_fail_no_user(self, page, try_login):
        # expect "Incorrect Credentials" message (no user created yet)
        assert "Incorrect Credentials" in page.content()

    def test_login_success(self, create_user, page, try_login):
        # Login again, this time successfully
        assert "Login successful. Welcome back!" in page.content()

Как щедро написал @CoffeeBasedLifeform в https://stackoverflow.com/a/78651148/1031191 , для django решением будет https://github.com/microsoft/playwright-pytest/issues/29#issuecomment-731515676

Копирование содержимого ссылки сюда:

Для запуска тестов Django с помощью playwright необходимо установить переменную окружения переменную DJANGO_ALLOW_ASYNC_UNSAFE = "true" django docs on this
. Это можно сделать следующим образом создав файл conftest.py в каталоге tests и установив переменную переменную окружения, используя

# conftest.py import os 
os.environ.setdefault("DJANGO_ALLOW_ASYNC_UNSAFE","true")
Вернуться на верх