3

我最近从 Django 的 TestCase 类切换到第三方 pytest 系统。这使我能够显着加快我的测试套件的速度(提高了 5 倍),并且总体而言是一次很棒的体验。

我确实有硒的问题。我制作了一个简单的夹具,将浏览器包含在我的测试中

@pytest.yield_fixture
def browser(live_server, transactional_db, admin_user):
    driver_ = webdriver.Firefox()
    driver_.server_url = live_server.url
    driver_.implicitly_wait(3)
    yield driver_
    driver_.quit()

但由于某种原因,数据库在测试之间没有正确重置。我有一个类似的测试

class TestCase:
    def test_some_unittest(db):
        # Create some items
        #...

    def test_with_selenium(browser):
        # The items from the above testcase exists in this testcase

中创建的对象test_some_unittest存在于 中test_with_selenium。我不确定如何解决这个问题。

4

2 回答 2

2

从 django.test.TestCase 切换到 pytest 意味着使用 pytest-django 插件,您的测试应该如下所示:


class TestSomething(object):
    def setup_method(self, method):
        pass

    @pytest.mark.django_db
    def test_something_with_dg(self):
       assert True

这首先意味着没有 django.test.TestCase (这是从 python std unittest 框架的派生)继承。

@pytest.mark.django_db 表示您的测试用例将在一个事务中运行,一旦测试用例结束,该事务将回滚。

django_db 标记的第一次出现也会触发 django 迁移。

请注意在特殊的 pytest 方法(例如 setup_method)中使用数据库调用,因为它不受支持且存在其他问题:

django-pytest setup_method 数据库问题

于 2015-12-07T15:37:50.230 回答
1
def _django_db_fixture_helper(transactional, request, _django_cursor_wrapper):
    if is_django_unittest(request):
        return

    if transactional:
        _django_cursor_wrapper.enable()

        def flushdb():
            """Flush the database and close database connections"""
            # Django does this by default *before* each test
            # instead of after.
            from django.db import connections
            from django.core.management import call_command

            for db in connections:
                call_command('flush', verbosity=0,
                             interactive=False, database=db)
            for conn in connections.all():
                conn.close()

        request.addfinalizer(_django_cursor_wrapper.disable)
        request.addfinalizer(flushdb)
    else:
        if 'live_server' in request.funcargnames:
            return
        from django.test import TestCase

        _django_cursor_wrapper.enable()
        _django_cursor_wrapper._is_transactional = False
        case = TestCase(methodName='__init__')
        case._pre_setup()
        request.addfinalizer(_django_cursor_wrapper.disable)
        request.addfinalizer(case._post_teardown)

正如我看到你使用 pytest-django (这很好)从它的这段代码中,如果它是非事务性数据库,它不会刷新数据库。因此,在您的“其他”测试中,您必须使用 transactional_db,然后它将根据您的需要被隔离。

所以你的代码看起来像:

class TestCase:
    def test_some_unittest(transactional_db):
        # Create some items
        #...

    def test_with_selenium(browser):
        # The items from the above testcase does not exist in this testcase

然而,对 pytest-django 的改进可能是在fixture 值的yield 之前而不是之后执行刷新,这更有意义。拆解中的内容并不重要,重要的是设置是否正确。作为一个建议,对于浏览器夹具,您可以使用 pytest-splinter 插件

于 2015-08-12T09:02:42.813 回答