pytest探究:如何發(fā)現(xiàn)測(cè)試內(nèi)容

pytest發(fā)現(xiàn)規(guī)則

  • 如果沒(méi)指定參數(shù),并且配置了 testpaths (詳見(jiàn)1.testpaths)馏慨,會(huì)從 testpaths 查找鞍恢,否則從當(dāng)前目錄查找希太。也可以通過(guò)命令行指定目錄,文件名琅锻,節(jié)點(diǎn) id 的組合卦停。
  • 遞歸目錄,直到遇到 norecursedirs (詳見(jiàn)3.norecursedirs)為止
  • 在所有目錄中搜索 test_*.py 或者 *_test.py 文件恼蓬,并通過(guò)測(cè)試包名(詳見(jiàn)4. 測(cè)試包名)導(dǎo)入他們惊完。
  • 從文件中收集測(cè)試項(xiàng),包括:
    • test 開(kāi)頭的函數(shù)或類(lèi)外方法
    • test 開(kāi)頭的函數(shù)或方法处硬,在 Test 開(kāi)頭的類(lèi)中(這個(gè)類(lèi)不能有 init方法)

1.testpaths

從 rootdir 下的 testpaths 開(kāi)始找 test(如果命令行沒(méi)設(shè)置其他的目錄小槐,文件,或測(cè)試ids) 荷辕,它可以加速測(cè)試收集凿跳,過(guò)濾掉不想要的測(cè)試內(nèi)容。

創(chuàng)建如下目錄結(jié)構(gòu)疮方,在 tox.ini 文件中加入 testpaths :

image

tox.ini 配置文件如下:

[pytest]
testpaths = a/a1

可以看到控嗜, pytest 設(shè)置 tox.ini 文件為 inifile ,同時(shí)設(shè)置了 testpaths 骡显,并且只從 a/a1 目錄下收集測(cè)試項(xiàng):

[
image

image1701×419 15.2 KB](https://ceshiren.com/uploads/default/original/2X/2/2e3c3ed384523af8f4cc67f8e510e1f0158b5090.png)

2.rootdir

rootdir 的作用如下:

  • 構(gòu)建 nodeids時(shí)疆栏,每一個(gè) test 都有唯一的標(biāo)識(shí) nodeid ,標(biāo)識(shí)的根目錄就是 rootdir 惫谤,包括絕對(duì)路徑壁顶,類(lèi)名, 函數(shù)名和參數(shù)化溜歪。
  • 存放插件的測(cè)試信息若专,比如 cache 1 插件在 rootdir 下創(chuàng)建了 .pytest_cache 目錄存儲(chǔ)交叉測(cè)試運(yùn)行狀態(tài)。

比如當(dāng) rootdir 為 pytest_example 時(shí)蝴猪,其下就存在 cache 插件存放目錄 .pytest_cache :

image

可以用命令行參數(shù)或者 ini_file 指定 `rootdir :

  • --rootdir=path 可以設(shè)置 rootdir 目錄
  • pytest.ini 中的 addopts 參數(shù)可以修改 pytest 默認(rèn)參數(shù)

pytest.ini 內(nèi)容如下调衰,它指定 pytest 命令的默認(rèn)參數(shù)為 --rootdir=path ,當(dāng)只執(zhí)行 pytest 命令時(shí)拯腮,會(huì)自動(dòng)加上 --rootdir=path

# content of pytest.ini or tox.ini
[pytest]
addopts = --rootdir=path

如果不顯示指定 rootdir 的位置窖式, pytest 會(huì)按照下述規(guī)則自動(dòng)尋找 rootdir :

  • 尋找多個(gè)參數(shù)的共同祖先目錄,如果沒(méi)有动壤,將當(dāng)前工作目錄設(shè)置為共同祖先目錄萝喘。
  • 從共同祖先目錄及上級(jí)目錄中找三個(gè)文件 pytest.ini , tox.inisetup.cfg ,若找到其中任何一個(gè)文件,則將其變?yōu)?ini-file 阁簸,而它所在的目錄就是 rootdir爬早。
  • 如果沒(méi)有 ini-file ,從共同祖先目錄及上級(jí)目錄中找 setup.py 启妹,如果有筛严,則將其所在目錄設(shè)為 rootdir
  • 如果沒(méi)有 setup.py 饶米,從每個(gè)參數(shù)及其上級(jí)目錄中找 pytest.ini , tox.inisetup.cfg 桨啃, 如果找到,它將成為 ini-file 檬输,并且其目錄將成為rootdir照瘾。
  • 如果沒(méi)有 ini-file ,把共同祖先目錄作為 rootdir丧慈,這么做的原因是析命,即使不是包,且沒(méi)有配置文件逃默,也能使用 pytest 鹃愤。

比如以下目錄,請(qǐng)注意其中的 pytest.ini 文件位置:

image

運(yùn)行如下 pytest 命令完域, pytest 首先找到兩個(gè)參數(shù)的公共祖先目錄 a 软吐,然后從 a 目錄中找到了 pytest.ini 文件,于是這個(gè)文件就是 inifile 筒主,而 rootdir 就是目錄 a :

[
image

image1132×219 28.7 KB](https://ceshiren.com/uploads/default/original/2X/b/b3662a7dca7c51c8501690cf9bb8b9406abb0713.png)

將 pytest.ini 的位置放入 a1目錄下:


image

pytest 首先找到了公共目錄 a 关噪,但是在目錄 a 及其上級(jí)目錄沒(méi)有發(fā)現(xiàn)任何配置文件(pytest.ini , tox.ini 和 setup.cfg鸟蟹,setup.py)乌妙,于是從每個(gè)參數(shù)及其上級(jí)目錄中找,發(fā)現(xiàn)目錄 a1 下存在 pytest.ini 建钥,它將成為 ini-file 藤韵,并且其目錄將成為rootdir。

[
image

image1166×217 27.9 KB](https://ceshiren.com/uploads/default/original/2X/8/8459740ccc0d34bfe8070cae9b2778f73f76580f.png)

沒(méi)有 pytest.ini 文件時(shí)熊经, rootdir 是 pytest_example 而不是 a 泽艘, 比如下圖

image

[
image

image1173×217 28.3 KB](https://ceshiren.com/uploads/default/original/2X/6/6ca3274a41472879e58ed16abc2cfcbc0d47f143.png)

如果沒(méi)有參數(shù), pytest 會(huì)把當(dāng)前目錄設(shè)為 rootdir 镐依。比如參考以下目錄結(jié)構(gòu)和運(yùn)行結(jié)果:

image

[
image

image1005×226 27.1 KB](https://ceshiren.com/uploads/default/original/2X/e/efd3d98414f2721188f69650bc5e61780e5a103a.png)

即使設(shè)置了 pytest.ini 匹涮,如果 pytest 沒(méi)有參數(shù)的話(huà),會(huì)把當(dāng)前目錄 a 設(shè)置為 rootdir :

image

[
image

image917×227 26.5 KB](https://ceshiren.com/uploads/default/original/2X/1/1ec2c9a6148d55a5d2f733b3f99e26f05e97cb86.png)

注意:只要存在 pytest.ini 文件槐壳,就能被 pytest 匹配上然低,但是 tox.inisetup.cfg 必須包含 [pytest] 或者 [tool:pytest] 部分才能被匹配,如果有多個(gè) ini-file ,最終只會(huì)挑選出一個(gè)(優(yōu)先選擇pytest.ini)雳攘。 pytest 存在一個(gè) bug 带兜,用戶(hù)可以自定義插件,插件可以傳參吨灭,如果傳入的是路徑刚照,比如 pytest --log-output ../../test.log args,上述插件不寫(xiě) args 的話(huà)喧兄, pytest 會(huì)使用 test.log 文件夾確定rootdir(參見(jiàn)issue 1435)无畔,比如 pytest --log-output ../../test.log 。即使用點(diǎn) . 來(lái)引用當(dāng)前工作目錄吠冤,也會(huì)發(fā)生上述問(wèn)題檩互。

3.配置 norecursedirs

https://docs.pytest.org/en/latest/reference.html#confval-norecursedirs 1

設(shè)置目錄的基本名字表達(dá)式(fnmatch-match風(fēng)格),用于是否進(jìn)行遞歸咨演。

*            匹配所有內(nèi)容
?           匹配所有單字符
[seq]     匹配 seq 中的任一個(gè)字符
[!seq]    匹配不在 seq 中的字符

默認(rèn)表達(dá)式有 :

'.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv' 闸昨,可以設(shè)置norecursedirs替代默認(rèn)表達(dá)式,比如不遞歸指定目錄:

[pytest] 
norecursedirs = .svn _build tmp*

pytest 會(huì)通過(guò) activation 腳本識(shí)別并忽略 python 虛擬環(huán)境薄风, pytest 不會(huì)收集虛擬環(huán)境中的 test 饵较,但可以使用 ??collect?in?virtualenv 選項(xiàng)開(kāi)啟收集。注意遭赂,norecursedirs 級(jí)別高于 ??collect?in?virtualenv 循诉,比如你開(kāi)啟了 ??collect?in?virtualenv 選項(xiàng),就必須重寫(xiě) norecursedirs 才能讓其生效(因?yàn)槟J(rèn)值有 venv 會(huì)過(guò)濾掉虛擬環(huán)境)撇他。

比如下面的目錄結(jié)構(gòu)茄猫,在 pytest_example 目錄下存在配置文件 tox.ini :

image

tox.ini 的內(nèi)容如下:

[pytest]
norecursedirs = a1

[
image

image1510×406 14.2 KB](https://ceshiren.com/uploads/default/original/2X/5/5f8afaa0b020e9010b4a4147d9a2d99f41e6220a.png)

4. 測(cè)試包名

如果 pytest 發(fā)現(xiàn)一個(gè)測(cè)試文件 a/b/test_module.py ,會(huì)發(fā)生以下情況:

  • 設(shè)置 basedir :發(fā)現(xiàn)第一個(gè)不包含 __init__.py 的上級(jí)目錄困肩,如果 ab 都包含 __init__.py 文件划纽, a 的父目錄將成為 basedir
  • 使用 sys.path.insert(0, basedir) 將 basedir 置于環(huán)境變量的首位锌畸。
  • import a.b.test_module 把路徑分割符 \ 轉(zhuǎn)換成了 “.” 勇劣,讓目錄名和文件名直接映射到導(dǎo)入名。

在較大的項(xiàng)目中潭枣,可能會(huì)相互導(dǎo)入多個(gè)測(cè)試模塊比默,規(guī)范的導(dǎo)入名稱(chēng)可規(guī)避意外情況,例如一個(gè)測(cè)試模塊被導(dǎo)入兩次盆犁。

測(cè)試

1. 無(wú)參數(shù)
現(xiàn)在不對(duì) pytest 設(shè)置額外參數(shù)命咐,不設(shè)置 testpaths ,也不設(shè)置 norecursedirs 谐岁。假設(shè)以下目錄結(jié)構(gòu)醋奠,在目錄 pytest_example 下有一個(gè)包 a 瓮下,它下面 存在一個(gè) test_a.py 和目錄 a1 ,目錄 a1 下面存在 test_a2.py:

pytest_example/
|- a/
   |- __init__.py
   |- test_a.py
   |- a1/
      |- tests/
         |- test_a1.py

test_a.py 和 test_a1.py 的代碼和執(zhí)行結(jié)果分別如下:


# 以下是 test_a.py 代碼
def test_a():
    print('test_a')
# 以下是 test_a2.py 代碼
class Test_A1:
    def test_a1(self):
        print("test_a1")

使用命令行 cd 到 pytest_example 目錄下钝域,執(zhí)行 pytest 命令讽坏,其結(jié)果如下:

[
image

image995×273 30.2 KB](https://ceshiren.com/uploads/default/original/2X/4/42e0d5faa63967a83976d8e8e9d1a8334ccc5aa7.png)

可以看出, pytest 從 pytest_example 目錄開(kāi)始遞歸收集測(cè)試例证,收集到了兩個(gè)測(cè)試內(nèi)容: test_a.py 和 test_a1.py路呜,它不會(huì)區(qū)分包和目錄,也不會(huì)捕獲標(biāo)準(zhǔn)輸出织咧, 輸出結(jié)果打印 rootdir 的內(nèi)容 胀葱,后面會(huì)講它的作用。

更多技術(shù)文章可點(diǎn)擊獲取 http://qrcode.testing-studio.com/f?from=jianshu&url=https://ceshiren.com/t/topic/3822

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末笙蒙,一起剝皮案震驚了整個(gè)濱河市抵屿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捅位,老刑警劉巖轧葛,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異艇搀,居然都是意外死亡尿扯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)焰雕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)衷笋,“玉大人,你說(shuō)我怎么就攤上這事矩屁”僮冢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵吝秕,是天一觀的道長(zhǎng)泊脐。 經(jīng)常有香客問(wèn)我,道長(zhǎng)郭膛,這世上最難降的妖魔是什么晨抡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任氛悬,我火速辦了婚禮则剃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘如捅。我一直安慰自己棍现,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布镜遣。 她就那樣靜靜地躺著己肮,像睡著了一般士袄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谎僻,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天娄柳,我揣著相機(jī)與錄音,去河邊找鬼艘绍。 笑死赤拒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诱鞠。 我是一名探鬼主播挎挖,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼航夺!你這毒婦竟也來(lái)了蕉朵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤阳掐,失蹤者是張志新(化名)和其女友劉穎始衅,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體缭保,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡觅闽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涮俄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛉拙。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖彻亲,靈堂內(nèi)的尸體忽然破棺而出孕锄,到底是詐尸還是另有隱情,我是刑警寧澤苞尝,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布畸肆,位于F島的核電站,受9級(jí)特大地震影響宙址,放射性物質(zhì)發(fā)生泄漏轴脐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一抡砂、第九天 我趴在偏房一處隱蔽的房頂上張望大咱。 院中可真熱鬧,春花似錦注益、人聲如沸碴巾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)厦瓢。三九已至提揍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間煮仇,已是汗流浹背劳跃。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浙垫,地道東北人售碳。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓惕稻,卻偏偏與公主長(zhǎng)得像若皱,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲸阔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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