pytest 快速入門(mén)說(shuō)明

快速開(kāi)始

pytest是目前比較流行的單元測(cè)試工具,可以幫助研發(fā)做單元測(cè)試, 可以幫助測(cè)試構(gòu)造自動(dòng)化測(cè)試case。pytest結(jié)合報(bào)告生成工具Allure,可以讓我們更好的查看測(cè)試結(jié)果。

image

1、用例文件:所有文件名為 test_ 開(kāi)頭 或者 _test 開(kāi)頭的文件會(huì)被識(shí)別為用例文件。
2、用例類,測(cè)試文件中每個(gè)Test開(kāi)頭的類就是一個(gè)測(cè)試用例類。
3、測(cè)試用例:測(cè)試類中每個(gè)test開(kāi)頭的方法就是一條測(cè)試用例,測(cè)試文件中每個(gè)test開(kāi)頭的函數(shù)也是一條測(cè)試用例
4、執(zhí)行用例:pytest 會(huì)遞歸查找當(dāng)前目錄下所有以 test 開(kāi)始或結(jié)尾的 Python 腳本,并執(zhí)行文件內(nèi)的所有以 test 開(kāi)始或結(jié)束的函數(shù)和方法。

Case 1

1. 編寫(xiě)用例

用例函數(shù)

def add(a, b):
    return a + b

def test_add():
    assert add(1, 2) == 3

2. 執(zhí)行測(cè)試

測(cè)試文件test_learn.py文件夾下執(zhí)行pytest

PyTest$  pytest 
============================================================================= test session starts =============================================================================
platform darwin -- Python 3.9.6, pytest-7.2.1, pluggy-1.0.0
rootdir: /Users/**/technical-operation-master/FSHandle/PyTest
plugins: allure-pytest-2.12.0
collected 1 item                                                                                                                                                              

test_learn.py .   
============================================================================== 1 passed in 0.02s ==============================================================================

test_learn.py . 測(cè)試結(jié)果中 .代表測(cè)試通過(guò)S代表測(cè)試跳過(guò),<font color='red'> F代表測(cè)試失敗</font>

Case 2

1. 編寫(xiě)用例 test_ 開(kāi)頭 或者 _test 開(kāi)頭

用例類和函數(shù)

def add(a, b):
    return a + b


def test_add():
    assert add(1, 2) == 3


class TestCalculateMethod:

    def subtraction(self, a, b):
        return a - b

    def test_subtraction(self):
        return self.subtraction(2, 1) == 1

    def test_add(self):
        assert add(1, 2) == 4

執(zhí)行測(cè)試pytest

========== test session starts ==========
platform darwin -- Python 3.9.6, pytest-7.2.1, pluggy-1.0.0
rootdir: /Users/**/technical-operation-master/FSHandle/PyTest
plugins: allure-pytest-2.12.0
collected 3 items                                                                                                                                                             

test_learn.py ..F [100%]                                                                                                          

========== FAILURES ==========

一共3個(gè)test case, 2個(gè)成功,1個(gè)失敗

測(cè)試函數(shù)

斷言

assert **  判斷**為真
assert not ** 判斷**不為真
assert a in b 判斷b包含a
assert a == b 判斷a等于b
assert a != b 判斷a不等于b

測(cè)試異常捕獲 pytest.raises(CustomException)

有些case需要測(cè)試,異常情況下是否可以正常拋出異常

import pytest

class CustomException(Exception):
    pass

class TestPytest:
    def test_exception_catch(self):         
        with pytest.raises(CustomException) as e:
            raise CustomException("custom exception")
        assert e.value.args[0] == "custom exception"

參數(shù)化 pytest.mark.parametrize("param_name", params)

比如登錄模塊,我們要驗(yàn)證正常用戶名、密碼、錯(cuò)誤的用戶名密碼、還有異常的用戶名密碼等case,無(wú)需再寫(xiě)多個(gè)case,或者在測(cè)試方法里邊構(gòu)造循環(huán),只需引入?yún)?shù)化即可實(shí)現(xiàn)。


@pytest.mark.parametrize("user_name, user_pass",
                         [("jack001", "eflds8fse30f4lfj"),
                          ("jack01", "sdfssfef"),
                          ("jack", "sdfs"),
                          ("jack", "sdfsdfsdf")])
def test_login(user_name, user_pass):
    assert len(user_name) > 5
    assert len(user_pass) > 5

執(zhí)行測(cè)試

?  pytest
=================== test session starts ===================
platform darwin -- Python 3.9.6, pytest-7.2.1, pluggy-1.0.0
rootdir: /Users/**/technical-operation/FSHandle
plugins: allure-pytest-2.12.0
collected 4 items                                                                                                                                                             

test_function.py ..FF  [100%]  

=================== FAILURES ===================

一共收集到了4個(gè)Case,2個(gè)成功,2個(gè)失敗

預(yù)見(jiàn)錯(cuò)誤 pytest.mark.xfail

import sys
@pytest.mark.xfail(sys.platform != 'darwin',
                   reason='other version is not implement')
def test_new_method():
    print(sys.platform)

Case跳過(guò) @pytest.mark.skip(reason='')


@pytest.mark.skip(reason='method is not ready')
def test_skip():
    assert True


@pytest.mark.skipif(sys.platform != 'darwin',
                    reason='other platform is not support')
def test_skip_if():
    assert True

通過(guò)運(yùn)行測(cè)試時(shí)制定測(cè)試內(nèi)容

pytest.main (['./path/test_module.py::TestClass::test_method'])
pytest ./path/test_module.py::TestClass::test_method
pytest.main(['-k','new','./path/test_module.py'])

預(yù)處理和后處理



@pytest.fixture(scope='function')
def func_scope():
    print('before')
    yield
    print('after')

@pytest.fixture(scope='module')
def mod_scope():
    print('before')
    yield
    print('after')

@pytest.fixture(scope='session')
def sess_scope():
    print('before')
    yield
    print('after')

@pytest.fixture(scope='class')
def class_scope():
    print('before')
    yield
    print('after')


class TestScope(object):
    def test_scope(self, class_scope, sess_scope, mod_scope, func_scope):
        pass

    def test_scope01(self, class_scope, sess_scope, mod_scope, func_scope):
        pass


運(yùn)行測(cè)試

?  pytest -s --setup-show
========== test session starts ==========
platform darwin -- Python 3.9.6, pytest-7.2.1, pluggy-1.0.0
rootdir: /Users/Developer/technical-operation/FSHandle
plugins: allure-pytest-2.12.0
collected 2 items                                                                                                                                                             

test_function.py before

SETUP    S sess_scopebefore

    SETUP    M mod_scopebefore

      SETUP    C class_scopebefore

        SETUP    F func_scope
        test_function.py::TestScope::test_scope (fixtures used: class_scope, func_scope, mod_scope, sess_scope).after

        TEARDOWN F func_scopebefore

        SETUP    F func_scope
        test_function.py::TestScope::test_scope01 (fixtures used: class_scope, func_scope, mod_scope, sess_scope).after

        TEARDOWN F func_scopeafter

      TEARDOWN C class_scopeafter

    TEARDOWN M mod_scopeafter

TEARDOWN S sess_scope

=========== 2 passed in 0.02s ===========

按照如下順序執(zhí)行:

  1. scope = session 被執(zhí)行了一次
  2. scope = module 被執(zhí)行了一次
  3. scope = class 如果func被放在class中, 則只執(zhí)行一次
  4. scope = class 如果func沒(méi)被放在class中, 則每個(gè)函數(shù)執(zhí)行前,都執(zhí)行一次
  5. scope = function 每次執(zhí)行方法前都會(huì)執(zhí)行

pytest參數(shù)說(shuō)明

-v  說(shuō)明:可以輸出用例更加詳細(xì)的執(zhí)行信息,比如用例所在的文件及用例名稱等
-s  說(shuō)明:輸入我們用例中的調(diào)式信息,比如print的打印信息等
-x:遇到錯(cuò)誤的用例,立即退出執(zhí)行,并輸出結(jié)果
-k  "關(guān)鍵字" 說(shuō)明:執(zhí)行用例包含“關(guān)鍵字”的用例,允許使用or、and
-q  說(shuō)明:簡(jiǎn)化控制臺(tái)的輸出,可以看出輸出信息和上面的結(jié)果都不一樣,下圖中有兩個(gè)..點(diǎn)代替了pass結(jié)果


# 如果要運(yùn)行多個(gè)標(biāo)識(shí)的話,用表達(dá)式,如下
pytest -k "slow or faster" test_1.py  運(yùn)行有slow標(biāo)識(shí)或 faster標(biāo)識(shí)用例

通過(guò)pytest.main()執(zhí)行測(cè)試

pytest.main(['./'])
# 指定路徑、模塊、類、方法
pytest.main (['./path/test_module.py::TestClass::test_method']) 
# 指定關(guān)鍵字
pytest.main(['-k','new','./path/test_module.py']) 

# -s,測(cè)試結(jié)果中顯示測(cè)試用例里print的內(nèi)容
pytest.main(["-s", "testcase/test_case.py"])
# -v,設(shè)置測(cè)試結(jié)果顯示的詳細(xì)程度
pytest.main(["-v", "testcase/test_case.py"])
# -q,設(shè)置測(cè)試結(jié)果顯示的詳細(xì)程度
pytest.main(["-q", "testcase/test_case.py"])

祝你好運(yùn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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