--You can write setup code using conftest.py
(can be created for each directory)
--Abundant hook functions
--You can pass data to test functions using DI-like features
--Used to create and get the object to be tested
--It is possible to pass a value to a test function using a decorator
--Pass preset values, expected test values, etc.
--You don't have to create a class to write test code like unittest
--Result output is easy to see
--Easy to skip tests when removing features or seeing off when the app is released.
This is what it means to write conftest.py
for each directory.
tests
├── __init__.py
├── event
│ ├── __init__.py
| |── conftest.py #Common setup code
│ ├── battle_event_1207
│ │ ├── __init__.py
│ │ ├── conftest.py #Limited time event setup code
│ │ └── test_event.py
│ └── battle_event_1213
│ ├── __init__.py
│ ├── conftest.py #Another one
│ └── test_event.py
└── logics
└── __init__.py
__ The web framework uses Flask __
--Testing the logic part of Model (excluding writing to the datastore: do not commit or use Mock) --Testing the utility function part
Where it is impossible unless you understand the application specifications and learn how to use the web framework / test framework
--The part where requests such as Controller are involved or straddle --The part that is useless unless you prepare a test data store --Transaction-related part
_ Considering whether to use Web Test or Flask's built-in Test _
It seems to be good to import or initialize the test target. If you create a file with the name conftest.py
, pytest will read it for you.
Also, the functions starting with pytest_
are special functions and mainly usepytest_funcarg__xxxx (request)
.
You can use this to pass objects that depend on the test function as arguments. On the test function side, if you specify an argument with the name xxxx
, it will be passed there.
conftest.py
# coding: utf-8
"""battle_event_1213 bootstrap.
Common processing of modules used in test code
Creation of test targets, etc.
"""
from datetime import datetime, timedelta
def pytest_report_header(config):
"""Test report header
"""
return "battle_event_1213 test"
def get_time_subtract_by_delta(seconds):
return datetime.now() + timedelta(seconds=-1 * seconds)
#def pytest_addoption(parser):
# parser.addoption('--ssh', action='store', default=None, help='specify ssh host to run tests with')
class MySetup(object):
"""Factory described here
"""
def getEventCls(self):
from event_models.battle_event_1213 import Event
return Event
def makeEvent(self, *args, **kwargs):
return self.getEventCls()(*args, **kwargs)
def pytest_funcarg__mysetup(request):
"""DI(Dependency injection)
Test function/In the method argument`mysetup`To specify
"""
return MySetup()
def pytest_funcarg__event(request):
return MySetup().makeEvent()
You can use the pytest.mark.skipif
decorator to skip the test when the condition is true. Although it is a function that has already been deleted, it is possible to leave only the test case for the time being, or to specify the expiration date and skip the function for a limited time when the time comes.
On the setup code side, the object returned by the function pytest_funcarg__event (request)
is passed to the ʻeventargument. Since you want to test the state of the object to be tested that is basically set up from the beginning, using
conftest.pyeliminates the trouble of setting up on the test code side. As in this example, you can use the
pytest.mark.parametrizedecorator to pass input and expected values to eliminate the hassle of repeatedly writing test functions / methods. It is passed as an argument to the test function, just like
pytest_funcarg__xxxx (request)`.
test_event.py
# coding: utf-8
import pytest
from datetime import datetime
#Test validity period
is_timeout_event = datetime.now() > datetime(2012,12,19,23,59)
check_event_period = pytest.mark.skipif('%s' % is_timeout_event)
#Test parameters
EXCEEDED_GAUGE = 140
MAX_GAUGE = 100
MAX_ATTACK_PT = 4
#Skip the test if you put some characters in skipif(I deleted the bad function, so I skipped the test)
@pytest.mark.skipif('"The gauge uses a great gauge so skip this test"')
class TestEventDame(object):
@pytest.mark.parametrize('prop', [
'dame_gauge',
])
def test_exists_properties(self, event, prop):
assert hasattr(event, prop)
@pytest.mark.parametrize(('input_val', 'set_val', 'mode'), [
(0, 0, False),
(1, 1, False),
(MAX_GAUGE, MAX_GAUGE, True),
(EXCEEDED_GAUGE, MAX_GAUGE, True),
])
def test_update_dame_gauge(self, event, input_val, set_val, mode):
event.update_dame_gauge(input_val)
assert event.dame_gauge == set_val
assert event.is_dame() is mode
@pytest.mark.parametrize(('value', 'expected'), [
(0, 0),
(1, 1),
(2, 2),
(3, 3),
(4, 6),
])
def test_get_attack_pt_effect(self, event, value, expected):
result = event.get_attack_pt_effect(value)
assert result == expected
#Skip this test at the end of the period
@check_event_period
class TestEventSugoiGauge(object):
@pytest.mark.parametrize('prop', [
'attack_pt',
'current_use_attack_pt',
'update_datetime',
'_use_full_attack_pt_count',
'_use_full_attack_pt_count_with_win',
])
def test_exists_properties(self, event, prop):
assert hasattr(event, prop)
@pytest.mark.parametrize(('value', 'expected'), [
(0, False),
(1, False),
(2, False),
(3, False),
(4, True),
])
def test_is_max_attack_pt(self, event, value, expected):
assert event.is_max_attack_pt(value) is expected
@pytest.mark.parametrize(('value', 'expected'), [
(0, 1),
(1, 2),
(9, 10),
])
def test_inc_use_full_attack_pt_count(self, event, value, expected):
event._use_full_attack_pt_count = value
event._use_full_attack_pt_count_with_win = value
event.inc_use_full_attack_pt_count()
event.inc_use_full_attack_pt_count_with_win()
assert event._use_full_attack_pt_count == expected
assert event._use_full_attack_pt_count_with_win == expected
@pytest.mark.parametrize(('value', 'win_flag', 'expected', 'win_expected'), [
(0, True, 0, 0),
(1, True, 0, 0),
(3, True, 0, 0),
(MAX_ATTACK_PT, False, 1, 0),
(MAX_ATTACK_PT, True, 1, 1),
])
def test_set_use_full_attack_pt(self, event, value, win_flag, expected, win_expected):
event.set_use_full_attack_pt(value, is_win=win_flag)
assert event._use_full_attack_pt_count == expected
assert event._use_full_attack_pt_count_with_win == win_expected
if __name__ == '__main__':
pytest.main()
I can't go back to unittest
-Translated pytest documentation
Recommended Posts