?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)
如果你想使用不同的 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()
如果數(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ā)生以下情況:
setUp()
? 運(yùn)行之前,Django 會(huì)對(duì)數(shù)據(jù)庫(kù)進(jìn)行刷新,將數(shù)據(jù)庫(kù)直接返回到 ?migrate
?被調(diào)用后的狀態(tài)。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ù)中。
如果你的應(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 配置。
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)泄露。
默認(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ù)原始值。
為了測(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)。
重新定義包含一系列值的設(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)有效果。
如果你想覆蓋一個(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/')
同樣,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ǔ) |
如果你使用任何 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()
?。
斷言表單字段在不同的輸入情況下表現(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.']})
斷言表單中的某個(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é)果。
斷言 ?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é)果。
斷言響應(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ì)被忽略,屬性排序并不重要。
斷言響應(yīng)產(chǎn)生了給定的 ?status_code
?并且該文本未出現(xiàn)在其內(nèi)容中。
將 ?html
?設(shè)置為 ?True
?,將 ?text
?作為 HTML 處理。與響應(yīng)內(nèi)容的比較將基于 HTML 語(yǔ)義,而不是逐個(gè)字符的平等。在大多數(shù)情況下,空格會(huì)被忽略,屬性排序并不重要。
斷言具有給定名稱(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')
斷言給定名稱(chēng)的模板在渲染響應(yīng)時(shí) 沒(méi)有 被使用。
你可以用 ?assertTemplateUsed()
? 一樣的方式將其作為上下文管理器。
斷言兩個(gè) URL 是相同的,忽略查詢字符串參數(shù)的順序,但同名參數(shù)除外。例如,?/path/?x=1&y=2
? 等于 ?/path/?y=2&x=1
?,但 ?/path/?a=1&a=2
?不等于 ?/path/?a=2&a=1
?。
斷言響應(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)行比較的方案。
斷言字符串 html1 和 html2 相等。比較是基于 HTML 語(yǔ)義的。比較時(shí)考慮到以下因素:
下面的例子是有效的測(cè)試,并且沒(méi)有引起任何 ?AssertionError
?:
self.assertHTMLEqual(
'<p>Hello <b>'world'!</p>',
'''<p>
Hello <b>'world'! </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ù)自定義。
斷言字符串 html1 和 html2 不 相等。比較是基于 HTML 語(yǔ)義的。
html1 和 html2 必須包含 HTML。如果其中一個(gè)不能被解析,將產(chǎn)生一個(gè) ?AssertionError
?。
錯(cuò)誤時(shí)的輸出可以用 ?msg
?參數(shù)自定義。
斷言字符串 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ù)自定義。
斷言字符串 xml1 和 xml2 不 相等。比較是基于 XML 語(yǔ)義的。
錯(cuò)誤時(shí)的輸出可以用 ?msg
?參數(shù)自定義。
斷言 HTML 片段 ?needle
?包含在 ?haystack
?中。
如果指定了 ?count
?整數(shù)參數(shù),則將嚴(yán)格核查 ?needle
?的出現(xiàn)次數(shù)。
在大多數(shù)情況下,空白是被忽略的,屬性排序并不重要。
斷言 JSON 片段 ?raw
?和 ?expected_data
?相等。通常的 JSON 非顯性空格規(guī)則適用,因?yàn)橹亓考?jí)是委托給 json 庫(kù)的。
錯(cuò)誤時(shí)的輸出可以用 ?msg
?參數(shù)自定義。
斷言 JSON 片段 ?raw
?和 ?expected_data
?不相等。
錯(cuò)誤時(shí)的輸出可以用 ?msg
?參數(shù)自定義。
斷言一個(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ù)自定義。
斷言當(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")
你可以給你的測(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)行。
更多建議: