《pytest測(cè)試實(shí)戰(zhàn)》讀書筆記

第一章 pytest入門

常用啟動(dòng)命令

1.pytest會(huì)在當(dāng)前目錄及子目錄尋找測(cè)試用例
2.Task結(jié)構(gòu),用于UI層和API層之間傳遞信息:

from collections import namedtuple
Task = namedtuple('Task',['summary','owner','done','id'])
# __new__.__defaults__創(chuàng)建默認(rèn)Task對(duì)象鼻听,不必指定所有屬性
Task.__new__.__defaults__ = (None,None,False,None) 
def test_defaluts():
    t1=Task()  # 默認(rèn)值
    t2=Task(None,None,False,None)
    assert T1 == T2
# 演示使用屬性名(而不是索引)來(lái)訪問(wèn)對(duì)象成員
def test_member_access():
    t=Task('buy milke','brain') 
    assert t.summary == 'buy milke'
    assert t.owner == 'brain'
    assert (t.done,t.id) == (False,None)
# `_asdict` 和 `_replace`函數(shù)

3.運(yùn)行單個(gè)測(cè)試用例: pytest -v test.py::test_asdict
4.常用命令行
--collect-only: 只是展示給定配置下運(yùn)行哪些測(cè)試用例瘪松,方便檢查
-k: 允許使用表達(dá)式指定運(yùn)行測(cè)試方法

pytest -k "asdict or defaluts" --collect-only  
pytest -k "asdict or defaluts" 
pytest -v -k "asdict or defaluts"  

-m 運(yùn)行指定標(biāo)記的用例
-m "mark1 and mark2"同時(shí)標(biāo)記mark1和mark2的
-m "mark1 or mark2"標(biāo)記mark1或mark2的
-m "mark1 and not mark2"標(biāo)記mark1,過(guò)濾掉mark2的
-x 遇到失敗停止pytest運(yùn)行
--maxfail=num 指定失敗幾次,停止運(yùn)行 。num=1時(shí)同-x (指運(yùn)行所有指定測(cè)試用例時(shí),失敗N次后停止)
-s 與 --capture=method 打印符合標(biāo)準(zhǔn)的輸出或信息酿联,如print
-l /--showlocals 測(cè)試失敗時(shí)打印出局部變量名和值,可避免一些不必要的print
-v 或者 --verbose : 可以查看具體運(yùn)行詳情
-q/--quiet:與-v相反夺巩,簡(jiǎn)化輸出信息贞让,常和--tb=line(僅打印異常的代碼位置)搭配使用
--tb=style決定失敗時(shí)輸出信息的顯示方式 (short,line柳譬,no:關(guān)閉,lang等)

第二章 編寫測(cè)試函數(shù)

演示如何使用assert喳张,如何處理可預(yù)期和不可預(yù)期的異常,如果借助類美澳,模塊销部,目錄來(lái)組織測(cè)試,以便管理大量的測(cè)試制跟。使用mark為預(yù)期會(huì)失敗的測(cè)試做標(biāo)記

測(cè)試示例程序

  1. test/func/init.py和test/unit/init.py都是空文件舅桩,作用是給pytest提供搜索路徑,找到測(cè)試根目錄和pytest.ini文件雨膨。(conftest.py也可以統(tǒng)一放在test根目錄)
  2. pytest.ini是可選的擂涛,它保存了pytest在該項(xiàng)目下的特定配置。
  3. conftest.py是pytest的“本地插件庫(kù)”聊记,包含hook函數(shù)和fixture歼指。hook可以將自定義邏輯引入pytest,用于改善pytest的執(zhí)行流程甥雕,fixture則是用于測(cè)試前后執(zhí)行配置及銷毀邏輯的外殼函數(shù),可以傳遞測(cè)試中用到的資源胀茵。
  4. 測(cè)試demo下載 傳送門
    安裝 cd code/tasks_proj pip install .

使用assert

  1. pytest.org上有很多復(fù)雜的assert例子
  2. 預(yù)期異常
with pytest.raises(TypeError):
    task.add(task='not a task object')
# 無(wú)論with內(nèi)容是什么社露,都會(huì)發(fā)生TypeError異常。如果測(cè)試通過(guò)琼娘,說(shuō)明發(fā)生了預(yù)期的TypeError異常峭弟;如果拋出其他類型的異常,則與預(yù)期不一致脱拼,測(cè)試失敗瞒瘸。

with pytest.raises(ValueError) as excinfo:
    tasks.start_task_db('some','mysql')
exception_msg=excinfo.value.args[0]
assert exception_msg == "db_type must be a 'tiny' or 'mongo'"
# 不止校驗(yàn)異常類型,還可以校驗(yàn)異常消息

標(biāo)記測(cè)試

  1. @pytest.mark.skip()裝飾器 : 跳過(guò)測(cè)試 (skipif可設(shè)置跳過(guò)條件)
  2. @pytest.mark.xfail():告訴pytest運(yùn)行此測(cè)試熄浓,但我們預(yù)期會(huì)失斍槌簟(如果實(shí)際失敗,則記過(guò)為xfail,如果實(shí)際成功俯在,則結(jié)果為XPASS竟秫,可在pytest.ini中強(qiáng)制執(zhí)行結(jié)果為fail
[pytest]
xfail_strict=ture

參數(shù)化

1.@pytest.mark.parametrize()第一個(gè)參數(shù)為逗號(hào)分隔的字符串列表,第二個(gè)參數(shù)是值列表parametrize()
2.parametrize()在測(cè)試運(yùn)行會(huì)優(yōu)化測(cè)試用例可視化跷乐,也可引入額外自定義參數(shù)肥败。ids:標(biāo)識(shí)用例的id

@pytest.mark.parametrize('a,b', [['2', '3'], ['1', '4']], ids=['2和3', '1和4'])
def test_param(a, b):
    print("===", int(a))
    assert int(a) + int(b) == 5

3.parametrize()可以加在測(cè)試類上,這樣數(shù)據(jù)集會(huì)被傳遞給所有類方法
4.parametrize()可以在參數(shù)值旁定義id做標(biāo)識(shí)愕提,pytest.param(<value>馒稍,id='something') 在id不能被參數(shù)化批量生成時(shí),需要自定義時(shí)浅侨,很管用

param = [
    pytest.param(1, 2, 5, id='failed'),
    pytest.param(3, 4, 7, id='success')]

@pytest.mark.parametrize('a,b,expect', param)
def test_param2(a, b, expect):
    assert int(a) + int(b) == int(expect)

第三章 pytest fixture

安裝tasks纽谒,cd code;pip install ./tasks_proj/
1.fixture函數(shù)會(huì)在測(cè)試函數(shù)之前運(yùn)行,如果fixture函數(shù)包含yield仗颈,那么系統(tǒng)會(huì)在yield處停止佛舱,轉(zhuǎn)而運(yùn)行測(cè)試函數(shù),等測(cè)試函數(shù)運(yùn)行完再回到fixture挨决,運(yùn)行yield后的代碼
2.--setup-show 回溯fixture的執(zhí)行過(guò)程
3.fixture內(nèi)發(fā)生的assert異常結(jié)果為ERROR请祖,測(cè)試函數(shù)assert發(fā)生的異常結(jié)果為FAIL
4.usefixtures
5.autouse=True 作用域內(nèi)的函數(shù)都運(yùn)行該fixture

fixture作用范圍scope

functionfixture默認(rèn)值,每個(gè)測(cè)試函數(shù)運(yùn)行一次脖祈,配置代碼再測(cè)試用例運(yùn)行之前運(yùn)行肆捕,銷毀代碼再測(cè)試用例運(yùn)行之后運(yùn)行
class每個(gè)測(cè)試類運(yùn)行一次,無(wú)論測(cè)試類里有多少類方法都可以共享這個(gè)fixture
module每個(gè)模塊只需要運(yùn)行一次盖高,無(wú)論模塊里有多少個(gè)測(cè)試函數(shù)慎陵,類方法或其他fixture都可以共享這個(gè)fixture
session每次會(huì)話只需要運(yùn)行一次,一次pytest會(huì)話中的所有測(cè)試函數(shù)喻奥,方法都可以共享這個(gè)fixture
--setup-show 可以觀察每個(gè)fixture被調(diào)用的次數(shù)席纽,以及在各自作用范圍下執(zhí)行配置,銷毀邏輯的順序
fixture只能使用同級(jí)別的或者更高級(jí)別的fixture撞蚕,不能反過(guò)來(lái)

fixture參數(shù)化

@pytest.fixture(params=tasks润梯,ids=task_ids) #也可參數(shù)化,也可指定id
def a_task(request):  # request是pytest內(nèi)建的fixture之一甥厦,代表fixture的調(diào)用狀態(tài)纺铭,有一個(gè)param字段,會(huì)被params列表的一個(gè)元素填充
    return request.param

2.fixture_value 內(nèi)置fixture刀疙?

  1. 對(duì)測(cè)試函數(shù)進(jìn)行參數(shù)化處理舶赔,可以多次運(yùn)行的只是該測(cè)試函數(shù);而使用參數(shù)化fixture谦秧,每個(gè)使用該fixture的測(cè)試函數(shù)都可以被運(yùn)行多次竟纳,這一特性非常強(qiáng)大撵溃。

第四章 內(nèi)置fixture

tmpdir和tmpdir_factory

內(nèi)置的tmpdirtmpdir_factory負(fù)責(zé)在測(cè)試開(kāi)始運(yùn)行前創(chuàng)建臨時(shí)文件或目錄,并在測(cè)試結(jié)束后刪除蚁袭。單個(gè)測(cè)試使用tmpdir征懈,多個(gè)測(cè)試使用tmpdir_factory
tmpdir的作用范圍是函數(shù)級(jí)別,tmpdir_factory的是會(huì)話級(jí)別 ,如果需要其他級(jí)別的揩悄,需要?jiǎng)?chuàng)建一個(gè)新的fixture卖哎。

def test_tmpdir(tmpdir):
    a_file=tmpdir.join("a.txt")
    b_dir=tmpdir.mkdir("something")
    b_file=b_dir.join("b.txt") 
    a_file.write("aaa")
    b_file.write("bbb")
    assert a_file.read()=="aaa"  and b_file.read()=="bbb"

pytestconfig

內(nèi)置的pytestconfig可以通過(guò)命令行參數(shù),選項(xiàng)删性,配置文件亏娜,插件,運(yùn)行目錄等方式來(lái)控制pytest蹬挺。它是request.config的快捷方式维贺,被稱為“pytest配置對(duì)象”

def pytest_addoption(parser):  #pytest的hook函數(shù)pytest_addoption,可添加命令行選項(xiàng)
    parser.addoption("--myopt",action="store_true",help="some my option")
    parser.addoption("--foo",action="store",default="bar",help="foo:bar or baz")

def test_option(pytestconfig):
    print(pytestconfig.gettoption('myopt'))
    print(pytestconfig.gettoption('foo'))
    print(pytestconfig.option.foo)
# 一些例子
def test_pytestconfig(pytestconfig):
    print(pytestconfig.args)
    print(pytestconfig.inifile)
    print(pytestconfig.invocation_dir)
    print(pytestconfig.rootdir)
    print(pytestconfig.getoption('showlocals'))

使用cache

cache用于測(cè)試會(huì)話傳遞給下一段會(huì)話
--last-failed(僅運(yùn)行上次未通過(guò)的)和--failed-first (之前未通過(guò)的首先運(yùn)行)很好的展示cache的功能巴帮,看看cache是如何存儲(chǔ)這些標(biāo)識(shí)數(shù)據(jù)的溯泣。
--cache-show可以顯示cache存儲(chǔ)的信息
--clear-cache 運(yùn)行前清空cache緩存

def test_cache(cache):
    cache.get(key,default)
    cache.set(key,value)

使用capsys

允許使用代碼讀取stdout和stderr,capsys.redouterr() 也可以臨時(shí)禁止抓取日志輸出capsys.redouterr() 榕茧。
pytest通常會(huì)抓取輸出垃沦,僅當(dāng)全部用例結(jié)束后,抓取到的日志才會(huì)顯示出來(lái)用押。--s參數(shù)可以關(guān)閉這個(gè)功能肢簿,在測(cè)試運(yùn)行期就把輸出直接發(fā)送到stdout,但有時(shí)可能只需要部分信息蜻拨,則可以用 capsys.disabled()臨時(shí)讓輸出繞過(guò)默認(rèn)的輸出捕獲機(jī)制
capsys.redouterr()

def test_disabled(capsys):
    with.capsys.disabled():
        print("aaaa")
    print("bbb")  # pytest -q 和 pytest -q -s的區(qū)別

monkeypatch

在運(yùn)行期間對(duì)類或模塊進(jìn)行動(dòng)態(tài)修改池充。常用于替換被測(cè)試代碼的部分運(yùn)行環(huán)境,或?qū)⑤斎胍蕾嚮蜉敵鲆蕾囂鎿Q成更容易測(cè)試的對(duì)象或函數(shù)缎讼。測(cè)試結(jié)束后收夸,無(wú)論結(jié)果是通過(guò)還是失敗,代碼都會(huì)復(fù)原(所有修改都會(huì)撤銷)
例如:修改環(huán)境變量monkey.setenv('HOME',tmpdir.mkdir('home'))
其他函數(shù)(setattr )

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末血崭,一起剝皮案震驚了整個(gè)濱河市卧惜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌功氨,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件手幢,死亡現(xiàn)場(chǎng)離奇詭異捷凄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)围来,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門跺涤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)匈睁,“玉大人,你說(shuō)我怎么就攤上這事桶错『剿簦” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵院刁,是天一觀的道長(zhǎng)糯钙。 經(jīng)常有香客問(wèn)我,道長(zhǎng)退腥,這世上最難降的妖魔是什么任岸? 我笑而不...
    開(kāi)封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮狡刘,結(jié)果婚禮上享潜,老公的妹妹穿的比我還像新娘。我一直安慰自己嗅蔬,他們只是感情好剑按,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著澜术,像睡著了一般艺蝴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瘪板,一...
    開(kāi)封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天吴趴,我揣著相機(jī)與錄音,去河邊找鬼侮攀。 笑死锣枝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的兰英。 我是一名探鬼主播撇叁,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼畦贸!你這毒婦竟也來(lái)了陨闹?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤薄坏,失蹤者是張志新(化名)和其女友劉穎趋厉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體胶坠,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡君账,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沈善。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乡数。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡椭蹄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出净赴,到底是詐尸還是另有隱情绳矩,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布玖翅,位于F島的核電站翼馆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏烧栋。R本人自食惡果不足惜写妥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望审姓。 院中可真熱鬧珍特,春花似錦、人聲如沸魔吐。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)酬姆。三九已至嗜桌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辞色,已是汗流浹背骨宠。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留相满,地道東北人层亿。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像立美,于是被迫代替她去往敵國(guó)和親匿又。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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