iT邦幫忙

2021 iThome 鐵人賽

DAY 25
0
Modern Web

Python x Django 網站實作&學習記錄系列 第 25

D25 Pytest 學習紀錄-pytest規則跟常用固件

  • 分享至 

  • xImage
  •  

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


上一篇
D24 Pytest 學習測試
下一篇
D26 將config等等隱密資訊另外放置 - yaml
系列文
Python x Django 網站實作&學習記錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言