成熟全功能的python測試工具
支援posix / windows, python的2.5-3.3 , pypy和jython - 2.5.1
1000測試用例自測零bug。
pytest更新時有很好的向後相容性
豐富的線上和pdf文檔
大量的第三方插件和内置幫助
在許多小型和大型項目群組織使用
許多測試執行個體
靈活
易學,有多種用法
assert語句斷言
追蹤和失敗斷言報告
列印調試和測試執行期間可以捕獲标準輸出
适合簡單的單元測試到複雜的功能測試
子產品化和參數化的平台
參數化的測試函數
支援屬性
skip和xfail處理失敗的用例
xdist插件分發測試給多個cpu
不斷地重新運作失敗的測試
靈活的python測試發現
內建
多範式:可以執行nose, unittest 和doctest風格的測試用例,甚至django和trial。
支援良好的內建實踐
支援擴充的xunit風格setup
支援非python測試
支援生成測試覆寫率報告
支援pep8相容的編碼風格
擴充插件和定制系統:
所有的收集,報告,運作方面都委派給hook函數
定制可以是每個目錄,每個項目或每個pypi上釋出的插件
很容易添加指令行選項或定制現有的行為
安裝
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 pip install -u pytest # or 2 easy_install -u pytest</pre>
檢查版本:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 # py.test --version 2 this is pytest version 2.5.2, imported from /usr/lib/python2.7/site-packages/pytest.pyc</pre>
第一個執行個體:
代碼:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 # content of test_sample.py
2 def func(x): 3 return x + 1
4 def test_answer(): 5 assert func(3) == 5</pre>
執行結果:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 # py.test
2 =========================================================================================================== test session starts ===========================================================================================================
3 platform linux2 -- python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
4 collected 1 items 5
6 test_sample.py f
7
8 ================================================================================================================ failures =================================================================================================================
9 _______________________________________________________________________________________________________________ test_answer _______________________________________________________________________________________________________________ 10
11 def test_answer(): 12 > assert func(3) == 5
13 e assert 4 == 5
14 e + where 4 = func(3) 15
16 test_sample.py:8: assertionerror 17 ======================================================================================================== 1 failed in 0.34 seconds =========================================================================================================</pre>
pytest通過标準測試發現規則發現test_answer函數,通常是查找 test_字首。我們得到了一個故障報告,因為我們調用func(3)沒有傳回5。pytest的進階內省斷言會智能報告assert的中間值,不需要記住那些junit傳統方法。
異常斷言
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 import pytest 2 def f(): 3 raise systemexit(1) 4 def test_mytest(): 5 with pytest.raises(systemexit): 6 f()</pre>
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 $ py.test -q test_sysexit.py 2 . 3 1 passed in 0.01 seconds</pre>
-q表示靜默模式:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 -q, --quiet decrease verbosity.</pre>
在類中分組用例
代碼
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 # content of test_class.py
2 class testclass: 3 def test_one(self): 4 x = "this"
5 assert 'h' in x 6
7 def test_two(self): 8 x = "hello"
9 assert hasattr(x, 'check')</pre>
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 # py.test test_class.py
4 collected 2 items 5
6 test_class.py .f
9 ___________________________________________________________________________________________________________ testclass.test_two ____________________________________________________________________________________________________________ 10
11 self = <test_class.testclass instance at 0x265aef0>
12
13 def test_two(self): 14 x = "hello"
15 > assert hasattr(x, 'check') 16 e assert hasattr('hello', 'check') 17
18 test_class.py:12: assertionerror 19 =================================================================================================== 1 failed, 1 passed in 0.01 seconds ====================================================================================================</pre>
功能測試示例:生成唯一的臨時目錄
功能測試經常需要建立一些檔案,并将其傳遞給應用程式對象。pytest提供 builtin fixtures/function 參數允許請求任意資源,例如唯一的臨時目錄:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 def test_needsfiles(tmpdir): 2 print tmpdir 3 assert 0</pre>
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 ]# py.test -q test_tmpdir.py
2 ff
3 ================================================================================================================ failures =================================================================================================================
4 _____________________________________________________________________________________________________________ test_needsfiles _____________________________________________________________________________________________________________
5
6 tmpdir = local('/tmp/pytest-0/test_needsfiles0')
8 def test_needsfiles(tmpdir):
9 print tmpdir 10 > assert 0
11 e assert 0
13 test_tmpdir.py:7: assertionerror 14 ------------------------------------------------------------------------------------------------------------- captured stdout -------------------------------------------------------------------------------------------------------------
15 /tmp/pytest-0/test_needsfiles0 16 1 failed in 0.07 seconds</pre>
斷言的前面的print内容也會列印出來,測試時可以多加print語句,保證異常時輸出一些有用的資訊。
下面方式可以檢視内置的
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 # py.test --fixtures
2
3 =========================================================================================================== test session starts ===========================================================================================================
4 platform linux2 -- python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
5 collected 5 items 6 capsys
7 enables capturing of writes to sys.stdout/sys.stderr and makes
8 captured output available via <code>capsys.readouterr()</code> method calls
9 which return a <code>(out, err)</code> tuple. 10
11 capfd 12 enables capturing of writes to file descriptors 1 and 2 and makes 13 captured output available via <code>capsys.readouterr()</code> method calls 14 which return a <code>(out, err)</code> tuple. 15
16 monkeypatch 17 the returned <code>monkeypatch</code> funcarg provides these 18 helper methods to modify objects, dictionaries or os.environ:: 19
20 monkeypatch.setattr(obj, name, value, raising=true) 21 monkeypatch.delattr(obj, name, raising=true) 22 monkeypatch.setitem(mapping, name, value) 23 monkeypatch.delitem(obj, name, raising=true) 24 monkeypatch.setenv(name, value, prepend=false) 25 monkeypatch.delenv(name, value, raising=true) 26 monkeypatch.syspath_prepend(path) 27 monkeypatch.chdir(path) 28
29 all modifications will be undone after the requesting 30 test function has finished. the <code>raising</code> 31 parameter determines if a keyerror or attributeerror 32 will be raised if the set/deletion operation has no target. 33
34 pytestconfig 35 the pytest config object with access to command line opts. 36 recwarn 37 return a warningsrecorder instance that provides these methods: 38
39 * <code>pop(category=none)</code>: return last warning matching the category. 40 * <code>clear()</code>: clear list of warnings 41
42 see http://docs.python.org/library/warnings.html for information
43 on warning categories. 44
45 tmpdir 46 return a temporary directory path object
47 which is unique to each test function invocation, 48 created as a sub directory of the base temporary 49 directory. the returned object is a <code>py.path.local</code>_ 50 path object. 51
52
53 ============================================================================================================ in 0.02 seconds =============================================================================================================</pre>
python -m pytest調用:
python -m pytest [...] 效果和py.test [...] 一樣
擷取版本,選項名,環境變量
py.test --version 看版本
py.test --fixtures 檢視内置參數
py.test -h | --help 指令行和配置檔案幫助
失敗後停止
首次失敗後停止執行:py.test -x
py.test --maxfail=2 兩次失敗之後停止執行
執行選擇用例
py.test test_mod.py,執行子產品中的用例
py.test somepath,執行路徑中用例
py.test -k stringexpr,執行字元串表達式中的用例,比如"myclass? and not method",選擇testmyclass.test_something,排除了testmyclass.test_method_simple。
py.test --pyargs pkg,導入pkg,使用其檔案系統位置來查找和執行用例。執行pypkg目錄下的所有用例。
調試輸出:
py.test --showlocals 在traceback中顯示本地變量
py.test -l 在traceback中顯示本地變量(快捷方式)
py.test --tb=long 預設的traceback資訊格式化形式
py.test --tb=native 标準庫格式化形式
py.test --tb=short 更短的格式
py.test --tb=line 每個錯誤一行
失敗時調用pdb (python debugger):
python帶有一個内置的python調試器稱為pdb。pytest可以在指令行選項指定調用:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">py.test --pdb </pre>
這将每次失敗時調用python調試器。
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">py.test -x --pdb # 失敗時調用pdb,然後退出測試。
py.test --pdb - maxfail=3# 前3次失敗調用pdb。 </pre>
設定斷點:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 import pytest 2 def test_function(): 3 ... 4 pytest.set_trace() # invoke pdb debugger and tracing</pre>
以前的版本中隻有通過py.test-s禁用指令行捕捉才可以進入pdb調試。
profiling測試執行時間:得到最執行慢的10個測試:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">py.test --durations=10 </pre>
建立junitxml格式的檔案
建立hudson或其他持續內建伺服器的結果檔案:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">py.test --junitxml=path </pre>
建立resultlog格式的檔案
要建立純文字的機器可讀的結果檔案,用于pypy-testweb展示等。
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">py.test --resultlog=path </pre>
發送測試報告給線上pastebin服務
bpaste可以為你的文本生成url連接配接,下面為建立每個測試失敗建立一個url:
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">py.test --pastebin=failed
py.test --pastebin=all
py.test --pastebin=failed -x </pre>
目前隻支援:py.test --pastebin=failed
禁用插件
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">py.test -p no:doctest </pre>
在python代碼中調用pytest
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">1 $ python myinvoke.py 2 ***
3 test run reporting finishing</pre>
使用虛拟環境
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;"> 1 #virtualenv .
2 new python executable in ./bin/python
3 installing setuptools, pip...done.
4 root@autotest:[/data/code/python/pytest]#source bin/activate
5 (pytest)root@autotest:[/data/code/python/pytest]#pip install pytest 6 downloading/unpacking pytest
7 downloading pytest-2.5.2.tar.gz (608kb): 608kb downloaded
8 running setup.py (path:/data/code/python/pytest/build/pytest/setup.py) egg_info for package pytest 9
10 downloading/unpacking py>=1.4.20 (from pytest) 11 downloading py-1.4.22.tar.gz (189kb): 189kb downloaded 12 running setup.py (path:/data/code/python/pytest/build/py/setup.py) egg_info for package py 13
14 installing collected packages: pytest, py 15 running setup.py install for pytest 16
17 installing py.test-2.7 script to /data/code/python/pytest/bin 18 installing py.test script to /data/code/python/pytest/bin 19 running setup.py install for py 20
21 successfully installed pytest py 22 cleaning up...</pre>
測試布局和導入規則
測試布局的方法有2種。一為放置在應用代碼之外,适用于有很多功能測試等情況。
<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "courier new" !important; font-size: 12px !important;">setup.py # your distutils/setuptools python package metadata
mypkg/ init.py
appmodule.py
tests/ test_app.py
...</pre>
二為嵌入測試目錄到應用,當(單元)測試和應用之間的有直接關系,并想一起釋出時有用:
...
test/ test_app.py
http://automationtesting.sinaapp.com/blog/m_pytest_doc1