本文目錄一覽:
python 函數變量 參數怎麼使用
剛學用Python的時候,特別是看一些庫的源碼時,經常會看到func(*args, **kwargs)這樣的函數定義,這個*和**讓人有點費解。其實只要把函數參數定義搞清楚了,就不難理解了。
先說說函數定義,我們都知道,下面的代碼定義了一個函數funcA
def funcA():
pass
顯然,函數funcA沒有參數(同時啥也不幹:D)。
下面這個函數funcB就有兩個參數了,
def funcB(a, b):
print a
print b
調用的時候,我們需要使用函數名,加上圓括號擴起來的參數列表,比如 funcB(100, 99),執行結果是:
100
99
很明顯,參數的順序和個數要和函數定義中一致,如果執行funcB(100),Python會報錯的:
TypeError: funcB() takes exactly 2 arguments (1 given)
我們可以在函數定義中使用參數默認值,比如
def funcC(a, b=0):
print a
print b
在函數funcC的定義中,參數b有默認值,是一個可選參數,如果我們調用funcC(100),b會自動賦值為0。
OK,目前為止,我們要定義一個函數的時候,必須要預先定義這個函數需要多少個參數(或者說可以接受多少個參數)。一般情況下這是沒問題的,但是也有在定義函數的時候,不能知道參數個數的情況(想一想C語言里的printf函數),在Python里,帶*的參數就是用來接受可變數量參數的。看一個例子
def funcD(a, b, *c):
print a
print b
print “length of c is: %d ” % len(c)
print c
調用funcD(1, 2, 3, 4, 5, 6)結果是
1
2
length of c is: 4
(3, 4, 5, 6)
我們看到,前面兩個參數被a、b接受了,剩下的4個參數,全部被c接受了,c在這裡是一個tuple。我們在調用funcD的時候,至少要傳遞2個參數,2個以上的參數,都放到c里了,如果只有兩個參數,那麼c就是一個empty tuple。
好了,一顆星我們弄清楚了,下面輪到兩顆星。
上面的例子里,調用函數的時候,傳遞的參數都是根據位置來跟函數定義里的參數表匹配的,比如funcB(100, 99)和funcB(99, 100)的執行結果是不一樣的。在Python里,還支持一種用關鍵字參數(keyword argument)調用函數的辦法,也就是在調用函數的時候,明確指定參數值付給那個形參。比如還是上面的funcB(a, b),我們通過這兩種方式調用
funcB(a=100, b=99)
和
funcB(b=99, a=100)
結果跟funcB(100, 99)都是一樣的,因為我們在使用關鍵字參數調用的時候,指定了把100賦值給a,99賦值給b。也就是說,關鍵字參數可以讓我們在調用函數的時候打亂參數傳遞的順序!
另外,在函數調用中,可以混合使用基於位置匹配的參數和關鍵字參數,前題是先給出固定位置的參數,比如
def funcE(a, b, c):
print a
print b
print c
調用funcE(100, 99, 98)和調用funcE(100, c=98, b=99)的結果是一樣的。
好了,經過以上鋪墊,兩顆星總算可以出場了:
如果一個函數定義中的最後一個形參有 ** (雙星號)前綴,所有正常形參之外的其他的關鍵字參數都將被放置在一個字典中傳遞給函數,比如:
def funcF(a, **b):
print a
for x in b:
print x + “: ” + str(b[x])
調用funcF(100, c=’你好’, b=200),執行結果
100
c: 你好
b: 200
大家可以看到,b是一個dict對象實例,它接受了關鍵字參數b和c。
Python的函數和參數
parameter 是函數定義的參數形式
argument 是函數調用時傳入的參數實體。
對於函數調用的傳參模式,一般有兩種:
此外,
也是關鍵字傳參
python的函數參數定義一般來說有五種: 位置和關鍵字參數混合 , 僅位置參數 , 僅關鍵字參數 , 可變位置參數 , 可變關鍵字參數 。其中僅位置參數的方式僅僅是一個概念,python語法中暫時沒有這樣的設計。
通常我們見到的函數是位置和關鍵字混合的方式。
既可以用關鍵字又可以用位置調用
或
這種方式的定義只能使用關鍵字傳參的模式
f(*some_list) 與 f(arg1, arg2, …) (其中some_list = [arg1, arg2, …])是等價的
網絡模塊request的request方法的設計
多數的可選參數被設計成可變關鍵字參數
有多種方法能夠為函數定義輸出:
非常晦澀
如果使用可變對象作為函數的默認參數,會導致默認參數在所有的函數調用中被共享。
例子1:
addItem方法的data設計了一個默認參數,使用不當會造成默認參數被共享。
python裡面,函數的默認參數被存在__default__屬性中,這是一個元組類型
例子2:
在例子1中,默認參數是一個列表,它是mutable的數據類型,當它寫進 __defauts__屬性中時,函數addItem的操作並不會改變它的id,相當於 __defauts__只是保存了data的引用,對於它的內存數據並不關心,每次調用addItem,都可以修改 addItem.__defauts__中的數據,它是一個共享數據。
如果默認參數是一個imutable類型,情況將會不一樣,你無法改變默認參數第一次存入的值。
例子1中,連續調用addItem(‘world’) 的結果會是
而不是期望的
parameterized參數化測試
1、官網:
2、parameterized:可以使用任何Python測試框架進行參數化測試。比如nose的參數化測試,py.test的參數化測試,unittest的參數化測試。
3、安裝parameterized:pip install parameterized
4、安裝nose:pip install nose
5、安裝pytest:pip install pytest
6、官網例子:
6.1、@parameterized 裝飾符接受一個由tuples或param(…)組成的列表等:
6.2、@parameterized.expand 裝飾符接受一個由tuples或param(…)組成的列表等,unittest僅支持這種@parameterized.expand 的用法,@parameterized.expand 可以用來在無法使用測試生成器的情況下生成測試方法(例如,當測試類是unittest.TestCase的子類時:
6.3、加法和乘法測試:
6.4、減法測試:
7、參數化參數
7.1、nose的參數化測試:nosetests -v test_math.py
7.2、py.test的參數化測試:py.test -v test_math.py()
7.3、unittest的參數化測試:python -m unittest -v test_math.py
8、兼容性:
Python方法的幾種常見參數類型
無默認值參數(關鍵字參數):
def myfun(a):
print(a)
這是參數的最簡單形式。這個a就是無默認值參數。在調用函數時必需為無默認值參數指定值。
無默認值參數可以通過兩種方式來指定值:
# 按參數定義順序不指名傳遞值
myfun(‘/src/image’)
# 無視定義順序,通過關鍵字指定值
myfun(a=’/src/image’)
無默認值參數在函數內部使用關鍵字作為變量名來訪問
無默認值參數可以有多個,也是一些其它參數類型的基礎。
默認值參數:
如果在定義時為參數指定一個默認值,那麼,這個參數就可以在調用時不指定值:
def myfun(a=”):
print(a)
# 不為a指定值
myfun()
# 按定義順序為a指定值
myfun(‘/src/lib’)
# 通過關鍵字為a指定值
myfun(a=’/src/lib’)
在定義時,所有默認值參數只能出現在所有無默認值參數之後,也就是說,在函數的定義中,要先定義無默認值參數,再定義默認值參數。
不定長參數:
在參數名之前添加一個*號,則該參數稱為不定長參數。一個函數只可以有一個不定長參數。不定長參數的定義位置沒有限制,它可以定義在無默認值參數之間,也可以定義在默認值參數之後,或者它們之間的任何一個位置。
在調用時,不定長參數之後定義的無前兩種類型的參數就只能使用關鍵字來指定值了。
不定長參數在函數內部被處理為一個tuple。
def _max(*e,base=9):
print(‘called “_max”:’)
print(‘ e:’, e)
print(‘ base:’, base)
# 只向不定長參數傳遞了值
# 輸出:
# called “_max”:
# e: (3, 4, 5)
# base: 9
_max(3, 4, 5)
# 也向默認值參數base傳遞了值
# 輸出:
# called “_max”:
# e: (3, 4)
# base: 5
_max(3, 4, base=5)
# 直接通過一個元組傳遞不定長參數的值
# 輸出:
# called “_max”:
# e: (3, 4)
# base: 5
p=(3, 4)
_max(*p, base=5)
# 使用混合方式傳遞不定長參數
# 輸出:
# called “_max”:
# e: (3, 4, 5, 6, 7)
# base: 10
p1=(3, 4)
p2=(6, 7)
_max(*p1, 5, *p2, base=10)
調用函數時如果沒有為不定長參數指定值,將導入一個空元組。
不定長關鍵字參數:
不定長關鍵字參數使用兩個星號作為前綴與其它類型的參數區分,它在函數內被導入為一個字典。調用時需要為不定長關鍵字參數給出約定的關鍵字名,賦值形式如同無默認值參數。
一般情況下,不定長參數是作為最後一個參數來定義。
def myfun(**kw):
print(kw)
myfun(base=1, home=’aaaa’)
以上只是基本的調用方式,有些時候,可以有更有趣的調用方式,例如定義了一個既含無默認值參數也含默認值參數的函數:
def iter_dir(homedir, exts=’*’, includesubdir=False, monoinfile=False,
titlere=’^[^ ^ ].*’, textengine=default_textengine,
encode=None):
調用時也可以用這樣的方式來傳遞值:
kwgs = {‘homedir’: ‘C:/Users/hunte/Documents/baiduyun/阿瑟·C·克拉克’,
‘exts’: ‘txt’,
‘includesubdir’: True}
myiter = iter_dir(**kwgs)
for file in myiter:
pass
Python – pytest
目錄
pytest是Python的單元測試框架,同自帶的unittest框架類似,但pytest框架使用起來更簡潔,效率更高。
pytest特點
安裝
測試
在測試之前要做的準備
我的演示腳本處於這樣一個的目錄中:
踩坑:你創建的pytest腳本名稱中不允許含有 . ,比如 1.簡單上手.py ,這樣會報錯。當然,可以這麼寫 1-簡單上手.py
demo1.py :
上例中,當我們在執行(就像Python解釋器執行普通的Python腳本一樣)測試用例的時候, pytest.main([“-s”, “demo1.py”]) 中的傳參需要是一個元組或者列表(我的pytest是5.2.2版本),之前的版本可能需要這麼調用 pytest.main(“-s demo1.py”) ,傳的參數是str的形式,至於你使用哪種,取決於報不報錯:
遇到上述報錯,就是參數需要一個列表或者元組的形式,而我們使用的是str形式。
上述代碼正確的執行結果是這樣的:
大致的信息就是告訴我們:
pytest.main([“-s”, “demo1.py”])參數說明
除了上述的函數這種寫法,也可以有用例類的寫法:
用法跟unittest差不多,類名要以 Test 開頭,並且其中的用例方法也要以 test 開頭,然後執行也一樣。
執行結果:
那麼,你這個時候可能會問,我記得unittest中有setup和teardown的方法,難道pytest中沒有嘛?你怎麼提都不提?穩住,答案是有的。
接下來,我們來研究一下pytest中的setup和teardown的用法。
我們知道,在unittest中,setup和teardown可以在每個用例前後執行,也可以在所有的用例集執行前後執行。那麼在pytest中,有以下幾種情況:
來一一看看各自的用法。
模塊級別setup_module/teardown_module
執行結果:
類級別的setup_class/teardown_class
執行結果:
類中方法級別的setup_method/teardown_method
執行結果:
函數級別的setup_function/teardown_function
執行結果:
小結
該腳本有多種運行方式,如果處於PyCharm環境,可以使用右鍵或者點擊運行按鈕運行,也就是在pytest中的主函數中運行:
也可以在命令行中運行:
這種方式,跟使用Python解釋器執行Python腳本沒有什麼兩樣。也可以如下面這麼執行:
當然,還有一種是使用配置文件運行,來看看怎麼用。
在項目的根目錄下,我們可以建立一個 pytest.ini 文件,在這個文件中,我們可以實現相關的配置:
那這個配置文件中的各項都是什麼意思呢?
首先, pytest.ini 文件必須位於項目的根目錄,而且也必須叫做 pytest.ini 。
其他的參數:
OK,來個示例。
首先,(詳細目錄參考開頭的目錄結構)在 scripts/test_case_01.py 中:
在 scripts/test_case_dir1/test_case02.py 中:
那麼,在不同的目錄或者文件中,共有5個用例將被執行,而結果則是兩個失敗三個成功。來執行驗證一下,因為有了配置文件,我們在終端中(前提是在項目的根目錄),直接輸入 pytest 即可。
由執行結果可以發現, 2 failed, 3 passed ,跟我們的預期一致。
後續執行相關配置都來自配置文件,如果更改,會有相應說明,終端都是直接使用 pytest 執行。
我們知道在unittest中,跳過用例可以用 skip ,那麼這同樣是適用於pytest。
來看怎麼使用:
跳過用例,我們使用 @pytest.mark.skipif(condition, reason) :
然後將它裝飾在需要被跳過用例的的函數上面。
效果如下:
上例執行結果相對詳細,因為我們在配置文件中為 addopts 增加了 -v ,之前的示例結果中,沒有加!
另外,此時,在輸出的控制台中, 還無法打印出 reason 信息,如果需要打印,則可以在配置文件中的 addopts 參數的 -s 變為 -rs :
如果我們事先知道測試函數會執行失敗,但又不想直接跳過,而是希望顯示的提示。
Pytest 使用 pytest.mark.xfail 實現預見錯誤功能::
需要掌握的必傳參數的是:
那麼關於預期失敗的幾種情況需要了解一下:
結果如下:
pytest 使用 x 表示預見的失敗(XFAIL)。
如果預見的是失敗,但實際運行測試卻成功通過,pytest 使用 X 進行標記(XPASS)。
而在預期失敗的兩種情況中,我們不希望出現預期失敗,結果卻執行成功了的情況出現,因為跟我們想的不一樣嘛,我預期這條用例失敗,那這條用例就應該執行失敗才對,你雖然執行成功了,但跟我想的不一樣,你照樣是失敗的!
所以,我們需要將預期失敗,結果卻執行成功了的用例標記為執行失敗,可以在 pytest.ini 文件中,加入:
這樣就就把上述的情況標記為執行失敗了。
pytest身為強大的單元測試框架,那麼同樣支持DDT數據驅動測試的概念。也就是當對一個測試函數進行測試時,通常會給函數傳遞多組參數。比如測試賬號登陸,我們需要模擬各種千奇百怪的賬號密碼。
當然,我們可以把這些參數寫在測試函數內部進行遍歷。不過雖然參數眾多,但仍然是一個測試,當某組參數導致斷言失敗,測試也就終止了。
通過異常捕獲,我們可以保證程所有參數完整執行,但要分析測試結果就需要做不少額外的工作。
在 pytest 中,我們有更好的解決方法,就是參數化測試,即每組參數都獨立執行一次測試。使用的工具就是 pytest.mark.parametrize(argnames, argvalues) 。
使用就是以裝飾器的形式使用。
只有一個參數的測試用例
來看(重要部分)結果::
可以看到,列表內的每個手機號,都是一條測試用例。
多個參數的測試用例
(重要部分)結果:
可以看到,每一個手機號與每一個驗證碼都組合一起執行了,這樣就執行了4次。那麼如果有很多個組合的話,用例數將會更多。我們希望手機號與驗證碼一一對應組合,也就是只執行兩次,怎麼搞呢?
在多參數情況下,多個參數名是以 , 分割的字符串。參數值是列表嵌套的形式組成的。
固件(Fixture)是一些函數,pytest 會在執行測試函數之前(或之後)加載運行它們,也稱測試夾具。
我們可以利用固件做任何事情,其中最常見的可能就是數據庫的初始連接和最後關閉操作。
Pytest 使用 pytest.fixture() 定義固件,下面是最簡單的固件,訪問主頁前必須先登錄:
結果:
在之前的示例中,你可能會覺得,這跟之前的setup和teardown的功能也類似呀,但是,fixture相對於setup和teardown來說更靈活。pytest通過 scope 參數來控制固件的使用範圍,也就是作用域。
比如之前的login固件,可以指定它的作用域:
很多時候需要在測試前進行預處理(如新建數據庫連接),並在測試完成進行清理(關閉數據庫連接)。
當有大量重複的這類操作,最佳實踐是使用固件來自動化所有預處理和後處理。
Pytest 使用 yield 關鍵詞將固件分為兩部分, yield 之前的代碼屬於預處理,會在測試前執行; yield 之後的代碼屬於後處理,將在測試完成後執行。
以下測試模擬數據庫查詢,使用固件來模擬數據庫的連接關閉:
結果:
可以看到在兩個測試用例執行前後都有預處理和後處理。
pytest中還有非常多的插件供我們使用,我們來介紹幾個常用的。
先來看一個重要的,那就是生成測試用例報告。
想要生成測試報告,首先要有下載,才能使用。
下載
如果下載失敗,可以使用PyCharm下載,怎麼用PyCharm下載這裡無需多言了吧。
使用
在配置文件中,添加參數:
效果很不錯吧!
沒完,看我大招
Allure框架是一個靈活的輕量級多語言測試報告工具,它不僅以web的方式展示了簡潔的測試結果,而且允許參與開發過程的每個人從日常執行的測試中最大限度的提取有用信息。
從開發人員(dev,developer)和質量保證人員(QA,Quality Assurance)的角度來看,Allure報告簡化了常見缺陷的統計:失敗的測試可以分為bug和被中斷的測試,還可以配置日誌、步驟、fixture、附件、計時、執行 歷史 以及與TMS和BUG管理系統集成,所以,通過以上配置,所有負責的開發人員和測試人員可以儘可能的掌握測試信息。
從管理者的角度來看,Allure提供了一個清晰的“大圖”,其中包括已覆蓋的特性、缺陷聚集的位置、執行時間軸的外觀以及許多其他方便的事情。allure的模塊化和可擴展性保證了我們總是能夠對某些東西進行微調。
少扯點,來看看怎麼使用。
Python的pytest中allure下載
但由於這個 allure-pytest 插件生成的測試報告不是 html 類型的,我們還需要使用allure工具再“加工”一下。所以說,我們還需要下載這個allure工具。
allure工具下載
在現在allure工具之前,它依賴Java環境,我們還需要先配置Java環境。
注意,如果你的電腦已經有了Java環境,就無需重新配置了。
配置完了Java環境,我們再來下載allure工具,我這裡直接給出了百度雲盤鏈接,你也可以去其他鏈接中自行下載:
下載並解壓好了allure工具包之後,還需要將allure包內的 bin 目錄添加到系統的環境變量中。
完事後打開你的終端測試:
返回了版本號說明安裝成功。
使用
一般使用allure要經歷幾個步驟:
來看配置 pytest.ini :
就是 –alluredir ./report/result 參數。
在終端中輸入 pytest 正常執行測試用例即可:
執行完畢後,在項目的根目下,會自動生成一個 report 目錄,這個目錄下有:
接下來需要使用allure工具來生成HTML報告。
此時我們在終端(如果是windows平台,就是cmd),路徑是項目的根目錄,執行下面的命令。
PS:我在pycharm中的terminal輸入allure提示’allure’ 不是內部或外部命令,也不是可運行的程序或批處理文件。但windows的終端沒有問題。
命令的意思是,根據 reportresult 目錄中的數據(這些數據是運行pytest後產生的)。在 report 目錄下新建一個 allure_html 目錄,而這個目錄內有 index.html 才是最終的allure版本的HTML報告;如果你是重複執行的話,使用 –clean 清除之前的報告。
結果很漂亮:
allure open
默認的,allure報告需要HTTP服務器來打開,一般我們可以通過pycharm來完成,另外一種情況就是通過allure自帶的open命令來完成。
allure的其他用法
當然,故事還是沒有完!在使用allure生成報告的時候,在編寫用例階段,還可以有一些參數可以使用:
allure.title與allure.description
feature和story
由上圖可以看到,不同的用例被分為不同的功能中。
allure.severity
allure.severity 用來標識測試用例或者測試類的級別,分為blocker,critical,normal,minor,trivial5個級別。
severity的默認級別是normal,所以上面的用例5可以不添加裝飾器了。
allure.dynamic
在之前,用例的執行順序是從上到下依次執行:
正如上例的執行順序是 3 1 2 。
現在,來看看我們如何手動控制多個用例的執行順序,這裡也依賴一個插件。
下載
使用
手動控制用例執行順序的方法是在給各用例添加一個裝飾器:
那麼, 現在的執行順序是 2 1 3 ,按照order指定的排序執行的。
如果有人較勁傳個0或者負數啥的,那麼它們的排序關係應該是這樣的:
失敗重試意思是指定某個用例執行失敗可以重新運行。
下載
使用
需要在 pytest.ini 文件中, 配置:
給 addopts 字段新增(其他原有保持不變) –reruns=3 字段,這樣如果有用例執行失敗,則再次執行,嘗試3次。
來看示例:
結果:
我們也可以從用例報告中看出重試的結果:
上面演示了用例失敗了,然後重新執行多少次都沒有成功,這是一種情況。
接下來,來看另一種情況,那就是用例執行失敗,重新執行次數內通過了,那麼剩餘的重新執行的次數將不再執行。
通過 random 模塊幫助我們演示出在某次執行中出現失敗的情況,而在重新執行的時候,會出現成功的情況,看結果:
可以看到,用例 02 重新執行了一次就成功了,剩餘的兩次執行就終止了。
一條一條用例的執行,肯定會很慢,來看如何並發的執行測試用例,當然這需要相應的插件。
下載
使用
在配置文件中添加:
就是這個 -n=auto :
並發的配置可以寫在配置文件中,然後其他正常的執行用例腳本即可。另外一種就是在終端中指定,先來看示例:
結果:
pytest-sugar 改變了 pytest 的默認外觀,添加了一個進度條,並立即顯示失敗的測試。它不需要配置,只需 下載插件即可,用 pytest 運行測試,來享受更漂亮、更有用的輸出。
下載
其他照舊執行用例即可。
pytest-cov 在 pytest 中增加了覆蓋率支持,來顯示哪些代碼行已經測試過,哪些還沒有。它還將包括項目的測試覆蓋率。
下載
使用
在配置文件中:
也就是配置 –cov=./scripts ,這樣,它就會統計所有 scripts 目錄下所有符合規則的腳本的測試覆蓋率。
執行的話,就照常執行就行。
結果:
更多插件參考:
有的時候,在 pytest.ini 中配置了 pytest-html 和 allure 插件之後,執行後報錯:
出現了這個報錯,檢查你配置的解釋器中是否存在 pytest-html 和 allure-pytest 這兩個模塊。如果是使用的pycharm ide,那麼你除了檢查settings中的解釋器配置之外,還需要保證運行腳本的編輯器配置是否跟settings中配置一致。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/309503.html