在 Python/Django 测试中使用 class 使代码更可重用

Using class in Python/Django testing to make code more reusable

我的测试架构需要一些帮助。我的代码有效,但对我来说似乎很难看。你能看看吗:

目标是在 Django 中对我的所有页面进行相同的测试:

我写了一个单元testing.py

from django.urls import reverse, resolve

class SinglePageTest(object):
    str_reverse = ''
    adresse = ''
    template = None
    template_path = ''
    str_contain = ''

    def initialize(self):
        self.url = reverse(self.str_reverse)
        self.view = resolve(self.adresse)
        self.response = self.client.get(self.url)

    def test_status_200(self):
        self.assertEqual(self.response.status_code, 200)

    def test_templates_home(self):
        self.assertTemplateUsed(self.response, self.template_path)

    def test_contains_HTML(self):
        self.assertContains(self.response,
                            self.str_contain)

    def test_url_resolve(self):
        self.assertEqual(self.view.func.__name__,
                         self.template.as_view().__name__)

当我需要在 test.py 中测试一个页面时,我会这样做:

from django.test import TestCase, SimpleTestCase
from DjangoTools.testing import SinglePageTest

class RetrievePassword(SimpleTestCase, SinglePageTest):
    def setUp(self):
        self.str_reverse = 'retrieve-password'
        self.adresse = '/accounts/retrieve-password'
        self.template = RetrievePasswordView
        self.template_path = 'accounts/retrieve-password.html'
        self.str_contain = '<h1> Récupérer le <span class="clr-org">mot de passe</span></h1>'
        super(RetrievePassword, self).setUp()
        SinglePageTest.initialize(self)

问题是 PyCharm 在 testing.py 中找不到很多方法的引用,这是正常的,因为我使用的是不包含这些方法的基本对象。

我的问题是:

  1. 这样做好吗?
  2. 我能说我在使用 Mixins 吗?
  3. 如何告诉pycharm找到assertTemplateUsedclient.get等等...

祝你有愉快的一天,


使用提供的解决方案后,unittest 正在尝试测试 testing.py class


问题解决方法:添加到基础class

def setUp(self):
    if self.__class__ is BaseSinglePageTest:
        raise SkipTest("%s is an abstract base class" % self.__class__)
    else:
        super(BaseSinglePageTest, self).setUp()

在这种情况下,线性继承应该可以很好地工作,而不是创建混合。

SimpleTestCase <- SinglePageTest <- RetrievePassword
from django.urls import reverse, resolve

class BaseSinglePageTest(SimpleTestCase):
    str_reverse = ''
    adresse = ''
    template = None
    template_path = ''
    str_contain = ''

    def initialize(self):
        self.url = reverse(self.str_reverse)
        self.view = resolve(self.adresse)
        self.response = self.client.get(self.url)

    def test_status_200(self):
        self.assertEqual(self.response.status_code, 200)

    def test_templates_home(self):
        self.assertTemplateUsed(self.response, self.template_path)

    def test_contains_HTML(self):
        self.assertContains(self.response,
                            self.str_contain)

    def test_url_resolve(self):
        self.assertEqual(self.view.func.__name__,
                         self.template.as_view().__name__)

然后像这样使用这个 class

from django.test import TestCase, SimpleTestCase
from DjangoTools.testing import SinglePageTest

class RetrievePassword(BaseSinglePageTest):
    def setUp(self):
        self.str_reverse = 'retrieve-password'
        self.adresse = '/accounts/retrieve-password'
        self.template = RetrievePasswordView
        self.template_path = 'accounts/retrieve-password.html'
        self.str_contain = '<h1> Récupérer le <span class="clr-org">mot de passe</span></h1>'
        super(RetrievePassword, self).setUp()
        SinglePageTest.initialize(self)

testing.py

从 django.test 导入 SimpleTestCase from django.urls import reverse, resolve 从单元测试导入 SkipTest

class BaseSinglePageTest(SimpleTestCase):
    str_reverse = ''
    adresse = ''
    template = None
    template_path = ''
    str_contain = ''

    def setUp(self):
        if self.__class__ is BaseSinglePageTest:
            raise SkipTest("%s is an abstract base class" % self.__class__)
        else:
            super(BaseSinglePageTest, self).setUp()

    def initialize(self):
        self.url = reverse(self.str_reverse)
        self.view = resolve(self.adresse)
        self.response = self.client.get(self.url)

    def test_status_200(self):
        self.assertEqual(self.response.status_code, 200)

    def test_templates_home(self):
        self.assertTemplateUsed(self.response, self.template_path)

    def test_contains_HTML(self):
        self.assertContains(self.response,
                            self.str_contain)

    def test_url_resolve(self):
        self.assertEqual(self.view.func.__name__,
                         self.template.as_view().__name__)

test.py

from django.contrib.auth import get_user_model, authenticate

from DjangoTools.tool_test import BaseSinglePageTest

class RetrievePassword(BaseSinglePageTest):
    def setUp(self):
        self.str_reverse = 'retrieve-password'
        self.adresse = '/accounts/retrieve-password'
        self.template = RetrievePasswordView
        self.template_path = 'accounts/retrieve-password.html'
        self.str_contain = '<h1> Récupérer le <span class="clr-org">mot de passe</span></h1>'
        super(RetrievePassword, self).setUp()
        BaseSinglePageTest.initialize(self)