Django LiveServerTestCase: setUpClass 方法中创建的用户在 test_method 中不可用?

13 投票
3 回答
4817 浏览
提问于 2025-04-17 16:31

我正在使用Django 1.4的LiveServerTestCase来进行Selenium测试,但在使用setUpClass这个类方法时遇到了问题。根据我的理解,MembershipTests.setUpClass是在所有单元测试运行之前只执行一次。

我把添加用户到数据库的代码放在了MembershipTests.setUpClass里,但当我运行MembershipTests.test_signup这个测试时,发现测试数据库里没有添加任何用户。我哪里做错了呢?我本以为在setUpClass里创建的用户可以在所有单元测试中都能用。

如果我把用户创建的代码放在MembershipTests.setUp里,然后运行MembershipTests.test_signup,我就能看到这个用户,但我不想在每个单元测试之前都执行这个,因为setUp就是这样工作的。正如你所看到的,我使用了一个自定义的LiveServerTestCase类,以便在我所有的测试中添加基本功能(test_utils.CustomLiveTestCase)。我怀疑这和我的问题有关。

提前谢谢你。

test_utils.py:

from selenium.webdriver.firefox.webdriver import WebDriver
from django.test import LiveServerTestCase

class CustomLiveTestCase(LiveServerTestCase):

    @classmethod
    def setUpClass(cls):
        cls.wd = WebDriver()
        super(CustomLiveTestCase, cls).setUpClass()

    @classmethod
    def tearDownClass(cls):
        cls.wd.quit()
        super(CustomLiveTestCase, cls).tearDownClass()

tests.py:

from django.contrib.auth.models import User
from django.test.utils import override_settings
from test_utils import CustomLiveTestCase 
from test_constants import *

@override_settings(STRIPE_SECRET_KEY='xxx', STRIPE_PUBLISHABLE_KEY='xxx')
class MembershipTests(CustomLiveTestCase):

    fixtures = [
        'account_extras/fixtures/test_socialapp_data.json',
        'membership/fixtures/basic/plan.json',
    ]

    def setUp(self):
        pass

    @classmethod
    def setUpClass(cls):
        super(MembershipTests, cls).setUpClass()
        user = User.objects.create_user(
            TEST_USER_USERNAME,
            TEST_USER_EMAIL,
            TEST_USER_PASSWORD
        )

    def test_signup(self):
        print "users: ", User.objects.all()

3 个回答

2

你可以像下面这样使用 TestCase.setUpTestData(对你的基础类做一些小改动):

test_utils.py:

from selenium.webdriver.firefox.webdriver import WebDriver
from django.test import LiveServerTestCase, TestCase

class CustomLiveTestCase(LiveServerTestCase, TestCase):

    @classmethod
    def setUpClass(cls):
        cls.wd = WebDriver()
        super(CustomLiveTestCase, cls).setUpClass()

    @classmethod
    def tearDownClass(cls):
        cls.wd.quit()
        super(CustomLiveTestCase, cls).tearDownClass()

tests.py:

from django.contrib.auth.models import User
from django.test.utils import override_settings
from test_utils import CustomLiveTestCase
from test_constants import *

@override_settings(STRIPE_SECRET_KEY='xxx', STRIPE_PUBLISHABLE_KEY='xxx')
class MembershipTests(CustomLiveTestCase):

    fixtures = [
        'account_extras/fixtures/test_socialapp_data.json',
        'membership/fixtures/basic/plan.json',
    ]

    @classmethod
    def setUpTestData(cls):
        super(MembershipTests, cls).setUpTestData()
        user = User.objects.create_user(
            TEST_USER_USERNAME,
            TEST_USER_EMAIL,
            TEST_USER_PASSWORD
        )

    def test_signup(self):
        print "users: ", User.objects.all()

如果不想改基础类,你也可以在 MembershipTests 中继承 TestCase,但每次需要测试数据的时候都得这样做。

注意,我还去掉了 def setUp: pass,因为这样会影响事务处理。

想了解更多细节,可以看看这个讨论串: https://groups.google.com/forum/#!topic/django-developers/sr3gnsc8gig

如果你在这个解决方案上遇到任何问题,随时告诉我!

17

每次测试方法运行时,数据库都会被清空并重新加载,而不是在整个测试类运行时。这样一来,你的用户数据每次都会丢失。应该在 setUp 方法里做这个,而不是在 setUpClass 方法里。

14

因为你正在使用 LiveServerTestCase,它和 TransactionTestCase 很像,都是在每次测试时都会创建和销毁数据库(清空表格)。

所以,使用 LiveServerTestCase 的话,你实际上是不能使用全局数据的。

撰写回答