简体   繁体   中英

pytest-django object not being persisted in test database

I am using pytest with pytest-django and pytest-bdd to test a simple django application. The settings file defines a test sqlite3 database, which is created when the tests are run. My first function creates a model object:

@given("A message exists")
def given_a_message_exists(transactional_db, message_text):
    message = message_models.Message(text=message_text)
    message.save()

But although I can open and inspect the database using sql-browser, the model is never persisted to the database. I can, in my next function, obtain the message from the django ORM, but the message isn't persisted in the database, and a call to a url route to delete the message returns a 404 with 'Message not found matching the query'.

@when("User visits the delete message page", target_fixture="page")
def user_visits_delete_message_page(transactional_db, browser, message_text):
    message = message_models.Message.objects.get(text=message_text)
    url = f"{browser.domain}/delete_message/{message.id}/{message.slug}/"
    browser.visit(url)
    return browser

When I run the site normally, everything works as expected.

Here are the fixtures from my conftest.py...

MESSAGE_TEXT = "Ipsum Lorum Dolum Est"

CREATE_MESSAGE_URL = reverse("django_messages:message_create")
LIST_MESSAGE_URL = reverse("django_messages:message_list")

LINKS_DICT = {
    "create_message": f"a[href='{CREATE_MESSAGE_URL}']",
    "list_message": f"a[href='{LIST_MESSAGE_URL}']",
}

PAGES_DICT = {
    "create_message": CREATE_MESSAGE_URL,
    "list_message": LIST_MESSAGE_URL,
}


@pytest.fixture()
def message_text():
    return MESSAGE_TEXT


@pytest.fixture()
def browser(sb, live_server, settings):
    staging_server = os.environ.get("STAGING_SERVER")
    if staging_server:
        sb.visit(staging_server)
    else:
        sb.visit(live_server)
    sb.domain = sb.get_domain_url(sb.get_current_url())
    settings.EMAIL_PAGE_DOMAIN = sb.domain
    sb.pages = PAGES_DICT
    sb.links = LINKS_DICT
    return sb

Why is the model not persisted to the database when I call message.save() ?

btw, I have tried, transactional_db, and db, along with a whole host of other permutations...

It turns out that using the browser fixture causes a problem that I don't fully understand yet. If I pass the browser into a step, and then return it as a target_fixture for later functions to consume then everything works as expected.

[EDIT] I discovered that if I define the browser in a fixture, that I must have referenced that browser fixture before or at the same time as the django object using it, or the browser refers to a different domain. So, in the below, even though the message is created in a fixture (test_message), I must refer to it having referenced the browser. If the function message_exists is not passed 'browser', then the message is not listed on the message_list page.

def message_exists(browser, test_message):
    test_message.save()
    return test_message


@when("User visits the message list page", target_fixture="page")
def user_visits_messages_page(db, browser):
    browser.visit(browser.domain + browser.pages["list_message"])
    return browser


@then("The message is listed")
def message_is_listed(message, page):
    page.assert_element(f"a[href='/{message.id}/{message.slug}/']")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM