ЁЯФ║ рдзрдбрд╛ 08 тАФ End-to-end tests: pyramid рд╡рд┐рд░реБрджреНрдз trophy
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 08 ┬╖ рдорд╛рдЧреАрд▓: lesson-07-contract-tests ┬╖ рдкреБрдвреАрд▓: lesson-09-property-based
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ07, рдЖрдгрд┐ рддреНрдпрд╛рд╢рд┐рд╡рд╛рдп end-to-end (e2e) tests тАФ рд╕рдВрдкреВрд░реНрдг system, рдмрд╛рд╣реЗрд░реВрди, рдПрдЦрд╛рджрд╛ user
рдЬрд╕рд╛ рд╡рд╛рдкрд░реЗрд▓ рддрд╕рд╛ тАФ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ team рдЬреНрдпрд╛рд╡рд░ рд╡рд╛рдж рдШрд╛рд▓рддреЗ рддреЛ рдкреНрд░рд╢реНрди: рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░рдЪреЗ рдХрд┐рддреА
tests? Test pyramid, testing trophy рдЖрдгрд┐ ice-cream cone рдпрд╛рдВрдЪреА рдПрдХрд╛ cost model рдиреЗ
рддреБрд▓рдирд╛. suite_cost() рдЖрдгрд┐ LAYERS exam/lab.py рдордзреНрдпреЗ;
pyramid() exam/demo.py рдордзреНрдпреЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╢рд╛рд│рд╛ рддрдкрд╛рд╕рдгреНрдпрд╛рдЪреЗ рддреАрди рдорд╛рд░реНрдЧ рдЖрд╣реЗрдд.
- Unit рдкреНрд░рд╢реНрди ЁЯУЭ тАФ рдХрддрд░рд┐рдирд╛ рдПрдХрд╛ рдмрд╛рдХрд╛рд╡рд░ рдПрдХрд╛ рд╡рд┐рджреНрдпрд╛рд░реНрдерд┐рдиреАрд▓рд╛ рдПрдХ рдкреНрд░рд╢реНрди рд╡рд┐рдЪрд╛рд░рддреЗ. рдкреНрд░рддреНрдпреЗрдХреА рджреЛрди рд╕реЗрдХрдВрдж.
- Integration рдкреНрд░рд╢реНрди ЁЯФМ тАФ рддреА marks book рдЪреА рдмреЗрд░реАрдЬ рдЦрд░реЛрдЦрд░ рдЬреБрд│рддреЗ рдХрд╛ рддреЗ рддрдкрд╛рд╕рддреЗ. рдереЛрдбреЗ рд╣рд│реВ.
- рд╢рд╛рд│реЗрдЪрд╛ рдкреВрд░реНрдг рджрд┐рд╡рд╕ ЁЯПл тАФ рдРрд╢реНрд╡рд░реНрдпрд╛ рдлрд╛рдЯрдХрд╛рддреВрди рдЖрдд рдпреЗрддреЗ, рд╡рд░реНрдЧ рд╢реЛрдзрддреЗ, рдкрд░реАрдХреНрд╖рд╛ рджреЗрддреЗ, рдЖрдгрд┐ report card рдШрд░реА рдкрд╛рдард╡рд▓реЗ рдЬрд╛рддреЗ. рд╣реЗ рд╕рдЧрд│реЗ рдПрдХрддреНрд░ рддрдкрд╛рд╕рддреЗ. рдкрдг рдпрд╛рд▓рд╛ рдкреВрд░реНрдг рджрд┐рд╡рд╕ рд▓рд╛рдЧрддреЛ, рдЖрдгрд┐ рдХрдзреА рдХрдзреА bus рдЙрд╢рд┐рд░рд╛ рдпреЗрддреЗ тАФ рдЖрдгрд┐ рдкрд░реАрдХреНрд╖реЗрд╢реА рдХрд╛рд╣реАрд╣реА рд╕рдВрдмрдВрдз рдирд╕рд▓реЗрд▓реНрдпрд╛ рдХрд╛рд░рдгрд╛рдиреЗ рддрдкрд╛рд╕рдгреА "fail" рд╣реЛрддреЗ.
рдХрддрд░рд┐рдирд╛рдиреЗ рд╕рдЧрд│реЗ рдкреВрд░реНрдг рд╢рд╛рд│реЗрдЪреНрдпрд╛ рджрд┐рд╡рд╕рд╛рдВрдиреА рддрдкрд╛рд╕рд╛рдпрдЪреЗ рдард░рд╡рд▓реЗ, рддрд░ рддрд┐рд▓рд╛ рд╢реЗрдХрдбреЛ рджрд┐рд╡рд╕ рд▓рд╛рдЧрддреАрд▓. рдкреНрд░рддреНрдпреЗрдХ run рд▓рд╛ рдкрд╛рд╡ рддрд╛рд╕ рд▓рд╛рдЧреЗрд▓, рдЖрдгрд┐ рдЬрд╡рд│рдЬрд╡рд│ рдкреНрд░рддреНрдпреЗрдХ run рдордзреНрдпреЗ рдХреБрдареЗ рдирд╛ рдХреБрдареЗ bus рдЙрд╢рд┐рд░рд╛ рдпреЗрдИрд▓рдЪ. ЁЯЪМ
рдореНрд╣рдгреВрди рддреА рдкреВрд░реНрдг рджрд┐рд╡рд╕ рдереЛрдбреЗ рдареЗрд╡рддреЗ, рдЫреЛрдЯреЗ рдкреНрд░рд╢реНрди рдЦреВрдк рдареЗрд╡рддреЗ, рдЖрдгрд┐ рдордзрд▓реНрдпрд╛ рднрд╛рдЧрд╛рд╡рд░ рджреАрдкрд┐рдХрд╛рд╢реА рд╡рд╛рдж рдШрд╛рд▓рддреЗ: рдХрддрд░рд┐рдирд╛рд▓рд╛ рдЦреВрдк unit рдкреНрд░рд╢реНрди рдЖрд╡рдбрддрд╛рдд (pyramid ЁЯФ║), рджреАрдкрд┐рдХрд╛рд▓рд╛ рдЦреВрдк integration рддрдкрд╛рд╕рдгреНрдпрд╛ рдЖрд╡рдбрддрд╛рдд (trophy ЁЯПЖ). рдЙрд▓рдЯрд╛ рдЖрдХрд╛рд░ тАФ рдмрд╣реБрддреЗрдХ рдкреВрд░реНрдг рджрд┐рд╡рд╕ тАФ рдореНрд╣рдгрдЬреЗ рдЧреЛрдВрдзрд│ рдЖрд╣реЗ рдпрд╛рд╡рд░ рджреЛрдШреАрдВрдЪреЗ рдПрдХрдордд рдЖрд╣реЗ (ice-cream cone ЁЯНж).
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart TB
subgraph pyr["ЁЯФ║ pyramid 400 / 80 / 10"]
p["60.0 s per run ┬╖ flaky 17%"]
end
subgraph tro["ЁЯПЖ trophy 150 / 300 / 10"]
t["80.8 s per run ┬╖ flaky 23%"]
end
subgraph ice["ЁЯНж ice-cream cone 50 / 50 / 200"]
i["1005.2 s per run ┬╖ flaky 87%"]
end
note["model: unit 0.005 s ┬╖ integration 0.1 s ┬╖ e2e 5 s per test<br/>flake chance 0.01% ┬╖ 0.05% ┬╖ 1%"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/testing/lesson-diagrams.html#l08
тЭУ рдХрд╛рдп
- End-to-end (e2e) test тАФ рдЦрд░реА system рдмрд╛рд╣реЗрд░реВрди рдЪрд╛рд▓рд╡рддреЛ: browser web app рдордзреВрди click рдХрд░рдд рдЬрд╛рддреЛ, app рдЦрд░рд╛ API рдмреЛрд▓рд╡рддреЗ, рдЖрдгрд┐ API рдЦрд░рд╛ database рд╡рд╛рдкрд░рддреЛ. рд╣реЗ рд╕рд┐рджреНрдз рдХрд░рддреЗ рдХреА рднрд╛рдЧ рдПрдХрдореЗрдХрд╛рдВрд╢реА рдЬреЛрдбрд▓реЗрд▓реЗ рдЖрд╣реЗрдд. рд╣рд╛ рд╕рд░реНрд╡рд╛рдд рд╣рд│реВ, рд╕рд░реНрд╡рд╛рдд рдирд╛рдЬреВрдХ рдкреНрд░рдХрд╛рд░ рдЖрд╣реЗ, рдЖрдгрд┐ рддреЛ fail рдЭрд╛рд▓рд╛ рдХреА рдХреБрдареЗ рдЪреБрдХрд▓реЗ рддреЗ рдХреНрд╡рдЪрд┐рддрдЪ рд╕рд╛рдВрдЧрддреЛ.
- Test pyramid тАФ Mike Cohn, Succeeding with Agile (2009): рддрд│рд╛рд╢реА рдЦреВрдк unit tests, рддреНрдпрд╛рд╡рд░ рдХрдореА service/integration tests, рдЯреЛрдХрд╛рд▓рд╛ рдЕрдЧрджреА рдереЛрдбреЗ UI tests.
- Testing trophy тАФ Kent C. Dodds (2018): рдкрд╛рдпрд╛рд╢реА static checks (types, linters), рддреНрдпрд╛рд╡рд░ integration tests рдЪрд╛ рдореЛрдард╛ рдерд░, рдХрдореА unit tests, рдереЛрдбреЗ e2e. рдпреБрдХреНрддрд┐рд╡рд╛рдж рдЕрд╕рд╛: рдЦрд▒реНрдпрд╛ рд╡рд╛рдкрд░рд╛рд╕рд╛рд░рдЦреЗ рджрд┐рд╕рдгрд╛рд░реЗ tests рдкреНрд░рддреНрдпреЗрдХ test рдорд╛рдЧреЗ рдЬрд╛рд╕реНрдд рд╡рд┐рд╢реНрд╡рд╛рд╕ рджреЗрддрд╛рдд, рдЖрдгрд┐ рдЖрдзреБрдирд┐рдХ tools рдореБрд│реЗ integration tests рдкреБрд░реЗрд╕реЗ рд╡реЗрдЧрд╡рд╛рди рд╣реЛрддрд╛рдд.
- Ice-cream cone тАФ рдПрдХ anti-pattern: рдмрд╣реБрддреЗрдХ manual рдХрд┐рдВрд╡рд╛ e2e tests, unit tests рдереЛрдбреЗ. рд╣рд│реВ, flaky, рд╕рд╛рдВрднрд╛рд│рд╛рдпрд▓рд╛ рдорд╣рд╛рдЧ.
- Flake тАФ code рди рдмрджрд▓рддрд╛ fail рд╣реЛрдгрд╛рд░рд╛ test (рдзрдбрд╛ 11). рдкреНрд░рддреНрдпреЗрдХ e2e test 1% рд╡реЗрд│рд╛ flake рд╣реЛрдд рдЕрд╕реЗрд▓, рддрд░ рдЕрд╢рд╛ 200 tests рдЪрд╛ suite рдмрд╣реБрддреЗрдХ runs рдордзреНрдпреЗ рд╡рд┐рдирд╛рдХрд╛рд░рдг рд▓рд╛рд▓ рд╣реЛрддреЛ: рдПрдХрд╣реА flake рди рд╣реЛрдгреНрдпрд╛рдЪреА рд╢рдХреНрдпрддрд╛ 0.99┬▓тБ░тБ░ тЙИ 13% рдЖрд╣реЗ.
- Cost model тАФ demo рдордзрд▓реЗ рдЖрдХрдбреЗ (рдкреНрд░рддреНрдпреЗрдХ e2e test рд╕рд╛рдареА 5 s рдЖрдгрд┐ 1% flake рд╢рдХреНрдпрддрд╛, рд╡рдЧреИрд░реЗ) рдЙрджрд╛рд╣рд░рдгрд╛рджрд╛рдЦрд▓ рдЖрд╣реЗрдд, рдкрдЯрдгреНрдпрд╛рдЬреЛрдЧреЗ рдореНрд╣рдгреВрди рдирд┐рд╡рдбрд▓реЗрд▓реЗ, рдореЛрдЬрд▓реЗрд▓реЗ рдирд╛рд╣реАрдд. рддреБрдордЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ suite рдЪреЗ рдЖрдХрдбреЗ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ; рдирд┐рдХрд╛рд▓рд╛рдЪрд╛ рдЖрдХрд╛рд░ рд╣рд╛рдЪ рдореБрджреНрджрд╛ рдЖрд╣реЗ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг suite рдЪрд╛ рд╡реЗрд│ рдЖрдгрд┐ рддреНрдпрд╛рд╡рд░рдЪрд╛ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдпрд╛рд╡рд░рдЪ рд▓реЛрдХ рддреЛ рдЪрд╛рд▓рд╡рддрд╛рдд рдХреА рдирд╛рд╣реА рд╣реЗ рдард░рддреЗ. рдЬреЛ suite рдкрд╛рд╡ рддрд╛рд╕ рдШреЗрддреЛ рдЖрдгрд┐ рдмрд╣реБрддреЗрдХ runs рдордзреНрдпреЗ рд╡рд┐рдирд╛рдХрд╛рд░рдг рд▓рд╛рд▓ рд╣реЛрддреЛ, рддреЛ рд╡рдЧрд│рд▓рд╛ рдЬрд╛рддреЛ, рд╣рд┐рд░рд╡рд╛ рд╣реЛрдИрдкрд░реНрдпрдВрдд рдкреБрдиреНрд╣рд╛ рдЪрд╛рд▓рд╡рд▓рд╛ рдЬрд╛рддреЛ, рдХрд┐рдВрд╡рд╛ delete рдХреЗрд▓рд╛ рдЬрд╛рддреЛ. Pyramid рдЖрдгрд┐ trophy рдордзрд▓реНрдпрд╛ рднрд╛рдЧрд╛рд╡рд░ рдЕрд╕рд╣рдордд рдЖрд╣реЗрдд рдкрдг рдЯреЛрдХрд╛рд╡рд░ рд╕рд╣рдордд: e2e tests рдереЛрдбреЗ рдареЗрд╡рд╛, рдЖрдгрд┐ рддреЗ рдлрдХреНрдд рдкреИрд╕реЗ рдорд┐рд│рд╡реВрди рджреЗрдгрд╛рд▒реНрдпрд╛ рдХрд┐рдВрд╡рд╛ рдореЛрдбрд▓реНрдпрд╛рд╕ рдмрд╛рддрдореА рд╣реЛрдИрд▓ рдЕрд╢рд╛ рдкреНрд░рд╡рд╛рд╕рд╛рдВрд╕рд╛рдареА.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
exam/lab.py рдордзреАрд▓ LAYERS рдордзреНрдпреЗ unit, integration рдЖрдгрд┐ e2e рд╕рд╛рдареА
(рдкреНрд░рддреНрдпреЗрдХ test рдЪреЗ seconds, test flake рд╣реЛрдгреНрдпрд╛рдЪреА рд╢рдХреНрдпрддрд╛) рдЖрд╣реЗ. suite_cost(counts) рд╡реЗрд│ рдмреЗрд░реАрдЬ рдХрд░рддреЗ
рдЖрдгрд┐ 1 тИТ ╬а(1 тИТ p)тБ┐ рдХрд╛рдврддреЗ, рдореНрд╣рдгрдЬреЗ run рдордзреАрд▓ рдХрд┐рдорд╛рди рдПрдХ test flake рд╣реЛрдгреНрдпрд╛рдЪреА рд╢рдХреНрдпрддрд╛.
exam/demo.py рдордзреАрд▓ pyramid() teaching app рдордзреВрди рдПрдХ рдЦрд░рд╛ end-to-end
pass рд╕реБрджреНрдзрд╛ рдЪрд╛рд▓рд╡рддреЗ: SQLite рдордзреНрдпреЗ save рдХреЗрд▓реЗрд▓реЗ marks, fake service рдХрдбреВрди attendance, рдЖрдгрд┐ рдмрд╛рд╣реЗрд░
рдПрдХ report card.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 exam/demo.py pyramid
python3 - <<'EOF'
from exam.lab import suite_cost, LAYERS
print("model:", LAYERS)
for e2e in (0, 10, 50, 200):
secs, flake = suite_cost({"unit": 400, "integration": 80, "e2e": e2e})
print(f"400 unit + 80 integration + {e2e:>3} e2e тЖТ {secs:>6.1f} s ┬╖ red for no reason {flake:.1%} of runs")
secs, flake = suite_cost({"unit": 0, "integration": 0, "e2e": 1})
print(f"one e2e test alone: {secs} s, flakes {flake:.1%} ┬╖ one unit test: {suite_cost({'unit': 1})[0]} s")
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
pyramid рд╣реЗ рдЫрд╛рдкрддреЗ:
тФАтФА one end-to-end run through the teaching app: database тЖТ attendance тЖТ report card тЖТ Aishwarya: average 74.33 ┬╖ B ┬╖ attendance 86.0% ┬╖ promoted True
pyramid 400 / 80 / 10 tests тЖТ 60.0 s per run ┬╖ a run hits at least one flaky failure 17% of the time
trophy 150 / 300 / 10 tests тЖТ 80.8 s per run ┬╖ a run hits at least one flaky failure 23% of the time
ice-cream cone 50 / 50 / 200 tests тЖТ 1005.2 s per run ┬╖ a run hits at least one flaky failure 87% of the time
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
model: {'unit': (0.005, 0.0001), 'integration': (0.1, 0.0005), 'e2e': (5.0, 0.01)}
400 unit + 80 integration + 0 e2e тЖТ 10.0 s ┬╖ red for no reason 7.7% of runs
400 unit + 80 integration + 10 e2e тЖТ 60.0 s ┬╖ red for no reason 16.5% of runs
400 unit + 80 integration + 50 e2e тЖТ 260.0 s ┬╖ red for no reason 44.2% of runs
400 unit + 80 integration + 200 e2e тЖТ 1010.0 s ┬╖ red for no reason 87.6% of runs
one e2e test alone: 5.0 s, flakes 1.0% ┬╖ one unit test: 0.005 s
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдпрд╛ model рдордзреНрдпреЗ рдПрдХ e2e test 1000 unit tests рдЗрддрдХрд╛ рд╡реЗрд│ рдШреЗрддреЛ. e2e tests 10 рд╡рд░реВрди 200 рдХреЗрд▓реНрдпрд╛рд╡рд░ run рдЪрд╛ рд╡реЗрд│ рд╕реБрдорд╛рд░реЗ 17 рдкрдЯ рдЭрд╛рд▓рд╛ рдЖрдгрд┐ рдмрд╣реБрддреЗрдХ runs рд╡рд┐рдирд╛рдХрд╛рд░рдг рд▓рд╛рд▓ рдЭрд╛рд▓реЗ. рддрд░реАрд╣реА app рдордзреВрди рдЧреЗрд▓реЗрд▓рд╛ рддреЛ e2e pass рдПрдХрд╛ test рдЗрддрдХрд╛ рдореЛрд▓рд╛рдЪрд╛ рд╣реЛрддрд╛: database, attendance client рдЖрдгрд┐ report card рдПрдХрдореЗрдХрд╛рдВрдд рдмрд╕рддрд╛рдд рд╣реЗ рддреНрдпрд╛рдиреЗ рджрд╛рдЦрд╡рд▓реЗ (74.33 тЖТ B, 86.0% тЖТ promoted) тАФ рдЬреЗ рдХреЛрдгрддрд╛рд╣реА unit test рдПрдХрдЯреНрдпрд╛рдиреЗ рджрд╛рдЦрд╡реВ рд╢рдХрдд рдирд╛рд╣реА. рдереЛрдбреЗ, рдкрдг рд╢реВрдиреНрдп рдирд╛рд╣реА.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рдкреНрд░рддреНрдпреЗрдХ edge case browser рдордзреВрди рддрдкрд╛рд╕рдгреЗ (boundary table unit tests рдордзреНрдпреЗ рдареЗрд╡рд╛)
- рдПрдХрд╣реА e2e test рдирд╕рдгреЗ тАФ рдкреНрд░рддреНрдпреЗрдХ рднрд╛рдЧ рдПрдХрдЯрд╛ рдЪрд╛рд▓рддреЛ рдЖрдгрд┐ login page рдорд╛рддреНрд░ рдореЛрдбрд▓реЗрд▓реЗ рдЕрд╕рддреЗ
- element рдЪреА рд╡рд╛рдЯ рдкрд╛рд╣рдгреНрдпрд╛рдРрд╡рдЬреА рдард░рд╛рд╡реАрдХ рд╡реЗрд│ sleep рдХрд░рдгреЗ (рдзрдбрд╛ 11)
- e2e tests рдиреА рдПрдХрдЪ test account рд╡рд╛рдкрд░рдгреЗ рдЖрдгрд┐ рдПрдХрдореЗрдХрд╛рдВрдЪреНрдпрд╛ data рд╡рд░ рдкрд╛рдп рджреЗрдгреЗ
- рд╕реНрд╡рддрдГрдЪреНрдпрд╛ suite рдЪрд╛ рд╡реЗрд│ рдЖрдгрд┐ flake rate рдореЛрдЬрдгреНрдпрд╛рдРрд╡рдЬреА pyramid рд╡рд┐рд░реБрджреНрдз trophy рдЕрд╕рд╛ рд╡рд╛рдж рдШрд╛рд▓рдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ project рдордзреНрдпреЗ тАФ Python рд╕рд╛рдареА Playwright рд╡рд╛рдкрд░реВрди рдПрдХ e2e test (pip install pytest-playwright, рдордЧ playwright install chromium). Playwright elements рддрдпрд╛рд░ рд╣реЛрдИрдкрд░реНрдпрдВрдд
рдЖрдкреЛрдЖрдк рд╡рд╛рдЯ рдкрд╛рд╣рддреЗ, рддреНрдпрд╛рдореБрд│реЗ рдмрд░реЗрдЪ flaky sleeps рдирд┐рдШреВрди рдЬрд╛рддрд╛рдд:
from playwright.sync_api import Page, expect
def test_report_card_page(page: Page):
page.goto("https://staging.school.example/report/42")
expect(page.get_by_role("heading", name="Report card")).to_be_visible()
expect(page.get_by_test_id("grade")).to_have_text("B")
pytest tests/e2e --browser chromium --tracing retain-on-failure # keep a trace to replay failures
JavaScript runner рдореНрд╣рдгрдЬреЗ npx playwright test; Cypress рдЖрдгрд┐ Selenium рд╣реЗ рдЗрддрд░ рдиреЗрд╣рдореАрдЪреЗ
рдкрд░реНрдпрд╛рдп рдЖрд╣реЗрдд. рддреБрдордЪреЗ рдЦрд░реЗ рдерд░ рдореЛрдЬрд╛:
pytest --durations=10 # the 10 slowest tests
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рддреБрдордЪреЗ 5тАУ10 рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ user рдкреНрд░рд╡рд╛рд╕ рд▓рд┐рд╣реВрди рдХрд╛рдврд╛ (log in, marks submit рдХрд░рдгреЗ, report cards publish рдХрд░рдгреЗ) рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХрд╛рд▓рд╛ рдПрдХ e2e test рджреНрдпрд╛. рдмрд╛рдХреА рд╕рдЧрд│реЗ pyramid рдордзреНрдпреЗ рдЦрд╛рд▓рдЪреНрдпрд╛ рдерд░рд╛рдд тАФ рдЖрдгрд┐ suite рдЪрд╛ run рд╡реЗрд│ рд╡ flake rate рдЗрддрд░ рдХреЛрдгрддреНрдпрд╛рд╣реА production metric рд╕рд╛рд░рдЦрд╛ track рдХрд░рд╛.
тПня╕П рдкреБрдвреЗ
рдЖрддреНрддрд╛рдкрд░реНрдпрдВрдд рдХрддрд░рд┐рдирд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рд╢реНрди рд╕реНрд╡рддрдГ рдирд┐рд╡рдбрддреЗ. рд╕рдВрдЧрдгрдХрд╛рдиреЗрдЪ рдПрдХрд╛ рдирд┐рдпрдорд╛рд╡рд░реВрди рд╢реЗрдХрдбреЛ рдкреНрд░рд╢реНрди рддрдпрд╛рд░ рдХреЗрд▓реЗ тАФ рдЖрдгрд┐ рдордЧ failure рд╢рдХреНрдп рддрд┐рддрдХрд╛ рд▓рд╣рд╛рди рдХреЗрд▓рд╛ рддрд░? Property-based testing.
git checkout lesson-09-property-based