Django模块测试

Django模块测试,django,django-testing,Django,Django Testing,我现在有一个不错的测试套件,但我想改进它。发生的事情是,我必须重复设置一个示例用户、财产、学校和城市对象的限制模型 下面是一个我现在拥有的东西的例子,它可以工作注意:可能会因为简化这个例子而被破坏,但逻辑是我想要的: class MainTestSetup(TestCase): def setUp(self): self.manage_text = 'Manage' User = get_user_model() # set up al

我现在有一个不错的测试套件,但我想改进它。发生的事情是,我必须重复设置一个示例用户、财产、学校和城市对象的限制模型

下面是一个我现在拥有的东西的例子,它可以工作注意:可能会因为简化这个例子而被破坏,但逻辑是我想要的:

class MainTestSetup(TestCase):
    def setUp(self):
        self.manage_text = 'Manage'

        User = get_user_model()

        # set up all types of users to be used
        self.staff_user = User.objects.create_user('staff_user', 'staff@gmail.com', 'testpassword')
        self.staff_user.is_staff = True
        self.staff_user.save()

        self.user = User.objects.create_user('user', 'user@gmail.com', 'testpassword')

        self.city = City.objects.create(name="Test Town", state="TX")
        self.school = School.objects.create(city=self.city, name="RE Test University",
                        long=-97.1234123, lat=45.7801234)
        self.company = Company.objects.create(name="Test Company", default_school=self.school)

    def login(self):
        self.client.login(username=self.user.username, 
            password='testpassword')

    def login_admin(self):
        self.client.login(username=self.staff_user, password="testpassword")


class MainViewTests(MainTestSetup):
    def test_home(self):
        url = reverse('home-list')
        manage_url = reverse('manage-property')

        anon_response = self.client.get(url)
        self.assertEqual(anon_response.status_code, 200)
        self.assertNotContains(anon_response, self.manage_text)

        self.login_admin()
        admin_response = self.client.get(url)
        self.assertContains(admin_response, self.manage_text)

    def test_search(self):
        url = reverse('search')
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

    ...more tests
正如您所见,MainViewTest从MainTestSetup类继承了设置和登录函数。这工作正常,但我有很多应用程序,并不是所有的都需要设置所有的模型。我试着做的是设置一组混音,只在我需要的测试设置中包含像用户、学校、公司这样的东西

此MainTestSetup将转变为以下内容:

class SchoolMixin(object):
    def setUp(self):
        self.city = City.objects.create(name="Test Town", state="TX")
        self.school = School.objects.create(city=self.city, name="RE Test University",
                        long=-97.1234123, lat=45.7801234)


class CompanyMixin(SchoolMixin):
    def setUp(self):
        self.company = Company.objects.create(name="Test Company", default_school=self.school)


class UserMixin(object):
    def setUp(self):
        User = get_user_model()

        # set up all types of users to be used
        self.staff_user = User.objects.create_user('staff_user', 'staff@gmail.com', 'testpassword')
        self.staff_user.is_staff = True
        self.staff_user.save()

        self.user = User.objects.create_user('user', 'user@gmail.com', 'testpassword')

    def login(self):
        self.client.login(username=self.user.username, 
            password='testpassword')

    def login_admin(self):
        self.client.login(username=self.staff_user, password="testpassword")


class MainTestSetup(UserMixin, CompanyMixin, TestCase):
    def setUp(self):
        self.manage_text = 'Manage'
这将为我的测试套件提供更多的灵活性——这只是一个小例子。它将允许我在其他应用程序中只包含必要的混音。例如,如果不需要公司,我将只包括上面示例中的SchoolMixin


我认为我的问题在于设置函数的固有性。我不知道如何通过super或其他方式正确继承?。我试过使用super,但没能让它工作。我必须承认,我对类/混合还不是很在行,所以任何帮助/指针都将不胜感激。

您可以通过使用两个库来简化和减少代码量:WebTest和FactoryBoy。你不需要这些混合物

逐步进行更改:

一,。从WebTest开始,这样您就可以摆脱登录方法,而无需准备密码。使用WebTest,您可以在加载页面时指定登录用户。例如,您将替换:

self.login_admin()
admin_response = self.client.get(url)
    self.staff_user = User.objects.create_user('staff_user', 'staff@gmail.com', 'testpassword')
    self.staff_user.is_staff = True
    self.staff_user.save()
与:

admin_response = = self.app.get(url, user=self.admin)
二,。然后使用factory_boy创建所需的所有对象。例如,您将替换:

self.login_admin()
admin_response = self.client.get(url)
    self.staff_user = User.objects.create_user('staff_user', 'staff@gmail.com', 'testpassword')
    self.staff_user.is_staff = True
    self.staff_user.save()
与:

三,。把它弄混。摆脱self.admin。替换为:

    admin = AdminFactory.create()
    response = = self.app.get(url, user=admin)
一旦您完成了所有这些,您的代码将变得更短,更易于阅读。你根本不需要这些混合物。例如,您的SchoolMixin可以这样替换:

    self.city = City.objects.create(name="Test Town", state="TX")
    self.school = School.objects.create(city=self.city, name="RE Test University",
                    long=-97.1234123, lat=45.7801234)
替换为:

    school = SchoolFactory.create()
这是因为工厂可以自动创建与子工厂相关的实体


下面是一个使用工厂进行测试的非常简单的完整示例:

保持单元测试的简单性通常比高效性或灵活性更重要,当然,在某种程度上,这听起来像是在尝试完成与py.test fixture非常相似的事情。如果你想用Django试试py.test,我建议你试试pytest Django.beauty,这正是我想要的。谢谢