Django 模块化测试

标签 django django-testing

我现在有一个“不错”的测试套件,但我想改进它。发生的情况是,我必须重复设置(例如限制模型)用户、属性(property)、学校和城市对象。

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

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', '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="76050217101036111b171f1a5815191b" rel="noreferrer noopener nofollow">[email protected]</a>', 'testpassword')
        self.staff_user.is_staff = True
        self.staff_user.save()

        self.user = User.objects.create_user('user', '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3540465047755258545c591b565a58" rel="noreferrer noopener nofollow">[email protected]</a>', '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 中包含诸如用户、学校、公司之类的内容。

这个 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', '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="11626570777751767c70787d3f727e7c" rel="noreferrer noopener nofollow">[email protected]</a>', 'testpassword')
        self.staff_user.is_staff = True
        self.staff_user.save()

        self.user = User.objects.create_user('user', '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4431372136042329252d286a272b29" rel="noreferrer noopener nofollow">[email protected]</a>', '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'

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

我相信我的问题在于 setUp 函数的继承。我不确定如何正确继承(通过 super,还是通过其他方式?)。我尝试过使用 super 但无法让它工作。我必须承认,我对类/混合还不是那么擅长,所以任何帮助/指示将不胜感激。

最佳答案

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

  1. https://pypi.python.org/pypi/django-webtest
  2. https://github.com/rbarrois/factory_boy

逐步进行更改:

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

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

与:

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

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

    self.staff_user = User.objects.create_user('staff_user', '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0b3b4a1a6a680a7ada1a9aceea3afad" rel="noreferrer noopener nofollow">[email protected]</a>', '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)

完成所有这些后,您的代码将变得更短且更易于阅读。你根本不需要这些 mixin。例如你的 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

关于Django 模块化测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27670121/

相关文章:

python - Pillow virtualenv 安装失败 : "command ' gcc-4. 2' failed"

django - 摆脱 django testsuite 中的空 models.py

django - 如何使用 django 测试系统测试 EmailMultiAlternatives 对象中的替代正文内容?

Django 测试 : increase testsRun counter

python - 在 Django 中的 Linode Ubuntu 21.10 上运行的 Apache 2 出现 403 错误

python - 使用登录的用户名作为 django 中的字段值

Django 固定装置和 auto_now_add 日期时间字段

python - 使用 apache 和 mod_wsgi 提供静态文件而不更改 apache 的配置?

django-testing - 如何测试 Django 表单集提交

Django 测试使用现有数据库