自動化測試有不少優勢,但這裏有3個主要的點:css
可重用性:不須要老是編寫新的腳本,除非必要,即便是新的操做系統版本也不須要編寫腳本。python
可靠性:人容易出錯,機器不太可能。當運行不能跳過的重複步驟/測試時,速度會更快。nginx
全天運行:您能夠在任什麼時候間或遠程啓動測試。夜間運行正在測試你的軟件,即便是在你睡着的時候。web
目前有多種可用的測試框架和工具。這些框架的風格也各不相同,好比數據驅動、關鍵字驅動、混合、BDD等等。您能夠選擇最適合您的要求。shell
Python和pytest在這場競爭中佔據了巨大的份額。Python及其相關工具之因此被大量使用,多是由於與其餘語言相比,沒有或不多編程經驗的人更能負擔得起它們。django
pytest框架使得編寫小型測試變得很容易,可是能夠擴展到支持應用程序和庫的複雜功能測試。編程
Pytest的一些主要特性:設計模式
自動發現測試模塊和功能api
有效的CLI來更好地控制您想要運行或跳過的內容瀏覽器
大型第三方插件生態系統
固定裝置-不一樣的類型,不一樣的範圍
與傳統的單元測試框架一塊兒工做
自動和可配置的測試發現
在默認狀況下,pytest指望在名稱以test_開頭或以_test.py結尾的python模塊中找到測試。在默認狀況下,它指望測試函數名以test_ 開頭。可是,能夠經過在pytest的一個配置文件中添加您本身的配置來修改這個測試發現協議。
# content of pytest.ini# Example 1: have pytest look for "check" instead of "test"# can also be defined in tox.ini or setup.cfg file, although the section# name in setup.cfg files should be "tool:pytest"[pytest]python_files = check_*.pypython_classes = Checkpython_functions = *_check
讓咱們看一下很是基本的測試函數。
class CheckClass(object): def one_check(self): x = "this" assert 'h' in x
def two_check(self): x = "hello" assert hasattr(x, 'check')
你注意到什麼了嗎?沒有花哨的assertEqual或assertDictEqual等,只是簡單明瞭的斷言。對於比較兩個對象的簡單操做,不須要導入這些斷言函數。assert是python已經提供的功能,所以無需從新發明。😊
固定裝置會起做用的
查看測試功能,測試錢包軟件的基本操做,好比,
// test_wallet.pyfrom wallet import Walletdef test_default_initial_amount(): wallet = Wallet() assert wallet.balance == 0 wallet.close()def test_setting_initial_amount(): wallet = Wallet(initial_amount=100) assert wallet.balance == 100 wallet.close()def test_wallet_add_cash(): wallet = Wallet(initial_amount=10) wallet.add_cash(amount=90) assert wallet.balance == 100 wallet.close()def test_wallet_spend_cash(): wallet = Wallet(initial_amount=20) wallet.spend_cash(amount=10) assert wallet.balance == 10 wallet.close()
嗯,有意思!你注意到了嗎,不少樣板文件。另外一件值得注意的事情是,測試除了測試功能以外還作了一些其餘的事情,例如實例化錢包並關閉它——Wallet .close()
如今讓咱們看看如何使用pytest fixture去除樣板
import pytestfrom _pytest.fixtures import SubRequestfrom wallet import Wallet#==================== fixturesdef wallet(request: SubRequest): param = getattr(request, ‘param’, None) if param: prepared_wallet = Wallet(initial_amount=param[0]) else: prepared_wallet = Wallet() yield prepared_wallet prepared_wallet.close()#==================== testsdef test_default_initial_amount(wallet): assert wallet.balance == 0@pytest.mark.parametrize(‘wallet’, [(100,)], indirect=True)def test_setting_initial_amount(wallet): assert wallet.balance == 100@pytest.mark.parametrize(‘wallet’, [(10,)], indirect=True)def test_wallet_add_cash(wallet): wallet.add_cash(amount=90) assert wallet.balance == 100@pytest.mark.parametrize(‘wallet’, [(20,)], indirect=True)def test_wallet_spend_cash(wallet): wallet.spend_cash(amount=10) assert wallet.balance == 10
整潔!不是嗎。測試函數很是微妙,只作它們想作的事情。夾具錢包負責設置和拆卸、實例化和關閉錢包。它不只有助於編寫可重用的代碼,還增長了數據分離的本質。若是仔細看,錢包數量是一塊測試邏輯以外提供的測試數據,而不是硬編碼在測試函數內部。
@pytest.mark.parametrize(‘wallet’, [(10,)], indirect=True)
在更可控的環境中,您能夠在存儲庫中有一個測試數據文件,例如test-data.ini,以及讀取該文件的包裝器,而且您的測試函數能夠調用包裝器的另外一個接口來讀取測試數據。
可是,建議將您的fixture做爲conftest.py文件的一部分。這是pytest中的一個特殊文件,它容許測試發現全局fixture。
可是,有一個針對許多不一樣數據集執行的測試用例!
不用擔憂,pytest有一個很酷的特性來參數化您的fixture。讓咱們用一個例子來看看它。
假設您的產品公開CLI接口以在本地管理它。此外,您的產品在啓動時設置了許多默認參數,您須要驗證全部這些參數的默認值。
咱們能夠考慮爲每一個設置編寫一個測試用例,可是使用pytest就容易得多了
(‘report_crashes’, ‘yes’),(‘stop_download_on_hang’, ‘no’),(‘stop_download_on_disconnect’, ‘no’),(‘reduce_connections_on_congestion’, ‘no’),(‘global.max_web_users’, ‘1024’),(‘global.max_downloads’, ‘5’),(‘use_kernel_congestion_detection’, ‘no’),(‘log_type’, ‘normal’),(‘no_signature_check’, ‘no’),(‘disable_xmlrpc’, ‘no’),(‘disable_ntp’, ‘yes’),(‘ssl_mode’, ‘tls_1_2’),])def test_settings_defaults(self, setting_name, setting_value): assert product_shell.run_command(setting_name) == \ self.」The current value for \’{0}\’ is \’{1}\’.」.format(setting_name, setting_value), \ ‘The {} default should be {}’.format(preference_name, preference_value)
很酷,不是嗎!,你只寫了13個測試用例(每一個不一樣setting_value),在將來若是你添加一個新的設置到你的產品,你須要作的就是,再添加一個tuple😌上面。
它是如何與selenium和API測試的UI測試集成的
嗯,你的產品能夠有多種界面。CLI -就像咱們上面討論的。相似地,GUI和API。在部署軟件以前,對全部軟件進行測試是很重要的。在多個組件相互依賴和耦合的企業軟件中,某個部分的更改可能會影響其餘部分。
記住,pytest只是一個促進「測試」的框架,而不是特定類型的測試。所以,您可使用selenium構建GUI測試,或者使用Python的請求庫構建API測試,而後使用pytest運行它。
例如,在高層次上,這多是您的測試存儲庫結構。
正如您在上面看到的,這能夠很好地分離組件。
apiobjects:爲調用API端點建立包裝器的好地方。您可使用BaseAPIObject和派生類來知足您的需求。
helper:編寫您的helper方法
庫文件,它能夠被不一樣的組件使用,例如你的fixture在conftest, pageobjects等。
pageobjects: pageobjects設計模式可用於建立不一樣GUI頁面的類。咱們在站得住使用Webium,它是Python的一個頁面對象模式實現庫。
套件:您能夠在這裏編寫pylint代碼驗證套件,這將有助於您對代碼質量有信心。
測試:能夠根據測試的風格對測試目錄進行分類。它使管理和研究您的測試變得容易。
這只是供參考,存儲庫的結構和依賴關係能夠按照您的須要進行佈局。
我有足夠的測試用例,想並行運行它們
您的測試套件中可能有大量的測試用例,而且有時您可能想並行地運行測試用例,以減小整體測試執行時間。
Pytest提供了一個很棒的並行運行測試的插件,名爲Pytest -xdist,它用一些獨特的執行模式擴展了Pytest。使用pip安裝此插件
pip install pytest-xdist
讓咱們經過一個示例來快速研究它。
我有一個自動化測試存儲庫CloudApp,用於使用selenium進行GUI測試。此外,它還隨着新的測試用例不斷增加,如今已經有了數百個測試。我想作的是並行運行它們,並減小測試執行時間。
在終端中,只需在項目根文件夾/ tests文件夾中鍵入pytest。這將執行全部測試。
pytest -s -v -n=2
並行運行測試的pytest-xdist
這還能夠幫助您在多個瀏覽器上並行運行測試。
報告
Pytest內置支持建立結果文件,可由Jenkins、Bamboo或其餘持續集成服務器讀取,使用以下調用:
pytest test/file/path — junitxml=path
這能夠生成很好的XML風格的輸出,能夠由許多CI系統解析器解釋。
Pytest的受歡迎程度逐年上升。此外,它還擁有普遍的社區支持,這讓您能夠訪問不少擴展,好比pytest-django,它能夠幫助您爲Django web應用程序集成編寫測試。記住,pytest支持運行unittest測試用例,因此若是您正在使用unittest, pytest是值得考慮的。😊
·END·
機器學習·數據分析
本文分享自微信公衆號 - Python學會(gh_39aead19f756)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。