Pytest系列16 -分布式測(cè)試插件之pytest-xdist的詳細(xì)使用

一、前言

平常我們功能測(cè)試用例非常多時(shí)段多,比如有1千條用例酸些,假設(shè)每個(gè)用例執(zhí)行需要1分鐘,如果單個(gè)測(cè)試人員執(zhí)行需要1000分鐘才能跑完
當(dāng)項(xiàng)目非常緊急時(shí)巷送,會(huì)需要協(xié)調(diào)多個(gè)測(cè)試資源來(lái)把任務(wù)分成兩部分驶忌,于是執(zhí)行時(shí)間縮短一半,如果有10個(gè)小伙伴笑跛,那么執(zhí)行時(shí)間就會(huì)變成十分之一付魔,大大節(jié)省了測(cè)試時(shí)間
為了節(jié)省項(xiàng)目測(cè)試時(shí)間,10個(gè)測(cè)試同時(shí)并行測(cè)試飞蹂,這就是一種分布式場(chǎng)景
同樣道理几苍,當(dāng)我們自動(dòng)化測(cè)試用例排常多的時(shí)候, 一條條按順序執(zhí)行會(huì)非常慢陈哑,pytest-xdist的出現(xiàn)就是為了讓自動(dòng)化測(cè)試用例可以分布式執(zhí)行妻坝,從而節(jié)省自動(dòng)化測(cè)試時(shí)間
pytest-xdist是屬于進(jìn)程級(jí)別的并發(fā)

二、分布式執(zhí)行用例的設(shè)計(jì)原則(重要)
  • 用例之間是獨(dú)立的惊窖,用例之間沒(méi)有依賴關(guān)系刽宪,用例可以完全獨(dú)立運(yùn)行【獨(dú)立運(yùn)行】
  • 用例執(zhí)行沒(méi)有順序,隨機(jī)順序都能正常執(zhí)行【隨機(jī)執(zhí)行】
  • 每個(gè)用例都能重復(fù)運(yùn)行界酒,運(yùn)行結(jié)果不會(huì)影響其他用例【不影響其他用例】
三圣拄、插件安裝

pip3 install pytest-xdist -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

四、pytest-xdist通過(guò)一些獨(dú)特的測(cè)試執(zhí)行模式擴(kuò)展了pytest

測(cè)試運(yùn)行并行化:如果有多個(gè)CPU或主機(jī)毁欣,則可以將它們用于組合的測(cè)試運(yùn)行庇谆。 這樣可以加快開發(fā)速度或使用遠(yuǎn)程計(jì)算機(jī)的特殊資源。
--looponfail:在子進(jìn)程中重復(fù)運(yùn)行測(cè)試凭疮。 每次運(yùn)行之后饭耳,pytest都會(huì)等到項(xiàng)目中的文件更改后再運(yùn)行之前失敗的測(cè)試。 重復(fù)此過(guò)程执解,直到所有測(cè)試通過(guò)寞肖,然后再次執(zhí)行完整運(yùn)行。
跨平臺(tái)覆蓋:您可以指定不同的Python解釋程序或不同的平臺(tái)衰腌,并在所有這些平臺(tái)上并行運(yùn)行測(cè)試逝淹。

五、快速入門

這是運(yùn)行代碼的包結(jié)構(gòu)

14xdist是項(xiàng)目文件夾名稱
│  conftest.py
│  test_1.py
│  __init__.py
│              
├─test_51job
│  │  conftest.py
│  │  test_case1.py
│  │  __init__.py 
│          
├─test_toutiao
│  │  test_case2.py
│
├─test_weibo
│  │  conftest.py
│  │  test_case3.py
│  │  __init__.py 
│          

具體代碼
最外層的conftest.py

# 外層conftest.py

@pytest.fixture(scope="session")
def login():
    print("====登錄功能桶唐,返回賬號(hào)栅葡,token===")
    name = "testyy"
    token = "npoi213bn4"
    yield name, token
    print("====退出登錄!S仍蟆欣簇!====")

最外層的test1.py

import pytest


@pytest.mark.parametrize("n", list(range(5)))
def test_get_info(login, n):
    sleep(1)
    name, token = login
    print("***基礎(chǔ)用例:獲取用戶個(gè)人信息***", n)
    print(f"用戶名:{name}, token:{token}")

test51job包下的conftest.py

import pytest


@pytest.fixture(scope="module")
def open_51(login):
    name, token = login
    print(f"###用戶 {name} 打開51job網(wǎng)站###")

test51job包下的test_case1.py

from time import sleep

import pytest


@pytest.mark.parametrize("n", list(range(5)))
def test_case2_01(open_51, n):
    sleep(1)
    print("51job规脸,列出所有職位用例", n)


@pytest.mark.parametrize("n", list(range(5)))
def test_case2_02(open_51, n):
    sleep(1)
    print("51job,找出所有python崗位", n)

test_toutiao包下的test_case2.py

from time import sleep

import pytest


@pytest.mark.parametrize("n", list(range(5)))
def test_no_fixture(login, n):
    sleep(1)
    print("==沒(méi)有__init__測(cè)試用例熊咽,我進(jìn)入頭條了==", login)

test_weibo包下的conftest.py

import pytest


@pytest.fixture(scope="function")
def open_weibo(login):
    name, token = login
    print(f"&&& 用戶 {name} 返回微博首頁(yè) &&&")

test_weibo包下的test_case3.py

from time import sleep

import pytest


@pytest.mark.parametrize("n", list(range(5)))
class TestWeibo:
    def test_case1_01(self, open_weibo, n):
        sleep(1)
        print("查看微博熱搜", n)

    def test_case1_02(self, open_weibo, n):
        sleep(1)
        print("查看微博范冰冰", n)

不使用分布式測(cè)試的命令和所需執(zhí)行時(shí)間

圖片.png

可以看到莫鸭,執(zhí)行一條用例大概1s(因?yàn)槊總€(gè)用例都加了 sleep(1) ),一共30條用例横殴,總共運(yùn)行30s被因;那么如果有1000條用例,執(zhí)行時(shí)間就真的是1000s

使用分布式測(cè)試的命令和所需執(zhí)行時(shí)間
pytest -s -n auto

圖片.png

可以看到衫仑,最終運(yùn)行時(shí)間只需要6s梨与,我的電腦是真6核,假12核
-n auto:可以自動(dòng)檢測(cè)到系統(tǒng)的CPU核數(shù)文狱;從測(cè)試結(jié)果來(lái)看粥鞋,檢測(cè)到的是邏輯處理器的數(shù)量,即假12核
使用auto等于利用了所有CPU來(lái)跑用例瞄崇,此時(shí)CPU占用率會(huì)特別高
可以指定多少個(gè)cpul來(lái)跑用例
命令:
pytest -s -n 2

圖片.png

pytest-xdist和pytest-html結(jié)合使用
命令:
pytest -s -n auto --html=report.html --self-contained-html
pytest-xdist按照一定的順序執(zhí)行
pytest-xdist默認(rèn)是無(wú)序執(zhí)行的呻粹,可以通過(guò) --dist 參數(shù)來(lái)控制順序
--dist=loadscope

  • 將按照同一個(gè)模塊module下的函數(shù)和同一個(gè)測(cè)試類class下的方法來(lái)分組,然后將每個(gè)測(cè)試組發(fā)給可以執(zhí)行的worker苏研,確保同一個(gè)組的測(cè)試用例在同一個(gè)進(jìn)程中執(zhí)行
  • 目前無(wú)法自定義分組等浊,按類class分組優(yōu)先于按模塊module分組

**--dist=loadfile **

  • 按照同一個(gè)文件名來(lái)分組,然后將每個(gè)測(cè)試組發(fā)給可以執(zhí)行的worker摹蘑,確保同一個(gè)組的測(cè)試用例在同一個(gè)進(jìn)程中執(zhí)行

如何讓scope=session的feature在test session中僅僅執(zhí)行一次
pytest-xdist是讓每個(gè)worker進(jìn)程執(zhí)行屬于自己的測(cè)試用例集下的所有測(cè)試用例
這意味著在不同進(jìn)程中凿掂,不同的測(cè)試用例可能會(huì)調(diào)用同一個(gè)scope范圍級(jí)別較高(例如session)的fixture,該fixture則會(huì)被執(zhí)行多次纹蝴,這不符合scope=session的預(yù)期

如何解決?
雖然pytest-xdist沒(méi)有內(nèi)置的支持來(lái)確保會(huì)話范圍的夾具僅執(zhí)行一次踪少,但是可以通過(guò)使用鎖定文件進(jìn)行進(jìn)程間通信來(lái)實(shí)現(xiàn)塘安。

例子
下面的示例只需要執(zhí)行一次login(因?yàn)樗侵恍枰獔?zhí)行一次來(lái)定義配置選項(xiàng),等等)
當(dāng)?shù)谝淮握?qǐng)求這個(gè)fixture時(shí)援奢,則會(huì)利用FileLock僅產(chǎn)生一次fixture數(shù)據(jù)
當(dāng)其他進(jìn)程再次請(qǐng)求這個(gè)fixture時(shí)兼犯,則會(huì)從文件中讀取數(shù)據(jù)

import pytest
from filelock import FileLock


@pytest.fixture(scope="session")
def login():
    print("====登錄功能,返回賬號(hào)集漾,token===")
    with FileLock("session.lock"):
        name = "testyy"
        token = "npoi213bn4"
        # web ui自動(dòng)化
        # 聲明一個(gè)driver切黔,再返回

        # 接口自動(dòng)化
        # 發(fā)起一個(gè)登錄請(qǐng)求,將token返回都可以這樣寫

    yield name, token
    print("====退出登錄>咂N诚肌!====")

參考鏈接
https://www.cnblogs.com/poloyy/p/12694861.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驱显,一起剝皮案震驚了整個(gè)濱河市诗芜,隨后出現(xiàn)的幾起案子瞳抓,更是在濱河造成了極大的恐慌,老刑警劉巖伏恐,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孩哑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡翠桦,警方通過(guò)查閱死者的電腦和手機(jī)横蜒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)销凑,“玉大人丛晌,你說(shuō)我怎么就攤上這事∥偶” “怎么了茵乱?”我有些...
    開封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)孟岛。 經(jīng)常有香客問(wèn)我瓶竭,道長(zhǎng),這世上最難降的妖魔是什么渠羞? 我笑而不...
    開封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任斤贰,我火速辦了婚禮,結(jié)果婚禮上次询,老公的妹妹穿的比我還像新娘荧恍。我一直安慰自己,他們只是感情好屯吊,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開白布送巡。 她就那樣靜靜地躺著,像睡著了一般盒卸。 火紅的嫁衣襯著肌膚如雪骗爆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天蔽介,我揣著相機(jī)與錄音摘投,去河邊找鬼。 笑死虹蓄,一個(gè)胖子當(dāng)著我的面吹牛犀呼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播薇组,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼外臂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了律胀?” 一聲冷哼從身側(cè)響起专钉,我...
    開封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤挑童,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后跃须,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體站叼,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年菇民,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尽楔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡第练,死狀恐怖阔馋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情娇掏,我是刑警寧澤呕寝,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站婴梧,受9級(jí)特大地震影響下梢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塞蹭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一孽江、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧番电,春花似錦岗屏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至娩井,卻和暖如春暇屋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撞牢。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叔营,地道東北人屋彪。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像绒尊,于是被迫代替她去往敵國(guó)和親畜挥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

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