Django單元測試基礎(chǔ)知識

相關(guān)資源

Django官方文檔
unittest文檔

簡單的例子

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

# Django的單元測試基于unittest庫
class StudentTestCase(TestCase):
    # 測試函數(shù)執(zhí)行前執(zhí)行
    def setUp(self):
        print("======in setUp")

    # 需要測試的內(nèi)容
    def test_add(self):
        student = Student(name='aaa')
        student.save()
        self.assertEqual(student.name, 'aaa')
    
    # 需要測試的內(nèi)容
    def test_check_exit(self):
        self.assertEqual(0,  Student.objects.count())

     # 測試函數(shù)執(zhí)行后執(zhí)行
    def tearDown(self):
        print("======in tearDown")

關(guān)于django的單元測試,需要知道的是

  1. 對于每一個測試方法都會將setUp()和tearDown()方法執(zhí)行一遍
  2. 會單獨(dú)新建一個測試數(shù)據(jù)庫來進(jìn)行數(shù)據(jù)庫的操作方面的測試幸冻,默認(rèn)在測試完成后銷毀宫盔。
  3. 在測試方法中對數(shù)據(jù)庫進(jìn)行增刪操作,最后都會被清除拷恨。也就是說,在test_add中插入的數(shù)據(jù),在test_add測試結(jié)束后插入的數(shù)據(jù)會被清除。
  4. django單元測試時為了模擬生產(chǎn)環(huán)境翼岁,會修改settings中的變量,例如, 把DEBUG變量修改為True, 把ALLOWED_HOSTS修改為[*]绳姨。

運(yùn)行單元測試

在單元測試中登澜,可以指定測試粒度。這樣可以專注于只測試還沒測試的單元測試飘庄,而已經(jīng)測試過的就不測試了脑蠕。

# 測試整一個工程
$ ./manage.py test 

# 只測試某個應(yīng)用
$ ./manage.py test app --keepdb


# 只測試一個Case
$ ./manage.py test animals.tests.StudentTestCase

# 只測試一個方法
$ ./manage.py test animals.tests.StudentTestCase.test_add

一些常見問題的解決

數(shù)據(jù)表多時創(chuàng)建數(shù)據(jù)庫銷毀過多時間

在單元測試時,若migrations的文檔過多時跪削,每次單元測試時間絕大部分都消耗在數(shù)據(jù)庫的創(chuàng)建谴仙。試過,單元測試代碼運(yùn)行只要幾十秒碾盐,而數(shù)據(jù)庫的創(chuàng)建卻用去了十分鐘晃跺。這是個讓人絕望的速度,萬幸的是django有提供命令使用進(jìn)行單元測試過后不刪除數(shù)據(jù)庫毫玖。 這個命令就是: --keepdb

指定測試數(shù)據(jù)庫的默認(rèn)字符集

在創(chuàng)建測試數(shù)據(jù)庫時掀虎,數(shù)據(jù)庫的默認(rèn)字符集也許不是我們想要的例如latin1「斗悖可以通過在數(shù)據(jù)庫配置中指定TEST_CHARSET, TEST_COLLATION 參數(shù)烹玉,來指定字符集以及排序規(guī)則

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'xxxx',
        'USER': 'xxxx',
        'PASSWORD': '',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': {
            'charset': 'utf8mb4',
            'init_command': 'SET default_storage_engine=INNODB',
        },
        'TEST_CHARSET': 'utf8',
        'TEST_COLLATION': 'utf8_general_ci',
    },

}

** settings變量的修改**

若干需要在單元測試時修改,setting命令阐滩。例如二打,django在單元測試時會將settings.DEBUG 設(shè)置為True, 而我們需要將其設(shè)置為False

方式1: 直接在修改

class BaseApiTest(TestCase):
    def setUp(self):
        #testcase DEBUG = False
        settings.DEBUG = False
        
    def test_b(self):
        self.assertEqual(2, 1+1)
    
    def tearDown(self):
        pass

方式2: 通過裝飾器修改

from django.test.utils import override_settings
    
class BaseTest(TestCase):   
    def setUp(self):
        pass
    
    # 利用該裝飾器,可以在但個測試函數(shù)內(nèi)修改settings變量, 而不影響
    @override_settings(DEBUG=False)
    def test_b(self):
        self.assertEqual(2, 1+1)
    
    def tearDown(self):
        pass

API權(quán)限問題的解決

在測試API的時候掂榔,往往需要等等進(jìn)行用戶登錄才有權(quán)限調(diào)用继效,此時需要指定登錄用戶來解決接口調(diào)用的權(quán)限問題

# 如果是API使用了rest_framework框架
from rest_framework.test import APIClient
class BaseTest(TestCase):   
    def setUp(self):
        
        # 創(chuàng)建一個用戶
        self.user = create_user(uuid4().hex, '123456789')
        self.client = APIClient()
        
        # 通過force_authenticate函數(shù)來執(zhí)行用戶
        self.client.force_authenticate(self.user)

    
    def test_b(self):
        self.assertEqual(2, 1+1)
    
    def tearDown(self):
        pass


Celery異步任務(wù)的測試

在代碼中幾乎肯定是會有celery異步任務(wù),若想對異步任務(wù)進(jìn)行單元測試装获∪鹦牛可以將CELERY_ALWAYS_EAGER=True, BROKER_BACKEND='memory'

from xxx.celery import app


@app.task(bind=True)
def add(self,x, y):
    return x + y

class TaskTest(TestCase):
    def setUp(self):
        settings.CELERY_ALWAYS_EAGER = True
        
    def test_add(self):
        self.assertEqual(2, add.apply_async((1,1)))
    
    def tearDown(self):
        pass

單元的等級(來自知乎的gashero)

在知乎上看到gashero根據(jù)經(jīng)驗總結(jié)出來的單元測試總結(jié),非常認(rèn)同穴豫。根據(jù)功能的重要性喧伞,來進(jìn)行不同程度的測試。

  • Level1:正常流程可用,即一個函數(shù)在輸入正確的參數(shù)時潘鲫,會有正確的輸出
  • Level2:異常流程可拋出邏輯異常翁逞,即輸入?yún)?shù)有誤時,不能拋出系統(tǒng)異常溉仑,而是用自己定義的邏輯異常通知上層調(diào)用代碼其錯誤之處
  • Level3:極端情況和邊界數(shù)據(jù)可用挖函,對輸入?yún)?shù)的邊界情況也要單獨(dú)測試,確保輸出是正確有效的
  • Level4:所有分支浊竟、循環(huán)的邏輯走通怨喘,不能有任何流程是測試不到的
  • Level5:輸出數(shù)據(jù)的所有字段驗證,對有復(fù)雜數(shù)據(jù)結(jié)構(gòu)的輸出振定,確保每個字段都是正確的地方

小小的感想

單元測試是需要時間必怜,若要把各種情況都測試一遍,也許單元測試的編寫時間要比寫代碼的時間還要長后频。目前由于時間關(guān)系梳庆,比較少寫單元測試,但我很是期望能擠出時間盡量的編程單元測試卑惜。對于我來說膏执,單元測試存在的意義就是,可以讓我放心的重構(gòu)代碼露久,可以在重構(gòu)代碼的時候省下測試重構(gòu)的代碼能否正確運(yùn)行的時間更米。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市毫痕,隨后出現(xiàn)的幾起案子征峦,更是在濱河造成了極大的恐慌,老刑警劉巖消请,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眶痰,死亡現(xiàn)場離奇詭異,居然都是意外死亡梯啤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門存哲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來因宇,“玉大人,你說我怎么就攤上這事祟偷〔旎” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵修肠,是天一觀的道長贺辰。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么饲化? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任莽鸭,我火速辦了婚禮,結(jié)果婚禮上吃靠,老公的妹妹穿的比我還像新娘硫眨。我一直安慰自己,他們只是感情好巢块,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布礁阁。 她就那樣靜靜地躺著,像睡著了一般族奢。 火紅的嫁衣襯著肌膚如雪姥闭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天越走,我揣著相機(jī)與錄音棚品,去河邊找鬼。 笑死弥姻,一個胖子當(dāng)著我的面吹牛南片,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播庭敦,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疼进,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秧廉?” 一聲冷哼從身側(cè)響起伞广,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疼电,沒想到半個月后嚼锄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔽豺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年区丑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片修陡。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡沧侥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出魄鸦,到底是詐尸還是另有隱情宴杀,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布拾因,位于F島的核電站旺罢,受9級特大地震影響旷余,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扁达,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一正卧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罩驻,春花似錦穗酥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至节吮,卻和暖如春抽高,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背透绩。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工翘骂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帚豪。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓碳竟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親狸臣。 傳聞我的和親對象是個殘疾皇子莹桅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • # Python 資源大全中文版 我想很多程序員應(yīng)該記得 GitHub 上有一個 Awesome - XXX 系列...
    aimaile閱讀 26,486評論 6 427
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)烛亦,斷路器诈泼,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • GitHub 上有一個 Awesome - XXX 系列的資源整理,資源非常豐富,涉及面非常廣煤禽。awesome-p...
    若與閱讀 18,650評論 4 418
  • 環(huán)境管理管理Python版本和環(huán)境的工具铐达。p–非常簡單的交互式python版本管理工具。pyenv–簡單的Pyth...
    MrHamster閱讀 3,794評論 1 61
  • 假如明天就是世界末日檬果,你今天會怎樣度過瓮孙? 假如這世間人都死去了,你會怎樣面對孤獨(dú)选脊? —— 9.23
    嵐風(fēng)的葉子閱讀 278評論 0 0