最近工作中用到了pytest,總結一些用法:
1. 安裝:
pip install pytest
2. 運行:
pytest 默認只能識別以test_
開頭的文件和測試用例,如果pytest后面不帶文件名,則默認執行當前目錄下所有以test_
開頭的文件。
- 執行某個文件里所有以 test 開頭的用例:
pytest test_demo.py
# test_demo.py def test_01(): assert 1+1 == 2 def test_02(): assert 1+3 == 4
執行結果:
$ pytest test_demo.py
========================================= test session starts ============================================
platform darwin -- Python 3.7.3, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: /Users/libo/python3workspace/learn, inifile:
plugins: rerunfailures-7.0, picked-0.4.1, parallel-0.0.9, forked-1.0.2, cov-2.7.1, allure-pytest-2.6.1
collected 2 items
test_demo.py .. [100%]
======================================== 2 passed in 0.04 seconds =========================================
如果只想執行test_01,可以使用pytest test_demo.py::test_01
- 如果用例是用類組織起來的:
# test_class.py class TestClass(object): def test_one(self): x = "this" assert 'h' in x def test_two(self): x = "hello" assert hasattr(x, 'check')
執行結果:
$ pytest test_class.py =========================================== test session starts ============================================ platform darwin -- Python 3.7.3, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 rootdir: /Users/libo/python3workspace/learn, inifile: plugins: rerunfailures-7.0, picked-0.4.1, parallel-0.0.9, forked-1.0.2, cov-2.7.1, allure-pytest-2.6.1 collected 2 items test_class.py .F [100%] ================================================= FAILURES ================================================= ____________________________________________ TestClass.test_two ____________________________________________ self = <test_class.TestClass object at 0x102f46780> def test_two(self): y = "world" > assert 'h' in y E AssertionError: assert 'h' in 'world' test_class.py:9: AssertionError ========================================== 1 failed, 1 passed in 0.08 seconds ====================================
如果一個文件里有多個類,你只想執行其中一個類里的用例:
pytest test_class.py::TestClass
- 執行某個文件夾下所有的以
test_
開頭的文件:pytest testcase/
# testcase/test_demo01.py def test_one(): x = 'this' assert 'h' in x # testcase/test_demo02.py def test_two(): y = 'world' assert 'h' in y
執行結果:
$ pytest testcase/ ========================================== test session starts ============================================ platform darwin -- Python 3.7.3, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 rootdir: /Users/libo/python3workspace/learn, inifile: plugins: rerunfailures-7.0, picked-0.4.1, parallel-0.0.9, forked-1.0.2, cov-2.7.1, allure-pytest-2.6.1 collected 2 items testcase/test_demo01.py . [ 50%] testcase/test_demo02.py F [100%] ============================================== FAILURES =========================================== _________________________________________________ test_two _________________________________________________ def test_two(): y = 'world' > assert 'h' in y E AssertionError: assert 'h' in 'world' testcase/test_demo02.py:3: AssertionError ==================================== 1 failed, 1 passed in 0.09 seconds ================================
- 執行帶某個標記的用例,比如用例中帶了
@pytest.mark.smoke
標記的用例:
# test_mark.py @pytest.mark.smoke def test_01(): assert 1+1 == 2 def test_02(): assert 1+3 == 4
$ pytest -m smoke test_mark.py
=========================================== test session starts ============================================
platform darwin -- Python 3.7.3, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: /Users/libo/python3workspace/learn, inifile:
plugins: rerunfailures-7.0, picked-0.4.1, parallel-0.0.9, forked-1.0.2, cov-2.7.1, allure-pytest-2.6.1
collected 2 items / 1 deselected / 1 selected
test_mark.py . [100%]
================================== 1 passed, 1 deselected in 0.03 seconds ==================================
可以看到只執行帶@pytest.mark.smoke
的用例。
- 按用例函數的名稱來執行:
pytest -k 01 test_mark.py
$ pytest -k 01 test_mark.py
=========================================== test session starts ============================================
platform darwin -- Python 3.7.3, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: /Users/libo/python3workspace/learn, inifile:
plugins: rerunfailures-7.0, picked-0.4.1, parallel-0.0.9, forked-1.0.2, cov-2.7.1, allure-pytest-2.6.1
collected 2 items / 1 deselected / 1 selected
test_mark.py . [100%]
================================== 1 passed, 1 deselected in 0.01 seconds ==================================
按照用例名字來執行,只執行名字里含有01的測試用例。
3. pytest fixture
@pytest_fixture
的作用是提供一個固定的參數給測試重復的使用,相當於unittest里的setup
和teardown
.
- pytest fixture 做函數的參數
# test_fixture.py @pytest.fixture(scope="module") def num(): n = random.randint(1, 5) return n def test_01(num): print(num) assert 0 def test_02(num): print(num) assert 0
- pytest fixture的scope有class, session 和 module.
- 此時執行可以多次執行看看兩個函數里num的數值是否是一樣:
$ pytest test_fixture.py =========================================== test session starts ============================================ platform darwin -- Python 3.7.3, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 rootdir: /Users/libo/python3workspace/learn, inifile: plugins: rerunfailures-7.0, picked-0.4.1, parallel-0.0.9, forked-1.0.2, cov-2.7.1, allure-pytest-2.6.1 collected 2 items test_fixture.py FF [100%] ================================================= FAILURES ================================================= _________________________________________________ test_01 __________________________________________________ num = 3 def test_01(num): print(num) > assert 0 E assert 0 test_fixture.py:12: AssertionError ------------------------------------------- Captured stdout call ------------------------------------------- 3 _________________________________________________ test_02 __________________________________________________ num = 3 def test_02(num): print(num) > assert 0 E assert 0 test_fixture.py:16: AssertionError --------------------------------