Django4.0 測(cè)試工具-測(cè)試用例特性

2022-03-17 11:32 更新

默認(rèn)測(cè)試客戶端

SimpleTestCase.client

?django.test.*TestCase? 實(shí)例中的每個(gè)測(cè)試用例都可以訪問(wèn)一個(gè) Django 測(cè)試客戶端的實(shí)例。這個(gè)客戶端可以用 ?self.client? 來(lái)訪問(wèn)。這個(gè)客戶端在每個(gè)測(cè)試中都會(huì)被重新創(chuàng)建,所以你不必?fù)?dān)心狀態(tài)(比如 cookie)會(huì)從一個(gè)測(cè)試轉(zhuǎn)移到另一個(gè)測(cè)試中。
這意味著,不必每個(gè)測(cè)試中實(shí)例化一個(gè) Client:

import unittest
from django.test import Client

class SimpleTest(unittest.TestCase):
    def test_details(self):
        client = Client()
        response = client.get('/customer/details/')
        self.assertEqual(response.status_code, 200)

    def test_index(self):
        client = Client()
        response = client.get('/customer/index/')
        self.assertEqual(response.status_code, 200)

你也可以引用 ?self.client?,像這樣:

from django.test import TestCase

class SimpleTest(TestCase):
    def test_details(self):
        response = self.client.get('/customer/details/')
        self.assertEqual(response.status_code, 200)

    def test_index(self):
        response = self.client.get('/customer/index/')
        self.assertEqual(response.status_code, 200)

自定義測(cè)試客戶端

SimpleTestCase.client_class

如果你想使用不同的 Client 類(lèi)(例如,一個(gè)具有自定義行為的子類(lèi)),使用 ?client_class ?類(lèi)屬性:

from django.test import Client, TestCase

class MyTestClient(Client):
    # Specialized methods for your environment
    ...

class MyTest(TestCase):
    client_class = MyTestClient

    def test_my_stuff(self):
        # Here self.client is an instance of MyTestClient...
        call_some_test_code()

輔助工具加載

TransactionTestCase.fixtures

如果數(shù)據(jù)庫(kù)中沒(méi)有任何數(shù)據(jù),那么數(shù)據(jù)庫(kù)支持的網(wǎng)站的測(cè)試用例就沒(méi)什么用了。測(cè)試使用ORM創(chuàng)建對(duì)象更易讀,也更易維護(hù),例如在 ?TestCase.setUpTestData()? 中。但是,你也可以使用輔助工具。
輔助工具是 Django 知道如何導(dǎo)入數(shù)據(jù)庫(kù)的數(shù)據(jù)集合。例如,如果你的網(wǎng)站有用戶賬戶,你可能會(huì)設(shè)置一個(gè)假用戶賬戶的輔助工具,以便在測(cè)試時(shí)填充你的數(shù)據(jù)庫(kù)。
創(chuàng)建輔助工具的最直接方法是使用 ?manage.py dumpdata? 命令。這假定你已經(jīng)在你的數(shù)據(jù)庫(kù)中擁有一些數(shù)據(jù)。
一旦你創(chuàng)建了一個(gè)輔助工具,并把它放在你的 ?INSTALLED_APPS ?中的 ?fixtures ?目錄下,你就可以通過(guò)在你的 ?django.test.TestCase? 子類(lèi)上指定一個(gè) ?fixtures ?類(lèi)屬性來(lái)在你的單元測(cè)試中使用它。

from django.test import TestCase
from myapp.models import Animal

class AnimalTestCase(TestCase):
    fixtures = ['mammals.json', 'birds']

    def setUp(self):
        # Test definitions as before.
        call_setup_methods()

    def test_fluffy_animals(self):
        # A test that uses the fixtures.
        call_some_test_code()

具體來(lái)說(shuō),將發(fā)生以下情況:

  • 在每次測(cè)試開(kāi)始時(shí),在 ?setUp()? 運(yùn)行之前,Django 會(huì)對(duì)數(shù)據(jù)庫(kù)進(jìn)行刷新,將數(shù)據(jù)庫(kù)直接返回到 ?migrate ?被調(diào)用后的狀態(tài)。
  • 然后,所有命名的輔助工具都會(huì)被安裝。在這個(gè)例子中,Django 將安裝任何名為 ?mammals ?的 JSON 輔助工具,然后是任何名為 ?birds ?的輔助工具。

出于性能方面的考慮, ?TestCase ?在 ?setUpTestData()? 之前為整個(gè)測(cè)試類(lèi)加載一次輔助工具,而不是在每次測(cè)試之前加載,并且它在每次測(cè)試之前使用事務(wù)來(lái)清理數(shù)據(jù)庫(kù)。在任何情況下,你都可以確定一個(gè)測(cè)試的結(jié)果不會(huì)受到另一個(gè)測(cè)試或測(cè)試執(zhí)行順序的影響。
默認(rèn)情況下,輔助工具只被加載到 ?default ?數(shù)據(jù)庫(kù)中。如果你使用多個(gè)數(shù)據(jù)庫(kù)并且設(shè)置了 ?TransactionTestCase.databases?,輔助工具將被加載到所有指定的數(shù)據(jù)庫(kù)中。

URLconf配置

如果你的應(yīng)用程序提供了視圖,你可能希望包含使用測(cè)試客戶端來(lái)行使這些視圖的測(cè)試。然而,最終用戶可以自由地在他們選擇的任何 URL 上部署應(yīng)用程序中的視圖。這意味著你的測(cè)試不能依賴(lài)于你的視圖將在特定的 URL 上可用這一事實(shí)。用 ?@override_settings(ROOT_URLCONF=...)? 來(lái)裝飾你的測(cè)試類(lèi)或測(cè)試方法的 URLconf 配置。

多數(shù)據(jù)庫(kù)支持

TransactionTestCase.databases

Django 設(shè)置了一個(gè)測(cè)試數(shù)據(jù)庫(kù),對(duì)應(yīng)于你設(shè)置中的 ?DATABASES ?定義的并且至少有一個(gè)測(cè)試引用了 ?databases ?的每個(gè)數(shù)據(jù)庫(kù)。
然而,運(yùn)行一個(gè) Django ?TestCase ?所花費(fèi)的時(shí)間很大一部分是被調(diào)用 ?flush ?所消耗的,它確保了你在每次測(cè)試運(yùn)行開(kāi)始時(shí)有一個(gè)干凈的數(shù)據(jù)庫(kù)。如果你有多個(gè)數(shù)據(jù)庫(kù),就需要多次刷新(每個(gè)數(shù)據(jù)庫(kù)一個(gè)),這可能是一個(gè)耗時(shí)的活動(dòng)——特別是當(dāng)你的測(cè)試不需要測(cè)試多數(shù)據(jù)庫(kù)活動(dòng)時(shí)。
作為一種優(yōu)化,Django 只在每次測(cè)試運(yùn)行開(kāi)始時(shí)刷新 ?default ?數(shù)據(jù)庫(kù)。如果你的設(shè)置包含多個(gè)數(shù)據(jù)庫(kù),并且你的測(cè)試要求每個(gè)數(shù)據(jù)庫(kù)都是干凈的,你可以使用測(cè)試套件上的 ?databases ?屬性來(lái)請(qǐng)求額外的數(shù)據(jù)庫(kù)被刷新。
例如:

class TestMyViews(TransactionTestCase):
    databases = {'default', 'other'}

    def test_index_page_view(self):
        call_some_test_code()

這個(gè)測(cè)試用例將在運(yùn)行 ?test_index_page_view ?之前刷新 ?default ?和 ?other ?測(cè)試數(shù)據(jù)庫(kù)。你也可以使用 ?'__all__'? 來(lái)指定所有的測(cè)試數(shù)據(jù)庫(kù)必須被刷新。
?databases ?標(biāo)志也控制 ?TransactionTestCase.fixtures? 被加載到哪些數(shù)據(jù)庫(kù)。默認(rèn)情況下,輔助工具只被加載到 ?default ?數(shù)據(jù)庫(kù)中。
對(duì)不在 ?databases ?中的數(shù)據(jù)庫(kù)的查詢將給出斷言錯(cuò)誤,以防止測(cè)試之間的狀態(tài)泄露。

TestCase.databases

默認(rèn)情況下,在 ?TestCase ?期間,僅將 ?default ?數(shù)據(jù)庫(kù)包裝在事務(wù)中,并且嘗試查詢其他數(shù)據(jù)庫(kù)將導(dǎo)致斷言錯(cuò)誤,以防止測(cè)試之間的狀態(tài)泄漏。
在測(cè)試類(lèi)上使用 ?databases ?類(lèi)屬性來(lái)請(qǐng)求對(duì)非 ?default ?數(shù)據(jù)庫(kù)進(jìn)行事務(wù)包裝。
例如:

class OtherDBTests(TestCase):
    databases = {'other'}

    def test_other_db_query(self):
        ...

這個(gè)測(cè)試只允許對(duì) ?other ?數(shù)據(jù)庫(kù)進(jìn)行查詢。就像 ?SimpleTestCase.databases? 和 ?TransactionTestCase.databases? 一樣,?'__all__'? 常量可以用來(lái)指定測(cè)試應(yīng)該允許對(duì)所有數(shù)據(jù)庫(kù)進(jìn)行查詢。

覆蓋配置

警告

使用下面的函數(shù)可以臨時(shí)改變測(cè)試中的設(shè)置值。不要直接操作 ?django.conf.settings?,因?yàn)?Django 不會(huì)在這種操作后恢復(fù)原始值。

SimpleTestCase.settings()

為了測(cè)試的目的,經(jīng)常需要臨時(shí)改變一個(gè)設(shè)置,并在運(yùn)行測(cè)試代碼后恢復(fù)到原始值。對(duì)于這個(gè)用例,Django 提供了一個(gè)標(biāo)準(zhǔn)的 Python 上下文管理器(見(jiàn) PEP 343),叫做 ?settings()?,可以這樣使用:

from django.test import TestCase

class LoginTestCase(TestCase):

    def test_login(self):

        # First check for the default behavior
        response = self.client.get('/sekrit/')
        self.assertRedirects(response, '/accounts/login/?next=/sekrit/')

        # Then override the LOGIN_URL setting
        with self.settings(LOGIN_URL='/other/login/'):
            response = self.client.get('/sekrit/')
            self.assertRedirects(response, '/other/login/?next=/sekrit/')

此示例將覆蓋 ?with ?塊中代碼的 ?LOGIN_URL ?設(shè)置,然后將其值重置為先前的狀態(tài)。

SimpleTestCase.modify_settings()

重新定義包含一系列值的設(shè)置可能會(huì)很麻煩。在實(shí)踐中,添加或刪除值通常是足夠的。Django 提供了 ?modify_settings()? 上下文管理器,以方便更改設(shè)置:

from django.test import TestCase

class MiddlewareTestCase(TestCase):

    def test_cache_middleware(self):
        with self.modify_settings(MIDDLEWARE={
            'append': 'django.middleware.cache.FetchFromCacheMiddleware',
            'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
            'remove': [
                'django.contrib.sessions.middleware.SessionMiddleware',
                'django.contrib.auth.middleware.AuthenticationMiddleware',
                'django.contrib.messages.middleware.MessageMiddleware',
            ],
        }):
            response = self.client.get('/')
            # ...

對(duì)于每個(gè)操作,你可以提供一個(gè)值的列表或一個(gè)字符串。當(dāng)值已經(jīng)存在于列表中時(shí),?append ?和 ?prepend ?沒(méi)有效果;當(dāng)值不存在時(shí),?remove ?也沒(méi)有效果。

override_settings(**kwargs)

如果你想覆蓋一個(gè)測(cè)試方法的設(shè)置,Django 提供了 ?override_settings()? 裝飾器。它的用法是這樣的:

from django.test import TestCase, override_settings

class LoginTestCase(TestCase):

    @override_settings(LOGIN_URL='/other/login/')
    def test_login(self):
        response = self.client.get('/sekrit/')
        self.assertRedirects(response, '/other/login/?next=/sekrit/')

裝飾器也可以應(yīng)用于 ?TestCase ?類(lèi):

from django.test import TestCase, override_settings

@override_settings(LOGIN_URL='/other/login/')
class LoginTestCase(TestCase):

    def test_login(self):
        response = self.client.get('/sekrit/')
        self.assertRedirects(response, '/other/login/?next=/sekrit/')

modify_settings(*args, **kwargs)

同樣,Django 也提供了 ?modify_settings()? 裝飾器:

from django.test import TestCase, modify_settings

class MiddlewareTestCase(TestCase):

    @modify_settings(MIDDLEWARE={
        'append': 'django.middleware.cache.FetchFromCacheMiddleware',
        'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
    })
    def test_cache_middleware(self):
        response = self.client.get('/')
        # ...

此裝飾器也可以應(yīng)用于測(cè)試用例類(lèi):

from django.test import TestCase, modify_settings

@modify_settings(MIDDLEWARE={
    'append': 'django.middleware.cache.FetchFromCacheMiddleware',
    'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
})
class MiddlewareTestCase(TestCase):

    def test_cache_middleware(self):
        response = self.client.get('/')
        # ...

當(dāng)給定一個(gè)類(lèi)時(shí),這些裝飾器直接修改該類(lèi)并返回它,它們不會(huì)創(chuàng)建并返回一個(gè)修改后的副本。因此,如果你試圖調(diào)整上面的例子,將返回值分配給一個(gè)不同于 ?LoginTestCase? 或 ?MiddlewareTestCase ?的名稱(chēng),你可能會(huì)驚訝地發(fā)現(xiàn),原來(lái)的測(cè)試用例類(lèi)仍然同樣受到裝飾器的影響。對(duì)于一個(gè)給定的類(lèi),?modify_settings()? 總是應(yīng)用在 ?override_settings()? 之后。

配置文件中包含了一些設(shè)置,這些設(shè)置只有在 Django 內(nèi)部初始化時(shí)才會(huì)被使用。如果你用 ?override_settings ?改變它們,當(dāng)你通過(guò)?django.conf.settings?模塊訪問(wèn)會(huì)得到被改變的配置。但是,Django 的內(nèi)部程序訪問(wèn)它的方式是不同的。實(shí)際上,使用 ?override_settings()? 或者 ?modify_settings() ?來(lái)使用這些設(shè)置,很可能達(dá)不到你預(yù)期的效果。
我們不建議改變 ?DATABASES ?的設(shè)置。改變 ?CACHES ?的設(shè)置是可能的,但如果你使用的是內(nèi)部緩存,比如 ?django.contrib.session?,就有點(diǎn)棘手。例如,你必須在使用緩存會(huì)話并覆蓋 ?CACHES ?的測(cè)試中重新初始化會(huì)話后端。
最后,避免將你的配置別名為模塊級(jí)常量,因?yàn)??override_settings()? 不會(huì)對(duì)這些值起作用,它們只在第一次導(dǎo)入模塊時(shí)才被評(píng)估。

你也可以在配置被覆蓋后,通過(guò)刪除配置來(lái)模擬沒(méi)有配置,比如這樣:

@override_settings()
def test_something(self):
    del settings.LOGIN_URL
    ...

覆蓋配置時(shí),請(qǐng)確保處理你的應(yīng)用代碼使用即使保留配置更改也能保持狀態(tài)的緩存或類(lèi)似功能的情況。Django 提供了 ?django.test.signals.setting_changed? 信號(hào),讓你在設(shè)置被改變時(shí),可以注冊(cè)回調(diào)來(lái)清理和重置狀態(tài)。
Django 自己也使用這個(gè)信號(hào)來(lái)重置各種數(shù)據(jù)。

覆蓋配置 數(shù)據(jù)重置
USE_TZ,TIME_ZONE 數(shù)據(jù)庫(kù)時(shí)區(qū)
TEMPLATES 模板引擎
SERIALIZATION_MODULES 序列化器緩存
LOCALE_PATHS,LANGUAGE_CODE 默認(rèn)翻譯和加載的翻譯
MEDIA_ROOT,DEFAULT_FILE_STORAGE 默認(rèn)文件存儲(chǔ)

清空測(cè)試發(fā)件箱

如果你使用任何 Django 的自定義 ?TestCase ?類(lèi),測(cè)試運(yùn)行器將在每個(gè)測(cè)試用例開(kāi)始時(shí)清除測(cè)試郵件發(fā)件箱的內(nèi)容。

斷言

由于 Python 的普通 ?unittest.TestCase? 類(lèi)實(shí)現(xiàn)了 ?assertTrue()? 和 ?assertEqual()? 等斷言方法,Django 的自定義 TestCase 類(lèi)提供了許多對(duì)測(cè)試 Web 應(yīng)用程序有用的自定義斷言方法。

大多數(shù)這些斷言方法給出的失敗消息可以使用 ?msg_prefix ?參數(shù)進(jìn)行自定義。 該字符串將作為斷言生成的任何失敗消息的前綴。 這使您可以提供其他詳細(xì)信息,以幫助您確定測(cè)試套件中失敗的位置和原因。

  • ?SimpleTestCase.assertRaisesMessage(expected_exception, expected_message, callable, *args, **kwargs)?
  • ?SimpleTestCase.assertRaisesMessage(expected_exception, expected_message)?

斷言執(zhí)行 ?callable ?引起 ?expected_exception?,并且在異常信息中發(fā)現(xiàn) ?expected_message?。任何其他結(jié)果都會(huì)被報(bào)告為失敗。它是 ?unittest.TestCase.assertRaisesRegex()? 的簡(jiǎn)單版本,不同的是 ?expected_message? 不作為正則表達(dá)式處理。
如果只給了 ?expected_exception? 和 ?expected_message? 參數(shù),則返回一個(gè)上下文管理器,以便被測(cè)試的代碼可以內(nèi)聯(lián)而不是作為一個(gè)函數(shù)來(lái)寫(xiě):

with self.assertRaisesMessage(ValueError, 'invalid literal for int()'):
    int('a')
  • ?SimpleTestCase.assertWarnsMessage(expected_warning, expected_message, callable, *args, **kwargs)?
  • ?SimpleTestCase.assertWarnsMessage(expected_warning, expected_message)?

類(lèi)似于 ?SimpleTestCase.assertRaisesMessage()?,但是 ?assertWarnsRegex() ?代替 ?assertRaisesRegex()?。

SimpleTestCase.assertFieldOutput(fieldclass, valid, invalid, field_args=None, field_kwargs=None, empty_value='')

斷言表單字段在不同的輸入情況下表現(xiàn)正確。

參數(shù):

  • ?fieldclass ?-- 待測(cè)試字段的類(lèi)。
  • ?valid ?-- 一個(gè)字典,將有效輸入映射到它們的預(yù)期干凈值。
  • ?invalid ?-- 一個(gè)字典,將無(wú)效輸入映射到一個(gè)或多個(gè)引發(fā)的錯(cuò)誤信息
  • ?field_args ?-- 傳遞給實(shí)例化字段的 ?args?。
  • ?field_kwargs ?-- 傳遞給實(shí)例化字段的 ?kwargs?。
  • ?empty_value ?-- ?empty_values ?中輸入的預(yù)期干凈輸出。

例如,以下代碼測(cè)試 ?EmailField ?接受 ?a@a.com? 作為有效的電子郵件地址,但拒絕 ?aaa?,并給出合理的錯(cuò)誤信息:

self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': ['Enter a valid email address.']})

SimpleTestCase.assertFormError(response, form, field, errors, msg_prefix='')

斷言表單中的某個(gè)字段在表單中呈現(xiàn)時(shí),會(huì)引發(fā)所提供的錯(cuò)誤列表。

?response ?必須是測(cè)試客戶端返回的響應(yīng)實(shí)例。

?form ?是 ?Form ?實(shí)例在響應(yīng)的模板上下文中給出的名稱(chēng)。

?field ?是表單中要檢查的字段名。如果 ?field ?的值為 ?None?,則會(huì)檢查非字段錯(cuò)誤(可以通過(guò) ?form.non_field_errors()?)。
?errors ?是一個(gè)錯(cuò)誤字符串,或一個(gè)錯(cuò)誤字符串列表,是表單驗(yàn)證的結(jié)果。

SimpleTestCase.assertFormsetError(response, formset, form_index, field, errors, msg_prefix='')

斷言 ?formset ?在渲染時(shí),會(huì)引發(fā)所提供的錯(cuò)誤列表。

?response ?必須是測(cè)試客戶端返回的響應(yīng)實(shí)例。

?formset ?是 ?Formset ?實(shí)例在響應(yīng)的模板上下文中給出的名稱(chēng)。

?form_index ?是 ?Formset ?中表單的編號(hào)。 如果 ?form_index ?的值為 ?None?,則將檢查非表單錯(cuò)誤(可以通過(guò) ?formset.non_form_errors()? 訪問(wèn)的錯(cuò)誤)。
?field ?是表單中要檢查的字段名。如果 ?field ?的值為 ?None?,則會(huì)檢查非字段錯(cuò)誤(可以通過(guò) ?form.non_field_errors()?)。
?errors ?是一個(gè)錯(cuò)誤字符串,或一個(gè)錯(cuò)誤字符串列表,是表單驗(yàn)證的結(jié)果。

SimpleTestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='', html=False)

斷言響應(yīng)產(chǎn)生了給定的 ?status_code? 并且該文本出現(xiàn)在其內(nèi)容中。 如果提供了 ?count?,則文本必須在響應(yīng)中準(zhǔn)確出現(xiàn) ?count ?次。

將 ?html ?設(shè)置為 ?True?,將 ?text ?作為 HTML 處理。與響應(yīng)內(nèi)容的比較將基于 HTML 語(yǔ)義,而不是逐個(gè)字符的平等。在大多數(shù)情況下,空格會(huì)被忽略,屬性排序并不重要。

SimpleTestCase.assertNotContains(response, text, status_code=200, msg_prefix='', html=False)

斷言響應(yīng)產(chǎn)生了給定的 ?status_code ?并且該文本未出現(xiàn)在其內(nèi)容中。

將 ?html ?設(shè)置為 ?True?,將 ?text ?作為 HTML 處理。與響應(yīng)內(nèi)容的比較將基于 HTML 語(yǔ)義,而不是逐個(gè)字符的平等。在大多數(shù)情況下,空格會(huì)被忽略,屬性排序并不重要。

SimpleTestCase.assertTemplateUsed(response, template_name, msg_prefix='', count=None)

斷言具有給定名稱(chēng)的模板用于呈現(xiàn)響應(yīng)。

?response ?必須是測(cè)試客戶端返回的響應(yīng)實(shí)例。

?template_name ?應(yīng)該是一個(gè)字符串,例如admin/index.html?

?count ?參數(shù)是一個(gè)整數(shù),表示模板應(yīng)該被渲染的次數(shù)。 默認(rèn)為無(wú),這意味著模板應(yīng)該被渲染一次或多次。

您可以將其用作上下文管理器,如下所示:

with self.assertTemplateUsed('index.html'):
    render_to_string('index.html')
with self.assertTemplateUsed(template_name='index.html'):
    render_to_string('index.html')

SimpleTestCase.assertTemplateNotUsed(response, template_name, msg_prefix='')

斷言給定名稱(chēng)的模板在渲染響應(yīng)時(shí) 沒(méi)有 被使用。
你可以用 ?assertTemplateUsed()? 一樣的方式將其作為上下文管理器。

SimpleTestCase.assertURLEqual(url1, url2, msg_prefix='')

斷言兩個(gè) URL 是相同的,忽略查詢字符串參數(shù)的順序,但同名參數(shù)除外。例如,?/path/?x=1&y=2? 等于 ?/path/?y=2&x=1?,但 ?/path/?a=1&a=2 ?不等于 ?/path/?a=2&a=1?。

SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)

斷言響應(yīng)返回了 ?status_code ?重定向狀態(tài),重定向到了 ?expected_url?(包括任何 GET 數(shù)據(jù)),并且最后一頁(yè)收到了 ?target_status_code?。

如果您的請(qǐng)求使用了 ?follow ?參數(shù),則 ?expected_url ?和 ?target_status_code ?將是重定向鏈最后點(diǎn)的 url 和狀態(tài)碼。

如果 ?fetch_redirect_response ?為 ?False?,則不會(huì)加載最終頁(yè)面。 由于測(cè)試客戶端無(wú)法獲取外部 URL,因此如果 ?expected_url ?不是您的 Django 應(yīng)用程序的一部分,這將特別有用。

在兩個(gè) URL 之間進(jìn)行比較時(shí),Scheme 得到了正確處理。 如果在我們被重定向到的位置沒(méi)有指定任何方案,則使用原始請(qǐng)求的方案。 如果存在,則 ?expected_url ?中的方案是用于進(jìn)行比較的方案。

SimpleTestCase.assertHTMLEqual(html1, html2, msg=None)

斷言字符串 html1 和 html2 相等。比較是基于 HTML 語(yǔ)義的。比較時(shí)考慮到以下因素:

  • 忽略 HTML 標(biāo)記前后的空格。
  • 所有類(lèi)型的空格都被認(rèn)為是等效的。
  • 所有打開(kāi)的標(biāo)簽都是隱式關(guān)閉的,例如 當(dāng)周?chē)臉?biāo)記關(guān)閉或 HTML 文檔結(jié)束時(shí)。
  • 空標(biāo)簽相當(dāng)于它們的自閉合版本。
  • HTML 元素的屬性順序并不重要。
  • 沒(méi)有參數(shù)的布爾屬性(如檢查)等于名稱(chēng)和值相等的屬性。
  • 引用相同字符的文本、字符引用和實(shí)體引用是等效的。

下面的例子是有效的測(cè)試,并且沒(méi)有引起任何 ?AssertionError?:

self.assertHTMLEqual(
    '<p>Hello <b>&#x27;world&#x27;!</p>',
    '''<p>
        Hello   <b>&#39;world&#39;! </b>
    </p>'''
)
self.assertHTMLEqual(
    '<input type="checkbox" checked="checked" id="id_accept_terms" />',
    '<input id="id_accept_terms" type="checkbox" checked>'
)

html1 和 html2 必須包含 HTML。如果其中一個(gè)不能被解析,將產(chǎn)生一個(gè) ?AssertionError?。
錯(cuò)誤時(shí)的輸出可以用 msg 參數(shù)自定義。

SimpleTestCase.assertHTMLNotEqual(html1, html2, msg=None)

斷言字符串 html1 和 html2 不 相等。比較是基于 HTML 語(yǔ)義的。
html1 和 html2 必須包含 HTML。如果其中一個(gè)不能被解析,將產(chǎn)生一個(gè) ?AssertionError?。
錯(cuò)誤時(shí)的輸出可以用 ?msg ?參數(shù)自定義。

SimpleTestCase.assertXMLEqual(xml1, xml2, msg=None)

斷言字符串 xml1 和 xml2 相等。比較是基于 XML 語(yǔ)義的。與 ?assertHTMLEqual()? 類(lèi)似,比較是在解析內(nèi)容上進(jìn)行的,因此只考慮語(yǔ)義差異,而不是語(yǔ)法差異。當(dāng)任何參數(shù)中傳遞了無(wú)效的 XML 時(shí),即使兩個(gè)字符串相同,也總是會(huì)引發(fā)一個(gè) ?AssertionError?。
忽略 XML 聲明、文檔類(lèi)型、處理指令和注釋。只有根元素和它的子元素被比較。
錯(cuò)誤時(shí)的輸出可以用 ?msg ?參數(shù)自定義。

SimpleTestCase.assertXMLNotEqual(xml1, xml2, msg=None)

斷言字符串 xml1 和 xml2 不 相等。比較是基于 XML 語(yǔ)義的。
錯(cuò)誤時(shí)的輸出可以用 ?msg ?參數(shù)自定義。

SimpleTestCase.assertInHTML(needle, haystack, count=None, msg_prefix='')

斷言 HTML 片段 ?needle ?包含在 ?haystack ?中。
如果指定了 ?count ?整數(shù)參數(shù),則將嚴(yán)格核查 ?needle ?的出現(xiàn)次數(shù)。
在大多數(shù)情況下,空白是被忽略的,屬性排序并不重要。

SimpleTestCase.assertJSONEqual(raw, expected_data, msg=None)

斷言 JSON 片段 ?raw ?和 ?expected_data ?相等。通常的 JSON 非顯性空格規(guī)則適用,因?yàn)橹亓考?jí)是委托給 json 庫(kù)的。
錯(cuò)誤時(shí)的輸出可以用 ?msg ?參數(shù)自定義。

SimpleTestCase.assertJSONNotEqual(raw, expected_data, msg=None)

斷言 JSON 片段 ?raw ?和 ?expected_data ?不相等。
錯(cuò)誤時(shí)的輸出可以用 ?msg ?參數(shù)自定義。

TransactionTestCase.assertQuerysetEqual(qs, values, transform=None, ordered=True, msg=None)

斷言一個(gè)查詢集 ?qs ?與一個(gè)特定的可迭代對(duì)象 ?values ?的值匹配。
如果提供了 ?transform?,?values ?將與應(yīng)用 ?transform ?于 ?qs ?而產(chǎn)生的列表中每個(gè)成員進(jìn)行比較。
默認(rèn)情況下,比較也是依賴(lài)于順序的。如果 ?qs ?不提供隱式排序,你可以將 ?ordered ?參數(shù)設(shè)置為 ?False?,這將使比較變成 ?collections.Counter? 比較。如果順序是未定義的(如果給定的 ?qs ?不是有序的,并且比較的對(duì)象是一個(gè)以上的有序值),會(huì)產(chǎn)生一個(gè) ?ValueError?。
錯(cuò)誤時(shí)的輸出可以用 ?msg ?參數(shù)自定義。

TransactionTestCase.assertNumQueries(num, func, *args, **kwargs)

斷言當(dāng) ?func ?與 ?*args? 和 ?**kwargs? 一起調(diào)用時(shí),會(huì)執(zhí)行 ?num ?次數(shù)據(jù)庫(kù)查詢。
如果 ?kwargs ?中存在 ?using ?鍵,則使用該鍵作為數(shù)據(jù)庫(kù)別名,以檢查查詢次數(shù):

self.assertNumQueries(7, using='non_default_db')

如果你想調(diào)用一個(gè)帶有 ?using ?參數(shù)的函數(shù),你可以通過(guò)用 ?lambda ?包裝調(diào)用來(lái)增加一個(gè)額外的參數(shù):

self.assertNumQueries(7, lambda: my_function(using=7))

你也可以用它作為上下文管理器:

with self.assertNumQueries(2):
    Person.objects.create(name="Aaron")
    Person.objects.create(name="Daniel")

標(biāo)記測(cè)試

你可以給你的測(cè)試打上標(biāo)簽,這樣你就可以輕松地運(yùn)行一個(gè)特定的子集。例如,你可以標(biāo)記快速或慢速測(cè)試:

from django.test import tag

class SampleTestCase(TestCase):

    @tag('fast')
    def test_fast(self):
        ...

    @tag('slow')
    def test_slow(self):
        ...

    @tag('slow', 'core')
    def test_slow_but_core(self):
        ...

你也可以標(biāo)記一個(gè)測(cè)試用例:

@tag('slow', 'core')
class SampleTestCase(TestCase):
    ...

子類(lèi)從超類(lèi)繼承標(biāo)簽,方法從其類(lèi)繼承標(biāo)簽。如:

@tag('foo')
class SampleTestCaseChild(SampleTestCase):

    @tag('bar')
    def test(self):
        ...

?SampleTestCaseChild.test ?將用 slow?、?core?、?bar?和 ?foo ?來(lái)標(biāo)注。
然后你可以選擇要運(yùn)行的測(cè)試。例如,只運(yùn)行快速測(cè)試:

...\> manage.py test --tag=fast

或者運(yùn)行快速測(cè)試和核心測(cè)試(即使它很慢):

...\> manage.py test --tag=fast --tag=core

你也可以通過(guò)標(biāo)簽來(lái)排除測(cè)試。如果要運(yùn)行不慢的核心測(cè)試:

...\> manage.py test --tag=core --exclude-tag=slow

?test --exclud-tag? 優(yōu)先于 ?test --tag?,所以如果一個(gè)測(cè)試有兩個(gè)標(biāo)簽,你選擇了其中一個(gè)而排除了另一個(gè),測(cè)試就不會(huì)被運(yùn)行。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)