flask 單元測試 (一)

框架選擇:

根據 https://blog.zengrong.net/pos...
得知:
flask項目自己使用的是pytest
nose是對標準庫unittest的封裝,如今比較流行,但文檔沒有pytest作的好,且近幾年一直處於維護狀態沒有更新。
Flask-Testing flask擴展
最終選擇:pytesthtml

pytest

特色:

  • 很是容易上手,入門簡單,文檔豐富,文檔中有不少實例能夠參考
  • 可以支持簡單的單元測試和複雜的功能測試
  • 支持參數化
  • 執行測試過程當中能夠將某些測試跳過,或者對某些預期失敗的case標記成失敗
  • 支持重複執行失敗的case
  • 支持運行由nose, unittest編寫的測試case
  • 具備不少第三方插件,而且能夠自定義擴展
  • 方便的和持續集成工具集成

在命令行輸入以下命令檢查pytest是否已安裝python

py.test --version

若是沒有flask

pip install -U pytest

第一個例子:測試函數

# content of test_sample.py


def func(x):
    return x+1


def test_func():
    assert func(3) == 5

運行:
執行測試時須要下面幾步:session

  1. 從命令行進入測試文件所在目錄,pytest會在該目錄中尋找以test開頭的文件
  2. 找到測試文件,進入測試文件中尋找以test_開頭的函數並執行
  3. 測試函數以斷言assert結尾
$ py.test
============================= test session starts ==============================
platform darwin -- Python 3.5.1, pytest-2.8.1, py-1.4.30, pluggy-0.3.1
rootdir: /Users/fc/project/test/pytest_sample, inifile:
collected 1 items

test_sample.py F

=================================== FAILURES ===================================
__________________________________ test_func ___________________________________

    def test_func():
>       assert func(3) == 5
E       assert 4 == 5
E        +  where 4 = func(3)

test_sample.py:9: AssertionError
=========================== 1 failed in 0.01 seconds ===========================

第二個例子: 測試類

# content of test_class.py


class TestClass(object):
    def test_one(self):
        x = 'this'
        assert 'h' in x

    def test_two(self):
        x = 'hello'
        assert hasattr(x, 'check')

運行
下面的-q是 quiet的意思,就是忽略一些很細節的信息
使用測試類時,注意下面幾點:app

  1. 測試類所在的文件以test_開頭
  2. 測試類以Test開頭,而且不能帶有__init__方法
  3. 類中測試函數以test_開頭
  4. 測試函數以assert斷言結尾
bogon:pytest_sample fc$ py.test -q test_class.py
.F
=================================== FAILURES ===================================
______________________________ TestClass.test_two ______________________________

self = <test_class.TestClass object at 0x10595b080>

    def test_two(self):
        x = 'hello'
>       assert hasattr(x, 'check')
E       assert hasattr('hello', 'check')

test_class.py:11: AssertionError
1 failed, 1 passed in 0.01 seconds
第三個例子:參數化測試函數
import pytest

params = [
    (2, 3, 5),
    (4, 5, 9),
    (6, 7, 12)
]


@pytest.mark.parametrize('a, b, expected', params)
def test_add(a, b, expected):
    assert a + b == expected

運行結果框架

$ py.test -q test_params.py
..F
=================================== FAILURES ===================================
_______________________________ test_add[6-7-12] _______________________________

a = 6, b = 7, expected = 12

    @pytest.mark.parametrize('a, b, expected', params)
    def test_add(a, b, expected):
>       assert a + b == expected
E       assert (6 + 7) == 12

test_params.py:12: AssertionError
1 failed, 2 passed in 0.01 seconds

說明:函數

  1. params是要進行測試的參數list,其中元素爲tuple,每一個tuple對應一套參數
  2. @pytest.mark.parametrize裝飾器的第一個參數是一個字符串,不過這個字符串實際上是以逗號分隔的一組參數,這個參數就是其所裝飾的函數的參數。
  3. @pytest.mark.parametrize裝飾器將params中的參數一套一套拿出來放入其所裝飾的函數中執行

第四個例子 fixture params

import pytest


@pytest.fixture(params=[1, 2, 3])
def test_data(request):
    return request.param


def test_not_2(test_data):
    assert test_data != 2

運行結果:工具

$ py.test -q fixture_params.py
.F.
======================================= FAILURES =======================================
____________________________________ test_not_2[2] _____________________________________

test_data = 2

    def test_not_2(test_data):
>       assert test_data != 2
E       assert 2 != 2

fixture_params.py:10: AssertionError
1 failed, 2 passed in 0.01 seconds

說明:post

  1. 把一個函數定用@pytest.fixture裝飾,那這個函數就是fixture函數
  2. 一個fixture函數能夠被其餘測試函數調用,將函數名看成參數便可,fixture的返回值會看成測試函數的參數
  3. fixture函數中的params字段默認爲None,若是有值,則每一個值都會調用執行一次

在flask項目中使用pytest

flask應用demo代碼

from flask import Flask


app = Flask(__name__)


@app.route('/')
def index():
    return 'hello'


@app.route('/login')
def login():
    return 'login'


@app.route('/logout')
def logout():
    return 'logout'


@app.errorhandler(404)
def page_not_found():
    return '404'


if __name__ == '__main__':
    app.run()

flask demo的測試代碼

from flaskr import app


class TestClass(object):
    def setup_class(self):
        """測試開始時候執行, 用來作準備工做,通常用來初始化資源。"""
        app.config['TESTING'] = True  # 這將會使得處理請求時的錯誤捕捉失效,以便於 您在進行對應用發出請求的測試時得到更好的錯誤反饋。
        # 測試客戶端將會給咱們一個通向應用的簡單接口,咱們能夠激發 對嚮應用發送請求的測試,而且此客戶端也會幫咱們記錄 Cookie 的 動態。
        self.app = app.test_client()

    def teardown_class(self):
        """測試結束時執行, 用來作收尾工做, 通常用來關閉資源"""
        pass

    def test_login(self):
        response = self.app.get('/login')
        assert b'login' == response.data

    def test_logout(self):
        response = self.app.get('logout')
        assert b'logout' == response.data

    def test_index(self):
        response = self.app.get('/')
        assert b'hello' == response.data
相關文章
相關標籤/搜索