pytest檔案命名規則
python 檔名為 test_*.py 或 *_test.py
method or function 的名字前綴為 test_*
位於 class 中同上命名規則的 method
但 class 的名字前綴為 Test* 且沒有 __init__ method
特殊檔名
conftest.py (可多個)
pytest.ini (唯一)
tox.ini
setup.cfg
引數化
可以使用不同的輸入來對同一個功能進行測試
tests/test_time.py
import pytest
from datetime import datetime, timedelta
testdata = [
(datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
(datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
]
@pytest.mark.parametrize("a,b,expected", testdata)
def test_timedistance_v0(a, b, expected):
diff = a - b
assert diff == expected
讓輸出資料有中文的設定
tests/pytest.ini
[pytest]
disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True
tests/test_passing.py
def test_passing():
assert (1, 2, 3) == (1, 2, 3)
tests/test_failing.py
def test_failing():
assert (1, 2, 3) == (3, 2, 1)
tests/test_raises.py
import pytest
import requests
def test_raises():
with pytest.raises(ZeroDivisionError) as e:
a = 1/0
exec_msg = e.value.args[0]
assert exec_msg == 'division by zero'
tests/test_postcode.py
import pytest
@pytest.fixture()
def postcode():
return '010'
def test_postcode(postcode):
assert postcode == '010'
fixture放在conftest.py內
pytest會自動去抓
tests/conftest.py
import pytest
@pytest.fixture()
def db():
print('Connection successful')
yield
print('Connection closed')
pytest -s test_db.py
pytest --setup-show test_db.py
tests/test_db.py
def search_user(user_id):
d = {
'001': 'xiaoming'
}
return d[user_id]
def test_search(db):
assert search_user('001') == 'xiaoming'
新增作用域的fixture
tests/conftest.py
@pytest.fixture(scope='function')
def func_scope():
pass
@pytest.fixture(scope='module')
def mod_scope():
pass
@pytest.fixture(scope='session')
def sess_scope():
pass
@pytest.fixture(scope='class')
def class_scope():
pass
tests/test_scope.py
import pytest
def test_multi_scope(sess_scope, mod_scope, func_scope):
pass
@pytest.mark.usefixtures('class_scope')
class TestClassScope:
def test_1(self):
pass
def test_2(self):
pass
tests/conftest.py
DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
@pytest.fixture(scope='session', autouse=True)
def timer_session_scope():
start = time.time()
print('\nstart: {}'.format(time.strftime(DATE_FORMAT, time.localtime(start))))
yield
finished = time.time()
print('finished: {}'.format(time.strftime(DATE_FORMAT, time.localtime(finished))))
print('Total time cost: {:.3f}s'.format(finished - start))
@pytest.fixture(autouse=True)
def timer_function_scope():
start = time.time()
yield
print(' Time cost: {:.3f}s'.format(time.time() - start))
tests/test_autouse.py
import time
def test_1():
time.sleep(1)
def test_2():
time.sleep(2)
tests/test_parametrize.py
import pytest
@pytest.mark.parametrize('passwd',['12345678','abcdefdfs','as52345fasdf4'])
def test_passwd_length(passwd):
assert len(passwd) >= 8
@pytest.fixture(params=[
('redis', '6379'),
('elasticsearch', '9200')
])
def param(request):
return request.param
@pytest.fixture(autouse=True)
def db(param):
print('\nSucceed to connect %s:%s' % param)
yield
print('\nSucceed to close %s:%s' % param)
# def test_api():
# assert 1 == 1
-參考資料: https://zwindr.blogspot.com/2019/01/python-pytest.html
-參考資料: https://iter01.com/504335.html
-參考資料: https://learning-pytest.readthedocs.io/zh/latest/doc