Django模块化测试

时间:2014-12-27 18:15:57

标签: django django-testing

我现在有一个“确定”的测试套件,但我想改进它。会发生什么事情,我不得不重复设置(限制一个例子的模型)用户,财产,学校和城市对象。

这是我现在所拥有的一个例子,它可以工作(注意:由于为简化示例所做的更改,可能会被破坏,但逻辑就是我所追求的):

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类中的setUp和login函数。这项工作正常,但我有很多应用程序,并不是都需要设置所有模型。我试图做的是设置一组mixin,仅在我需要的TestSetups中包含User,School,Company等内容。

这个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'

这将为我的测试套件提供更大的灵活性 - 这只是一个小例子。它允许我在其他应用程序中只包含必要的Mixins。例如,如果不需要公司,我将仅包括上述示例中的SchoolMixin。

我相信我的问题在于setUp函数的存在。我不确定如何正确地继承(通过超级,或者其他东西?)。我尝试使用超级但未能使它工作。我不得不承认,我对类/ mixin的关注度不是很高,所以任何帮助/指针都会非常感激。

1 个答案:

答案 0 :(得分:3)

您可以使用2个库来简化和减少代码量:WebTest和FactoryBoy。你不会需要这些Mixins。

  1. https://pypi.python.org/pypi/django-webtest
  2. https://github.com/rbarrois/factory_boy
  3. 逐步进行更改:

    1。从WebTest开始,这样您就可以摆脱login_方法(并且您也不需要准备密码)。使用WebTest,您可以在加载页面时指定登录用户。例如,您将替换:

    self.login_admin()
    admin_response = self.client.get(url)
    

    with:

    admin_response = = self.app.get(url, user=self.admin)
    

    2. 然后使用factory_boy创建您需要的所有对象。例如,您将替换:

        self.staff_user = User.objects.create_user('staff_user', 'staff@gmail.com', 'testpassword')
        self.staff_user.is_staff = True
        self.staff_user.save()
    

    使用:

        self.staff_user = StaffFactory.create()
    

    3。混合起来。摆脱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()
    

    那是因为工厂可以使用" SubFactories"自动创建相关实体。

    以下是使用工厂进行测试的完整非常简单的示例:http://codeku.co/testing-in-django-1