рдкреАрдЫреЗ рдЕрдЧрд▓рд╛ 
рдореИрдВрдиреЗ рдкрд╛рдпрд╛ рдХрд┐ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХреЗ рд╕рд╛рде рдкрд╛рдпрдерди рдкрд░реАрдХреНрд╖рдг рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдкрд░реАрдХреНрд╖рдг рд╡рд╛рддрд╛рд╡рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрддреНрдпрдВрдд рдЙрдкрдпреЛрдЧреА рдкрд░рд┐рдЪрдпрд╛рддреНрдордХ рдорд╛рд░реНрдЧрджрд░реНрд╢рд┐рдХрд╛ рд╣реИред рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдореБрдЭреЗ рдореЗрд░реА рдХрдВрдкрдиреА рдореЗрдВ рд▓рд╛рднрд╛рдВрд╢ рд▓рд╛рддрд╛ рд╣реИред
рдХреНрд░рд┐рд╕ рд╢реЗрд╡рд░
VP of Product, Uprising Technology

рдЗрд╕ рдкреБрд╕реНрддрдХ рдореЗрдВ рдЙрджрд╛рд╣рд░рдг Python 3.6 рдФрд░ pytest 3.2 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВред рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ 3.2 рдкрд╛рдпрдерди 2.6, 2.7, рдФрд░ рдкрд╛рдпрдерди 3.3+ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред
рдЯрд╛рд╕реНрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рд╕реНрд░реЛрдд рдХреЛрдб, рд╕рд╛рде рд╣реА рд╕рд╛рде рдЗрд╕ рдкреБрд╕реНрддрдХ рдореЗрдВ рджрд┐рдЦрд╛рдП рдЧрдП рд╕рднреА рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рдкреБрд╕реНрддрдХ рдХреЗ рд╡реЗрдм рдкреЗрдЬ pragprog.com рдкрд░ рд▓рд┐рдВрдХ рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рд╕реНрд░реЛрдд рдХреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ; рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдкрд╛рд▓рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╛ рдЕрдкрдиреА рдЦреБрдж рдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░реЗрдВ (рдЖрдкрдХреЗ рд╣рд╛рде рдЕрдирдЯреВрдЯ рд╣реЛ рдЧрдП рд╣реИрдВ!), рдЖрдкрдХреЛ рдкреБрд╕реНрддрдХ рдХреЗ рд╡реЗрдм рдкреЗрдЬ рдкрд░ рдЬрд╛рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдХрд╛рдо рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╡рд╣рд╛рдБ, рдкреБрд╕реНрддрдХ рдХреЗ рд╡реЗрдм рдкреЗрдЬ рдкрд░, рдЗрд░реЗрдЯрд╛ рд╕рдВрджреЗрд╢реЛрдВ рдФрд░ рдПрдХ рдЪрд░реНрдЪрд╛ рдордВрдЪ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рд╣реИред
рд╕реНрдкреЙрдЗрд▓рд░ рдХреЗ рддрд╣рдд рдЗрд╕ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рд▓реЗрдЦреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИред
рд╕рд╛рдордЧреНрд░реА рдХреА рддрд╛рд▓рд┐рдХрд╛ рдЪрд▓реЛ рдЪрд▓рддреЗ рд╣реИрдВ
рдпрд╣ рдкрд░реАрдХреНрд╖рдг рд╣реИ:
ch1 / test_one.py
def test_passing(): assert (1, 2, 3) == (1, 2, 3)
рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдкрд░ рдпрд╣ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:
$ cd /path/to/code/ch1 $ pytest test_one.py ===================== test session starts ====================== collected 1 items test_one.py . =================== 1 passed in 0.01 seconds ===================

Test_one.py рдХреЗ рдмрд╛рдж рдбреЙрдЯ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдпрд╣ рдкрд╛рд░рд┐рдд рд╣реЛ рдЧрдпрд╛ред рдпрджрд┐ рдЖрдкрдХреЛ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдЪрд╛рд╣рд┐рдП, рддреЛ рдЖрдк -v
рдпрд╛ --verbose
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
$ pytest -v test_one.py ===================== test session starts ====================== collected 1 items test_one.py::test_passing PASSED =================== 1 passed in 0.01 seconds ===================

рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд░рдВрдЧ рдЯрд░реНрдорд┐рдирд▓ рд╣реИ, рддреЛ PASSED рдФрд░ рдирд┐рдЪрд▓рд╛ рд░реЗрдЦрд╛ рд╣рд░рд╛ рд╣реИред рд╡рд╛рд╣!
рдпрд╣ рдПрдХ рдЕрд╕рдлрд▓ рдкрд░реАрдХреНрд╖рд╛ рд╣реИ:
ch1 / test_two.py
def test_failing(): assert (1, 2, 3) == (3, 2, 1)
рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдЯреЗрд╕реНрдЯ рдлреЗрд▓рд┐рдпрд░ рджрд┐рдЦрд╛рддрд╛ рд╣реИ, рдХрдИ рдХрд╛рд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ рдХрд┐ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдкрд╛рдЗрд╕реНрдЯ рдХреЛ рдХреНрдпреЛрдВ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВред рдЖрдЗрдпреЗ рджреЗрдЦрддреЗ рд╣реИрдВ рдХреНрдпрд╛ рдЖрддрд╛ рд╣реИ:
$ pytest test_two.py ===================== test session starts ====================== collected 1 items test_two.py F =========================== FAILURES =========================== _________________________ test_failing _________________________ def test_failing(): > assert (1, 2, 3) == (3, 2, 1) E assert (1, 2, 3) == (3, 2, 1) E At index 0 diff: 1 != 3 E Use -v to get the full diff test_two.py:2: AssertionError =================== 1 failed in 0.04 seconds ===================

рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛! рдкрд░реАрдХреНрд╖рдг рдкрд░реАрдХреНрд╖рдг test_failing рд╣рдореЗрдВ рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣ рдЕрд╕рдлрд▓ рдХреНрдпреЛрдВ рд╣реБрдЖ, рдЗрд╕рдХрд╛ рдЦрдВрдб рдорд┐рд▓рддрд╛ рд╣реИред
рдФрд░ рд╕рдмрд╕реЗ рд╕рдЯреАрдХ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдкрд╣рд▓рд╛ рдХреНрд░реИрд╢: рдЗрдВрдбреЗрдХреНрд╕ 0 рдПрдХ рдмреЗрдореЗрд▓ рд╣реИред
рдЗрд╕ рд╕рдВрджреЗрд╢ рдХрд╛ рдПрдХ рдмрдбрд╝рд╛ рд╣рд┐рд╕реНрд╕рд╛ рд▓рд╛рд▓ рд╣реИ, рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╛рд╣рд░ рдЦрдбрд╝рд╛ рд╣реИ (рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд░рдВрдЧ рдЯрд░реНрдорд┐рдирд▓ рд╣реИ)ред
рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рд╕рд╛рд░реА рдЬрд╛рдирдХрд╛рд░реА рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рдПрдХ рдкрдВрдХреНрддрд┐ рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧ -v
рдХреЛ рдорддрднреЗрджреЛрдВ рдХреЗ рдФрд░ рднреА рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рддреА рд╣реИред
рдЪрд▓реЛ рдЗрд╕ рдПрдХ -v
:
$ pytest -v test_two.py ===================== test session starts ====================== collected 1 items test_two.py::test_failing FAILED =========================== FAILURES =========================== _________________________ test_failing _________________________ def test_failing(): > assert (1, 2, 3) == (3, 2, 1) E assert (1, 2, 3) == (3, 2, 1) E At index 0 diff: 1 != 3 E Full diff: E - (1, 2, 3) E ? ^ ^ E + (3, 2, 1) E ? ^ ^ test_two.py:2: AssertionError =================== 1 failed in 0.04 seconds ===================

рд╡рд╛рд╣!
рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рд╣рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рдЕрдВрддрд░ рд╣реИ рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрд░рдЯ (^) рдЪрд░рд┐рддреНрд░ рдЬреЛрдбрд╝рддрд╛ рд╣реИред
рдпрджрд┐ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреНрд░рднрд╛рд╡рд┐рдд рд╣реИрдВ рдХрд┐ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛, рдкрдврд╝рдирд╛ рдФрд░ рдЪрд▓рд╛рдирд╛ рдХрд┐рддрдирд╛ рдЖрд╕рд╛рди рд╣реИ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдкрдврд╝рдирд╛ рдХрд┐рддрдирд╛ рдЖрд╕рд╛рди рд╣реИ, рдЬрд╣рд╛рдВ рд╡рд┐рдлрд▓рддрд╛ рд╣реБрдИ рд╣реИ, рдареАрдХ рд╣реИ ... рдЖрдкрдиреЗ рдЕрднреА рддрдХ рдХреБрдЫ рднреА рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИред рдЬрд╣рд╛рдВ рд╕реЗ рдЖрдпрд╛ рд╣реИ, рд╡рд╣рд╛рдВ рдФрд░ рднреА рдХрдИ рдЪрдорддреНрдХрд╛рд░ рд╣реИрдВред рдореБрдЭреЗ рд░рд╣рдиреЗ рджреЛ рдФрд░ рдореБрдЭреЗ рджрд┐рдЦрд╛рдУ рдХрд┐ рдореБрдЭреЗ рдХреНрдпреЛрдВ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдкрд░реАрдХреНрд╖рдг рдордВрдЪ рд╣реИред
рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдХреЗ рд╢реЗрд╖ рднрд╛рдЧ рдореЗрдВ, рдЖрдк рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВрдЧреЗ, рдЗрд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рддрд░реАрдХреЛрдВ рдХреЛ рджреЗрдЦреЗрдВрдЧреЗ, рдФрд░ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ рд╕реЗ рдХреБрдЫ рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдВрдЧреЗред рднрд╡рд┐рд╖реНрдп рдХреЗ рдЕрдзреНрдпрд╛рдпреЛрдВ рдореЗрдВ, рдЖрдк рд╕реАрдЦреЗрдВрдЧреЗ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХреИрд╕реЗ рд▓рд┐рдЦрдирд╛ рд╣реИ рдЬреЛ рдХрд┐ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХреА рд╢рдХреНрддрд┐ рдХреЛ рдЕрдзрд┐рдХрддрдо рдХрд░рддреЗ рд╣реИрдВ, рд╕реНрдерд╛рдкрдирд╛ рдХреЛрдб рдХреЛ рд╕реЗрдЯрдЕрдк рдореЗрдВ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ рдФрд░ рдЬреБрдбрд╝рдирд╛рд░ рдирд╛рдордХ рдЦрдВрдб рдХреЛ рдЕрд▓рдЧ рдХрд░реЗрдВ, рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдзрд┐рднрд╛рд░ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЬреБрдбрд╝рдирд╛рд░ рдФрд░ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВред
рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рдореБрдЭреЗ рдорд╛рдлреА рдорд╛рдВрдЧрдиреА рд╣реЛрдЧреАред рд╕реЙрд░реА assert (1, 2, 3) == (3, 2, 1)
рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рдпрд╣ рдмрд╣реБрдд рдЙрдмрд╛рдК рд╣реИред рдореБрдЭреЗ рдЦрд░реНрд░рд╛рдЯреЗ рд╕реБрдирд╛рдИ рджреЗрддреЗ рд╣реИрдВред! рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЬреАрд╡рди рдореЗрдВ рдХреЛрдИ рднреА рдЗрд╕ рддрд░рд╣ рдХреА рдкрд░реАрдХреНрд╖рд╛ рдирд╣реАрдВ рд▓рд┐рдЦрддрд╛ рд╣реИред рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдРрд╕реЗ рдХреЛрдб рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рдЕрдиреНрдп рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐, рд╣рдореЗрд╢рд╛ рд╕рдХрд╛рд░рд╛рддреНрдордХ рд░реВрдк рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рдФрд░ (1, 2, 3) == (1, 2, 3)
рд╣рдореЗрд╢рд╛ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рд╣рдо рдмрд╛рдХреА рдХрд┐рддрд╛рдмреЛрдВ рдореЗрдВ рднреА рдЗрд╕ рддрд░рд╣ рдХреЗ рдореВрд░реНрдЦрддрд╛рдкреВрд░реНрдг рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рд╣рдо рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдгреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред рд╣рдо рдПрдХ рдирдореВрдирд╛ рдХрд╛рд░реНрдп рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдЬрд┐рд╕рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕рдордЭрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрддрдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реИ рдЬрд┐рддрдирд╛ рдХрд┐ рдЙрдмрд╛рдК рд╣реЛред
рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдПрдХ рдЕрдиреНрдп рдЙрдкрдпреЛрдЧреА рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдЖрдкрдХреА рдорд╛рдиреНрдпрддрд╛рдУрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рдХреЗ рддрд╣рдд рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдореЙрдбреНрдпреВрд▓ рдФрд░ рдкреИрдХреЗрдЬреЛрдВ рдХреА рдЖрдкрдХреА рд╕рдордЭ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдкрд╛рдпрдерди рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рд╢рд╛рдорд┐рд▓ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рдЯрд╛рд╕реНрдХ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЯрд╛рд╕реНрдХ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдирд╛рдорд╛рдВрдХрд┐рдд рдХрд╛рд░рдЦрд╛рдиреЗ рдХреА рд╡рд┐рдзрд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдЬреЛ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдФрд░ рдПрдкреАрдЖрдИ рдХреЗ рдмреАрдЪ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдХреЗ рдмрд╛рдХреА рд╣рд┐рд╕реНрд╕реЛрдВ рдореЗрдВ, рдореИрдВ рдЯрд╛рд╕реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░реВрдВрдЧреА рдХрд┐ рдХреИрд╕реЗ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХреЛ рд╢реБрд░реВ рдХрд░реЗрдВ рдФрд░ рдХреБрдЫ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдпрд╣рд╛рдБ рдХрд╛рд░реНрдп рд╣реИ:
from collections import namedtuple Task = namedtuple('Task', ['summary', 'owner', 'done', 'id'])
рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдХреВрджрддреЗ рд╣реИрдВ, рдЪрд▓реЛ рдПрдХ рдХрджрдо рдкреАрдЫреЗ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВред
рдлреИрдХреНрдЯреНрд░реА рдирд╛рдореНрдЯреБрдкрд▓ () рдлрд╝рдВрдХреНрд╢рди рдкрд╛рдпрдерди 2.6 рдХреЗ рдмрд╛рдж рд╕реЗ рдореМрдЬреВрдж рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЕрднреА рднреА рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХрдИ рдкрд╛рдпрдерди рдбреЗрд╡рд▓рдкрд░реНрд╕ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рдХрд┐ рдпрд╣ рдХрд┐рддрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реИред рдХрдо рд╕реЗ рдХрдо, рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ (1, 2, 3) == (1, 2, 3)
рдпрд╛ (1, 2)==3
рд╕реЗ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрдЧрд╛ред
рдЙрджрд╛рд╣рд░рдгреЛрдВ рдкрд░ рдЬрд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдЗрдП рдПрдХ рдХрджрдо рдкреАрдЫреЗ рд╣рдЯреЗрдВ рдФрд░ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВ рдХрд┐ рдХрд╣рд╛рдБ рд╕реЗ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рдХреИрд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВред
рдЦрдирди pytest
рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдореБрдЦреНрдпрд╛рд▓рдп https://docs.pytest.org ред рдпрд╣ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рджрд╕реНрддрд╛рд╡реЗрдЬ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ https://pypi.python.org/pypi/pytest рдкрд░ PyPI (рдкрд╛рдпрдерди рдкреИрдХреЗрдЬ рдЗрдВрдбреЗрдХреНрд╕) рд╕реЗ рдлреИрд▓рддрд╛ рд╣реИред
PyPI рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡рд┐рддрд░рд┐рдд рдЕрдиреНрдп рдкрд╛рдпрдерди рдкреИрдХреЗрдЬреЛрдВ рдХреА рддрд░рд╣, рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЖрднрд╛рд╕реА рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рдЗрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
$ pip3 install -U virtualenv $ python3 -m virtualenv venv $ source venv/bin/activate $ pip install pytest
рдпрджрд┐ рдЖрдк virtualenv рдпрд╛ рдкрд╛рдЗрдк рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдореИрдВ рдЖрдкрдХреЛ рдкреЗрд╢ рдХрд░реВрдВрдЧрд╛ред рдкреГрд╖реНрда резрел реп рдкрд░ рдкрд░рд┐рд╢рд┐рд╖реНрдЯ рез, "рдЖрднрд╛рд╕реА рд╡рд╛рддрд╛рд╡рд░рдг", рдкреГрд╖реНрда резрел реп рдФрд░ рдкрд░рд┐рд╢рд┐рд╖реНрдЯ реи рджреЗрдЦреЗрдВред
рдЦрд┐рдбрд╝рдХрд┐рдпреЛрдВ, рдЕрдЬрдЧрд░ 2 рдФрд░ рд╡реЗрдирд╡ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?
рд╡рд░реНрдЪреБрдЕрдирд╡ рдФрд░ рдкрд╛рдЗрдк рдЙрджрд╛рд╣рд░рдг рдХреЛ рдХрдИ POSIX рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреИрд╕реЗ рдХрд┐ рд▓рд┐рдирдХреНрд╕ рдФрд░ рдореИрдХрдУрдПрд╕, рд╕рд╛рде рд╣реА рдкрд╛рдпрдерди рдХреЗ рдХрдИ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдкрд░, рдЬрд┐рд╕рдореЗрдВ рдкрд╛рдпрдерди 2.7.9 рдФрд░ рдмрд╛рдж рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рд╢рд╛рдорд┐рд▓ рд╣реИрдВред
рд▓рд╛рдЗрди рдореЗрдВ venv / bin / activate рд╕реЛрд░реНрд╕ рд╡рд┐рдВрдбреЛрдЬ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп venv \ Scripts \ activate.bat рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдпрд╣ рдХрд░реЗрдВ:
C:\> pip3 install -U virtualenv C:\> python3 -m virtualenv venv C:\> venv\Scripts\activate.bat (venv) C:\> pip install pytest
рдкрд╛рдпрдерди 3.6 рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рдж рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдк virtualenv рдХреЗ рдмрдЬрд╛рдп venv рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЖрдкрдХреЛ рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕реЗ рдкрд╛рдЗрдерди 3.6 рдФрд░ рдмрд╛рдж рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВрдиреЗ рд╕реБрдирд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдЕрднреА рднреА рд╡рд░реНрдЪреБрдЕрди рдХреЗ рд╕рд╛рде рдмреЗрд╣рддрд░ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддреЗ рд╣реИрдВред
рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдЪрд▓рд╛рдПрдВ
$ pytest --help usage: pytest [options] [file_or_dir] [file_or_dir] [...] ...
рдмрд┐рдирд╛ рдХрд┐рд╕реА рддрд░реНрдХ рдХреЗ, рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдЖрдкрдХреА рд╡рд░реНрддрдорд╛рди рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рднреА рдЙрдкрдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдЧрд╛ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдЪрд▓рд╛рдПрдЧрд╛ рдЬреЛ рдЗрд╕реЗ рдкрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдХрд┐рд╕реА рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо, рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдирд╛рдо рдпрд╛ рдЙрдирдХреА рд╕реВрдЪреА рджреЗрддреЗ рд╣реИрдВ, рддреЛ рд╡реЗ рд╡рд░реНрддрдорд╛рди рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рдмрдЬрд╛рдп рд╡рд╣рд╛рдВ рдорд┐рд▓ рдЬрд╛рдПрдВрдЧреЗред рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдкрд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рддреНрдпреЗрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдкреБрди: рдЬрд╛рдВрдЪ рдХреА рдЬрд╛рддреА рд╣реИред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЪрд▓реЛ рдПрдХ рдЙрдкрдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдирд╛рдордХ рдХрд╛рд░реНрдп рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдлрд╝рд╛рдЗрд▓ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ:
ch1 / рдХрд╛рд░реНрдп / test_three.py
""" Task.""" from collections import namedtuple Task = namedtuple('Task', ['summary', 'owner', 'done', 'id']) Task.__new__.__defaults__ = (None, None, False, None) def test_defaults(): """ , .""" t1 = Task() t2 = Task(None, None, False, None) assert t1 == t2 def test_member_access(): """ .field () namedtuple.""" t = Task('buy milk', 'brian') assert t.summary == 'buy milk' assert t.owner == 'brian' assert (t.done, t.id) == (False, None)
Test_member_access () рдкрд░реАрдХреНрд╖рдг рдпрд╣ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдХрд┐ рдЗрдВрдбреЗрдХреНрд╕ рджреНрд╡рд╛рд░рд╛ рдирд╛рдо nd рджреНрд╡рд╛рд░рд╛ рд╕рджрд╕реНрдпреЛрдВ рддрдХ рдХреИрд╕реЗ рдкрд╣реБрдВрдЪрд╛ рдЬрд╛рдП, рдЬреЛ рдиреЗрдордЯреВрдкреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдореБрдЦреНрдп рдХрд╛рд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИред
рдЖрдЗрдП _ddict () рдФрд░ _replace () рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреБрдЫ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ
рд╕рднреА рдлрд╝реАрд▓реНрдб рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдП рдмрд┐рдирд╛ рдЯрд╛рд╕реНрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк __new __.__ defaults__
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред Test_defaults () рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдпрд╣ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдирд╛ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдЪреВрдХ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИред
test_member_access()
рдкрд░реАрдХреНрд╖рдг рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ nd рдирд╛рдо рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рддрдХ рдХреИрд╕реЗ рдкрд╣реБрдВрдЪреЗрдВ, рдЬреЛ рдХрд┐ рдЗрдВрдбреЗрдХреНрд╕ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рдореБрдЦреНрдп рдХрд╛рд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдирд╣реАрдВ рд╣реИред
рдЖрдЗрдП _asdict()
рдФрд░ _replace()
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджреВрд╕рд░реА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреБрдЫ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдЬреЛрдбрд╝реЗрдВ
ch1 / рдХрд╛рд░реНрдп / test_four.py
""" Task.""" from collections import namedtuple Task = namedtuple('Task', ['summary', 'owner', 'done', 'id']) Task.__new__.__defaults__ = (None, None, False, None) def test_asdict(): """_asdict() .""" t_task = Task('do something', 'okken', True, 21) t_dict = t_task._asdict() expected = {'summary': 'do something', 'owner': 'okken', 'done': True, 'id': 21} assert t_dict == expected def test_replace(): """ fields.""" t_before = Task('finish book', 'brian', False) t_after = t_before._replace(id=10, done=True) t_expected = Task('finish book', 'brian', True, 10) assert t_after == t_expected
Pytest рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЗ рдкрд╛рд╕ рдлрд╝рд╛рдЗрд▓реЛрдВ рдФрд░ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИред рдпрджрд┐ рдЖрдк рдХреЛрдИ рдлрд╝рд╛рдЗрд▓ рдпрд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдФрд░ рдЙрдкрдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдореЗрдВ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рдЦреЛрдЬ рдХрд░реЗрдЧрд╛ред рдпрд╣ test_ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЦреЛрдЬрддрд╛ рд╣реИ рдпрд╛ _test рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк ch1 рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рд╕реЗ pytest рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдХрдорд╛рдВрдбреНрд╕ рдХреЗ рдмрд┐рдирд╛, рдЖрдк рдЪрд╛рд░ рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдПрдВрдЧреЗ:
$ cd /path/to/code/ch1 $ pytest ===================== test session starts ====================== collected 6 items test_one.py . test_two.py F tasks/test_four.py .. tasks/test_three.py .. =========================== FAILURES =========================== _________________________ test_failing _________________________ def test_failing(): > assert (1, 2, 3) == (3, 2, 1) E assert (1, 2, 3) == (3, 2, 1) E At index 0 diff: 1 != 3 E Use -v to get the full diff test_two.py:2: AssertionError ============== 1 failed, 5 passed in 0.08 seconds ==============

рдХреЗрд╡рд▓ рд╣рдорд╛рд░реЗ рдирдП рдХрд╛рд░реНрдп рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдЙрди рд╕рднреА рдлрд╝рд╛рдЗрд▓ рдирд╛рдореЛрдВ рдХреЗ рд╕рд╛рде pytest рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдЖрдк рдЪрд▓рд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдпрд╛ рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛, рдпрд╛ рдЙрд╕ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╕реЗ pytest рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВ рдЬрд╣рд╛рдБ рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рд╕реНрдерд┐рдд рд╣реИрдВ:
$ pytest tasks/test_three.py tasks/test_four.py ===================== test session starts ====================== collected 4 items tasks/test_three.py .. tasks/test_four.py .. =================== 4 passed in 0.02 seconds =================== $ pytest tasks ===================== test session starts ====================== collected 4 items tasks/test_four.py .. tasks/test_three.py .. =================== 4 passed in 0.03 seconds =================== $ cd /path/to/code/ch1/tasks $ pytest ===================== test session starts ====================== collected 4 items test_four.py .. test_three.py .. =================== 4 passed in 0.02 seconds ===================

рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдПрдХреНрдЬрд╝реАрдХреНрдпреВрд╢рди рдкрд╛рд░реНрдЯ, рдЬрд╣рд╛рдБ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдкрд╛рд╕ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдкрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреМрди рд╕рд╛ рдЯреЗрд╕реНрдЯ рдЪрд▓рд╛рдирд╛ рд╣реИ, рдЯреЗрд╕реНрдЯ рдбрд┐рд╕реНрдХрд╡рд░реА рдХрд╣рд▓рд╛рддрд╛ рд╣реИред рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдЙрди рд╕рднреА рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдо рдЪрд▓рд╛рдирд╛ рдЪрд╛рд╣рддреЗ рдереЗ рдХреНрдпреЛрдВрдХрд┐ рд╣рдордиреЗ рдЙрдирдХрд╛ рдирд╛рдо рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдирд╛рдордХрд░рдг рд╕рдореНрдореЗрд▓рдиреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд░рдЦрд╛ рдерд╛ред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд╛рдордХрд░рдг рд╕рдореНрдореЗрд▓рдиреЛрдВ рдХрд╛ рдПрдХ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдЕрд╡рд▓реЛрдХрди рд╣реИ рддрд╛рдХрд┐ рдЖрдкрдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдХреЛ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗ:
- рдЯреЗрд╕реНрдЯ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ
test_<something>.py
рдпрд╛ <something>_test.py
рдирд╛рдо рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред - рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдзрд┐рдпреЛрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ
test_<something>
рдХрд╣рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред - рдЯреЗрд╕реНрдЯ рдХрдХреНрд╖рд╛рдУрдВ рдХреЛ
Test<Something>
рдХрд╣рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реА рдкрд░реАрдХреНрд╖рдг рдлрд╛рдЗрд▓реЗрдВ рдФрд░ рдлрд╝рдВрдХреНрд╢рди test_
рд╕рд╛рде рд╢реБрд░реВ test_
, рддреЛ рд╣рдорд╛рд░реЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИред рдЗрди рдЦреЛрдЬ рдирд┐рдпрдореЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рддрд░реАрдХреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд╡рд┐рднрд┐рдиреНрди рдирд╛рдореЛрдВ рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рд╣реИред
рдореИрдВ рдЗрд╕реЗ рдЕрдзреНрдпрд╛рдп 6, "рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди," рдкреГрд╖реНрда 113 рдкрд░ рдХрд╡рд░ рдХрд░реВрдВрдЧрд╛ред
рдЖрдЗрдП рдХреЗрд╡рд▓ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдЪрд▓рд╛рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
$ cd /path/to/code/ch1/tasks $ pytest test_three.py ================= test session starts ================== platform darwin -- Python 3.6.2, pytest-3.2.1, py-1.4.34, pluggy-0.4.0 rootdir: /path/to/code/ch1/tasks, inifile: collected 2 items test_three.py .. =============== 2 passed in 0.01 seconds ===============
рдкрд░рд┐рдгрд╛рдо рд╣рдореЗрдВ рдХрд╛рдлреА рдХреБрдЫ рдмрддрд╛рддрд╛ рд╣реИред
===== рдкрд░реАрдХреНрд╖рдг рд╕рддреНрд░ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ ====
ред
рдкрд╛рдЗрдЯреЗрд╕реНрдЯ рдЯреЗрд╕реНрдЯ рд╕реЗрд╢рди рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрд▓рд┐рдЧреЗрдВрдЯ рд╕реЗрдкрд░реЗрдЯрд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдПрдХ рд╕рддреНрд░ рдПрдХ рдПрдХрд▓ pytest рдХреЙрд▓ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдХрдИ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдореЗрдВ рдЪрд▓ рд░рд╣реЗ рд╕рднреА рдкрд░реАрдХреНрд╖рдг рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдпрд╣ рд╕рддреНрд░ рдкрд░рд┐рднрд╛рд╖рд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реЛ рдЬрд╛рддреА рд╣реИ, рдЬрдм рдореИрдВ рдкреГрд╖реНрда 56 рдкрд░, рд╕реНрдерд┐рд░рддрд╛ рдХреНрд╖реЗрддреНрд░ рдкрд░рд┐рднрд╛рд╖рд╛ рдореЗрдВ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдЬреБрдбрд╝рдирд╛рд░ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рд╕рддреНрд░ рдХреНрд╖реЗрддреНрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддрд╛ рд╣реВрдВред
рдбрд╛рд░реНрд╡рд┐рди рдордВрдЪ - рдореЗрд░реЗ рдореИрдХ рдкрд░ред рд╡рд┐рдВрдбреЛрдЬ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░, рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдЕрд▓рдЧ рд╣реИред рдкрд╛рдпрдерди рдФрд░ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИрдВ, рд╕рд╛рде рд╣реА рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдкреИрдХреЗрдЬ рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рднреАред Pyest рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП pyest рдЯреАрдо рджреНрд╡рд╛рд░рд╛ py рдФрд░ pluggy рджреЛрдиреЛрдВ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдкреИрдХреЗрдЬ рд╣реИред
rootdir: / path / to / code / ch1 / рдХрд╛рд░реНрдпреЛрдВ, inifile:
rootdir
рд╕рднреА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╢реАрд░реНрд╖-рд╕рдмрд╕реЗ рд╕рд╛рдЭрд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдЦреЛрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИред inifile
(рдпрд╣рд╛рдВ рдЦрд╛рд▓реА) рдЙрдкрдпреЛрдЧ рдХреА рдЧрдИ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рддрд╛ рд╣реИред рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓реЗрдВ pytest.ini
, tox.ini
рдпрд╛ setup.cfg
ред рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП, рдкреГрд╖реНрда 6 рдкрд░ рдЕрдзреНрдпрд╛рдп 6, "рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди" рджреЗрдЦреЗрдВред
2 рдЖрдЗрдЯрдо рдПрдХрддреНрд░ рдХрд┐рдП
рдпреЗ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рджреЛ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдп рд╣реИрдВред
test_three.py ..
test_three.py
рдкрд░реАрдХреНрд╖рдг рдлрд╝рд╛рдЗрд▓ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрдВрдХреНрддрд┐ рд╣реИред рджреЛ рдмрд┐рдВрджреБрдУрдВ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рдкрд╛рд╕ рдХрд┐рдП рдЧрдП рд╣реИрдВ - рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рдлрд╝рдВрдХреНрд╢рди рдпрд╛ рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд┐рдВрджреБред рдЕрдВрдХ рдХреЗрд╡рд▓ рдЙрддреНрддреАрд░реНрдг рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрднрд┐рдкреНрд░реЗрдд рд╣реИрдВред рдХреНрд░рдорд╢рдГ F, E, s, x, рдФрд░ X рдХреЗ рд╕рд╛рде рд╡рд┐рдлрд▓рддрд╛рдПрдВ, рддреНрд░реБрдЯрд┐рдпрд╛рдВ, рд╕реНрдХрд┐рдк, xfails рдФрд░ xpasses рдХреЛ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдкрд╛рд╕рд┐рдВрдЧ рдЯреЗрд╕реНрдЯ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдЕрдВрдХ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ -v
рдпрд╛ --verbose
рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
== 2 0.01 рд╕реЗрдХрдВрдб рдореЗрдВ рдкрд╛рд░рд┐рдд ==
рдпрд╣ рд░реЗрдЦрд╛ рдкрд╛рд░рд┐рдд рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдФрд░ рдкреВрд░реЗ рдкрд░реАрдХреНрд╖рдг рд╕рддреНрд░ рдкрд░ рдмрд┐рддрд╛рдП рдЧрдП рд╕рдордп рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддреА рд╣реИред рдпрджрд┐ рдкрд╛рд╕ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ, рддреЛ рдпрд╣рд╛рдВ рдкреНрд░рддреНрдпреЗрдХ рд╢реНрд░реЗрдгреА рдХреА рд╕рдВрдЦреНрдпрд╛ рднреА рджрд░реНрд╢рд╛рдИ рдЬрд╛рдПрдЧреАред
рдПрдХ рдкрд░реАрдХреНрд╖рд╛ рдкрд░рд┐рдгрд╛рдо рдПрдХ рдкреНрд░рд╛рдердорд┐рдХ рддрд░реАрдХрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣рд╛ рд╣реИ рдпрд╛ рдкрд░рд┐рдгрд╛рдо рджреЗрдЦрдиреЗ рдХреЗ рдмрд╛рдж рд╕рдордЭ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рдХреЗ рджреМрд░рд╛рди рдХреНрдпрд╛ рд╣реБрдЖред рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдореЗрдВ, рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкрд░рд┐рдгрд╛рдо рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рди рдХрд┐ рдХреЗрд╡рд▓ рдкрд╛рд╕ рдпрд╛ рдЕрд╕рдлрд▓ред рдпрд╣рд╛рдБ рдкрд░реАрдХреНрд╖рдг рд╕рдорд╛рд░реЛрд╣ рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рдкрд░рд┐рдгрд╛рдо рд╣реИрдВ:
- PASSED (ред): рдЯреЗрд╕реНрдЯ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкреВрд░рд╛ рд╣реБрдЖред
- FAILED (F): рдЯреЗрд╕реНрдЯ рдлреЗрд▓ (рдпрд╛ XPASS + рд╕рдЦреНрдд)ред
- SKIPPED (s): рдкрд░реАрдХреНрд╖рдг рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЖрдк рдкреГрд╖реНрда 34 рдкрд░, рд▓рдВрдШрди рдкрд░реАрдХреНрд╖рдг рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХрд┐рдП рдЧрдП
@pytest.mark.skip()
рдпрд╛ pytest.mark.skipif()
рд╕рдЬреНрдЬрд╛рдХрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред - xfail (x): рдкрд░реАрдХреНрд╖рд╛ рдЙрддреНрддреАрд░реНрдг рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЗрд╕реЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЕрд╕рдлрд▓ рд░рд╣рд╛ рдерд╛ред рдЖрдк рдкреГрд╖реНрда 37 рдкрд░ рдкрд░реАрдХреНрд╖рдг рдЪрд┐рд╣реНрдиреЛрдВ рдореЗрдВ рд╡рд░реНрдгрд┐рдд
@pytest.mark.xfail()
рдбреЗрдХреЛрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд┐рдлрд▓ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдирд┐рд░реНрджреЗрд╢ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП pytest рдХреЛ рдмрд╛рдзреНрдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред - XPASS (X): рдкрд░реАрдХреНрд╖рдг рдкрд╛рд╕ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдерд╛, рдЗрд╕реЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдФрд░ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛! ...
- рддреНрд░реБрдЯрд┐ (рдИ): рдкрд░реАрдХреНрд╖рдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдмрд╛рд╣рд░ рдПрдХ рдЕрдкрд╡рд╛рдж рдЙрддреНрдкрдиреНрди рд╣реБрдЖ, рдпрд╛ рддреЛ рд╕реНрдерд┐рд░рддрд╛ рдореЗрдВ, рдЕрдзреНрдпрд╛рдп 3 рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ, рдкреГрд╖реНрда 49 рдкрд░, рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдлрд┐рдХреНрд╕реНрдЪрд░, рдпрд╛ рд╣реБрдХ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рдЕрдзреНрдпрд╛рдп 5 рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ, рдкреНрд▓рдЧрдЗрдиреНрд╕, рдкреГрд╖реНрда 95 рдкрд░ред
рдХреЗрд╡рд▓ рдПрдХ рдЯреЗрд╕реНрдЯ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рди
рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╢рд╛рдпрдж рдЖрдк рдЬреЛ рдкрд╣рд▓реА рдЪреАрдЬ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╡рд╣ рдХреЗрд╡рд▓ рдПрдХ рдХреЛ рдЪрд▓рд╛рдирд╛ рд╣реИред рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕реАрдзреЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ рдФрд░ рдирд╛рдо рдЬреЛрдбрд╝реЗрдВ ::test_name
:
$ cd /path/to/code/ch1 $ pytest -v tasks/test_four.py::test_asdict =================== test session starts =================== collected 3 items tasks/test_four.py::test_asdict PASSED ================ 1 passed in 0.01 seconds =================
рдЕрдм рдХреБрдЫ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдкрд░ рдирдЬрд░ рдбрд╛рд▓рддреЗ рд╣реИрдВред
рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
рд╣рдордиреЗ рдПрдХ-рджреЛ рдмрд╛рд░ рд╡рд░реНрдмреЛрдЬрд╝, -v
рдпрд╛ --verbose
рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдИ рдФрд░ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ рдЬреЛ рдЬрд╛рдирдиреЗ рд▓рд╛рдпрдХ рд╣реИрдВред рд╣рдо рдЗрд╕ рдкреБрд╕реНрддрдХ рдореЗрдВ рдЙрди рд╕рднреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ, рдХреЗрд╡рд▓ рдХреБрдЫред рдЖрдк pytest --help
рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреВрд░реА рд╕реВрдЪреА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдиреАрдЪреЗ рдХреБрдЫ рд╡рд┐рдХрд▓реНрдк рджрд┐рдП рдЧрдП рд╣реИрдВ рдЬреЛ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реЛрддреЗ рд╣реИрдВред рдпрд╣ рдкреВрд░реА рд╕реВрдЪреА рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдпреЗ рд╡рд┐рдХрд▓реНрдк рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИрдВред
$ pytest --help usage: pytest [options] [file_or_dir] [file_or_dir] [...] ... subset of the list ... positional arguments: file_or_dir general: -k EXPRESSION only run tests which match the given substring expression. An expression is a python evaluatable expression where all names are substring-matched against test names and their parent classes. Example: -k 'test_method or test_other' matches all test functions and classes whose name contains 'test_method' or 'test_other', while -k 'not test_method' matches those that don't contain 'test_method' in their names. Additionally keywords are matched to classes and functions containing extra names in their 'extra_keyword_matches' set, as well as functions which have names assigned directly to them. -m MARKEXPR only run tests matching given mark expression. example: -m 'mark1 and not mark2'. --markers show markers (builtin, plugin and per-project ones). -x, --exitfirst exit instantly on first error or failed test. --maxfail=num exit after first num failures or errors. ... --capture=method per-test capturing method: one of fd|sys|no. -s shortcut for --capture=no. ... --lf, --last-failed rerun only the tests that failed at the last run (or all if none failed) --ff, --failed-first run all tests but run the last failures first. This may re-order tests and thus lead to repeated fixture setup/teardown ... reporting: -v, --verbose increase verbosity. -q, --quiet decrease verbosity. --verbosity=VERBOSE set verbosity ... -l, --showlocals show locals in tracebacks (disabled by default). --tb=style traceback print mode (auto/long/short/line/native/no). ... --durations=N show N slowest setup/test durations (N=0 for all). ... collection: --collect-only only collect tests, don't execute them. ... test session debugging and configuration: --basetemp=dir base temporary directory for this test run.(warning: this directory is removed if it exists) --version display pytest lib version and import information. -h, --help show help message and configuration info
рдХреЗрд╡рд▓---collect
--collect-only
рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рджрд┐рдП рдЧрдП рдорд╛рдкрджрдВрдбреЛрдВ рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд╕рд╛рде рдХреМрди рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗред рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдкрд╣рд▓реЗ рджрд┐рдЦрд╛рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рддрд╛рдХрд┐ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдВрджрд░реНрдн рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред рдпрджрд┐ рдЖрдк ch1 рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ рдЕрдм рддрдХ рджреЗрдЦреЗ рдЧрдП рд╕рднреА рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдп рджреЗрдЦрдиреЗ рдЪрд╛рд╣рд┐рдП:
$ cd /path/to/code/ch1 $ pytest --collect-only =================== test session starts =================== collected 6 items <Module 'test_one.py'> <Function 'test_passing'> <Module 'test_two.py'> <Function 'test_failing'> <Module 'tasks/test_four.py'> <Function 'test_asdict'> <Function 'test_replace'> <Module 'tasks/test_three.py'> <Function 'test_defaults'> <Function 'test_member_access'> ============== no tests ran in 0.03 seconds ===============
--collect-only
рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреНрдп рд╡рд┐рдХрд▓реНрдк рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдЪреБрдиреЗ рдЧрдП рд╣реИрдВред рд╣рдо рдЗрд╕реЗ -k
рд╕рд╛рде рдлрд┐рд░ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
-рдкреНрд░рд╢реНрди
-k
рдЖрдкрдХреЛ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдПрдХ рдмрд╣реБрдд рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рд╡рд┐рдХрд▓реНрдк! рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рдЕрд▓рдЧ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╢реЙрд░реНрдЯрдХрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЕрдЧрд░ рдирд╛рдо рдЕрджреНрд╡рд┐рддреАрдп рд╣реИ, рдпрд╛ рдЙрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдЪрд▓рд╛рдПрдВ рдЬрд┐рдирдХреЗ рдирд╛рдореЛрдВ рдореЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЙрдкрд╕рд░реНрдЧ рдпрд╛ рдкреНрд░рддреНрдпрдп рд╣реИред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЖрдк рдкрд░реАрдХреНрд╖рдг test_asdict()
рдФрд░ test_defaults()
рдЪрд▓рд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЖрдк рдлрд╝рд┐рд▓реНрдЯрд░ рдХреА рдЬрд╛рдБрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: --collect-only
-
$ cd /path/to/code/ch1 $ pytest -k "asdict or defaults" --collect-only =================== test session starts =================== collected 6 items <Module 'tasks/test_four.py'> <Function 'test_asdict'> <Module 'tasks/test_three.py'> <Function 'test_defaults'> =================== 4 tests deselected ==================== ============== 4 deselected in 0.03 seconds ===============
рдЕрд╣рд╛! рдпрд╣ рд╣рдорд╛рд░реА рдЬрд░реВрд░рдд рдХреЗ рд╕рдорд╛рди рд╣реИред рдЕрдм рдЖрдк рдЙрдиреНрд╣реЗрдВ рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВ
$ pytest -k "asdict or defaults" =================== test session starts =================== collected 6 items tasks/test_four.py . tasks/test_three.py . =================== 4 tests deselected ==================== ========= 2 passed, 4 deselected in 0.03 seconds ==========
рдКрдкреНрд╕! рдмрд╕ рдЗрд╢рд╛рд░рд╛ рдХрд░рддрд╛ рд╣реИред рддреЛ рдлрд┐рд░ рд╡реЗ рдкрд╛рд╕ рд╣реЛ рдЧрдПред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╡реЗ рд╕рд╣реА рдкрд░реАрдХреНрд╖рдг рдереЗ? рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ -v
рдпрд╛ --verbose
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛:
$ pytest -v -k "asdict or defaults" =================== test session starts =================== collected 6 items tasks/test_four.py::test_asdict PASSED tasks/test_three.py::test_defaults PASSED =================== 4 tests deselected ==================== ========= 2 passed, 4 deselected in 0.02 seconds ==========
рдЕрд╣рд╛! рдпреЗ рд╕рд╣реА рдкрд░реАрдХреНрд╖рдг рдереЗред
-M MAREXEXPR
рдорд╛рд░реНрдХрд░ рдПрдХ рд╕рд╛рде рдЪрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рд╕рдмрд╕реЗрдЯ рдХреЛ рдЯреИрдЧ рдХрд░рдиреЗ рдХреЗ рд╕рд░реНрд╡реЛрддреНрддрдо рддрд░реАрдХреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ, test_replace()
рдФрд░ test_member_access()
рдЪрд▓рд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛, рднрд▓реЗ рд╣реА рд╡реЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╣реЛрдВ, рдЙрдиреНрд╣реЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рдирд╛ рд╣реИред рдХрд┐рд╕реА рднреА рдорд╛рд░реНрдХрд░ рдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк run_these_please
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЗрд╕ рддрд░рд╣ @pytest.mark.run_these_please
рдбреЗрдХреЛрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ:
import pytest ... @pytest.mark.run_these_please def test_member_access(): ...
рдЕрдм test_replace()
рд▓рд┐рдП рднреА test_replace()
ред рддрдм рдЖрдк pytest -m run_these_please
рд╕рд╛рде рдПрдХ рд╣реА рдорд╛рд░реНрдХрд░ рдХреЗ рд╕рд╛рде рд╕рднреА рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ:
$ cd /path/to/code/ch1/tasks $ pytest -v -m run_these_please ================== test session starts =================== collected 4 items test_four.py::test_replace PASSED test_three.py::test_member_access PASSED =================== 2 tests deselected =================== ========= 2 passed, 2 deselected in 0.02 seconds =========
рдорд╛рд░реНрдХрд░ рдХреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рд░реНрдХрд░ рд╣реЛрдирд╛ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред рдЖрдк рджреЛрдиреЛрдВ рдорд╛рд░реНрдХрд░реЛрдВ рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП -m "mark1 and mark2"
рдЬреИрд╕реЗ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, -m "mark1 and not mark2"
рдЙрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдЬрд┐рдирдореЗрдВ рд▓реЗрдмрд▓ 1 рд╣реИ, рд▓реЗрдХрд┐рди рд▓реЗрдмрд▓ 2 рдирд╣реАрдВ, -m "mark1 or mark2"
рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрджрд┐ рдХреЗ рд╕рд╛рде, рдореИрдВ рдорд╛рд░реНрдХрд┐рдВрдЧ рд╡реЗрд░рд┐рдлрд┐рдХреЗрд╢рди рдореЗрдердбреНрд╕ рдореЗрдВ рдорд╛рд░реНрдХрд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдЪрд░реНрдЪрд╛ рдХрд░реВрдВрдЧрд╛, рдкреГрд╖реНрда 31 рдкрд░ред
-x, --exitfirst
рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдХрд╛ рд╕рд╛рдорд╛рдиреНрдп рд╡реНрдпрд╡рд╣рд╛рд░ рд╕рднреА рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬреЛ рдЗрд╕реЗ рдкрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдкрд░реАрдХреНрд╖рдг рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдореБрдЦрд░ рдпрд╛ рдЕрдкрд╡рд╛рдж рд╡рд┐рдлрд▓рддрд╛ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдлрд┐рд░ pytest рдЕрдЧрд▓рд╛ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рддрд╛ рд╣реИред рдЕрдзрд┐рдХрд╛рдВрд╢ рднрд╛рдЧ рдХреЗ рд▓рд┐рдП, рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдЪрд╛рд╣рд┐рдПред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЬрдм рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдбреАрдмрдЧ рдХрд░рдирд╛ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рддреБрд░рдВрдд рдкреВрд░реЗ рдкрд░реАрдХреНрд╖рдг рд╕рддреНрд░ рдореЗрдВ рд╣рд╕реНрддрдХреНрд╖реЗрдк рдХрд░рддрд╛ рд╣реИ рдЬрдм рдкрд░реАрдХреНрд╖рдг рд╕рд╣реА рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ -x
рд╡рд┐рдХрд▓реНрдк рдХрд░рддрд╛ рд╣реИред рдЖрдЗрдП рдЗрд╕ рд╕рдордп рд╣рдо рдЙрди рдЫрд╣ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдкрд░ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ:
$ cd /path/to/code/ch1 $ pytest -x ====================== test session starts ==================== collected 6 items test_one.py . test_two.py F ============================ FAILURES ========================= __________________________ test_failing _______________________ def test_failing(): > assert (1, 2, 3) == (3, 2, 1) E assert (1, 2, 3) == (3, 2, 1) E At index 0 diff: 1 != 3 E Use -v to get the full diff test_two.py:2: AssertionError =============== 1 failed, 1 passed in 0.38 seconds ============
рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░, рдЖрдк рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╕рднреА рдЫрд╣ рдкрд░реАрдХреНрд╖рдг (рдпрд╛ "рдЖрдЗрдЯрдо") рдПрдХрддреНрд░ рдХрд┐рдП рдЧрдП рдереЗ, рдФрд░ рдиреАрдЪреЗ рдХреА рд░реЗрдЦрд╛ рдкрд░ рдЖрдк рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдлрд▓ рд╣реЛ рдЧрдпрд╛ рдФрд░ рдПрдХ рдкрд╛рд╕ рд╣реЛ рдЧрдпрд╛, рдФрд░ рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ рдиреЗ "рдмрд╛рдзрд┐рдд" рд▓рд╛рдЗрди рдкреНрд░рджрд░реНрд╢рд┐рдд рдХреАред рд╣рдореЗрдВ рдпрд╣ рдмрддрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╡рд╣ рдмрдВрдж рд╣реИред -x
рдмрд┐рдирд╛ -x
рд╕рднреА рдЫрд╣ рдкрд░реАрдХреНрд╖рдг рдЪрд▓реЗрдВрдЧреЗред рдЪрд▓реЛ рдлрд┐рд░ рд╕реЗ -x
рдмрд┐рдирд╛ рджреЛрд╣рд░рд╛рдПрдВред рд╣рдо рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕рд┐рдВрдЧ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА --tb=no
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рд╣реА рдЗрд╕реЗ рджреЗрдЦ рд▓рд┐рдпрд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рджреЗрдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ:
$ cd /path/to/code/ch1 $ pytest --tb=no =================== test session starts =================== collected 6 items test_one.py . test_two.py F tasks/test_four.py .. tasks/test_three.py .. =========== 1 failed, 5 passed in 0.09 seconds ============
, -x
, pytest test_two.py .
--maxfail=num
-x
. , , , --maxfail
, , . , . , --maxfail = 2
, , --maxfail = 1
, -x
:
$ cd /path/to/code/ch1 $ pytest --maxfail=2 --tb=no =================== test session starts =================== collected 6 items test_one.py . test_two.py F tasks/test_four.py .. tasks/test_three.py .. =========== 1 failed, 5 passed in 0.08 seconds ============ $ pytest --maxfail=1 --tb=no =================== test session starts =================== collected 6 items test_one.py . test_two.py F !!!!!!!!! Interrupted: stopping after 1 failures !!!!!!!!!! =========== 1 failed, 1 passed in 0.19 seconds ============
E --tb=no
, .
-s and --capture=method
-s
тАФ , stdout , . --capture=no
. , . , , , . -s
--capture=no
. print()
, .
, , -l/--showlocals
, , .
--capture=fd
--capture=sys
. тАФ --capture=sys
sys.stdout/stderr
mem-. --capture=fd
1 2 .
sys
fd
. , , . -s
. , -s
, .
; . , , .
-lf, --last-failed
. --lf
:
, --tb
, , .
$ cd /path/to/code/ch1 $ pytest --lf =================== test session starts =================== run-last-failure: rerun last 1 failures collected 6 items test_two.py F ======================== FAILURES ========================= ______________________ test_failing _______________________ def test_failing(): > assert (1, 2, 3) == (3, 2, 1) E assert (1, 2, 3) == (3, 2, 1) E At index 0 diff: 1 != 3 E Use -v to get the full diff test_two.py:2: AssertionError =================== 5 tests deselected ==================== ========= 1 failed, 5 deselected in 0.08 seconds ==========
тАУff, --failed-first
--ff/--failed-first
, --last-failed
, , :
$ cd /path/to/code/ch1 $ pytest --ff --tb=no =================== test session starts =================== run-last-failure: rerun last 1 failures first collected 6 items test_two.py F test_one.py . tasks/test_four.py .. tasks/test_three.py .. =========== 1 failed, 5 passed in 0.09 seconds ============
test_failing()
test\_two.py
test\_one.py
. , test_failing()
, --ff
-v, --verbose
-v/--verbose
. , , .
, --ff
--tb=no
:
$ cd /path/to/code/ch1 $ pytest -v --ff --tb=no =================== test session starts =================== run-last-failure: rerun last 1 failures first collected 6 items test_two.py::test_failing FAILED test_one.py::test_passing PASSED tasks/test_four.py::test_asdict PASSED tasks/test_four.py::test_replace PASSED tasks/test_three.py::test_defaults PASSED tasks/test_three.py::test_member_access PASSED =========== 1 failed, 5 passed in 0.07 seconds ============

FAILED PASSED.
-q, --quiet
-q/--quiet
-v/--verbose
; . --tb=line
, .
- q
:
$ cd /path/to/code/ch1 $ pytest -q .F.... ======================== FAILURES ========================= ______________________ test_failing _______________________ def test_failing(): > assert (1, 2, 3) == (3, 2, 1) E assert (1, 2, 3) == (3, 2, 1) E At index 0 diff: 1 != 3 E Full diff: E - (1, 2, 3) E ? ^ ^ E + (3, 2, 1) E ? ^ ^ test_two.py:2: AssertionError 1 failed, 5 passed in 0.08 seconds
-q
, . -q
( --tb=no
), , .
-l, --showlocals
-l/--showlocals
tracebacks
.
. test_replace()
t_expected = Task('finish book', 'brian', True, 10)
рдкрд░
t_expected = Task('finish book', 'brian', True, 11)
10 11 . . --l/--showlocals
:
$ cd /path/to/code/ch1 $ pytest -l tasks =================== test session starts =================== collected 4 items tasks/test_four.py .F tasks/test_three.py .. ======================== FAILURES ========================= ______________________ test_replace _______________________ @pytest.mark.run_these_please def test_replace(): """replace() should change passed in fields.""" t_before = Task('finish book', 'brian', False) t_after = t_before._replace(id=10, done=True) t_expected = Task('finish book', 'brian', True, 11) > assert t_after == t_expected E AssertionError: assert Task(summary=...e=True, id=10) == Task(summary='...e=True, id=11) E At index 3 diff: 10 != 11 E Use -v to get the full diff t_after = Task(summary='finish book', owner='brian', done=True, id=10) t_before = Task(summary='finish book', owner='brian', done=False, id=None) t_expected = Task(summary='finish book', owner='brian', done=True, id=11) tasks\test_four.py:28: AssertionError =========== 1 failed, 3 passed in 0.08 seconds ============

t_after
, t_before
t_expected
, assert-.
--tb=style
--tb=style
. pytest , , . tracebacks , , . --tb=style
. , , short, line no. short
assert E ; line
; no .
test_replace()
, , . --tb=no
$ cd /path/to/code/ch1 $ pytest --tb=no tasks =================== test session starts =================== collected 4 items tasks/test_four.py .F tasks/test_three.py .. =========== 1 failed, 3 passed in 0.04 seconds ============
--tb=line in many cases is enough to tell what's wrong. If you have a ton of failing tests, this option can help to show a pattern in the failures:
--tb=line
, , . , :
$ pytest --tb=line tasks =================== test session starts =================== collected 4 items tasks/test_four.py .F tasks/test_three.py .. ======================== FAILURES ========================= /path/to/code/ch1/tasks/test_four.py:20: AssertionError: assert Task(summary=...e=True, id=10) == Task( summary='...e=True, id=11) =========== 1 failed, 3 passed in 0.05 seconds ============
verbose tracebacks --tb=short
:
$ pytest --tb=short tasks =================== test session starts =================== collected 4 items tasks/test_four.py .F tasks/test_three.py .. ======================== FAILURES ========================= ______________________ test_replace _______________________ tasks/test_four.py:20: in test_replace assert t_after == t_expected E AssertionError: assert Task(summary=...e=True, id=10) == Task( summary='...e=True, id=11) E At index 3 diff: 10 != 11 E Use -v to get the full diff =========== 1 failed, 3 passed in 0.04 seconds ============
, , .
, .
pytest --tb=long
traceback. pytest --tb=auto
tracebacks , . . pytest --tb=native
traceback .
--durations=N
--durations=N
, . ; N tests/setups/teardowns . --durations=0
, .
, time.sleep(0.1)
. , :
$ cd /path/to/code/ch1 $ pytest --durations=3 tasks ================= test session starts ================= collected 4 items tasks/test_four.py .. tasks/test_three.py .. ============== slowest 3 test durations =============== 0.10s call tasks/test_four.py::test_replace 0.00s setup tasks/test_three.py::test_defaults 0.00s teardown tasks/test_three.py::test_member_access ============== 4 passed in 0.13 seconds
sleep , . : call(), (setup) (teardown). , , , , . 3, pytest Fixtures, . 49.
--version
--version
pytest , :
$ pytest --version This is pytest version 3.0.7, imported from /path/to/venv/lib/python3.5/site-packages/pytest.py
pytest , pytest site-packages .
-h, --help
-h/--help
, , pytest. , stock- pytest, , , .
-h
:
- : pytest [] [file_or_dir] [file_or_dir] [...]
- ,
- , ini , 6, , . 113
- , pytest ( 6, , . 113)
- , pytest
--markers
, 2, , . 23 - , pytest
--fixtures
, 3, pytest, . 49
:
(shown according to specified file_or_dir or current dir if not specified)
, , . , pytest conftest.py, - (hook functions), , .
pytest conftest.py . conftest.py ini, pytest.ini 6 ┬л┬╗, 113.
рдЕрднреНрдпрд╛рд╕
, python -m virtualenv
python -m venv
. , , , , , . , . 1, , . 155, .
.
- $ source venv/bin/activate - $ deactivate On Windows: - C:\Users\okken\sandbox>venv\scripts\activate.bat - C:\Users\okken\sandbox>deactivate
pytest . . 2, pip, 159, . , pytest, , .
. , . pytest .
assert. assert something == something_else; , :
- assert 1 in [2, 3, 4]
- assert a < b
- assert 'fizz' not in 'fizzbuzz'
рдЖрдЧреЗ рдХреНрдпрд╛ рд╣реИ
, pytest . , . , , , , .
рдкреАрдЫреЗ рдЕрдЧрд▓рд╛ 