運行pytest可以指定目錄和文件,如果不指定,pytest會搜索當前目錄及其子目錄中以test_開頭或以_test結尾得測試函數。我們把pytest搜索測試文件和測試用例的過程稱爲測試搜索(test discovery)。只要遵循pytest的命名規則,pytest就能自動搜索所有待執行的測試用例。
1、測試文件命名規則,test_xxx.py或xxx_test.py
2、方法、測試函數命名規則,test_xxx
3、測試類命名規則,Testxxx,並且不能帶有 init 方法
項目目錄:
test_01/test_01.py代碼如下:
#!/usr/bin/env python
# _*_coding:utf-8_*_
import pytest
class Test(object):
def test_login_01(self):
"""用例1"""
print('執行用例test_login_01斷言1')
pytest.assume(1 == 1)
print('執行用例test_login_01斷言2')
pytest.assume(2 == 2)
def test_login_02(self):
"""用例2"""
print('執行用例test_login_02斷言1')
pytest.assume(3 == 3)
print('執行用例test_login_02斷言2')
pytest.assume(True)
test_01/test_02.py代碼如下:
#!/usr/bin/env python
# _*_coding:utf-8_*_
import pytest
class Test(object):
def test_login_03(self):
"""用例1"""
print('執行用例test_login_03斷言1')
pytest.assume(1 == 1)
print('執行用例test_login_03斷言2')
pytest.assume(2 == 2)
def test_login_04(self):
"""用例2"""
print('執行用例test_login_04斷言1')
pytest.assume(3 == 3)
print('執行用例test_login_04斷言2')
pytest.assume(True)
不加任何參數,控制檯輸出了執行用例所在的文件、用例執行結果(..)、文件百分比
命令行執行:pytest
#test_01.py
if __name__ == '__main__':
pytest.main()
C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe C:/Users/admin/Desktop/AutoTest/Test/test/test_01/test_01.py
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\admin\Desktop\AutoTest\Test\test\test_01
plugins: assume-2.2.1, ordering-0.6
收集的測試用例:[<Function test_login_01>, <Function test_login_02>, <Function test_login_03>, <Function test_login_04>]
collected 4 items
test_01.py .. [ 50%]
test_02.py .. [100%]
============================== 4 passed in 0.08s ==============================
Process finished with exit code 0
-v 說明:控制檯可以輸出用例更加詳細的執行信息,比如用例所在的文件、類、用例名稱、用例執行結果(PASSED)、用例百分比等。
命令行執行:pytest -v
#test_01.py
if __name__ == '__main__':
pytest.main(['-v'])
C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe C:/Users/admin/Desktop/AutoTest/Test/test/test_01/test_01.py
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\admin\Desktop\AutoTest\Test\test\test_01
plugins: assume-2.2.1, ordering-0.6
collecting ... 收集的測試用例:[<Function test_login_01>, <Function test_login_02>, <Function test_login_03>, <Function test_login_04>]
collected 4 items
test_01.py::Test::test_login_01 PASSED [ 25%]
test_01.py::Test::test_login_02 PASSED [ 50%]
test_02.py::Test::test_login_03 PASSED [ 75%]
test_02.py::Test::test_login_04 PASSED [100%]
============================== 4 passed in 0.08s ==============================
Process finished with exit code 0
-k 說明:允許你使用表達式指定希望運行的測試用例,如果某測試用例名是唯一的,或者多個測試用例名的前綴和後綴相同,就可以使用表達式快速定位,如果你想執行的測試用例名字需包含login_01,就可以這麼寫pytest.main(['-v', '-k', 'login_01]),如果你想執行的測試用例名字需包含login_01和login_03,就可以這沒寫pytest.main(['-v', '-k', 'login_01 or login_03'])
控制檯輸出了選擇了2個用例,未選擇2個用例、通過了2個用例
collected 4 items / 2 deselected / 2 selected
======================= 2 passed, 2 deselected in 0.05s =======================
命令行執行:pytest -k 'login_01 or login_03'
#test_01.py
if __name__ == '__main__':
pytest.main(['-v', '-k', 'login_01 or login_03'])
C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe C:/Users/admin/Desktop/AutoTest/Test/test/test_01/test_01.py
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\admin\Desktop\AutoTest\Test\test\test_01
plugins: assume-2.2.1, ordering-0.6
collecting ... 收集的測試用例:[<Function test_login_01>, <Function test_login_02>, <Function test_login_03>, <Function test_login_04>]
collected 4 items / 2 deselected / 2 selected
test_01.py::Test::test_login_01 PASSED [ 50%]
test_02.py::Test::test_login_03 PASSED [100%]
======================= 2 passed, 2 deselected in 0.05s =======================
Process finished with exit code 0
-m 說明:標記用於測試用例並分組,以便快速選中並運行,以test_login_01()和test_login_02()爲例,希望同時選中並執行,需預先做好標記,假設標記名是run,則可使用@pytest.mark.run裝飾器來做標記,調用執行用pytest.main(['-v', '-m', 'run'])
命令行執行:pytest -m run
#test_01.py
#!/usr/bin/env python
# _*_coding:utf-8_*_
import pytest
class Test(object):
@pytest.mark.run
def test_login_01(self):
"""用例1"""
print('執行用例test_login_01斷言1')
pytest.assume(1 == 1)
print('執行用例test_login_01斷言2')
pytest.assume(2 == 2)
@pytest.mark.run
def test_login_02(self):
"""用例2"""
print('執行用例test_login_02斷言1')
pytest.assume(3 == 3)
print('執行用例test_login_02斷言2')
pytest.assume(True)
if __name__ == '__main__':
pytest.main(['-v', '-m', 'run'])
C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe C:/Users/admin/Desktop/AutoTest/Test/test/test_01/test_01.py
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\admin\Desktop\AutoTest\Test\test\test_01
plugins: assume-2.2.1, ordering-0.6
collecting ... 收集的測試用例:[<Function test_login_01>, <Function test_login_02>, <Function test_login_03>, <Function test_login_04>]
collected 4 items / 2 deselected / 2 selected
test_01.py::Test::test_login_01 PASSED [ 50%]
test_01.py::Test::test_login_02 PASSED [100%]
======================= 2 passed, 2 deselected in 0.07s =======================
Process finished with exit code 0
-s 說明:該選項允許測試運行時輸出任何符合標準的輸出流信息,例如代碼裏面的print。正常情況下,所有輸出都會被捕獲,測試失敗時,pytest會做出判斷並輸出失敗報告。
命令行執行:pytest -s
#test_01.py
if __name__ == '__main__':
pytest.main(['-v', '-s'])
C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe C:/Users/admin/Desktop/AutoTest/Test/test/test_01/test_01.py
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\admin\Desktop\AutoTest\Test\test\test_01
plugins: assume-2.2.1, ordering-0.6
collecting ... 收集的測試用例:[<Function test_login_01>, <Function test_login_02>, <Function test_login_03>, <Function test_login_04>]
collected 4 items
test_01.py::Test::test_login_01 執行用例test_login_01斷言1
執行用例test_login_01斷言2
PASSED
test_01.py::Test::test_login_02 執行用例test_login_02斷言1
執行用例test_login_02斷言2
PASSED
test_02.py::Test::test_login_03 執行用例test_login_03斷言1
執行用例test_login_03斷言2
PASSED
test_02.py::Test::test_login_04 執行用例test_login_04斷言1
執行用例test_login_04斷言2
PASSED
============================== 4 passed in 0.07s ==============================
Process finished with exit code 0
-x 說明:正常情況下,pytest會運行每一個搜索到的測試用例,如果某個測試函數被斷言失敗,或者觸發了外部異常,則該測試用例的運行就會停止,pytest將其標記爲失敗後會繼續運行下一個測試用例。通常這就是我們期望的運行模式,但是在debug時,我們希望遇到失敗時立即停止整個會話,這時-x就派上用場了。
命令行執行:pytest -x
#test_01.py
#!/usr/bin/env python
# _*_coding:utf-8_*_
import pytest
class Test(object):
def test_login_01(self):
"""用例1"""
print('執行用例test_login_01斷言1')
pytest.assume(1 == 0)
print('執行用例test_login_01斷言2')
pytest.assume(2 == 2)
def test_login_02(self):
"""用例2"""
print('執行用例test_login_02斷言1')
pytest.assume(3 == 3)
print('執行用例test_login_02斷言2')
pytest.assume(True)
if __name__ == '__main__':
pytest.main(['-v', '-x'])
C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe C:/Users/admin/Desktop/AutoTest/Test/test/test_01/test_01.py
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\admin\Desktop\AutoTest\Test\test\test_01
plugins: assume-2.2.1, ordering-0.6
collecting ... 收集的測試用例:[<Function test_login_01>, <Function test_login_02>, <Function test_login_03>, <Function test_login_04>]
collected 4 items
test_01.py::Test::test_login_01 FAILED [ 25%]
================================== FAILURES ===================================
_____________________________ Test.test_login_01 ______________________________
tp = <class 'pytest_assume.plugin.FailedAssumption'>, value = None, tb = None
def reraise(tp, value, tb=None):
try:
if value is None:
value = tp()
if value.__traceback__ is not tb:
> raise value.with_traceback(tb)
E pytest_assume.plugin.FailedAssumption:
E 1 Failed Assumptions:
E
E test_01.py:11: AssumptionFailure
E >> pytest.assume(1 == 0)
E AssertionError: assert False
C:\Users\admin\AppData\Roaming\Python\Python37\site-packages\six.py:702: FailedAssumption
---------------------------- Captured stdout call -----------------------------
執行用例test_login_01斷言1
執行用例test_login_01斷言2
=========================== short test summary info ===========================
FAILED test_01.py::Test::test_login_01 - pytest_assume.plugin.FailedAssumption:
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!
============================== 1 failed in 0.08s ==============================
Process finished with exit code 0
--maxfail=num 說明:假設你允許pytest失敗幾次後再停止,則可以使用--maxfail選項,明確指定可以失敗幾次後停止整個會話。
命令行執行:pytest --maxfail=2
#test_01.py
#!/usr/bin/env python
# _*_coding:utf-8_*_
import pytest
class Test(object):
def test_login_01(self):
"""用例1"""
print('執行用例test_login_01斷言1')
pytest.assume(1 == 0)
print('執行用例test_login_01斷言2')
pytest.assume(2 == 2)
def test_login_02(self):
"""用例2"""
print('執行用例test_login_02斷言1')
pytest.assume(3 == 3)
print('執行用例test_login_02斷言2')
pytest.assume(True)
test_01.py中有一個斷言失敗,最大失敗次數設置成1 pytest.main(['-v', '--maxfail=1'])和pytest.main(['-v', '-x'])效果一樣的,當遇到第一個失敗時,就停止整個會話執行
#test_01.py
if __name__ == '__main__':
pytest.main(['-v', '--maxfail=1'])
C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe C:/Users/admin/Desktop/AutoTest/Test/test/test_01/test_01.py
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\admin\Desktop\AutoTest\Test\test\test_01
plugins: assume-2.2.1, ordering-0.6
collecting ... 收集的測試用例:[<Function test_login_01>, <Function test_login_02>, <Function test_login_03>, <Function test_login_04>]
collected 4 items
test_01.py::Test::test_login_01 FAILED [ 25%]
================================== FAILURES ===================================
_____________________________ Test.test_login_01 ______________________________
tp = <class 'pytest_assume.plugin.FailedAssumption'>, value = None, tb = None
def reraise(tp, value, tb=None):
try:
if value is None:
value = tp()
if value.__traceback__ is not tb:
> raise value.with_traceback(tb)
E pytest_assume.plugin.FailedAssumption:
E 1 Failed Assumptions:
E
E test_01.py:11: AssumptionFailure
E >> pytest.assume(1 == 0)
E AssertionError: assert False
C:\Users\admin\AppData\Roaming\Python\Python37\site-packages\six.py:702: FailedAssumption
---------------------------- Captured stdout call -----------------------------
執行用例test_login_01斷言1
執行用例test_login_01斷言2
=========================== short test summary info ===========================
FAILED test_01.py::Test::test_login_01 - pytest_assume.plugin.FailedAssumption:
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!
============================== 1 failed in 0.06s ==============================
Process finished with exit code 0
test_01.py中有一個斷言失敗,最大失敗次數設置成2 pytest.main(['-v', '--maxfail=2']),當遇到第一個失敗時,未滿足2個失敗的條件,所以會繼續執行後續的用例。
#test_01.py
#!/usr/bin/env python
# _*_coding:utf-8_*_
import pytest
class Test(object):
def test_login_01(self):
"""用例1"""
print('執行用例test_login_01斷言1')
pytest.assume(1 == 0)
print('執行用例test_login_01斷言2')
pytest.assume(2 == 2)
def test_login_02(self):
"""用例2"""
print('執行用例test_login_02斷言1')
pytest.assume(3 == 3)
print('執行用例test_login_02斷言2')
pytest.assume(True)
if __name__ == '__main__':
pytest.main(['-v', '--maxfail=2'])
C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe C:/Users/admin/Desktop/AutoTest/Test/test/test_01/test_01.py
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- C:\Users\admin\AppData\Local\Programs\Python\Python37\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\admin\Desktop\AutoTest\Test\test\test_01
plugins: assume-2.2.1, ordering-0.6
collecting ... 收集的測試用例:[<Function test_login_01>, <Function test_login_02>, <Function test_login_03>, <Function test_login_04>]
collected 4 items
test_01.py::Test::test_login_01 FAILED [ 25%]
test_01.py::Test::test_login_02 PASSED [ 50%]
test_02.py::Test::test_login_03 PASSED [ 75%]
test_02.py::Test::test_login_04 PASSED [100%]
================================== FAILURES ===================================
_____________________________ Test.test_login_01 ______________________________
tp = <class 'pytest_assume.plugin.FailedAssumption'>, value = None, tb = None
def reraise(tp, value, tb=None):
try:
if value is None:
value = tp()
if value.__traceback__ is not tb:
> raise value.with_traceback(tb)
E pytest_assume.plugin.FailedAssumption:
E 1 Failed Assumptions:
E
E test_01.py:11: AssumptionFailure
E >> pytest.assume(1 == 0)
E AssertionError: assert False
C:\Users\admin\AppData\Roaming\Python\Python37\site-packages\six.py:702: FailedAssumption
---------------------------- Captured stdout call -----------------------------
執行用例test_login_01斷言1
執行用例test_login_01斷言2
=========================== short test summary info ===========================
FAILED test_01.py::Test::test_login_01 - pytest_assume.plugin.FailedAssumption:
========================= 1 failed, 3 passed in 0.09s =========================
Process finished with exit code 0