revise August 2023 e2e stability articles
Build and deploy / deploy (push) Successful in 16s

This commit is contained in:
2026-07-31 15:08:57 +03:00
parent 5cbd53d8ec
commit 3d310bd605
7 changed files with 966 additions and 1 deletions
@@ -0,0 +1,62 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="0 0 1200 800" role="img" aria-labelledby="title desc">
<title id="title">Классификация flaky e2e-теста без роста timeout</title>
<desc id="desc">Последовательность из четырёх проверок: уникальность selector, semantic readiness, различие initial attempt и retry, evidence конкретной попытки. У каждого шага есть отдельное действие; timeout не является первым решением.</desc>
<defs>
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 Z" fill="#486581"/></marker>
</defs>
<rect width="1200" height="800" fill="#f7fafc"/>
<rect x="48" y="42" width="1104" height="84" rx="18" fill="#102a43"/>
<text x="84" y="93" fill="#ffffff" font-family="Arial, sans-serif" font-size="34" font-weight="700">Flaky: классифицировать слой, не повышать timeout</text>
<text x="84" y="116" fill="#d9e2ec" font-family="Arial, sans-serif" font-size="17">Каждый ответ сужает следующую проверку; ни один не объявляет корневую причину.</text>
<path d="M435 252 L435 278" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M435 387 L435 413" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M435 522 L435 548" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<g>
<rect x="68" y="156" width="735" height="96" rx="16" fill="#e0f2fe" stroke="#0ea5e9" stroke-width="3"/>
<circle cx="116" cy="204" r="25" fill="#0369a1"/>
<text x="108" y="214" fill="#ffffff" font-family="Arial, sans-serif" font-size="26" font-weight="700">1</text>
<text x="160" y="194" fill="#102a43" font-family="Arial, sans-serif" font-size="25" font-weight="700">Selector</text>
<text x="160" y="223" fill="#334e68" font-family="Arial, sans-serif" font-size="20">Locator разрешается ровно в один пользовательский control?</text>
<rect x="852" y="170" width="280" height="67" rx="14" fill="#fff1f2" stroke="#e11d48" stroke-width="2"/>
<text x="874" y="198" fill="#9f1239" font-family="Arial, sans-serif" font-size="20" font-weight="700">Нет → сузить locator</text>
<text x="874" y="220" fill="#9f1239" font-family="Arial, sans-serif" font-size="16">Не трогать readiness.</text>
</g>
<g>
<rect x="68" y="291" width="735" height="96" rx="16" fill="#ecfdf5" stroke="#10b981" stroke-width="3"/>
<circle cx="116" cy="339" r="25" fill="#047857"/>
<text x="108" y="349" fill="#ffffff" font-family="Arial, sans-serif" font-size="26" font-weight="700">2</text>
<text x="160" y="329" fill="#102a43" font-family="Arial, sans-serif" font-size="25" font-weight="700">Readiness condition</text>
<text x="160" y="358" fill="#334e68" font-family="Arial, sans-serif" font-size="20">После click виден терминальный пользовательский факт?</text>
<rect x="852" y="305" width="280" height="67" rx="14" fill="#fff7ed" stroke="#f97316" stroke-width="2"/>
<text x="874" y="333" fill="#9a3412" font-family="Arial, sans-serif" font-size="20" font-weight="700">Нет → назвать state</text>
<text x="874" y="355" fill="#9a3412" font-family="Arial, sans-serif" font-size="16">Не ждать spinner или sleep.</text>
</g>
<g>
<rect x="68" y="426" width="735" height="96" rx="16" fill="#eef2ff" stroke="#6366f1" stroke-width="3"/>
<circle cx="116" cy="474" r="25" fill="#4338ca"/>
<text x="108" y="484" fill="#ffffff" font-family="Arial, sans-serif" font-size="26" font-weight="700">3</text>
<text x="160" y="464" fill="#102a43" font-family="Arial, sans-serif" font-size="25" font-weight="700">Retry</text>
<text x="160" y="493" fill="#334e68" font-family="Arial, sans-serif" font-size="20">Initial failed, retry passed — это результат двух попыток.</text>
<rect x="852" y="440" width="280" height="67" rx="14" fill="#eef2ff" stroke="#6366f1" stroke-width="2"/>
<text x="874" y="468" fill="#3730a3" font-family="Arial, sans-serif" font-size="20" font-weight="700">Сохранить оба outcome</text>
<text x="874" y="490" fill="#3730a3" font-family="Arial, sans-serif" font-size="16">Не называть retry причиной.</text>
</g>
<g>
<rect x="68" y="561" width="735" height="96" rx="16" fill="#f5f3ff" stroke="#8b5cf6" stroke-width="3"/>
<circle cx="116" cy="609" r="25" fill="#6d28d9"/>
<text x="108" y="619" fill="#ffffff" font-family="Arial, sans-serif" font-size="26" font-weight="700">4</text>
<text x="160" y="599" fill="#102a43" font-family="Arial, sans-serif" font-size="25" font-weight="700">Evidence</text>
<text x="160" y="628" fill="#334e68" font-family="Arial, sans-serif" font-size="20">Trace/log/snapshot привязан к номеру попытки и одному вопросу?</text>
<rect x="852" y="575" width="280" height="67" rx="14" fill="#f5f3ff" stroke="#8b5cf6" stroke-width="2"/>
<text x="874" y="603" fill="#5b21b6" font-family="Arial, sans-serif" font-size="20" font-weight="700">Собрать один факт</text>
<text x="874" y="625" fill="#5b21b6" font-family="Arial, sans-serif" font-size="16">Не обещать root cause.</text>
</g>
<rect x="68" y="696" width="1064" height="62" rx="14" fill="#102a43"/>
<text x="96" y="734" fill="#ffffff" font-family="Arial, sans-serif" font-size="23" font-weight="700">Только после этого: малый diff, owner, rollback. Timeout — верхняя граница, не readiness condition.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

@@ -0,0 +1,61 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="0 0 1200 800" role="img" aria-labelledby="title desc">
<title id="title">Цикл triage flaky e2e-теста</title>
<desc id="desc">Пять шагов замкнутого цикла: зафиксировать initial и retry outcome, проверить selector, проверить readiness, связать evidence с попыткой, сделать маленький diff с rollback. При недостатке фактов цикл возвращается к карточке, а не повышает timeout.</desc>
<defs>
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 Z" fill="#486581"/></marker>
</defs>
<rect width="1200" height="800" fill="#f8fafc"/>
<rect x="48" y="42" width="1104" height="84" rx="18" fill="#102a43"/>
<text x="84" y="92" fill="#ffffff" font-family="Arial, sans-serif" font-size="34" font-weight="700">Flaky triage: один факт → одна проверка → малый diff</text>
<text x="84" y="116" fill="#d9e2ec" font-family="Arial, sans-serif" font-size="17">Цикл не ищет «идеальный timeout»: он сохраняет объяснимый контракт и rollback.</text>
<path d="M369 251 C470 182, 593 177, 686 224" fill="none" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M840 299 C913 365, 913 469, 830 521" fill="none" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M700 599 C580 662, 442 649, 356 592" fill="none" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M205 520 C133 454, 134 341, 214 286" fill="none" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<g>
<rect x="95" y="195" width="280" height="138" rx="20" fill="#e0f2fe" stroke="#0284c7" stroke-width="3"/>
<text x="123" y="237" fill="#075985" font-family="Arial, sans-serif" font-size="24" font-weight="700">1. Карточка</text>
<text x="123" y="270" fill="#102a43" font-family="Arial, sans-serif" font-size="18">initial outcome</text>
<text x="123" y="295" fill="#102a43" font-family="Arial, sans-serif" font-size="18">retry outcome</text>
<text x="123" y="318" fill="#334e68" font-family="Arial, sans-serif" font-size="15">Не удалять initial error.</text>
</g>
<g>
<rect x="700" y="195" width="280" height="138" rx="20" fill="#ecfdf5" stroke="#059669" stroke-width="3"/>
<text x="728" y="237" fill="#047857" font-family="Arial, sans-serif" font-size="24" font-weight="700">2. Selector</text>
<text x="728" y="270" fill="#102a43" font-family="Arial, sans-serif" font-size="18">user-facing locator</text>
<text x="728" y="295" fill="#102a43" font-family="Arial, sans-serif" font-size="18">ровно один match?</text>
<text x="728" y="318" fill="#334e68" font-family="Arial, sans-serif" font-size="15">Нет → отдельный locator diff.</text>
</g>
<g>
<rect x="700" y="493" width="280" height="138" rx="20" fill="#fff7ed" stroke="#ea580c" stroke-width="3"/>
<text x="728" y="535" fill="#9a3412" font-family="Arial, sans-serif" font-size="24" font-weight="700">3. Readiness</text>
<text x="728" y="568" fill="#102a43" font-family="Arial, sans-serif" font-size="18">terminal UI-state</text>
<text x="728" y="593" fill="#102a43" font-family="Arial, sans-serif" font-size="18">после действия?</text>
<text x="728" y="616" fill="#334e68" font-family="Arial, sans-serif" font-size="15">Не ждать spinner или sleep.</text>
</g>
<g>
<rect x="95" y="493" width="280" height="138" rx="20" fill="#f5f3ff" stroke="#7c3aed" stroke-width="3"/>
<text x="123" y="535" fill="#5b21b6" font-family="Arial, sans-serif" font-size="24" font-weight="700">4. Evidence</text>
<text x="123" y="568" fill="#102a43" font-family="Arial, sans-serif" font-size="18">trace/log/snapshot</text>
<text x="123" y="593" fill="#102a43" font-family="Arial, sans-serif" font-size="18">какой attempt?</text>
<text x="123" y="616" fill="#334e68" font-family="Arial, sans-serif" font-size="15">Один артефакт — один вопрос.</text>
</g>
<g>
<rect x="421" y="338" width="358" height="166" rx="24" fill="#102a43"/>
<text x="455" y="386" fill="#ffffff" font-family="Arial, sans-serif" font-size="26" font-weight="700">5. Решение</text>
<text x="455" y="421" fill="#d9e2ec" font-family="Arial, sans-serif" font-size="19">малый diff в одном слое</text>
<text x="455" y="448" fill="#d9e2ec" font-family="Arial, sans-serif" font-size="19">owner + rollback + next check</text>
<text x="455" y="479" fill="#fbbf24" font-family="Arial, sans-serif" font-size="17" font-weight="700">Timeout не меняется автоматически</text>
</g>
<path d="M375 264 L416 354" fill="none" stroke="#94a3b8" stroke-width="4" stroke-dasharray="8 8" marker-end="url(#arrow)"/>
<path d="M700 264 L782 354" fill="none" stroke="#94a3b8" stroke-width="4" stroke-dasharray="8 8" marker-end="url(#arrow)"/>
<path d="M700 560 L782 488" fill="none" stroke="#94a3b8" stroke-width="4" stroke-dasharray="8 8" marker-end="url(#arrow)"/>
<path d="M375 560 L416 488" fill="none" stroke="#94a3b8" stroke-width="4" stroke-dasharray="8 8" marker-end="url(#arrow)"/>
<rect x="172" y="690" width="856" height="61" rx="14" fill="#e0e7ff" stroke="#6366f1" stroke-width="2"/>
<text x="205" y="728" fill="#312e81" font-family="Arial, sans-serif" font-size="22" font-weight="700">Недостаточно фактов? Вернуться к карточке и собрать один недостающий сигнал.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

@@ -0,0 +1,66 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="0 0 1200 800" role="img" aria-labelledby="title desc">
<title id="title">Четыре контракта ожидания в e2e-тесте</title>
<desc id="desc">Горизонтальная схема разделяет selector, actionability, readiness condition и retry. Под ними evidence привязан к попытке. Подписи показывают, что каждый слой не доказывает следующий.</desc>
<defs>
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 Z" fill="#486581"/></marker>
<marker id="down" markerWidth="10" markerHeight="10" refX="5" refY="8" orient="auto"><path d="M0,0 L10,0 L5,10 Z" fill="#9fb3c8"/></marker>
</defs>
<rect width="1200" height="800" fill="#f8fafc"/>
<rect x="50" y="42" width="1100" height="88" rx="18" fill="#102a43"/>
<text x="84" y="91" fill="#ffffff" font-family="Arial, sans-serif" font-size="34" font-weight="700">Ожидание e2e: четыре разных контракта</text>
<text x="84" y="115" fill="#d9e2ec" font-family="Arial, sans-serif" font-size="17">Верхняя полоса — действие и результат. Нижняя — политика исполнения и evidence.</text>
<path d="M303 292 L335 292" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M574 292 L606 292" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M845 292 L877 292" stroke="#486581" stroke-width="5" marker-end="url(#arrow)"/>
<g>
<rect x="70" y="190" width="230" height="205" rx="18" fill="#e0f2fe" stroke="#0284c7" stroke-width="3"/>
<text x="96" y="236" fill="#075985" font-family="Arial, sans-serif" font-size="25" font-weight="700">1. Selector</text>
<text x="96" y="272" fill="#102a43" font-family="Arial, sans-serif" font-size="19">Где действие?</text>
<text x="96" y="300" fill="#334e68" font-family="Arial, sans-serif" font-size="17">role/name или</text>
<text x="96" y="324" fill="#334e68" font-family="Arial, sans-serif" font-size="17">явный test id</text>
<text x="96" y="365" fill="#9f1239" font-family="Arial, sans-serif" font-size="16" font-weight="700">Не доказывает:</text>
<text x="96" y="385" fill="#9f1239" font-family="Arial, sans-serif" font-size="15">успех операции</text>
</g>
<g>
<rect x="340" y="190" width="230" height="205" rx="18" fill="#ecfdf5" stroke="#059669" stroke-width="3"/>
<text x="366" y="236" fill="#047857" font-family="Arial, sans-serif" font-size="25" font-weight="700">2. Actionability</text>
<text x="366" y="272" fill="#102a43" font-family="Arial, sans-serif" font-size="19">Можно click?</text>
<text x="366" y="300" fill="#334e68" font-family="Arial, sans-serif" font-size="17">visible, stable,</text>
<text x="366" y="324" fill="#334e68" font-family="Arial, sans-serif" font-size="17">enabled, events</text>
<text x="366" y="365" fill="#9f1239" font-family="Arial, sans-serif" font-size="16" font-weight="700">Не доказывает:</text>
<text x="366" y="385" fill="#9f1239" font-family="Arial, sans-serif" font-size="15">product-ready</text>
</g>
<g>
<rect x="610" y="190" width="230" height="205" rx="18" fill="#fff7ed" stroke="#ea580c" stroke-width="3"/>
<text x="636" y="236" fill="#9a3412" font-family="Arial, sans-serif" font-size="25" font-weight="700">3. Readiness</text>
<text x="636" y="272" fill="#102a43" font-family="Arial, sans-serif" font-size="19">Что увидел user?</text>
<text x="636" y="300" fill="#334e68" font-family="Arial, sans-serif" font-size="17">terminal state,</text>
<text x="636" y="324" fill="#334e68" font-family="Arial, sans-serif" font-size="17">status, итог</text>
<text x="636" y="365" fill="#9f1239" font-family="Arial, sans-serif" font-size="16" font-weight="700">Не доказывает:</text>
<text x="636" y="385" fill="#9f1239" font-family="Arial, sans-serif" font-size="15">selector was valid</text>
</g>
<g>
<rect x="880" y="190" width="230" height="205" rx="18" fill="#eef2ff" stroke="#4f46e5" stroke-width="3"/>
<text x="906" y="236" fill="#3730a3" font-family="Arial, sans-serif" font-size="25" font-weight="700">4. Retry</text>
<text x="906" y="272" fill="#102a43" font-family="Arial, sans-serif" font-size="19">Что сделал runner?</text>
<text x="906" y="300" fill="#334e68" font-family="Arial, sans-serif" font-size="17">initial / retry</text>
<text x="906" y="324" fill="#334e68" font-family="Arial, sans-serif" font-size="17">outcome, worker</text>
<text x="906" y="365" fill="#9f1239" font-family="Arial, sans-serif" font-size="16" font-weight="700">Не доказывает:</text>
<text x="906" y="385" fill="#9f1239" font-family="Arial, sans-serif" font-size="15">root cause</text>
</g>
<path d="M185 414 L185 477" stroke="#9fb3c8" stroke-width="4" stroke-dasharray="8 8" marker-end="url(#down)"/>
<path d="M455 414 L455 477" stroke="#9fb3c8" stroke-width="4" stroke-dasharray="8 8" marker-end="url(#down)"/>
<path d="M725 414 L725 477" stroke="#9fb3c8" stroke-width="4" stroke-dasharray="8 8" marker-end="url(#down)"/>
<path d="M995 414 L995 477" stroke="#9fb3c8" stroke-width="4" stroke-dasharray="8 8" marker-end="url(#down)"/>
<rect x="70" y="493" width="1040" height="132" rx="18" fill="#f5f3ff" stroke="#7c3aed" stroke-width="3"/>
<text x="102" y="538" fill="#5b21b6" font-family="Arial, sans-serif" font-size="26" font-weight="700">Evidence принадлежит попытке, а не всей истории</text>
<text x="102" y="574" fill="#334e68" font-family="Arial, sans-serif" font-size="20">Trace, snapshot и action log отвечают на один вопрос конкретного запуска.</text>
<text x="102" y="602" fill="#334e68" font-family="Arial, sans-serif" font-size="20">Если evidence записан on-first-retry, он не заменяет контекст initial failure.</text>
<rect x="70" y="671" width="1040" height="72" rx="16" fill="#102a43"/>
<text x="103" y="715" fill="#ffffff" font-family="Arial, sans-serif" font-size="23" font-weight="700">Правка меняет один слой: locator, readiness, test data или evidence policy. Не все сразу.</text>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB