python學習-pytest(五)-pytest常用方法


最近工作中用到了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里的setupteardown.

  • 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 ------------------------------------------- Captured stdout call ------------------------------------------- 3 ========================================= 2 failed in 0.06 seconds ========================================= 
  • 多次執行可以看見兩個函數里num的值是總是相同的,如果只是普通的函數調用,兩個函數里的值肯定不可能總是相等的。因此pytest fixture可以用來共享數據。
  • 此外pytest fixture 還可以實現類似teardown的操作,方法是首先把return換成yield,然后把銷毀的相關操作放在yield后面。
# conftest.py import smtplib import pytest @pytest.fixture(scope="module") def smtp_connection(): smtp_connection = smtplib.SMTP("smtp.gmail.com", 587, timeout=5) yield smtp_connection # provide the fixture value print("teardown smtp") smtp_connection.close() 
# test_module.py def test_ehlo(smtp_connection): response, msg = smtp_connection.ehlo() assert response == 250 assert b"smtp.gmail.com" in msg assert 0 # for demo purposes def test_noop(smtp_connection): response, msg = smtp_connection.noop() assert response == 250 assert 0 # for demo purpose 
$ pytest -s -q --tb=no test_module.py FFteardown smtp 2 failed in 6.81 seconds 

從上面的運行可以看出來,在執行完兩個測試用例之后才調用yield后面的print語句。如果我們把scope改成scope="function"那么fixture的setup和teardown就會在每一個測試用例開始和結束時執行。

  • 像上面的close操作也可以使用with語句來實現:
import smtplib import pytest @pytest.fixture(scope="module") def smtp_connection(): with smtplib.SMTP("smtp.gmail.com", 587, timeout=5) as smtp_connection: yield smtp_connection # provide the fixture value 

4. pytest.mark.parametrize

pytest 內置的pytest.mark.parametrize裝飾器支持將測試函數的參數的參數化。

import pytest


@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)]) def test_eval(test_input, expected): assert eval(test_input) == expected 

可以直接通過@pytest.mark.parametrize傳遞參數,而不需要在測試函數里面通過for循環來實現。

@pytest.mark.parametrize還可以添加起來使用:

import pytest @pytest.mark.parametrize("x", [0, 1]) @pytest.mark.parametrize("y", [2, 3]) def test_foo(x, y): assert x + y == 2 

上面的例子里會一共有4中情況:x=0/y=2,x=0/y=3,x=1/y=2,x=1/y=3一共四種情況。

更多用法可以參考官方文檔.

5. pytest.ini

pytest的主配置文件,可以改變pytest的默認行為。我們可以把經常使用的一些選項放到pytest.ini中,或者在里面添加一些markers。

# pytest.ini 文件 [pytest] addopts = --verbose --reruns 5 # 需要安裝 pytest-rerunfailures 插件 --clean-alluredir # 需要 allure-pytest 插件 --alluredir=/tmp/allure-results/ markers = smoke: 冒煙測試用例 

使用 pytest --help 可以看到常用的pytest.ini選項:

[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found: markers (linelist) markers for test functions empty_parameter_set_mark (string) default marker for empty parametersets norecursedirs (args) directory patterns to avoid for recursion testpaths (args) directories to search for tests when no files or directories are given in the command line. console_output_style (string) console output: classic or with additional progress information (classic|progress). usefixtures (args) list of default fixtures to be used with this project python_files (args) glob-style file patterns for Python test module discovery python_classes (args) prefixes or glob names for Python test class discovery python_functions (args) prefixes or glob names for Python test function and method discovery xfail_strict (bool) default for the strict parameter of xfail markers when not given explicitly (default: False) doctest_optionflags (args) option flags for doctests doctest_encoding (string) encoding used for doctest files cache_dir (string) cache directory path. filterwarnings (linelist) Each line specifies a pattern for warnings.filterwarnings. Processed after -W and --pythonwarnings. log_print (bool) default value for --no-print-logs log_level (string) default value for --log-level log_format (string) default value for --log-format log_date_format (string) default value for --log-date-format log_cli (bool) enable log display during test run (also known as "live logging"). log_cli_level (string) default value for --log-cli-level log_cli_format (string) default value for --log-cli-format log_cli_date_format (string) default value for --log-cli-date-format log_file (string) default value for --log-file log_file_level (string) default value for --log-file-level log_file_format (string) default value for --log-file-format log_file_date_format (string) default value for --log-file-date-format addopts (args) extra command line options minversion (string) minimally required pytest version workers (string) Set the max num of workers (aka processes) to start (int or "auto" - one per core) tests_per_worker (string) Set the max num of concurrent tests for each worker (int or "auto" - split evenly) 
  • addopts:更改命令行的默認行為,可以把一些總是用到的選項添加到這里,這樣就不用每次執行的時候都輸入該命令。
  • markers:自定義的標記,可以使用pytest --markers看到。
  • pytest.ini文件放到工程的目錄即可。


作者:利歐leo丶
鏈接:https://www.jianshu.com/p/ab8e87547676
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM