Django單元測試

測試例子均來源於官方文檔,可自行查閱:https://docs.djangoproject.com/en/2.2/topics/testing/

除了官方文檔提到的內容,本文主要寫一下自己使用過程中碰到的問題和解決方法

0X01 如何編寫單元測試

Python有unittest庫來進行單元測試,Django的單元測試是基於unittest庫的,只不過在unittest的基礎上進行了封裝,並提供了一系列單元測試工具,來幫助你進行測試。Django在創建APP之後,默認會在APP目錄下創建一個tests.py文件,這裏就是存放你測試代碼的地方,當然,如果需要測試的內容多了,都放在一個文件中顯然不合理,所以Django提供高級玩法,模塊化測試,這個後面再說,先上一個例子:

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

class AnimalTestCase(TestCase):
    def setUp(self):
        Animal.objects.create(name="lion", sound="roar")
        Animal.objects.create(name="cat", sound="meow")

    def test_animals_can_speak(self):
        """Animals that can speak are correctly identified"""
        lion = Animal.objects.get(name="lion")
        cat = Animal.objects.get(name="cat")
        self.assertEqual(lion.speak(), 'The lion says "roar"')
        self.assertEqual(cat.speak(), 'The cat says "meow"')

上面就是一個最基礎的測試用例,你所編寫的測試類需要繼承於TestCase,當你運行測試時,Django會找到所有的以test開頭的文件,運行這些文件中所有父類是TestCase的類中的測試方法,測試方法爲以test開頭的函數。

上面的例子中,setUp函數會在運行test_xxxx函數前被調用,可以進行一些初始化操作,例如創建測試數據,獲取Token等。

0X02 運行單元測試

在Django項目目錄下使用manage.py來運行單元測試,該命令會運行所有APP的所有tests.py中的所有測試:

python manage.py test

運行某個package下的所有測試:

python manage.py test package_name

運行某個package下的某個測試類(TestCase):

python manage.py test pack.tests.xxxTestCase

運行某個package下的某個測試類的某個測試方法:

python manage.py test pack.tests.xxxTestCase.test_animals_can_speak

上面提到過,默認會匹配所有以test_func開頭的測試方法,你也可以自己制定測試方法的正則:

python manage.py test --pattern="tests_*.py"

在運行單元測試的時候,可以使用ctrl+c來結束測試,測試程序將等待當前正在運行的測試結束,然後正常退出。在退出期間,測試程序會和往常一樣輸出測試失敗的詳細信息、運行了多少測試、出現的錯誤和故障,並且會像往常一樣銷燬測試數據庫。

連續按下兩次ctrl+c將會強制退出測試程序,此時會缺少一些詳細信息,也不會銷燬測試數據庫,慎用。

0X03 測試數據庫

需要和model交互的話會需要用到數據庫,但Django不會使用生產環境的數據庫進行測試,會創建單獨的測試數據庫,例如settings.py中定義的連接的數據庫爲product_db,那麼默認創建的測試數據庫就爲test_product_db。

上面提到過,在執行單元測試命令後,會自動創建測試數據庫,結束測試後會自動銷燬測試數據庫。每次都去創建和銷燬比較耗時,如果不需要銷燬測試數據庫可以攜帶keepdb參數,不銷燬數據庫:

python manage.py test --keepdb

如上一節所述,如果強制中斷測試運行,則可能不會銷燬測試數據庫。在下一次運行時,將詢問您是否要重用或銷燬數據庫。使用該選項可以禁止該提示並自動銷燬數據庫。例如,在連續集成服務器上運行測試時,這可能很有用,例如,測試可能會因超時而中斷:

python manage.py test --noinput

默認Django settings中指定的是sqlite數據庫,那麼測試數據庫將創建在內存中,不會使用文件系統。在settings.py中的DATABASES提供了很多關於測試數據庫的選項,例如指定測試數據庫的名字:、

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'mydatabaseuser',
        'NAME': 'mydatabase',
        'TEST': {
            'NAME': 'mytestdatabase',
        },
    },
}

更多字段:https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-TEST_NAME

有一個地方暫時沒有捋清楚什麼意思,如果有兄弟知道可以分享下,原文:https://docs.djangoproject.com/en/2.2/ref/applications/#django.apps.AppConfig.ready

Finding data from your production database when running tests?

If your code attempts to access the database when its modules are compiled, this will occur before the test database is set up, with potentially unexpected results. For example, if you have a database query in module-level code and a real database exists, production data could pollute your tests. It is a bad idea to have such import-time database queries in your code anyway - rewrite your code so that it doesn’t do this.

This also applies to customized implementations of ready().

未完待續,明天繼續寫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章