рдкрд╛рдпрдерди рдХреЗ рд╕рд╛рде рдкрд╛рдпрдерди рдкрд░реАрдХреНрд╖рдгред рдкрд╛рдЗрд╕реНрдЯреЗрд╕реНрдЯ, рдЕрдзреНрдпрд╛рдп 1 рдХреЗ рд╕рд╛рде рд╢реБрд░реБрдЖрдд рдХрд░рдирд╛

рдкреАрдЫреЗ рдЕрдЧрд▓рд╛


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

рдХреНрд░рд┐рд╕ рд╢реЗрд╡рд░
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.


рдЕрднреНрдпрд╛рд╕


  1. , python -m virtualenv python -m venv . , , , , , . , . 1, , . 155, .


  2. .


     - $ source venv/bin/activate - $ deactivate On Windows: - C:\Users\okken\sandbox>venv\scripts\activate.bat - C:\Users\okken\sandbox>deactivate 

  3. pytest . . 2, pip, 159, . , pytest, , .


  4. . , . pytest .


  5. assert. assert something == something_else; , :


    • assert 1 in [2, 3, 4]
    • assert a < b
    • assert 'fizz' not in 'fizzbuzz'


рдЖрдЧреЗ рдХреНрдпрд╛ рд╣реИ


, pytest . , . , , , , .


рдкреАрдЫреЗ рдЕрдЧрд▓рд╛

Source: https://habr.com/ru/post/hi448782/


All Articles