 æ»ã 次ãž
 æ»ã 次㞠
ãã®ç« ã§ã¯ãpytestã«åœ±é¿ããæ§æãã¡ã€ã«ã調ã¹ãpytestããããã«åºã¥ããŠåäœãã©ã®ããã«å€æŽãããã説æããTasksãããžã§ã¯ãã®æ§æã¿ã¹ã¯ã«ããã€ãã®å€æŽãå ããŸãã

ãã®æ¬ã®äŸã¯ãPython 3.6ãšpytest 3.2ã䜿çšããŠæžãããŠããŸãã pytest 3.2ã¯ãPython 2.6ã2.7ãããã³Python 3.3+ããµããŒãããŠããŸãã
Tasksãããžã§ã¯ãã®ãœãŒã¹ã³ãŒããšããã®æ¬ã«ç€ºãããŠãããã¹ãŠã®ãã¹ãã®ãœãŒã¹ã³ãŒãã¯ã pragprog.comã«ããæ¬ã®WebããŒãžã®ãªã³ã¯ããå
¥æã§ããŸãã ãã¹ãã³ãŒããçè§£ããããã«ãœãŒã¹ã³ãŒããããŠã³ããŒãããå¿
èŠã¯ãããŸããã ãã¹ãã³ãŒãã¯ãäŸã§ã¯äŸ¿å©ãªåœ¢åŒã§ç€ºãããŠããŸãã ãã ãããããžã§ã¯ãã®ã¿ã¹ã¯ãå®è¡ãããããã¹ããµã³ãã«ã調æŽããŠèªåã®ãããžã§ã¯ãããã¹ããããããã«ã¯ïŒæãçžã£ãŠããªãïŒïŒãæžç±ã®WebããŒãžã«ã¢ã¯ã»ã¹ããŠäœåãããŠã³ããŒãããå¿
èŠããããŸãã æžç±ã®WebããŒãžã«ã¯ã æ£èª€è¡šã®ã¡ãã»ãŒãžãžã®ãªã³ã¯ãšãã£ã¹ã«ãã·ã§ã³ãã©ãŒã©ã ããããŸãã
ãã¿ãã¬ã®äžã«ã¯ããã®ã·ãªãŒãºã®èšäºã®ãªã¹ãããããŸãã
æ§æ
ãããŸã§ã®ãšããã95ããŒãžã®ç¬¬5ç« ããã©ã°ã€ã³ãã§è©³çްã«èª¬æããconftest.pyãé€ããäž»ã«pytestã«åœ±é¿ãäžããããŸããŸãªéãã¹ããã¡ã€ã«ã«ã€ããŠèª¬æããŸããããã®ç« ã§ã¯ãæ§æãã¡ã€ã«ã«ã€ããŠèª¬æããŸãã pytestã«åœ±é¿ãäžããpytestããããã«åºã¥ããŠåäœãã©ã®ããã«å€æŽããããè°è«ããTasksãããžã§ã¯ãã®æ§æãã¡ã€ã«ã«ããã€ãã®å€æŽãå ããŸãã
pytestæ§æãã¡ã€ã«ã«ã€ããŠ
pytestã®ããã©ã«ãã®åäœã倿Žããæ¹æ³ã説æããåã«ãpytestã®ãã¹ãŠã®éãã¹ããã¡ã€ã«ãç¹ã«ã誰ãããããåŠçããå¿
èŠããããã調ã¹ãŠã¿ãŸãããã
次ã®ããšãç¥ã£ãŠããå¿
èŠããããŸãã
- pytest.ini ïŒããã¯ãããã©ã«ãã®åäœã倿Žã§ããã¡ã€ã³ã®Pytestæ§æãã¡ã€ã«ã§ãã ããªãã®æ°ã®æ§æå€æŽãè¡ãããšãã§ããããããã®ç« ã®å€§éšåã¯pytest.iniè¡ããèšå®ã«å°å¿µããŠããŸãã
- conftest.py ïŒããã¯ã conftest.pyãã¡ã€ã«conftest.pyãã£ã¬ã¯ããªãšãã®ãã¹ãŠã®ãµããã£ã¬ã¯ããªã«ããã¯é¢æ°ãšãã£ã¯ã¹ãã£ãæ¥ç¶ã§ããããã«ããããŒã«ã«ãã©ã°ã€ã³ã§ããconftest.pyãã¡ã€ã«ã«ã€ããŠã¯ã95ããŒãžã®ç¬¬5ç« ããã©ã°ã€ã³ãã§èª¬æããŠããŸãã
- __init__.pyïŒåãã¹ããµããã£ã¬ã¯ããªã«é
眮ãããšããã®ãã¡ã€ã«ã«ãããè€æ°ã®ãã¹ããã£ã¬ã¯ããªã«åããã¹ããã¡ã€ã«åãä»ããããšãã§ããŸãã 120ããŒãžã®ããã¡ã€ã«åã®è¡çªã®åé¿ãã®èšäºã§ããã¹ããã£ã¬ã¯ããªã«- __init__.pyãã¡ã€ã«ããªããã°äœãããŸããããªããã®äŸãèŠãŠãããŸãã
toxã䜿çšããå Žåã¯ã次ã®ããšã«èå³ããããŸãã
- tox.ini ïŒãã®ãã¡ã€ã«ã¯pytest.iniã«äŒŒãŠããŸãããtoxçštoxã ãã ããtox.iniãã¡ã€ã«ãštox.iniãã¡ã€ã«ã®äž¡æ¹ãä¿æãã代ããã«ãpytestã«pytestæ§æãé
眮ãpytestã1ã€ã®æ§æãã¡ã€ã«ãä¿åã§ããŸãã Toxã«ã€ããŠã¯ã125ããŒãžã®ç¬¬7ç« ãä»ã®ããŒã«ã§ã®pytestã®äœ¿çšãã§èª¬æããŠããŸãã
Pythonããã±ãŒãžïŒã¿ã¹ã¯ãªã©ïŒãé
åžããå Žåããã®ãã¡ã€ã«ã¯è峿·±ããã®ã«ãªããŸãã
- setup.cfg ïŒããã¯ã setup.pyåäœã«åœ±é¿ãäžããINIãã¡ã€ã«ã§ãããsetup.pyã æ°è¡ãsetup.pyã«è¿œå ããŠãpython setup.py testãå®è¡ãããã¹ãŠã®pytestpython setup.py testãå®è¡ã§ããŸãã ããã±ãŒãžãé
åžããŠããå Žåããã§ã«setup.cfgãã¡ã€ã«ãããããã®ãã¡ã€ã«ã䜿çšããŠPytestæ§æãä¿åã§ããŸãã ãããã©ã®ããã«è¡ããããã¯ã175ããŒãžã®ä»é²4ãPythonãããžã§ã¯ãã®ããã±ãŒãžåãšé
åžãã§ç¢ºèªã§ããŸãã
pytestèšå®ãã©ã®ãã¡ã€ã«ã«å
¥ããŠãããã©ãŒãããã¯åºæ¬çã«åãã§ãã
pytest.ini ïŒ
ch6 / format / pytest.ini
 [pytest] addopts = -rsxX -l --tb=short --strict xfail_strict = true ... more options ... 
tox.ini ïŒ
ch6 / format / tox.ini
 ... tox specific stuff ... [pytest] addopts = -rsxX -l --tb=short --strict xfail_strict = true ... more options ... 
setup.cfg ïŒ
ch6 / format / setup.cfg
 ... packaging specific stuff ... [tool:pytest] addopts = -rsxX -l --tb=short --strict xfail_strict = true ... more options ... 
å¯äžã®éãã¯ãsetup.cfgã®ã»ã¯ã·ã§ã³ããããŒã[tool:pytest]ã§ã¯ãªã[tool:pytest]ããšã§ãã
pytest -helpã䜿çšããŠæå¹ãªiniãã¡ã€ã«ãªãã·ã§ã³ãäžèŠ§è¡šç€ºãã
pytest --helpããpytest --helpã®ãã¹ãŠã®æå¹ãªãã©ã¡ãŒã¿ãŒã®ãªã¹ããååŸã§ãpytest --help ã
 $ pytest --help ... [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) junit_suite_name (string) Test suite name for JUnit report junit_logging (string) Write captured log messages to JUnit report: one of no|system-out|system-err 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 xvfb_width (string) Width of the Xvfb display xvfb_height (string) Height of the Xvfb display xvfb_colordepth (string) Color depth of the Xvfb display xvfb_args (args) Additional arguments for Xvfb xvfb_xauth (bool) Generate an Xauthority token for Xvfb. Needs xauth. ... 
ãã®ç« ã§ã¯ã125ããŒãžã®ç¬¬7ç« ãä»ã®ããŒã«ã§ã®pytestã®äœ¿çšãã§èª¬æãããŠããdoctest_optionflagsé€ãããããã®èšå®ããã¹ãŠç¢ºèªã§ããŸãã
ãã©ã°ã€ã³ã¯iniãã¡ã€ã«ãªãã·ã§ã³ã远å ã§ããŸã
åã®èšå®ãªã¹ãã¯äžå®ã§ã¯ãããŸããã ãã©ã°ã€ã³ïŒããã³conftest.pyãã¡ã€ã«ïŒã®å Žåãiniãã¡ã€ã«ãªãã·ã§ã³ã远å ã§ããŸãã 远å ããããªãã·ã§ã³ã¯ãpytest --helpã³ãã³ãã®åºåã«ã远å ãããŸãã
ããã§ãã³ã¢pytestã§äœ¿çšå¯èœãª.iniãã¡ã€ã«ã®çµã¿èŸŒã¿èšå®ã§è¡ãããšãã§ããããã€ãã®æ§æå€æŽãèŠãŠã¿ãŸãããã
ããã©ã«ãã®ã³ãã³ãã©ã€ã³ãªãã·ã§ã³ã倿Žãã
pytestã®ã³ãã³ãã©ã€ã³ãªãã·ã§ã³ããã§ã«äœ¿çšããŸããã詳现åºå-l/--showlocals -v/--verbose -verbose㯠ã倱æãããã¹ãã®ã¹ã¿ãã¯ãã¬ãŒã¹ãå«ãããŒã«ã«å€æ°ã衚瀺ããŸãã themâfor a projectã¯ããããã®optionsâoräžéšãåžžã«äœ¿çšãããã䜿çšããthemâfor a projectã奜ãoptionsâorããoptionsâor ã å¿
èŠãªãã©ã¡ãŒã¿ãŒã®addoptsã«pytest.iniãã€ã³ã¹ããŒã«ããå Žåãããããå
¥åããå¿
èŠã¯ãªããªããŸããã ç§ã奜ããªã»ããã¯æ¬¡ã®ãšããã§ãã
 [pytest] addopts = -rsxX -l --tb=short --strict 
-rsxX䜿çšãããšã xfailedã¯ãã¹ãŠã®skipped ã xfailedãŸãã¯xpassedãã¹ãã®çç±ãå ±åã§ããŸãã -lã¹ã€ããã䜿çšãããšãpytestã¯åé害ã®å Žåã«ããŒã«ã«å€æ°ã®ã¹ã¿ãã¯ãã¬ãŒã¹ã衚瀺ã§ããŸãã --tb=shortã¯ãã¹ã¿ãã¯ãã¬ãŒã¹ã®ã»ãšãã©ãåé€ããŸãã ãã ãããã¡ã€ã«ãšè¡çªå·ã¯æ®ããŸãã --strictã¯ãæ§æãã¡ã€ã«ã«ç»é²ãããŠããªãããŒã¯ã³ã®äœ¿çšãçŠæ¢ããŸãã ãããè¡ãæ¹æ³ã«ã€ããŠã¯ã次ã®ã»ã¯ã·ã§ã³ã§èª¬æããŸãã
ããŒã«ãŒã®ã¿ã€ããã¹ãé²ãããã«ããŒã«ãŒãç»é²ãã
31ããŒãžã®ããã¹ã颿°ã®ã©ãã«ä»ããã§èª¬æãããŠããã«ã¹ã¿ã ããŒã«ãŒã¯ãç¹å®ã®ããŒã«ãŒã§å®è¡ãããã¹ãã®ãµãã»ãããããŒã¯ããã®ã«æé©ã§ãã ãã ããããŒã«ãŒãééããã®ã¯ç°¡åããããããæçµçã«ããã€ãã®ãã¹ãã«ã¯@pytest.mark.smokeãšããã¿ã°ãä»ããããäžéšã®ãã¹ãã«ã¯@pytest.mark.smokeãšããã¿ã°ãä»ããããŸãã ããã©ã«ãã§ã¯ãããã¯ãšã©ãŒã§ã¯ãããŸããã pytestã¯ã2ã€ã®ããŒã«ãŒãäœæãããšèããŠããŸãã ãã ããããã¯ã次ã®ããã«ãpytest.iniã«ããŒã¯ã³ãç»é²ããããšã§ä¿®æ£ã§ããŸãã
 [pytest] ... markers = smoke: Run the smoke test test functions get: Run the test functions that test tasks.get() ... 
ãããã®ããŒã«ãŒãç»é²ããããšã«ããã pytest --markersãšãã®èª¬æã䜿çšããŠè¡šç€ºããããšãã§ããŸãã
 $ cd /path/to/code/ch6/b/tasks_proj/tests $ pytest --markers @pytest.mark.smoke: Run the smoke test test functions @pytest.mark.get: Run the test functions that test tasks.get() @pytest.mark.skip(reason=None): skip the ... ... 
ããŒã«ãŒãç»é²ãããŠããªãå ŽåãããŒã«ãŒã¯--markersãªã¹ãã«è¡šç€ºãããŸããã ããããç»é²ããããšããããã¯ãªã¹ãã«è¡šç€ºãããŸã--strictã䜿çšãããšããšã©ãŒã®ããããŒã¯ã³ãŸãã¯æªç»é²ã®ããŒã¯ã³ã¯ãšã©ãŒãšããŠè¡šç€ºãããŸãã ch6/a/tasks_projãšch6/b/tasks_projã®å¯äžã®éãã¯ãpytest.iniãã¡ã€ã«ã®å
容ã§ãã ch6/a空ã§ãã ããŒã«ãŒãç»é²ããã«ãã¹ããå®è¡ããŠã¿ãŸãããã
 $ cd /path/to/code/ch6/a/tasks_proj/tests $ pytest --strict --tb=line ============================= test session starts ============================= collected 45 items / 2 errors =================================== ERRORS ==================================== ______________________ ERROR collecting func/test_add.py ______________________ 'smoke' not a registered marker ________________ ERROR collecting func/test_api_exceptions.py _________________ 'smoke' not a registered marker !!!!!!!!!!!!!!!!!!! Interrupted: 2 errors during collection !!!!!!!!!!!!!!!!!!! =========================== 2 error in 1.10 seconds =========================== 
pytest.iniããŒã«ãŒã䜿çšããŠããŒã«ãŒãç»é²ãã--strict ã addopts --strictã远å ããããšãã§ããŸãã åŸã§æè¬ããŸãã å
ã«é²ã¿ãpytest.iniãã¡ã€ã«ãã¿ã¹ã¯ãããžã§ã¯ãã«è¿œå ããŸãããã
pytest.iniããŒã«ãŒã䜿çšããŠããŒã«ãŒãç»é²ãã--strictã¯ã addopts --strictã远å ããããšãã§ããŸãã åŸã§æè¬ããŸãã ç¶ããŠãpytest.iniãã¡ã€ã«ãã¿ã¹ã¯ãããžã§ã¯ãã«è¿œå ããŸãã
pytest.iniããŒã¯ã³ã䜿çšããŠããŒã¯ã³ãç»é²ããå Žåã pytest.iniã--strictããŠæ¢åã®ããŒã¯ã³ã«--strictã远å ããããšãã§ããŸãã ã¯ãŒã«ïŒïŒ pytest.iniæè¬ãã pytest.iniãã¡ã€ã«ãtasksãããžã§ã¯ãã«è¿œå ããŸãã
ch6 / b / tasks_proj / tests / pytest.ini
 [pytest] addopts = -rsxX -l --tb=short --strict markers = smoke: Run the smoke test test functions get: Run the test functions that test tasks.get() 
ããã©ã«ãã§åªå
ããããã©ã°ã®çµã¿åããã¯æ¬¡ã®ãšããã§ãã
- -rsxXã¯ãã¹ããããxfailedããŸãã¯xpassedã®ãã¹ãã- -rsxXã
- --tb = shorté害æã®ãã¬ãŒã¹ãçãããã«ã¯- --tb = shortã
- --strict宣èšãããããŒã¯ã³ã®ã¿ãèš±å¯ããŸãã
 ãããžã§ã¯ãã®ããŒã«ãŒã®ãªã¹ãã
ããã«ãããç
ãã¹ããªã©ã®ãã¹ãã宿œã§ããŸãã
 $ cd /path/to/code/ch6/b/tasks_proj/tests $ pytest --strict -m smoke ===================== test session starts ====================== collected 57 items func/test_add.py . func/test_api_exceptions.py .. ===================== 54 tests deselected ====================== =========== 3 passed, 54 deselected in 0.06 seconds ============ 
æå°ã®ãã€ãã¹ãèŠä»¶
minversionãã©ã¡ãŒã¿ãŒã䜿çšminversionãšããã¹ãã«å¿
èŠãªpytestã®æå°ããŒãžã§ã³ãæå®ã§ãminversion ã ããšãã°ãæµ®åå°æ°ç¹æ°ããã¹ããããšãã«approx()ã䜿çšããŠããã¹ãã§ãããªãè¿ããçåŒã決å®ããã€ããã§ããã ãããããã®é¢æ°ã¯ããŒãžã§ã³3.0ãŸã§pytestã«å°å
¥ãããŠããŸããã§ããã æ··ä¹±ãé¿ããããã«ã approx()ã䜿çšãããããžã§ã¯ãã«ä»¥äžã远å ããŸãã
 [pytest] minversion = 3.0 
ãããã£ãŠã誰ããå€ãããŒãžã§ã³ã®pytestã䜿çšããŠãã¹ããå®è¡ããããšãããšããšã©ãŒã¡ãã»ãŒãžã衚瀺ãããŸãã
pytestãééã£ãå Žæãæ€çŽ¢ããªãããã«ãã
ãååž°ãã®å®çŸ©ã®1ã€ããç¬èªã®ã³ãŒãã§2åèªãããšã§ããããšããåç¥ã§ããïŒ ãŸããããã å®éãããã¯ãµããã£ã¬ã¯ããªã®ã¢ã«ãŠã³ãã£ã³ã°ãæå³ããŸãã pytestã¯ãååž°çã«å€æ°ã®ãã£ã¬ã¯ããªã調ã¹ããã¹ãæ€åºãæå¹ã«ããŸãã ãã ããpytestã®è¡šç€ºããé€å€ãããã£ã¬ã¯ããªãããã€ããããŸãã
norecurseã®ããã©ã«ãå€ã¯'. * Build dist CVS _darcs {arch} and *.egg. Having '.*' '. * Build dist CVS _darcs {arch} and *.egg. Having '.*' '. * Build dist CVS _darcs {arch} and *.egg. Having '.*'ã¯ããããã§å§ãŸããã¹ãŠã®ãã£ã¬ã¯ããªã衚瀺ãããªããããä»®æ³ç°å¢ã«ã.venvããšããååãä»ããæ£åœãªçç±ã§ãã
Tasksãããžã§ã¯ãã®å Žåãpytestã䜿çšããŠãã¹ããã¡ã€ã«ãæ€çŽ¢ããã®ã¯æéã®ç¡é§ã«ãªãããã srcãæå®ããŠã害ã¯ãããŸããã
 [pytest] norecursedirs = .* venv src *.egg dist build 
ãã®ãã©ã¡ãŒã¿ãŒãªã©ãæ¢ã«æçšãªå€ãæã£ãŠãããã©ã¡ãŒã¿ãŒããªãŒããŒã©ã€ãããå Žåã以åã®ã³ãŒãã§*.egg dist build䜿çšããŠè¡ã£ãããã«ãããã©ã«ãå€ãäœã§ããããç¥ããå¿
èŠãªå€ãè¿ããšäŸ¿å©ã§ãã
norecursedirsã¯ãã¹ããã¹ã«ãšã£ãŠã¯äžçš®ã®çµæãªã®ã§ãããã«ã€ããŠã¯åŸã§èŠãŠã¿ãŸãããã
ãã¹ããã£ã¬ã¯ããªããªãŒã®ä»æ§
norecursedirsã¯pytestã«ã©ããèŠãtestpathsæç€ºããŸããã testpathsã¯pytestã«ã©ããèŠãããæç€ºããŸãã testspathsã¯ããã¹ããèŠã€ããããã®ã«ãŒããã£ã¬ã¯ããªã«çžå¯Ÿçãªãã£ã¬ã¯ããªã®ãªã¹ãã§ãã ãã£ã¬ã¯ããªããã¡ã€ã«ããŸãã¯nodeidåŒæ°ãšããŠæå®ãããŠããªãå Žåã«ã®ã¿äœ¿çšãããŸãã
Tasksãããžã§ã¯ãã®å Žåããã¹ãã®ä»£ããã«tasks_projãã£ã¬ã¯ããªã«é
眮ãããšããŸãã
 \code\tasks_proj>tree/f . â pytest.ini â ââââsrc â ââââtasks â api.py â ... â ââââtests â conftest.py â pytest.ini â ââââfunc â test_add.py â ... â ââââunit â test_task.py â __init__.py â ... 
ããããããã¹ããtestpathsã«å
¥ããã®ãçã«ããªã£ãŠãããããããŸããïŒ
 [pytest] testpaths = tests 
ããã§ã tasks_projãã£ã¬ã¯ããªããpytestãå®è¡ãããšãpytestã¯tasks_proj/testsã®ã¿ãæ€çŽ¢ãtasks_proj/tests ã ããã§ã®åé¡ã¯ããã¹ãã®éçºããã³ãããã°äžã«ããã¹ããã£ã¬ã¯ããªãç¹°ãè¿ãåŠçããããšãå€ãããããã¹å
šäœãæå®ããã«ãµããã£ã¬ã¯ããªãŸãã¯ãã¡ã€ã«ãç°¡åã«ãã¹ãã§ããããšã§ãã ãããã£ãŠããã®ãªãã·ã§ã³ã¯ã€ã³ã¿ã©ã¯ãã£ããªãã¹ãã§å°ã圹ç«ã¡ãŸãã
ãã ããç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ãµãŒããŒãŸãã¯ããã¯ã¹ããå®è¡ãããã¹ãã«ã¯æé©ã§ãã ãããã®å Žåãã«ãŒããã£ã¬ã¯ããªãä¿®æ£ãããããšãããã£ãŠããããããã®ä¿®æ£ãããã«ãŒããã£ã¬ã¯ããªã«é¢é£ãããã£ã¬ã¯ããªãäžèŠ§è¡šç€ºã§ããŸãã ãããã¯ããã¹ãæéãæ¬åœã«ççž®ãããå Žåã§ãããã®ã§ããã¹ãã®æ€çŽ¢ããªããããšã¯çŽ æŽãããããšã§ãã
äžèŠãããšããã¹ããã¹ãšnorecursedirsäž¡æ¹ãåæã«äœ¿çšããã®ã¯ã°ãããŠããããã«æãããããããŸããã ãã ããæ¢ã«èŠãããã«ããã¹ããã¹ã¯ãã¡ã€ã«ã·ã¹ãã ã®ããŸããŸãªéšåããã®å¯Ÿè©±åãã¹ãã§ã¯ã»ãšãã©åœ¹ã«ç«ã¡ãŸããã ãããã®å Žåã norecursedirsã圹ç«ã¡ãŸãã ããã«ããã¹ããå«ãŸãªããã¹ããã£ã¬ã¯ããªãããå Žåã¯ã norecursedirsã䜿çšããŠnorecursedirsãåé¿ã§ããŸãã ããããå®éã«ã¯ããã¹ããæããªããã¹ãã«è¿œå ã®ãã£ã¬ã¯ããªã眮ãããšã®ãã€ã³ãã¯äœã§ããïŒ
ãã¹ãæ€åºã«ãŒã«ã®å€æŽ
pytestã¯ãç¹å®ã®ãã¹ãæ€åºã«ãŒã«ã«åºã¥ããŠå®è¡ãããã¹ããèŠã€ããŸãã æšæºãã¹ãæ€åºã«ãŒã«ïŒ
â¢1ã€ä»¥äžã®ãã£ã¬ã¯ããªããå§ããŸãã ã³ãã³ãã©ã€ã³ã§ãã¡ã€ã«ãŸãã¯ãã£ã¬ã¯ããªã®ååãæå®ã§ããŸãã äœãæå®ããªãã£ãå ŽåãçŸåšã®ãã£ã¬ã¯ããªã䜿çšãããŸãã
â¢ãã¹ãã¢ãžã¥ãŒã«ã®ã«ã¿ãã°ãšãã®ãã¹ãŠã®ãµããã£ã¬ã¯ããªãæ€çŽ¢ããŸãã
â¢ãã¹ãã¢ãžã¥ãŒã«ã¯ã test_*.py *_test.pyãŸãã¯*_test.pyé¡äŒŒããååã®ãã¡ã€ã«ã§ãã
â¢testã§å§ãŸã颿°ã®ãã¹ãã¢ãžã¥ãŒã«ã調ã¹ãŸãã 
â¢Testã§å§ãŸãã¯ã©ã¹ãæ¢ããŸãã `test , å§ãŸã , init` , ã¯ã©ã¹ã®ã¡ãœãããæ¢ããŸãã
ãããã¯æšæºã®æ€åºã«ãŒã«ã§ãã ãã ãããããã¯å€æŽã§ããŸãã
python_classes
pytestãšã¯ã©ã¹ã®ãã¹ããèŠã€ããããã®éåžžã®ã«ãŒã«ã¯ãã¯ã©ã¹ãTest*ã§å§ãŸãå Žåãã¯ã©ã¹ãæœåšçãªãã¹ãã¯ã©ã¹ãšèŠãªãããšã§ãã ã¯ã©ã¹ã«__init__()ã¡ãœããã__init__()ããšãã§ããŸããã ãããããã¹ãã¯ã©ã¹ã«<something>TestãŸãã¯<something>Suiteãšããååãä»ãããå Žåã¯ã©ãã§ããããã python_classesåºçªpython_classes ã
 [pytest] python_classes = *Test Test* *Suite 
ããã«ãããæ¬¡ã®ãããªã¯ã©ã¹ãåŒã³åºãããšãã§ããŸãã
 class DeleteSuite(): def test_delete_1(): ... def test_delete_2(): ... .... 
python_files
pytest_classesãšåæ§ã«ã python_filesã¯ããã©ã«ãã®ãã¹ãæ€åºã«ãŒã«ã倿ŽããŸããããã¯ã test_*ã§å§ãŸããã¡ã€ã«ãŸãã¯æåŸã«*_testãæã€ãã¡ã€ã«ã®æ€çŽ¢ã§æ§æãããŸãã
ãã¹ãŠã®ãã¹ããã¡ã€ã«ã«check_<something>.pyãšããååãä»ããã«ã¹ã¿ã ãã¹ããã¬ãŒã ã¯ãŒã¯ããããšããŸãã çã«ããªã£ãŠããããã§ãã ãã¹ãŠã®ãã¡ã€ã«ã®ååã倿Žãã代ããã«ã次ã®ããã«pytest.iniè¡ã远å ããã ãã§ãã
 [pytest] python_files = test_* *_test check_* 
ãšãŠãç°¡åã§ãã å¿
èŠã«å¿ããŠãåœåèŠåãåŸã
ã«è»¢éããããåã«check_*ãŸãŸã«ããŠããããšãcheck_* ã
python_functions
python_functionsã¯ä»¥åã®2ã€ã®èšå®ãšåæ§ã«æ©èœããŸããããã¹ã颿°ãšã¡ãœããåçšã§ãã ããã©ã«ãå€ã¯test_*ã§ãã ãããŠã check_*ã远å ããã«ã¯check_*æšæž¬ãã-ãããè¡ãïŒ
 [pytest] python_functions = test_* check_* 
pyteståœåpytestã¯ããã»ã©å¶éãããŠããªãããã§ãã ãããã£ãŠãããã©ã«ãã®åœåèŠåãæ°ã«å
¥ããªãå Žåã¯ãåã«å€æŽããŠãã ããã ããã«ãããããããç§ã¯ããªãããã®ãããªæ±ºå®ã®ããã®ãã説åŸåã®ããçç±ãæã£ãŠããããšããå§ãããŸãã æ°çŸã®ãã¹ããã¡ã€ã«ãç§»è¡ããããšã¯ãééããªãæ£åœãªçç±ã§ãã
XPASSçŠæ¢
xfail_strict = trueèšå®ãããšã @pytest.mark.xfailããŒã¯ããããã¹ãããšã©ãŒã®åå ãšããŠèªèãããªãããšãæå³ããŸãã ãã®èšå®ã¯åžžã«ããã¹ãã ãšæããŸãã xfailããŒã¯ã³ã®è©³çްã«ã€ããŠã¯ã37ããŒãžã®ã倱æãåŸ
ã€ãã¹ãã®ããŒã¯ä»ãããåç
§ããŠãã ããã
ãã¡ã€ã«åã®ç«¶åãé²ã
ãããžã§ã¯ãã®åãã¹ããµããã£ã¬ã¯ããªã«__init__.pyãã¡ã€ã«ã__init__.pyããšã®æçšæ§ã¯ãé·ãéç§ãæ··ä¹±ãããŸããã ãã ãããããã®æç¡ã¯ç°¡åã§ãã ãã¹ãŠã®ãã¹ããµããã£ã¬ã¯ããªã«__init__.pyãã¡ã€ã«ãããå Žåãè€æ°ã®ãã£ã¬ã¯ããªã«åããã¹ããã¡ã€ã«åãä»ããããšãã§ããŸãã ããã§ãªãå Žåãããã¯æ©èœããŸããã
以äžã«äŸã瀺ããŸãã ãã£ã¬ã¯ããªaãšbäž¡æ¹ã«ãã¡ã€ã«test_foo.pyããããŸãã ãããã®ãã¡ã€ã«ã«äœãå«ãŸããŠãããã¯é¢ä¿ãããŸãããããã®äŸã§ã¯æ¬¡ã®ããã«ãªããŸãã
ch6 / dups / a / test_foo.py
 def test_a(): pass 
ch6 / dups / b / test_foo.py
 def test_b(): pass 
ãã®ãã£ã¬ã¯ããªæ§é ã§ã¯ïŒ
 dups âââ a â âââ test_foo.py âââ b âââ test_foo.py 
ãããã®ãã¡ã€ã«ã«ã¯åãå
容ãããããŸãããããã¹ãã¯ç ŽæããŠããŸãã ããããåå¥ã«å®è¡ããããšã¯å¯èœpytestãã dupsãã£ã¬ã¯ããªããpytestãå®è¡ããæ¹æ³ã¯ãããŸããã
 $ cd /path/to/code/ch6/dups $ pytest a ============================= test session starts ============================= collected 1 item a\test_foo.py . ========================== 1 passed in 0.05 seconds =========================== $ pytest b ============================= test session starts ============================= collected 1 item b\test_foo.py . ========================== 1 passed in 0.05 seconds =========================== $ pytest ============================= test session starts ============================= collected 1 item / 1 errors =================================== ERRORS ==================================== _______________________ ERROR collecting b/test_foo.py ________________________ import file mismatch: imported module 'test_foo' has this __file__ attribute: /path/to/code/ch6/dups/a/test_foo.py which is not the same as the test file we want to collect: /path/to/code/ch6/dups/b/test_foo.py HINT: remove __pycache__ / .pyc files and/or use a unique basename for your test file modules !!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!! =========================== 1 error in 0.34 seconds =========================== 
äœãæç¢ºã§ã¯ãããŸããïŒ
ãã®ãšã©ãŒã¡ãã»ãŒãžã¯ãåé¡ã®åå ã瀺ããŠããããã§ã¯ãããŸããã
ãã®ãã¹ããä¿®æ£ããã«ã¯ã空ã®__init__.pyãã¡ã€ã«ããµããã£ã¬ã¯ããªã«è¿œå ããã ãã§ãã åãéè€ãã¡ã€ã«åãæã€dups_fixedãã£ã¬ã¯ããªã®äŸã次ã«ç€ºããŸããã dups_fixedãã¡ã€ã«ã远å ãããŠããŸãã
 dups_fixed/ âââ a â âââ __init__.py â âââ test_foo.py âââ b âââ __init__.py âââ test_foo.py 
ããã§ã¯ã dups_fixedãããã¬ãã«ããããäžåºŠè©ŠããŠã¿ãŸãããã
 $ cd /path/to/code/ch6/ch6/dups_fixed/ $ pytest ============================= test session starts ============================= collected 2 items a\test_foo.py . b\test_foo.py . ========================== 2 passed in 0.15 seconds =========================== 
ã ããããã¯è¯ããªããŸãã
ãã¡ããããã¡ã€ã«åãéè€ããããšã¯æ±ºããŠãªããšç¢ºä¿¡ã§ããã®ã§ãããã¯åé¡ã§ã¯ãããŸããã ãã¹ãŠãæ£åžžã§ãã ãããããããžã§ã¯ãã¯æé·ããŠããããã¹ãã«ã¿ãã°ã¯æé·ããŠããŸãã ãããã®ãã¡ã€ã«ãããã«çœ®ãã ãã§ãã ãããç¿æ
£ã«ããŠãããäžåºŠå¿é
ããå¿
èŠã¯ãããŸããã
æŒç¿
95ããŒãžã®ç¬¬5ç« ããã©ã°ã€ã³ãã§ã-niceã³ãã³ãã©ã€ã³ãªãã·ã§ã³ãå«ãpytest-niceãšãããã©ã°ã€ã³ãäœæããŸããã niceãšåŒã°ããpytest.iniãªãã·ã§ã³ãå«ããããã«æ¡åŒµããŸãããã
95ããŒãžã®ç¬¬5ç« ããã©ã°ã€ã³ãã§ã pytest-niceã³ãã³ãã©ã€ã³--niceãå«ãpytest-niceãšãããã©ã°ã€ã³ãäœæããŸããã niceãšåŒã°ããpytest.iniãªãã·ã§ã³ãå«ããããã«ãããæ¡åŒµããŸãããã
- pytest_addoption- pytest_nice.pyããã¯é¢æ°ã«æ¬¡ã®è¡ã远å ããŸãïŒ- parser.addini('nice', type='bool', help='Turn failures into opportunities.')- pytest_addoption- pytest_nice.py- parser.addini('nice', type='bool', help='Turn failures into opportunities.')
- getoption()ã䜿çšãããã©ã°ã€ã³å
ã®å Žæã- getini('nice')ãåŒã³åºã- getini('nice')ããããŸãã ãããã®å€æŽãè¡ããŸãã
- pytest.iniãã¡ã€ã«ã«- niceã远å ããŠããããæåã§ç¢ºèªããŸãã
- ãã©ã°ã€ã³ãã¹ããå¿ããªãã§ãã ããã ãã¹ãã远å ããŠã pytest.iniã®niceãã©ã¡ãŒã¿ãŒpytest.iniæ£ããpytest.iniããããšã確èªããŸãã
- ãã©ã°ã€ã³ãã£ã¬ã¯ããªã«ãã¹ãã远å ããŸãã 远å ã®Pytesteræ©èœãèŠã€ããå¿
èŠããããŸã ã
次ã¯äœã§ãã
pytestã¯ããèªäœãéåžžã«åŒ·åã§ããïŒç¹ã«ãã©ã°ã€ã³ã®å ŽåïŒãä»ã®ãœãããŠã§ã¢éçºããŒã«ããœãããŠã§ã¢ãã¹ãããŒã«ãšãããŸãçµ±åã§ããŸãã æ¬¡ã®ç« ã§ã¯ãä»ã®åŒ·åãªãã¹ãããŒã«ãšçµã¿åãããpytestã®äœ¿çšã«ã€ããŠæ€èšããŸãã
 æ»ã 次ãž
 æ»ã 次㞠