1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        聊一聊,Python自動化測試框架

        共 7947字,需瀏覽 16分鐘

         ·

        2021-01-14 22:26

        關(guān)注上方“測試開發(fā)技術(shù)”,選擇星標,

        干貨技術(shù),第一時間送達!


        在Python語言系中,有很多可用的自動化測試框架,比如早期大多數(shù)人會選用 unittest+HTMLTestRunner、Nose等,最近幾年比較常用的有Robot Framework,Robot Framework它是Python下一款非常通用的測試框架,采用擴展插件的機制可以幫助我們實現(xiàn)幾乎任何類型的自動化測試工作,如接口自動化測試、App自動化測試、Web UI自動化測試等,而針對Robot Framework框架系統(tǒng)性的使用和講解,筆者年初出版上市過一本《自動化測試實戰(zhàn)寶典》一書,感興趣的,可參閱此書:重磅消息 |《自動化測試實戰(zhàn)寶典:從小工到專家》隆重上市!。


        今天本文重點介紹在Python語言下,另外一款通用的測試框架Pytest,雖說作為Robot Framework框架一書的作者去介紹Pytest,貌似不太合理,但框架技術(shù)本是一家,能快速解決實際問題的框架就是好框架,在年初的時候,也發(fā)表過一篇關(guān)于Robot Framework與Pytest框架選擇的一些建議:?聊一聊:Robot Framework被誤會多年的秘密,感興趣的讀者可以看看。


        一句話總結(jié):Pytest核心思路和Robot Framework大體一樣,可以通過插件擴展的形式,來滿足不同場景下的自動化測試需求。

        1. Pytest介紹

        Pytest是一個非常成熟的全功能的Python測試框架,與python自帶的unittest測試框架類似,但是比unittest框架使用起來更簡潔,功能更強大。

        提供完善的在線文檔,并有著大量的第三方插件和內(nèi)置幫助,適用于許多小型或大型項目。適合簡單的單元測試到復(fù)雜的功能測試。還可以執(zhí)行 nose, unittestdoctest 風(fēng)格的測試用例。支持良好的集成實踐, 支持擴展的 xUnit 風(fēng)格 setup,支持非 Python 測試。支持生成測試覆蓋率報告,支持 PEP8 兼容的編碼風(fēng)格。

        2. Pytest安裝及基本使用

        Pytest安裝非常簡單,可以通過 pip 命令直接在線安裝:

        pip?install?-U?pytest

        Pytest 官方文檔:https://docs.pytest.org/en/latest/

        安裝好之后,調(diào)用 pytest測試腳本方式:

        1、py.test:

        Pytest 提供直接調(diào)用的命令行工具,即 py.test,最新版本 pytest 和 py.test 兩個命令行工具都可用

        2、python -m pytest:

        效果和 py.test 一樣, 這種調(diào)用方式在多 Python 版本測試的時候是有用的, 例如測試 Python3:

        python3?-m?pytest?[...]

        基本語法:

        usage:?py.test?[options]?[file_or_dir]?[file_or_dir]?[...]

        部分參數(shù)介紹:

        py.test?--version???????????????查看版本
        py.test?--fixtures,?--funcargs??查看可用的?fixtures
        pytest?--markers????????????????查看可用的?markers
        py.test?-h,?--help??????????????命令行和配置文件幫助

        #?失敗后停止
        py.test?-x???????????首次失敗后停止執(zhí)行
        py.test?--maxfail=2??兩次失敗之后停止執(zhí)行

        #?調(diào)試輸出
        py.test?-l,?--showlocals??在?traceback?中顯示本地變量
        py.test?-q,?--quiet???????靜默模式輸出
        py.test?-v,?--verbose?????輸出更詳細的信息
        py.test?-s????????????????捕獲輸出,?例如顯示?print?函數(shù)的輸出
        py.test?-r?char???????????顯示指定測試類型的額外摘要信息
        py.test?--tb=style????????錯誤信息輸出格式
        ????-?long????默認的traceback信息格式化形式
        ????-?native??標準庫格式化形式
        ????-?short???更短的格式
        ????-?line????每個錯誤一行

        #?運行指定?marker?的測試
        pytest?-m?MARKEXPR

        #?運行匹配的測試
        py.test?-k?stringexpr

        #?只收集并顯示可用的測試用例,但不運行測試用例
        py.test?--collect-only

        #?失敗時調(diào)用?PDB
        py.test?--pdb

        3.Pytest用例執(zhí)行

        3.1 用例查找規(guī)則

        如果不帶參數(shù)運行pytest,那么其先從配置文件(pytest.ini,tox.ini,setup.cfg)中查找配置項 testpaths 指定的路徑中的test case,如果沒有則從當前目錄開始查找,否則,命令行參數(shù)就用于目錄、文件查找。查找的規(guī)則如下:

        • 查找指定目錄中以 test 開頭的目錄
        • 遞歸遍歷目錄,除非目錄指定了不同遞歸
        • 查找文件名以 test_ 開頭的文件
        • 查找以 Test 開頭的類(該類不能有 init 方法)
        • 查找以 test_ 開頭的函數(shù)和方法并進行測試

        如果要從默認的查找規(guī)則中忽略查找路徑,可以加上 --ingore 參數(shù),例如:

        pytest?--ignore=test_case/xxx.py

        3.2 執(zhí)行選擇用例

        1、執(zhí)行單個模塊中的全部用例:

        py.test?test_demo.py

        2、執(zhí)行指定路徑下的全部用例:

        py.test?somepath

        3、執(zhí)行字符串表達式中的用例:

        py.test?-k?stringexpr

        4、運行指定模塊中的某個用例,如運行 test_demo.py 模塊中的 test_func 測試函數(shù):

        pytest?test_demo.py::test_func

        5、運行某個類下的某個用例,如運行 TestClass 類下的 test_method 測試方法:

        pytest?test_demo.py::TestClass::test_method

        4.Pytest Fxiture特性

        fixturepytest 特有的功能,它用 pytest.fixture 標識,定義在函數(shù)前面。在編寫測試函數(shù)的時候,可以將此函數(shù)名稱做為傳入?yún)?shù),pytest 將會以依賴注入方式,將該函數(shù)的返回值作為測試函數(shù)的傳入?yún)?shù)。

        pytest.fixture(scope='function',?params=None,?autouse=False,?ids=None)

        4.1 作為參數(shù)

        fixture 可以作為其他測試函數(shù)的參數(shù)被使用,前提是其必須返回一個值:

        @pytest.fixture()
        def?hello():
        ????return?"hello"

        def?test_string(hello):
        ????assert?hello?==?"hello",?"fixture?should?return?hello"

        4.2 作為 setup

        fixture 也可以不返回值,這樣可以用于在測試方法運行前運行一段代碼:

        @pytest.fixture()??#?默認參數(shù),每個測試方法前調(diào)用
        def?before():
        ???print('before?each?test')

        def?test_1(before):
        ???print('test_1()')

        @pytest.mark.usefixtures("before")
        def?test_2():
        ???print('test_2()')

        這種方式與 setup_method、setup_module 等的用法相同,其實它們也是特殊的 fixture。

        在上例中,有一個測試用了 pytest.mark.usefixtures裝飾器來標記使用哪個 fixture,這中用法表示在開始測試前應(yīng)用該 fixture 函數(shù)但不需要其返回值。

        4.3 fixture作用范圍

        fixtrue 可以通過設(shè)置 scope 參數(shù)來控制其作用域(同時也控制了調(diào)用的頻率)。如果 scope='module',那么 fixture 就是模塊級的,這個 fixture 函數(shù)只會在每次相同模塊加載的時候執(zhí)行。這樣就可以復(fù)用一些需要時間進行創(chuàng)建的對象。fixture 提供四種作用域,用于指定 fixture 初始化的規(guī)則:

        • function:每個測試函數(shù)之前執(zhí)行一次,默認
        • class: 每個類之前執(zhí)行一次,
        • module:每個模塊加載之前執(zhí)行一次
        • session:每次 session 之前執(zhí)行一次,即每次測試執(zhí)行一次

        4.4 反向請求

        fixture 函數(shù)可以通過接受 request 對象來反向獲取請求中的測試函數(shù)、類或模塊上下文。例如:

        @pytest.fixture(scope="module")
        def?smtp(request):
        ????import?smtplib
        ????server?=?getattr(request.module,?"smtpserver",?"smtp.qq.com")
        ????smtp?=?smtplib.SMTP(server,?587,?timeout=5)
        ????yield?smtp
        ????smtp.close()

        有時需要全面測試多種不同條件下的一個對象,功能是否符合預(yù)期??梢酝ㄟ^設(shè)置 fixture 的 params 參數(shù),然后通過 request 獲取設(shè)置的值:

        class?Foo(object):
        ????def?__init__(self,?a,?b,?c):
        ????????self.a?=?a
        ????????self.b?=?b
        ????????self.c?=?c

        ????def?echo(self):
        ????????print(self.a,?self.b,?self.c)
        ????????return?True

        @pytest.fixture(params=[["1",?"2",?"3"],?["x",?"y",?"z"]])
        def?foo(request):
        ????return?Foo(*request.param)

        def?test_foo(foo):
        ????assert?foo.echo()

        設(shè)置 params 參數(shù)后,運行 test 時將生成不同的測試 id,可以通過 ids 自定義 id:

        @pytest.fixture(params=[1,?2,?4,?8],?ids=["a",?"b",?"c",?"d"])
        def?param_a(request):
        ????return?request.param

        def?test_param_a(param_a):
        ????print?param_a

        4.5 setup/teardown

        setup/teardown 是指在模塊、函數(shù)、類開始運行以及結(jié)束運行時執(zhí)行一些動作。比如在一個函數(shù)中測試一個數(shù)據(jù)庫應(yīng)用,測需要在函數(shù)開始前連接數(shù)據(jù)庫,在函數(shù)運行結(jié)束后斷開與數(shù)據(jù)庫的連接。setup/teardown 是特殊的 fixture,其可以有一下幾種實現(xiàn)方式:

        #?模塊級別
        def?setup_module(module):
        ????pass

        def?teardown_module(module):
        ????pass


        #?類級別
        @classmethod
        def?setup_class(cls):
        ????pass

        @classmethod
        def?teardown_class(cls):
        ????pass


        #?方法級別
        def?setup_method(self,?method):
        ????pass

        def?teardown_method(self,?method):
        ????pass


        #?函數(shù)級別
        def?setup_function(function):
        ????pass

        def?teardown_function(function):
        ????pass

        有時候,還希望有全局的 setup 或 teardown,以便在測試開始時做一些準備工作,或者在測試結(jié)束之后做一些清理工作。這可以用 hook 來實現(xiàn):

        def?pytest_sessionstart(session):
        ????#?setup_stuff

        def?pytest_sessionfinish(session,?exitstatus):
        ????#?teardown_stuff

        也可以用 fixture 的方式實現(xiàn):

        @fixture(scope='session',?autouse=True)
        def?my_fixture():
        ????#?setup_stuff
        ????yield
        ????#?teardown_stuff

        4.6 自動執(zhí)行

        有時候需要某些 fixture 在全局自動執(zhí)行,如某些全局變量的初始化工作,亦或一些全局化的清理或者初始化函數(shù)。這時可以通過設(shè)置 fixture 的 autouse 參數(shù)來讓 fixture 自動執(zhí)行。設(shè)置為 autouse=True 即可使得函數(shù)默認執(zhí)行。以下例子會在開始測試前清理可能殘留的文件,接著將程序目錄設(shè)置為該目錄:

        work_dir?=?"/c/temp"
        @pytest.fixture(scope="session",?autouse=True)
        def?clean_workdir():
        ????shutil.rmtree(work_dir)

        5. Pytest Mark特性

        Pytest中marker 的作用是,用來標記測試,以便于選擇性的執(zhí)行測試用例。Pytest 提供了一些內(nèi)建的 marker:

        #?跳過測試
        @pytest.mark.skip(reason=None)

        #?滿足某個條件時跳過該測試
        @pytest.mark.skipif(condition)

        #?預(yù)期該測試是失敗的
        @pytest.mark.xfail(condition,?reason=None,?run=True,?raises=None,?strict=False)

        #?參數(shù)化測試函數(shù)。給測試用例添加參數(shù),供運行時填充到測試中
        #?如果?parametrize?的參數(shù)名稱與?fixture?名沖突,則會覆蓋掉?fixture
        @pytest.mark.parametrize(argnames,?argvalues)

        #?對給定測試執(zhí)行給定的?fixtures
        #?這種用法與直接用?fixture?效果相同
        #?只不過不需要把?fixture?名稱作為參數(shù)放在方法聲明當中
        @pytest.mark.usefixtures(fixturename1,?fixturename2,?...)

        #?讓測試盡早地被執(zhí)行
        @pytest.mark.tryfirst

        #?讓測試盡量晚執(zhí)行
        @pytest.mark.trylast

        其中使用 pytest.skip 和 pytest.xfail 能夠?qū)崿F(xiàn)跳過測試的功能,skip 表示直接跳過測試,而 xfail 則表示存在預(yù)期的失敗。

        除了內(nèi)建的 markers 外,pytest 還支持沒有實現(xiàn)定義的 markers,如:

        @pytest.mark.old_test
        def?test_one():
        ????assert?False

        @pytest.mark.new_test
        def?test_two():
        ????assert?False

        @pytest.mark.windows_only
        def?test_three():
        ????assert?False

        通過使用 -m 參數(shù)可以讓 pytest 選擇性的執(zhí)行部分測試:

        $?pytest?test.py?-m?'not?windows_only'

        更詳細的關(guān)于 marker 的說明可以參考官方文檔:https://docs.pytest.org/en/latest/example/markers.html

        6. conftest.py文件

        從廣義理解,conftest.py 是一個本地的 per-directory 插件,在該文件中可以定義目錄特定的 hooksfixtures。py.test 框架會在它測試的項目中尋找 conftest.py 文件,然后在這個文件中尋找針對整個目錄的測試選項,比如是否檢測并運行 doctest 以及應(yīng)該使用哪種模式檢測測試文件和函數(shù)。

        總結(jié)起來,conftest.py 文件大致有如下幾種功能:

        • Fixtures: 用于給測試用例提供靜態(tài)的測試數(shù)據(jù),其可以被所有的測試用于訪問,除非指定了范圍。
        • 加載插件: 用于導(dǎo)入外部插件或模塊:pytest_plugins ="myapp.testsupport.myplugin"
        • 定義鉤子: 用于配置鉤子(hook),如 pytest_runtest_setuppytest_runtest_teardown、pytest_config等。
        • 測試根路徑: 如果將 conftest.py 文件放在項目根路徑中,則 pytest 會自己搜索項目根目錄下的子模塊,并加入到 sys.path 中,這樣便可以對項目中的所有模塊進行測試,而不用設(shè)置 PYTHONPATH 來指定項目模塊的位置。

        可以有多個 conftest.py 文件同時存在,其作用范圍是目錄。例如測試非常復(fù)雜時,可以為特定的一組測試創(chuàng)建子目錄,并在該目錄中創(chuàng)建 conftest.py 文件,并定義一個 futures 或 hooks。就像如下的結(jié)構(gòu):

        test_case
        ├──?conftest.py
        ├──?module1
        │???└──?conftest.py
        ├──?module2
        │???└──?conftest.py
        └──?module3
        ????└──?conftest.py

        7. Pytest插件機制

        Pytest之所以稱之為全功能測試框架,得益于它能通過外部插件或者自定義插件的形式擴展所需的功能,這里推薦幾款常用的第三方插件:

        • pytest-xdist: 分布式測試
        • pytest-cov: 生成測試覆蓋率報告
        • pytest-pep8: 檢測代碼是否符合 PEP8 規(guī)范
        • pytest-flakes: 檢測代碼風(fēng)格
        • pytest-html: 生成 html 報告
        • pytest-randomly: 測試順序隨機
        • pytest-rerunfailures: 失敗重試
        • pytest-timeout: 超時測試

        如果你覺得文章還不錯,請大家?點贊、分享、關(guān)注?下,因為這將是我持續(xù)輸出更多優(yōu)質(zhì)文章的最強動力!

        推薦閱讀
        重磅消息 |《自動化測試實戰(zhàn)寶典:從小工到專家》隆重上市!

        推薦一款最強Python自動化神器!不用寫一行代碼!

        推薦一款萬能抓包神器:Fiddler Everywhere

        推薦一款技術(shù)人必備的接口測試神器:Apifox

        推薦一款Python開源庫,技術(shù)人必備的造數(shù)據(jù)神器!

        重磅消息 | 2020年最新全棧測試開發(fā)技能實戰(zhàn)指南(第1期)

        END

        所有原創(chuàng)文章
        第一時間發(fā)布至此公眾號「測試開發(fā)技術(shù)」

        長按二維碼/微信掃碼 ?關(guān)注


        關(guān)注后,回復(fù)「me」試試
        點擊閱讀原文

        瀏覽 23
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产乱淫a∨片免费视频 | 性网站在线观看 | www.怡红院 | 色婷婷久久久久 | 水蜜桃一区二区 | 国产永久精品大片wwwApp | AV成人电影在线 | 女教师含羞撅起屁股粗暴 | 国产婷婷色一区二区三区四区 | 免费一级淫片AAA |