1. 程式人生 > 其它 >pytest學習及總結(一)

pytest學習及總結(一)

技術標籤:python

pytest

1.捕獲異常

pytest.raises(異常型別)

2.標記測試函式

1.顯式指定函式名
pytest 指令碼路徑/***.py::函式名
2.使用模糊匹配
pytest -k 模糊匹配名 路徑/test_*.py
3.pytest.mark
在函式前加上@pytest.mark.finished
測試時使用pytest -m finished 路徑/***.py

3.跳過測試

如果測試中有一些函式需要被略過,則需要在需要被跳過的函式前加
1. @pytest.mark.skip(reason='out-of-date api')reason裡面寫
2. @pytest.mark.skipif(條件(相當於if裡面的條件),reason='out-of-date api')
import pytest
import sys


@pytest.mark.skip(reason='out-of-date api')
def test_connect():
    pass


@pytest.mark.skipif(sys.version < '3.6.5', reason='not support util 0.2.0')
def test_api():
    print('aaa')


def test_function(record_property):
    record_property('example_key', 1)
    assert True

4.預見錯誤

測試時可以預見錯誤,如果預見錯誤,但測試通過則為xpass,預見錯誤,實際檢測出來也是錯誤的話,則為xfail
@pytest.mark.xfail(預見的錯誤,reason='')
用x進行標記
import pytest
import sys


@pytest.mark.xfail(sys.version < '3.5.0', reason='not syrpport until v3.7.0')
def test_api():
    a = 1
    b = 2
    assert a != b

5.引數化

用於校驗一個或多個測試用例,例如使用者名稱與密碼校驗
pytest.mark.parametrize(argnames,argvalues)
其中argnames可以是一個或者多個引數
import pytest


@pytest.mark.parametrize('passwd', ['123456', 'abcdefdfs', 'as52345fasdf4'])
def test_passwd_length(passwd):
    assert len(passwd) >= 8


@pytest.mark.parametrize('user, passwd',
                         [('jack', 'abcdefgh'),
                          ('tom', 'a123456a')])
def test_passwd_md5(user, passwd):
    db = {
        'jack': 'e8dc4081b13434b45189a720b77b6818',
        'tom': '1702a132e769a623c1adb78353fc9503'
    }
    import hashlib
    assert hashlib.md5(passwd.encode()).hexdigest() == db[user]


@pytest.mark.parametrize('user,passwd',
                         [pytest.param('jack', 'abcdefgh', id='User<Jack>'),
                          pytest.param('tom', 'a123456a', id='User<Tom>')])
def test_passwd_md5_id(user, passwd):
    db = {
        'jack': 'e8dc4081b13434b45189a720b77b6818',
        'tom': '1702a132e769a623c1adb78353fc9503'
    }
    import hashlib
    assert hashlib.md5(passwd.encode()).hexdigest() == db[user]

6.韌體

韌體是一些函式,pytest會在執行測試之前或者之後執行它們,可以利用韌體做任何事情。還可以將韌體全部寫在 conftest.py中,便於集中管理韌體。複雜專案中還可以在不同的目錄級別中定義韌體,作用域是其所在的目錄以及子目錄。

import pytest


@pytest.fixture()
def postcode():
    return '011'


def test_postcode(postcode):
    assert postcode == '010'
6.1.預處理和後處理

在測試前或者測試結束後需要進行一些操作,當這些操作需要大量重複時,便可以使用韌體中的預處理和後處理。

預處理:測試前執行。如:連線資料庫

後處理:測試後進行。如:關閉資料庫連線

pytest使用yield關鍵詞將韌體分為兩部分,yield之前是預處理測試前進行,yield之後是後處理,測試後進行。

@pytest.fixture()
def db():
    print('Connection successful')
    yield
    print('Connection closed')


def search_user(user_id):
    d = {
        '001': 'xiaoming'
    }
    return d[user_id]


def test_search(db):
    assert search_user('001') == 'xiaoming'

可以使用pytest -s ***.py 或 pytest --setup-show ***.py顯示詳細的測試資訊。

6.2作用域

pytest使用作用域指定韌體的作用範圍,在定義韌體時,可以使用scope引數宣告作用域

function 每個測試函式都會執行韌體
class 每個測試類執行一次,包括類裡面的所有函式
module 每個模組執行一次,包括模組裡面的類和函式
session 一次測試只執行一次,所有找到的函式和方法都可以使用

@pytest.fixture(scope='function')
@pytest.fixture(scope='class')
@pytest.fixture(scope='module')
@pytest.fixture(scope='session')

類作用域需要使用@pytest.mark.usefixtures('class_scope')
import pytest


@pytest.fixture(scope='function')
def func_scope():
    pass


@pytest.fixture(scope='module')
def mod_scope():
    pass


@pytest.fixture(scope='session')
def sess_scope():
    pass


@pytest.fixture(scope='class')
def class_scope():
    pass


def test_multi_scope(sess_scope, mod_scope, func_scope):
    pass


@pytest.mark.usefixtures('class_scope')
class TestClassScope:
    def test_1(self):
        pass

    def test_2(self):
        pass
6.3自動執行

如果需要讓韌體自動執行,可以在使用時定義autouse引數

如下例子統計函式執行時間,結合scope使用,可以定義作用範圍

import pytest
import time

DATE_FORMAT = '%Y-%m-%d %H:%M:%S'


@pytest.fixture(scope='session', autouse=True)
def timer_session_scope():
    start = time.time()
    print('\nstart:  {}'.format(time.strftime(DATE_FORMAT, time.localtime(start))))
    yield
    finished = time.time()
    print('\nfinished:  {}'.format(time.strftime(DATE_FORMAT, time.localtime(finished))))
    print('Total time cost:  {:.3f}'.format(finished - start))


@pytest.fixture(autouse=True)
def time_function_scope():
    start = time.time()
    yield
    print('  Time cost:  {:.3f}'.format(time.time() - start))


def test_1():
    time.sleep(1)


def test_2():
    time.sleep(1)
結果:                          
test_autouse.py::test_1
start:  2020-11-24 13:39:59		# 會話開始計時
PASSED  Time cost:  1.014		# 函式1耗時時間

test_autouse.py::test_2 		# 
PASSED  Time cost:  1.002		# 函式2耗時時間

finished:  2020-11-24 13:40:01	# 會話結束
Total time cost:  2.025			# 整個會話耗時

6.4重新命名

如果需要對韌體名稱進行重新命名,則在定義時加上name引數

import pytest


@pytest.fixture(name='age')
def calculate_average_age():
    return 28


def test_age(age):
    assert age == 28
6.5引數化

測試函式中函式可以引數化,在韌體中韌體引數也可以引數化,例如資料庫的連線測試,可以將其測試引數合併在一起,合併為一個韌體,測試更加方便。韌體在使用時必須要用params引數進行引數化。

其中需要用到request內建韌體,並使用request.param屬性獲取引數。

import pytest


@pytest.fixture(params=[
    ('redis', '6379'),
    ('elasticsearch', '9200')
])
def param(request):
    return request.param


@pytest.fixture(autouse=True)
def db(param):
    print('\n Succeed to connect %s %s' % param)
    

    print('\n Succeed to close %s %s' % param)


def test_api():
    assert 1 == 1

6.6內建韌體

6.6.1tmpdirtmpdir_factory

tmpdir.mkdir()可以建立臨時目錄,tmpdir.join()可以建立檔案

def test_tmpdir(tmpdir):
    a_dir = tmpdir.mkdir('mytmpdir')
    a_file = a_dir.join('tmpfile.txt')
    a_file.write('hello,pytest')
    assert a_file.read() == 'hello,pytest'

tmpdir_factory可以在作用域使用,包括session module class function

@pytest.fixture(scope='module')
def my_tmpdir_factory(tmpdir_factory):
    a_dir = tmpdir_factory.mktemp('mytmpdir')
    a_file = a_dir.join('tmpfile.txt')
    a_file.write('hello,pytest')
    return a_file

6.6.2pytestconfig

pytestconfig可以讀取命令列引數配置以及檔案,其中在配置檔案conftest.py中使用鉤子函式pytest_addoption

# conftest.py
import pytest


def pytest_addoption(parser):
    parser.addoption('--host',
                     action='store',
                     help='host of db')
    parser.addoption('--port',
                     action='store',
                     default='8888',
                     help='port of db')


@pytest.fixture
def config(request):
    return request.config
# test_config
def test_option1(pytestconfig):
    print('host1: %s' % pytestconfig.getoption('host'))
    print('port1: %s' % pytestconfig.getoption('port'))

    # 其中pytestconfig是request.config的快捷方式,可以使用韌體

def test_option2(config):
    print('host2: %s' % config.getoption('host'))
    print('port2: %s' % config.getoption('port'))

# 測試時可以在測試程式碼中指定引數:
pytest -sv --host=localhost test_config::test_option1

6.6.3capsys

主要用於捕獲sysoutsyserr

import sys


def ping(output):
    print('ping....', file=output)


def test_stdout(capsys):
    ping(sys.stdout)
    out, err = capsys.readouterr()
    assert out == 'ping....\n'
    assert err == ''


def test_stderr(capsys):
    ping(sys.stderr)
    out, err = capsys.readouterr()
    assert out == ''
    assert err == 'ping....\n'

6.6.4recwarn

recwarn可以捕獲程式中warnings產生的警告,pytest中用pytest.warns

import warnings, pytest


def warn():
    warnings.warn('Deprecated function', DeprecationWarning)


def test_warn(recwarn):
    warn()
    assert len(recwarn) == 1
    w = recwarn.pop()
    assert w.category == DeprecationWarning


def test_warn2():
    with pytest.warns(None) as warnings:
        warn()
    assert len(warnings) == 1
    w = warnings.pop()
    assert w.category == DeprecationWarning

7.

7.1 pytest指令
pytest -x # 在第一次測試失敗之後停止測試
pytest --maxfail = 2 # 第二次測試失敗之後停止測試
pytest -r 
# r後面可以跟很多引數,顯示不同的資訊
f -failed
E -error
s -skipped
x -xfailed
X -xpassed
p -passed
P -passed with output
a -all execpt pP
7.2pdb除錯
進入pdb除錯介面指令:python -m pdb test_pdb.py
h 顯示幫助指令 
h l 顯示列表顯示的詳細資訊
b 給目標位置設定斷點
	b 12 給第12行設定斷點
    b test_fun.add 給add函式設定斷點
    b 顯所有斷點
cl 刪除斷點
	cl 2 刪除第二個斷點
    cl 刪除所有斷點

歡迎使用Markdown編輯器

你好! 這是你第一次使用 Markdown編輯器 所展示的歡迎頁。如果你想學習如何使用Markdown編輯器, 可以仔細閱讀這篇文章,瞭解一下Markdown的基本語法知識。

新的改變

我們對Markdown編輯器進行了一些功能拓展與語法支援,除了標準的Markdown編輯器功能,我們增加了如下幾點新功能,幫助你用它寫部落格:

  1. 全新的介面設計 ,將會帶來全新的寫作體驗;
  2. 在創作中心設定你喜愛的程式碼高亮樣式,Markdown 將程式碼片顯示選擇的高亮樣式 進行展示;
  3. 增加了 圖片拖拽 功能,你可以將本地的圖片直接拖拽到編輯區域直接展示;
  4. 全新的 KaTeX數學公式 語法;
  5. 增加了支援甘特圖的mermaid語法1 功能;
  6. 增加了 多螢幕編輯 Markdown文章功能;
  7. 增加了 焦點寫作模式、預覽模式、簡潔寫作模式、左右區域同步滾輪設定 等功能,功能按鈕位於編輯區域與預覽區域中間;
  8. 增加了 檢查列表 功能。

功能快捷鍵

撤銷:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜體:Ctrl/Command + I
標題:Ctrl/Command + Shift + H
無序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
檢查列表:Ctrl/Command + Shift + C
插入程式碼:Ctrl/Command + Shift + K
插入連結:Ctrl/Command + Shift + L
插入圖片:Ctrl/Command + Shift + G
查詢:Ctrl/Command + F
替換:Ctrl/Command + G

合理的建立標題,有助於目錄的生成

直接輸入1次#,並按下space後,將生成1級標題。
輸入2次#,並按下space後,將生成2級標題。
以此類推,我們支援6級標題。有助於使用TOC語法後生成一個完美的目錄。

如何改變文字的樣式

強調文字 強調文字

加粗文字 加粗文字

標記文字

刪除文字

引用文字

H2O is是液體。

210 運算結果是 1024.

插入連結與圖片

連結: link.

圖片: Alt

帶尺寸的圖片: Alt

居中的圖片: Alt

居中並且帶尺寸的圖片: Alt

當然,我們為了讓使用者更加便捷,我們增加了圖片拖拽功能。

如何插入一段漂亮的程式碼片

部落格設定頁面,選擇一款你喜歡的程式碼片高亮樣式,下面展示同樣高亮的 程式碼片.

// An highlighted block
var foo = 'bar';

生成一個適合你的列表

  • 專案
    • 專案
      • 專案
  1. 專案1
  2. 專案2
  3. 專案3
  • 計劃任務
  • 完成任務

建立一個表格

一個簡單的表格是這麼建立的:

專案Value
電腦$1600
手機$12
導管$1

設定內容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列第二列第三列
第一列文字居中第二列文字居右第三列文字居左

SmartyPants

SmartyPants將ASCII標點字元轉換為“智慧”印刷標點HTML實體。例如:

TYPEASCIIHTML
Single backticks'Isn't this fun?'‘Isn’t this fun?’
Quotes"Isn't this fun?"“Isn’t this fun?”
Dashes-- is en-dash, --- is em-dash– is en-dash, — is em-dash

建立一個自定義列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何建立一個註腳

一個具有註腳的文字。2

註釋也是必不可少的

Markdown將文字轉換為 HTML

KaTeX數學公式

您可以使用渲染LaTeX數學表示式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通過尤拉積分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

你可以找到更多關於的資訊 LaTeX 數學表示式here.

新的甘特圖功能,豐富你的文章

Mon 06 Mon 13 Mon 20 已完成 進行中 計劃一 計劃二 現有任務 Adding GANTT diagram functionality to mermaid
  • 關於 甘特圖 語法,參考 這兒,

UML 圖表

可以使用UML圖表進行渲染。 Mermaid. 例如下面產生的一個序列圖:

張三 李四 王五 你好!李四, 最近怎麼樣? 你最近怎麼樣,王五? 我很好,謝謝! 我很好,謝謝! 李四想了很長時間, 文字太長了 不適合放在一行. 打量著王五... 很好... 王五, 你怎麼樣? 張三 李四 王五

這將產生一個流程圖。:

連結 長方形 圓角長方形 菱形
  • 關於 Mermaid 語法,參考 這兒,

FLowchart流程圖

我們依舊會支援flowchart的流程圖:

Created with Raphaël 2.2.0 開始 我的操作 確認? 結束 yes no
  • 關於 Flowchart流程圖 語法,參考 這兒.

匯出與匯入

匯出

如果你想嘗試使用此編輯器, 你可以在此篇文章任意編輯。當你完成了一篇文章的寫作, 在上方工具欄找到 文章匯出 ,生成一個.md檔案或者.html檔案進行本地儲存。

匯入

如果你想載入一篇你寫過的.md檔案,在上方工具欄可以選擇匯入功能進行對應副檔名的檔案匯入,
繼續你的創作。


  1. mermaid語法說明 ↩︎

  2. 註腳的解釋 ↩︎