<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 20:04:07 UTC","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="VRA5W3_1RUpRueisR1vIeLs_5YIyuW1F85l0WDfrhXO6wfJsjYvoKuf6zDRLVDgPezbIKDqOk-dOee4MZexiHQ";gon.locale="ru";gon.language="ru";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLSeibfGq-KvWQ2Fyru-zkFFRVTLBuzXAHAoEyN1p49FtDmNoNA";
//]]>
</script>
<meta charset="utf-8">
<title>Виды тестирования | Введение в тестирование веб-приложений</title>
<meta name="description" content="Виды тестирования / Введение в тестирование веб-приложений: Знакомимся с функциональным и UI-тестированием">
<link rel="canonical" href="https://ru.hexlet.io/courses/web-testing-basics/lessons/types-of-testing/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Виды тестирования">
<meta property="og:title" content="Введение в тестирование веб-приложений">
<meta property="og:description" content="Виды тестирования / Введение в тестирование веб-приложений: Знакомимся с функциональным и UI-тестированием">
<meta property="og:url" content="https://ru.hexlet.io/courses/web-testing-basics/lessons/types-of-testing/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="6ZgqD5rllpIBeL5oT4lczGQS233Sjrx3MECTOdpHQaUGSeE4aJs78rc7mvBDhqy7pBv219q5QtWNoAltiECmyw" />
<script src="/vite/assets/inertia-DfXos102.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-BrRXra1y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-cb8xch9l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzk1MCwicHVyIjoiYmxvYl9pZCJ9fQ==--4a16fe638654fb8d5ae09d7e8ab8e16ff228214f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Bug%20fixing-amico.png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzkyOCwicHVyIjoiYmxvYl9pZCJ9fQ==--f60f9dfdd11bed62e5573394ea442764a862e2c8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Mobile%20testing-bro.png"/><link rel="preload" as="image" href="/vite/assets/development-BVihs_d5.png"/><div id="app" data-page="{"component":"web/courses/lessons/theory_unit","props":{"errors":{},"locale":"ru","language":"ru","httpsHost":"https://ru.hexlet.io","host":"ru.hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26T20:04:06.844Z","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":"88d071f1d3384eb4bd1deb37910235c7","formAuthToken":"ybfM6DKauTEifGAXV-otwvB3enXP1K_ndfAS8r_k7OkmZgffwOQUUZQ_RI9b5d21MH5X38fjUUXIEIim7eMLhw","topics":[{"id":88127,"title":"Пункты:\n- Выбор категории товаров в фильтре содержит список: «Транспорт», «Электроника», «Одежда», «Развлечения», «Инструменты»\n- Выбор категории товаров в фильтре позволяет задать пустое значение\n\nне противоречат друг другу? потому что я как раз первый пункт не включила в ответ из-за того, что есть еще пустое поле","plain_title":"Пункты: - Выбор категории товаров в фильтре содержит список: «Транспорт», «Электроника», «Одежда», «Развлечения», «Инструменты» - Выбор категории товаров в фильтре позволяет задать пустое значение не противоречат друг другу? потому что я как раз первый пункт не включила в ответ из-за того, что есть еще пустое поле ","creator":{"public_name":"Vera","id":365627,"is_tutor":false},"comments":[{"creator":{"public_name":"Vera","id":365627,"is_tutor":false},"id":176243,"body":"Спасибо, Иван","topic_id":88127},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":176209,"body":"**Vera**, представьте, что вы сначала отфильтровали товары по цене и категории (например \"транспорт\"), а затем решили посмотреть все товары по цене (без выбора определенной категории). Если бы не было пустого поля, то вы бы физически не могли бы сделать такую выборку, и всегда по умолчанию в каждом списке было бы какое-то значение. Поэтому в подобные списки принято добавлять пустой выбор, чтобы можно было отключать этот критерий поиска.\n\nНу и в целом эти пункты не противоречат друг другу, один список может содержать другой список. Эти пункты дополняют информацию о том, как должен выглядеть выбор категории в фильтре.","topic_id":88127}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":88559,"title":"На странице товаров, весь интерфейс помещается в экран. Форма добавления всегда видна. Если товаров слишком много, то появляется прокрутка товаров в списке товаров\n\nПро какую прокрутку товаров в списке товаров имеется ввиду? Там про справа имеется ввиду который ползунок? ","plain_title":"На странице товаров, весь интерфейс помещается в экран. Форма добавления всегда видна. Если товаров слишком много, то появляется прокрутка товаров в списке товаров Про какую прокрутку товаров в списке товаров имеется ввиду? Там про справа имеется ввиду который ползунок? ","creator":{"public_name":"Иван Григорьев","id":492405,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":176848,"body":"**Иван Григорьев**, да, имеется ввиду ползунок, с помощью которого можно прокрутить список.","topic_id":88559}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":87031,"title":"Здравствуйте, почему не соблюдается требование:\nЕсли поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\n\nЕсли я оставляю пустыми название и цену, то у меня фильтруется только по категории, цена и название не участвует в фильтрации.","plain_title":"Здравствуйте, почему не соблюдается требование: Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации Если я оставляю пустыми название и цену, то у меня фильтруется только по категории, цена и название не участвует в фильтрации. ","creator":{"public_name":"Lisa","id":593310,"is_tutor":false},"comments":[{"creator":{"public_name":"Николай Рябинин","id":619985,"is_tutor":false},"id":175749,"body":"**Ivan Gagarinov**, \nсоглашусь с Lisa. На мой взгляд, требование : Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации - соблюдается.\nВы советуете : Попробуйте сначала отфильтровать со значением, а затем с пустым полем.\n\nОК. Фильтруем по цене - 50. Получаем Ножницы, Носки, Молоток, Отвёртка.\n\nФильтруем по категории: Инструменты. Получаем: Ножницы, Молоток, Отвёртка.\n\nФильтруем по имени: Ножницы. Получаем: Ножницы.\n\nОчищаем поле Название. Жмём Отфильтровать. Получаем: Ножницы, Молоток, Отвёртка.\n\nОчищаем поле Категория. Остаётся только цена 50. Получаем: Ножницы, Носки, Молоток, Отвёртка.\n\nТребование работает.","topic_id":87031},{"creator":{"public_name":"Николай Рябинин","id":619985,"is_tutor":false},"id":175836,"body":"**Ivan Gagarinov**, да, теперь попытка отфильтровать что-нибудь после очистки одного из полей фильтра приводит к появлению пустого списка, как будто этим полем мы фильтруем по несуществующему значению. \nСугубо ИМХО, исходя из того, что требование : **Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации** - не должно соблюдаться, логичнее было бы оставить на экране предыдущий отфильтрованный список, как если бы очистка не сработала. ","topic_id":87031},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":175786,"body":"**Николай Рябинин**, здравствуйте. В упражнении были исправления, и по ошибке это поведение было исправлено. Я вернул как было. Сделайте, пожалуйста, сброс упражнения и проверьте еще раз работу фильтра.","topic_id":87031},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":175940,"body":"**Николай Рябинин**, баги, которые используются в уроках — это не просто баги, взятые с потолка. Это реальные баги, с которыми мы сталкиваемся на своей практике. Довольно часто в коде может быть такая ошибка, что при выборе пустого элемента в списке, в фильтр записывается пустая строка. В итоге, этот параметр участвует в фильтрации списка и пропускает только пустые строки.","topic_id":87031},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":174585,"body":"**Lisa**, здравствуйте. Попробуйте сначала отфильтровать со значением, а затем с пустым полем.","topic_id":87031}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":81693,"title":"Здравствуйте, подскажите что не так, почему тест не проходит, уже много разных вариантов пробовала, на данный момент он выглядит так:\n\n1) Фильтр позволяет отфильтровать товары по нескольким значениям одновременно: имя, категория, цена\n2) Форма фильтра сбрасывается по кнопке сброса без перезагрузки страницы\n3) Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\n4) Выбор категории товаров в фильтре содержит список: «Транспорт», «Электроника», «Одежда», «Развлечения», «Инструменты»\n5) Выбор категории товаров в фильтре позволяет задать пустое значение\n\n\nВ чем здесь ошибка?\nСпасибо","plain_title":"Здравствуйте, подскажите что не так, почему тест не проходит, уже много разных вариантов пробовала, на данный момент он выглядит так: 1) Фильтр позволяет отфильтровать товары по нескольким значениям одновременно: имя, категория, цена 2) Форма фильтра сбрасывается по кнопке сброса без перезагрузки страницы 3) Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации 4) Выбор категории товаров в фильтре содержит список: «Транспорт», «Электроника», «Одежда», «Развлечения», «Инструменты» 5) Выбор категории товаров в фильтре позволяет задать пустое значение В чем здесь ошибка? Спасибо ","creator":{"public_name":"Елена Резанова","id":441183,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":166945,"body":"**Елена**, здравствуйте. Напишите пожалуйста своему наставнику в группе с просьбой помочь вам. Очень важно, чтобы вы понимали как тестировать каждый пункт и что он означает. Наставник может подробно вам объяснить. Например, сброс формы фильтра без перезагрузки страницы, чем он отличается от сброса с перезагрузкой, и как их различить? ","topic_id":81693}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":89271,"title":"Застряла на этом задании. Не особа ясна формулировка :\n1. Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации - что значит очищается? когда мы просто оставляем одно из полей пустым? Если так, то тест должен сработать, потому что этот параметр не участвует в фильтрации\n2. В редактировании товара отображается список с категориями - список отображается, но он пустой, как понять что тут имеется в виду?\n3. В редактировании товара сохраняются новые значения: имя товара, новая категория, новая цена - новые значения сохраняются, но опять же список категорий не отображается, как это понять?","plain_title":"Застряла на этом задании. Не особа ясна формулировка : 1. Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации - что значит очищается? когда мы просто оставляем одно из полей пустым? Если так, то тест должен сработать, потому что этот параметр не участвует в фильтрации 2. В редактировании товара отображается список с категориями - список отображается, но он пустой, как понять что тут имеется в виду? 3. В редактировании товара сохраняются новые значения: имя товара, новая категория, новая цена - новые значения сохраняются, но опять же список категорий не отображается, как это понять? ","creator":{"public_name":"Марина Клыкова","id":543318,"is_tutor":false},"comments":[{"creator":{"public_name":"Марина Клыкова","id":543318,"is_tutor":false},"id":178018,"body":"**Ivan Gagarinov**, Здравствуйте! Это требование не должно выполняться - \"Фильтр позволяет отфильтровать товары по нескольким значениям одновременно: имя, категория, цена\" - т.к. отсутствует значение ИМЯ, есть НАЗВАНИЕ. А в задании тест срабатывает.","topic_id":89271},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":178025,"body":"**Марина Клыкова**, здравствуйте. Это одно и тоже. Я поправил текст. Спасибо, что обратили на это внимание.","topic_id":89271},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":177863,"body":"**Марина Клыкова**, \n\n1. Да, если поле пустое (нет значения), то параметр не должен участвовать в фильтрации.\n2. Имеется ввиду, что список отображается и заполнен значениями категорий\n3. Убрал этот пункт, чтобы он не вызывал проблем из-за списка категорий","topic_id":89271},{"creator":{"public_name":"Марина Клыкова","id":543318,"is_tutor":false},"id":177875,"body":"У меня всеравно не срабатывают тесты, не могу понять где ошибка? \n\n1.На странице товаров, весь интерфейс помещается в экран. Форма добавления всегда видна. Если товаров слишком много, то появляется прокрутка товаров в списке товаров. - это требование полностью выполняется, тест должен сработать (+)\n2. Все элементы фильтра расположены в один ряд, кнопки выровнены по полям ввода - требование не выполнено, кнопки Очистить фильтр и отфильтровать не выравнены (-)\n3. Фильтр позволяет отфильтровать товары по нескольким значениям одновременно: имя, категория, цена - не верно, первое значение не Имя, а Название (-)\n4. Форма фильтра сбрасывается по кнопке сброса без перезагрузки страницы - не верно, есть перезагрузка если зайти в Девтулс (-)\n5. Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации - верно (+)\n6. Выбор категории товаров в фильтре содержит список: «Транспорт», «Электроника», «Одежда», «Развлечения», «Инструменты» - соответствует (+)\n7. Выбор категории товаров в фильтре позволяет задать пустое значение - позволяет (+)\n8. В редактировании товара отображается список с категориями - список не отображается (-)","topic_id":89271},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":177898,"body":"**Марина Клыкова**, обычно мы здесь не даем правильных ответов и не делаем ревью ваших решений. Для ревью у нас есть план обучения с наставником. В вашем ответе есть ошибки. Например, первый пункт не соблюдается, так как форма добавления не всегда видна, хоть полоса прокрутки и есть. Вы можете пропустить задание или посмотреть подсказку. В этом нет ничего плохого. Главное полученные знания и опыт.","topic_id":89271}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":87803,"title":"Требование \"Фильтр позволяет отфильтровать товары по нескольким значениям одновременно: имя, категория, цена\" не выполняется. Нет фильтрации (выбора) по имени и цене. А в ответ входит?","plain_title":"Требование \"Фильтр позволяет отфильтровать товары по нескольким значениям одновременно: имя, категория, цена\" не выполняется. Нет фильтрации (выбора) по имени и цене. А в ответ входит? ","creator":{"public_name":"Петр","id":618081,"is_tutor":false},"comments":[{"creator":{"public_name":"Николай Рябинин","id":619985,"is_tutor":false},"id":175750,"body":"**Петр**, проверил, у меня сейчас фильтр по нескольким значениям одновременно работает .","topic_id":87803},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":175730,"body":"**Петр**, фильтр должен работать с выбором имени и цены. Если это не так, напишите, пожалуйста, я проверю в чем дело.","topic_id":87803},{"creator":{"public_name":"Петр","id":618081,"is_tutor":false},"id":175753,"body":"Всё проверил. Работает. Спасибо.","topic_id":87803},{"creator":{"public_name":"Сергей","id":659228,"is_tutor":false},"id":180382,"body":"**Ivan Gagarinov**, Здравствуйте, у меня такая проблема сейчас, нельзя сделать фильтр по цене и названию.\nhttps://ru.hexlet.io/code_reviews/1105922","topic_id":87803},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":180393,"body":"**Сергей**, здравствуйте. Проверил, все работает. Проверьте, что правильно все вводите. Лучше задавать вопрос в новом топике, так как здесь идет обсуждение вопроса Петра. Так ваш вопрос не потеряется.","topic_id":87803}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":91698,"title":"Не очень понимаю формулировку\n\nВыбор категории товаров в фильтре содержит список: «Транспорт», «Электроника», «Одежда», «Развлечения», «Инструменты»\n\nЯ не согласна с этим утверждением, потому что в списке есть еще пустой вариант ответа ","plain_title":"Не очень понимаю формулировку Выбор категории товаров в фильтре содержит список: «Транспорт», «Электроника», «Одежда», «Развлечения», «Инструменты» Я не согласна с этим утверждением, потому что в списке есть еще пустой вариант ответа ","creator":{"public_name":"Екатерина","id":681882,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":181216,"body":"**Екатерина**, пустой вариант нужен для того, чтобы сбросить фильтр. Иначе работа фильтра была бы сломана и всегда приходилось бы выбирать какую-то категорию товара. Плюс еще есть дополнительный пункт, что выбор категории позволяет задать пустой вариант.","topic_id":91698}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":92545,"title":"Требование 5 - \"Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\" - выполняется, но почему то его нет в правильном решении.","plain_title":"Требование 5 - \"Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\" - выполняется, но почему то его нет в правильном решении. ","creator":{"public_name":"Ульяна Лесная","id":661592,"is_tutor":false},"comments":[{"creator":{"public_name":"Olga Pejenkova","id":364375,"is_tutor":true},"id":182463,"body":"**Ульяна Лесная**, \n\nвы правильно подметили, это упражнение было обновлено, сделайте, пожалуйста, сброс, чтобы изменения стали для вас доступными.","topic_id":92545}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":93402,"title":"Формулировка: \"Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\". \nДумаю, что эта строка не корректная для правильного решения. Или написана не грамотно. Из-за нее не удалось решить задание! \nНапример, в фильтре я не указываю цену (пустое значение), в выдаче я все равно получу табличку с полями Название и Цена! ","plain_title":"Формулировка: \"Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\". Думаю, что эта строка не корректная для правильного решения. Или написана не грамотно. Из-за нее не удалось решить задание! Например, в фильтре я не указываю цену (пустое значение), в выдаче я все равно получу табличку с полями Название и Цена! ","creator":{"public_name":"Victor","id":467044,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":183493,"body":"**Vic**, здравствуйте. В таблице выводятся все поля, независимо от используемых фильтров. Установка фильтра никак не меняет на отображаемые столбцы в таблице, в задании нет такого требования.","topic_id":93402},{"creator":{"public_name":"Victor","id":467044,"is_tutor":false},"id":183517,"body":"Вы не поняли меня, правильная строчка \"Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\" (посмотрел ее в подсказке) сообщает нам, что поле, которое пустое не участвует в фильтрации. А итоговая таблица включает это поле в результатах, тогда разъясните как понимать эту строку (в ответе)?","topic_id":93402},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":183520,"body":"**Vic**, если вы указываете какое-то значение в поле, то происходит фильтрация по этому значению (и по другим, если другие поля тоже заполнены). Если поле пустое, то оно перестает участвовать в фильтрации, фильтр по этому полю отключен. Это значит, что в итоговой выборке будут элементы с любым значением в этом критерии.","topic_id":93402},{"creator":{"public_name":"Victor","id":467044,"is_tutor":false},"id":183525,"body":"\"Если поле пустое, то оно перестает участвовать в фильтрации, фильтр по этому полю отключен.\" И как же это определить, что поле не участвует, когда итоговая картина другая?","topic_id":93402},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":183530,"body":"**Vic**, не совсем понял что значит \"картина другая\". Какая должна быть? Вы можете отфильтровать по какому-то критерию, а затем очистить поле. В первом случае должен быть список, в котором совпадает поле, а во втором с любыми значениями, это значит, что критерий не участвует в фильтрации. Типичные случаи ошибок, когда поле продолжает участвовать в фильтрации, а пустое значение расценивается как пустая строка. Из-за этого фильтр проходят только те элементы, у которых это свойство равно пустой строке. То есть получается, что критерий продолжает участвовать в фильтрации, если значение в поле было удалено.","topic_id":93402},{"creator":{"public_name":"Victor","id":467044,"is_tutor":false},"id":183540,"body":"Иван, ну Вы вопрос-то читаете (выше), как я должен понять, что поле не участвует в фильтрации? Наверное, как минимум это поле должно быть неактивным (бледнее по цвету или т.п. )? Такого нет в примере.","topic_id":93402},{"creator":{"public_name":"Victor","id":467044,"is_tutor":false},"id":183581,"body":"**Ivan Gagarinov**, ну, значит такая формулировка мне не понятна, перемудрили)","topic_id":93402},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":183541,"body":"**Vic**, я прочитал ваш вопрос и ответил, объяснил вам как это проверить. Попробуйте проверить этот же функционал на любом другом сайте, например, в яндекс-маркете. В фильтрах выбираете например цену, указываете максимальную цену, выше которой не должны выводиться товары. Как вы проверите, что работает удаление этого фильтра? Точно так же, удаляете максимальную цену, оставляете пустое поле, вам показываются снова все товары. Ни о каких неактивных полях или другом цвете речи не идет. Единственный критерий — это что поле должно быть пустое. Если поле пустое, значит этот критерий отключен в фильтрации.","topic_id":93402},{"creator":{"public_name":"Victor","id":467044,"is_tutor":false},"id":183582,"body":"**Ivan Gagarinov**, и как теперь это задание сделать пройденным?","topic_id":93402}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}},{"id":94927,"title":"Цитата из теории: \"При автоматическом тестировании все тесты — это скрипты, которые пишут разработчики.\"\nМожно ли считать тестировщиков, которые пишут автотесты, разработчиками?\nИли в теории при объяснении автоматического тестирования что-то упущено?","plain_title":"Цитата из теории: \"При автоматическом тестировании все тесты — это скрипты, которые пишут разработчики.\" Можно ли считать тестировщиков, которые пишут автотесты, разработчиками? Или в теории при объяснении автоматического тестирования что-то упущено? ","creator":{"public_name":"Xenia Plotnikova","id":286300,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":185453,"body":"**Xenia Plotnikova**, здравствуйте. В целом да, можно считать такого тестировщика разработчиком. По сути такому тестировщику необходимо знать и использовать язык программирования.","topic_id":94927}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Виды тестирования","entity_url":null,"active":true}}],"lesson":{"exercise":{"id":2127,"slug":"web_testing_basics_types_of_testing_exercise","name":null,"state":"active","kind":"exercise","language":"javascript","locale":"ru","has_web_view":true,"has_test_view":false,"reviewable":true,"readme":"В этом задании вы продолжите тестировать SPA-приложение с каталогом товаров. В приложении добавлен фильтр. Каждый товар теперь относится к определенной категории. Фильтр позволяет выбрать товары по имени, категории товара и цене товара.\n\nПриложение должно соответствовать нескольким требованиям:\n\n* На странице товаров, весь интерфейс помещается в экран. Формы добавления и фильтра всегда видны. Если товаров слишком много, то появляется прокрутка товаров в списке товаров вместо прокрутки всей страницы\n* Все элементы фильтра расположены в один ряд, кнопки выровнены по полям ввода\n* Фильтр позволяет отфильтровать товары по нескольким значениям одновременно: название, категория, цена\n* Форма фильтра сбрасывается по кнопке сброса без перезагрузки страницы\n* Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\n* Выбор категории товаров в фильтре содержит список: \"Транспорт\", \"Электроника\", \"Одежда\", \"Развлечения\", \"Инструменты\"\n* Выбор категории товаров в фильтре позволяет задать пустое значение\n* В редактировании товара отображается список с категориями\n\n## solution\n\nЗапишите в файл _solution_ все требования, которые соблюдаются. Помните, что одно различие — одна строчка. Сохраняйте заглавные буквы и кавычки. Самый простой способ — скопировать правильные варианты в файл.\n\nПример файла с решением:\n\n```\nНа странице товаров весь интерфейс помещается в экран. Если товаров слишком много, то появляется прокрутка товаров\nВсе элементы фильтра расположены в один ряд, кнопки выровнены по полям ввода\n```\n","prepared_readme":"В этом задании вы продолжите тестировать SPA-приложение с каталогом товаров. В приложении добавлен фильтр. Каждый товар теперь относится к определенной категории. Фильтр позволяет выбрать товары по имени, категории товара и цене товара.\n\nПриложение должно соответствовать нескольким требованиям:\n\n* На странице товаров, весь интерфейс помещается в экран. Формы добавления и фильтра всегда видны. Если товаров слишком много, то появляется прокрутка товаров в списке товаров вместо прокрутки всей страницы\n* Все элементы фильтра расположены в один ряд, кнопки выровнены по полям ввода\n* Фильтр позволяет отфильтровать товары по нескольким значениям одновременно: название, категория, цена\n* Форма фильтра сбрасывается по кнопке сброса без перезагрузки страницы\n* Если поле фильтра очищается (устанавливается пустое значение), то этот параметр не участвует в фильтрации\n* Выбор категории товаров в фильтре содержит список: \"Транспорт\", \"Электроника\", \"Одежда\", \"Развлечения\", \"Инструменты\"\n* Выбор категории товаров в фильтре позволяет задать пустое значение\n* В редактировании товара отображается список с категориями\n\n## solution\n\nЗапишите в файл _solution_ все требования, которые соблюдаются. Помните, что одно различие — одна строчка. Сохраняйте заглавные буквы и кавычки. Самый простой способ — скопировать правильные варианты в файл.\n\nПример файла с решением:\n\n```\nНа странице товаров весь интерфейс помещается в экран. Если товаров слишком много, то появляется прокрутка товаров\nВсе элементы фильтра расположены в один ряд, кнопки выровнены по полям ввода\n```\n","has_solution":true,"entity_name":"Виды тестирования"},"units":[{"id":7271,"name":"theory","url":"/courses/web-testing-basics/lessons/types-of-testing/theory_unit"},{"id":7518,"name":"quiz","url":"/courses/web-testing-basics/lessons/types-of-testing/quiz_unit"},{"id":7384,"name":"exercise","url":"/courses/web-testing-basics/lessons/types-of-testing/exercise_unit"}],"links":[],"ordered_units":[{"id":7271,"name":"theory","url":"/courses/web-testing-basics/lessons/types-of-testing/theory_unit"},{"id":7518,"name":"quiz","url":"/courses/web-testing-basics/lessons/types-of-testing/quiz_unit"},{"id":7384,"name":"exercise","url":"/courses/web-testing-basics/lessons/types-of-testing/exercise_unit"}],"id":3267,"slug":"types-of-testing","state":"approved","name":"Виды тестирования","course_order":900,"goal":"Знакомимся с функциональным и UI-тестированием","self_study":null,"theory_video_provider":"vimeo","theory_video_uid":"774794877","theory":"В процессе изучения темы тестирования вы будете сталкиваться с различными вариациями проведения тестов:\n\n\n\nЭтот список охватывает широкий спектр разных вариаций и подвариаций тестирования. Их не нужно знать все. Также не нужно уметь тестировать по каждому из этих вариантов. Но чтобы понимать других разработчиков, важно знать основные термины, которые встречаются в профессии.\n\nВ этом уроке мы разберем основные типы тестирования и постараемся отделить разные виды друг от друга. В рамках одного урока сложно описать каждый вид, поэтому остановимся на самых базовых понятиях:\n\n* Функциональное и нефункциональное тестирование\n* Статическое и динамическое тестирование\n* Ручное и автоматизированное тестирование\n\n## Функциональное и нефункциональное тестирование\n\nПредставим, что мы стали тестировщиком на Хекслете. Нам поставили задачу протестировать страницу с теорией уроков. Такую же страницу, на которой мы сейчас находимся.\n\nРассмотрим, что стоит протестировать на странице:\n\n1. Страница загрузилась, и теория появилась на странице\n2. Кнопка «Далее» отправляет на упражнение, квиз или следующий урок\n3. Кнопки «Домой» и «Навигация» выполняют свою функцию\n4. Со страницы можно переключиться в обсуждение и обратно\n5. При нажатии на «Сложности и вопросы?» появляется модальное окно\n\nЭти действия — проверка работоспособности всех функций страницы: от загрузки текста теории до появления вспомогательных окон. Так мы проверим функционал страницы.\n\nТакое тестирование называется **функциональным**. Его задача — проверить работоспособность всех функций страниц: от ссылок до правильной работы интегрированных решений от других компаний, которые используются на сайте.\n\nФункциональное тестирование не учитывает удобство, дизайн, верстку, защищенность. Проверяется только работоспособность функционала приложения, исходя из заявленных требований. Например:\n\n* Функциональное тестирование машины — машина доедет из пункта «А» в пункт «Б»\n* Функциональное тестирование чайника — он нагреет воду до заданного количества градусов\n* Функциональное тестирование колонки — она воспроизводит звук в заданном диапазоне\n\nЧасто функциональное тестирование проводится с помощью автоматизированных тестов — специальных программ, которые пишут разработчики и запускают в процессе разработки. Подробнее про автоматическое тестирование мы поговорим позже.\n\nКогда основной функционал страницы протестирован, начинается этап **нефункционального** тестирования — проверка удобства и качества приложения.\n\nВ процессе изучения этого курса мы много раз сталкивались с нефункциональным тестированием, например:\n\n* Проверка корректной адаптивности страницы\n* Проверка мультиязычности\n* Проверка безопасности полей ввода\n\nЭти тесты не влияют на функционал продукта, но являются их неотъемлемой частью. Если выделить категории, то нефункциональное тестирование рассматривает:\n\n* Удобство использования\n* Корректную работу в разном окружении: операционные системы, браузеры, разные модели телефонов\n* Защищенность приложения\n* Производительность приложения\n\nВсе тесты, которые проводились выше, называются динамическими. Разберем, что это такое, и как они отличаются от статичных тестов.\n\n## Статическое и динамическое тестирование\n\nВ прошлом разделе все тесты назывались **динамическими** — тесты, которые выполняются на запущенном проекте. В случае с Хекслетом — на работающем сайте. Этот сайт находится в публичном доступе, как сейчас, или на специальном сервере. Доступ к этому серверу имеют только разработчики.\n\nВ противовес динамическому тестированию существует **статическое**. Его цель — проверка написанного кода без запуска приложения. В этот момент изучаются технические требования — код проверяется на явные логические ошибки. Это похоже на то, как наставники дают код-ревью и проверяют написанный студентами код.\n\nДинамическое и статическое тестирование может проводиться в автоматическом и ручном режимах. Рассмотрим эти виды тестирования подробнее.\n\n## Автоматическое и ручное тестирование\n\nПри прохождении этого курса мы просили открывать страницы и проверять их по разным пунктам: от проверки адаптивности до работы с безопасностью. Эти процессы делались непосредственно вами, то есть выполнялось **ручное** тестирование. А ответы в упражнениях проверялись с помощью скрипта без участия человека. Такое тестирование называется **автоматическим**.\n\nРассмотрим подробнее оба вида тестирования и их отличия друг от друга.\n\nРучным называется тестирование, при котором тестировщик вручную проверяет функционал страницы по заранее определенному техническому заданию. При таком типе тестирования тестировщик обычно проверяет участки, которые сложно проверить при автоматическом тестировании:\n\n* Пользовательский интерфейс\n* Удобство использования\n* Проверка различных типов поведения пользователя\n\nПри этом тестировщик может найти новые баги, которые не нашлись в процессе автоматического тестирования.\n\nВ ручном тестировании участвует человек, который подвержен внешним факторам: настроение, самочувствие, физическое состояние. Один и тот же сценарий ручного тестирования может различаться из-за этих факторов, что приведет к нахождению новых багов.\n\nНапример, мы тестируем кнопку заказа товара. В обычных сценариях мы вводим данные и нажимаем на кнопку «Заказать». Но нас могут отвлечь. За это время сайт может «выкинуть» нас из корзины и сбросить весь заказ из-за ошибки в коде. Так будет найден новый баг. Этот пример показывает, как человеческий фактор играет роль в тестировании.\n\nПри автоматическом тестировании все действия и ожидаемый результат записываются заранее. Например, разработчик создал калькулятор и проверяет, что выражение `2 + 2 * 2` вернет `6`, а не `8`. Он пишет тест вида:\n\n```javascript\nexpect(calc('2 + 2 * 2')).toBe(6)\n```\n\nПри каждом запуске тестов скрипт будет проверять, что пример возвращает `6` и логика работы не нарушена. Таких тестов может быть сотни. Зачастую они запускаются, когда создается новый функционал или выкладывается новая версия. Это гарантирует, что новые изменения не сломали уже работающий функционал.\n\nАвтоматическое тестирование не может заменить ручное. Последнее может быть полезным при проверке пользовательского интерфейса, а также при проверке сложных функций программы. Еще ручное тестирование может помочь выявить ошибки, которые могут быть упущены при автоматическом тестировании.\n\n## Выводы\n\nТестирование включает в себя широкий спектр задач и подзадач, для которых требуются специалисты разных уровней и подготовки. Среди всех видов тестирования можно выделить несколько базовых групп:\n\n* Функциональное и нефункциональное тестирование\n* Статическое и динамическое тестирование\n* Ручное и автоматизированное тестирование\n\nФункциональное тестирование направлено на тестирование заявленного функционала приложения. А нефункциональное тестирование направлено на тестирование вторичных вещей: удобство и качество.\n\nВ зависимости от того, где тестируется приложение, разделяют два вида тестов: статические и динамические. Динамические тесты используются на работающем приложении, а статические — определяют качество написанного кода и отсутствие логических ошибок в нем.\n\nПочти все тесты можно сделать в автоматическом или ручном режиме. При ручном тестировании за тестирование отвечает специалист, который самостоятельно проверяет приложение по разным критериям. При автоматическом тестировании все тесты — это скрипты, которые пишут разработчики. После этого роль человека заканчивается и тесты проверяют всё автоматически.\n\nЭти типы тестирования не могут заменить друг друга, а происходят параллельно. Это позволяет протестировать все области приложения в разных сценариях.\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":7261,"name":"theory","url":"/courses/web-testing-basics/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":7261,"name":"theory","url":"/courses/web-testing-basics/lessons/intro/theory_unit"}],"id":3262,"slug":"intro","state":"approved","name":"Введение","course_order":60,"goal":"Знакомимся с темой курса","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"В этом курсе мы поговорим о ручном тестировании: из чего оно состоит, какие инструменты используются и на что обращать внимание при тестировании.\n\nНесмотря на то, что курс является вводным, он полезен как для разработчиков, так и для новичков:\n\n* **Новичкам в тестировании** — познакомиться с основами тестирования, выяснить, из чего оно состоит, и какие аспекты приложения или сайта требует\n* **Начинающим разработчикам** — выявить типичные проблемы при создании сайта, которых можно избежать уже на этапе постановки задачи. Например, как ускорить загрузку сайта, как обеспечить базовую защиту от атак и так далее\n* **Кто уже тестирует** — структурировать информацию, найти новые подходы к тестированию и почерпнуть новые темы, которые пригодятся в работе\n\nПроцесс тестирования в крупных приложениях неразрывно связан с разработкой, и на это есть три причины.\n\n### Качество\n\nБольшинство проектов в интернете рассчитано на массовое использование, будь то сайт с рецептами или приложение для просмотра сериалов. Такие проекты постоянно вводят новые функции и разделы, из-за чего сложно отслеживать их работоспособность.\n\nПредставьте свои ощущения, если вместо рецепта ваших любимых кексиков откроется страница с контактами или количество ингредиентов будет рассчитываться неправильно.\n\nТак как разработчики заняты разработкой продукта, то главными героями являются тестировщики. Их задача — проверить новый функционал и убедиться, что старый работает исправно. После этого продукт можно открывать для всех пользователей.\n\n### Понятность\n\nРазработчики сделали возможность изменения языка озвучки для сериала. Для компании важно, чтобы этот функционал не просто работал, но и был доступен для понимания. Он не должен быть скрыт за кучей настроек или расположен в том месте, где его не ожидаешь.\n\nТестировщики, как фокус-группа, не просто находят технические проблемы, но и следят, чтобы функционал был понятен и прост для использования. Такая область, как понятность и удобность использования, еще называется юзабилити, от английского usability — удобство использования.\n\n### Безопасность\n\nСайт или приложение = большое количество кода. Чем больше проект и больше в нем данных, тем больше встает вопрос о безопасности. Если продукт можно взломать простыми способами, которые написаны на первой странице поисковой системы, то будьте уверены — кто-то воспользуется этим.\n\nЕсли злоумышленник получит персональные данные, то может пострадать сайт, приложение, репутация или пользователи.\n\nОдна из задач тестировщика — проверить базовые виды атак, которые можно исправить сразу. Например, добавление кода на JavaScript в поля формы.\n\n## Что изучается в курсе\n\nВ процессе прохождения курса мы изучим, что тестируют специалисты, какие используют инструменты и на что стоит обращать внимание при заходе на сайт. Также изучим:\n\n* Как проверить сайт на разных устройствах: компьютер, планшет, смартфоны\n* Почему сайт может отличаться в разных программах и устройствах\n* Из чего состоит сайт, что такое HTML и CSS\n* Какой инструмент в браузерах необходим для тестировщиков\n* С какими проблемами безопасности можно встретиться и как их выявлять\n* Какие типы тестирования существуют\n"},"id":245,"slug":"web-testing-basics","challenges_count":4,"name":"Введение в тестирование веб-приложений","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"free","description":"На этом курсе вы узнаете о веб-приложениях и изучите основы их тестирования. \nВ процессе прохождения курса мы изучим, что тестируют специалисты, какие используют инструменты и на что стоит обращать внимание при заходе на сайт. Вы узнаете, как на работоспособность веб-приложения влияет многообразие устройств, скорость соединения и другие условия. Вы познакомитесь с основами юзабилити и доступности. Вы научитесь находить уязвимости, ошибки верстки и логики работы веб-приложения. Вы научитесь диагностировать работу сайта с помощью инструментов Devtools. \nОсвоить тестирование веб-приложений с нуля непросто, поэтому с первого же урока вы будете подкреплять теорию практикой. В упражнениях курса вы будете проводить тестирование различных страниц, каталогов, форм и приложений.","kind":"basic","updated_at":"2026-01-20T11:40:26.695Z","language":"other","duration_cache":62880,"skills":["Использовать DevTools для диагностики запросов","Обнаруживать ошибки в верстке и UX приложения","Тестировать SPA-приложения","Находить уязвимости веб-приложений, например, XSS"],"keywords":[],"lessons_count":15,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjIyMSwicHVyIjoiYmxvYl9pZCJ9fQ==--23e3df9feea39eaed8d150557abd4377bc99b425/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJwbmciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--6067466c2912ca31a17eddee04b8cf2a38c6ad17/image.png"},"recommendedLandings":[{"stack":{"id":56,"slug":"qa-engineer","title":"Инженер по тестированию","audience":"for_beginners","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"finished","order":40,"duration_in_months":4},"id":100,"slug":"qa-engineer","title":"Инженер по ручному тестированию","subtitle":"Изучите виды тестирования, тест-кейсы, DevTools, Postman, SQL, Git и HTTP/HTTPS.","subtitle_for_lists":"Изучите виды тестирования, тест-кейсы, DevTools, Postman, SQL, Git и HTTP/HTTPS.","locale":"ru","current":true,"duration_in_months_text":"4 месяца","stack_slug":"qa-engineer","price_text":"от 3 368 ₽","duration_text":"4 месяца","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzk1MCwicHVyIjoiYmxvYl9pZCJ9fQ==--4a16fe638654fb8d5ae09d7e8ab8e16ff228214f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Bug%20fixing-amico.png"},{"stack":{"id":121,"slug":"testing-basics-free","title":"Основы тестирования","audience":"for_beginners","start_type":"anytime","pricing_model":"free","priority":"low","kind":"track","state":"published","stack_state":"finished","order":1000,"duration_in_months":1},"id":200,"slug":"testing-basics-free","title":"Основы тестирования","subtitle":"Изучите основы тестирование, HTML/CSS, DevTools и веб-стандарты","subtitle_for_lists":"","locale":"ru","current":true,"duration_in_months_text":"1 месяц","stack_slug":"testing-basics-free","price_text":"Бесплатно","duration_text":"1 месяц","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzkyOCwicHVyIjoiYmxvYl9pZCJ9fQ==--f60f9dfdd11bed62e5573394ea442764a862e2c8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Mobile%20testing-bro.png"}],"lessonMemberUnit":null,"accessToLearnUnitExists":true,"accessToCourseExists":true},"url":"/courses/web-testing-basics/lessons/types-of-testing/theory_unit","version":"8f286f6358a90a7bef2263b3a6edf5a90a94fa42","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Введение в тестирование веб-приложений</p></div><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size);margin-bottom:var(--mantine-spacing-xl)" class="m_8a5d1357 mantine-Title-root" data-order="1">Теория: Виды тестирования</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Виды тестирования","inLanguage":"ru","isPartOf":{"@type":"LearningResource","name":"Введение в тестирование веб-приложений"},"isAccessibleForFree":"False","hasPart":{"@type":"WebPageElement","isAccessibleForFree":"False","cssSelector":".paywalled"}}</script><div class=""><div style="--alert-color:var(--mantine-color-indigo-light-color);margin-bottom:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-lg)" class="m_66836ed3 mantine-Alert-root" id="mantine-_R_remqrdub_" role="alert" aria-describedby="mantine-_R_remqrdub_-body" aria-labelledby="mantine-_R_remqrdub_-title"><div class="m_a5d60502 mantine-Alert-wrapper"><div class="m_667f2a6a mantine-Alert-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-rocket "><path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3"></path><path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3"></path><path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg></div><div class="m_667c2793 mantine-Alert-body"><div class="m_6a03f287 mantine-Alert-title"><span id="mantine-_R_remqrdub_-title" class="m_698f4f23 mantine-Alert-label">Полный доступ к материалам</span></div><div id="mantine-_R_remqrdub_-body" class="m_7fa78076 mantine-Alert-message"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Зарегистрируйтесь и получите доступ к этому и десяткам других курсов</p><a style="--button-height:var(--button-height-xs);--button-padding-x:var(--button-padding-x-xs);--button-fz:var(--mantine-font-size-xs);--button-bg:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-hover:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-color:var(--mantine-color-white);--button-bd:none" class="mantine-focus-auto mantine-active m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root" data-variant="gradient" data-size="xs" href="/u/new"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">Зарегистрироваться</span></span></a></div></div></div></div></div><div style="margin-bottom:var(--mantine-spacing-xl)" class=""><div class="ratio ratio-16x9"><iframe width="100%" height="auto" src="//player.vimeo.com/video/774794877" loading="lazy" allowFullScreen="" title="video"></iframe></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><p>В процессе изучения темы тестирования вы будете сталкиваться с различными вариациями проведения тестов:</p>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjQ4OCwicHVyIjoiYmxvYl9pZCJ9fQ==--7f9876cafeed34aca8bb14efbd28ef4f99eaf209/testing.png" alt="Виды тестирования" loading="lazy"/></p>
<p>Этот список охватывает широкий спектр разных вариаций и подвариаций тестирования. Их не нужно знать все. Также не нужно уметь тестировать по каждому из этих вариантов. Но чтобы понимать других разработчиков, важно знать основные термины, которые встречаются в профессии.</p>
<p>В этом уроке мы разберем основные типы тестирования и постараемся отделить разные виды друг от друга. В рамках одного урока сложно описать каждый вид, поэтому остановимся на самых базовых понятиях:</p>
<ul>
<li>Функциональное и нефункциональное тестирование</li>
<li>Статическое и динамическое тестирование</li>
<li>Ручное и автоматизированное тестирование</li>
</ul>
<h2 id="heading-2-1">Функциональное и нефункциональное тестирование</h2>
<p>Представим, что мы стали тестировщиком на Хекслете. Нам поставили задачу протестировать страницу с теорией уроков. Такую же страницу, на которой мы сейчас находимся.</p>
<p>Рассмотрим, что стоит протестировать на странице:</p>
<ol>
<li>Страница загрузилась, и теория появилась на странице</li>
<li>Кнопка «Далее» отправляет на упражнение, квиз или следующий урок</li>
<li>Кнопки «Домой» и «Навигация» выполняют свою функцию</li>
<li>Со страницы можно переключиться в обсуждение и обратно</li>
<li>При нажатии на «Сложности и вопросы?» появляется модальное окно</li>
</ol>
<p>Эти действия — проверка работоспособности всех функций страницы: от загрузки текста теории до появления вспомогательных окон. Так мы проверим функционал страницы.</p>
<p>Такое тестирование называется <strong>функциональным</strong>. Его задача — проверить работоспособность всех функций страниц: от ссылок до правильной работы интегрированных решений от других компаний, которые используются на сайте.</p>
<p>Функциональное тестирование не учитывает удобство, дизайн, верстку, защищенность. Проверяется только работоспособность функционала приложения, исходя из заявленных требований. Например:</p>
<ul>
<li>Функциональное тестирование машины — машина доедет из пункта «А» в пункт «Б»</li>
<li>Функциональное тестирование чайника — он нагреет воду до заданного количества градусов</li>
<li>Функциональное тестирование колонки — она воспроизводит звук в заданном диапазоне</li>
</ul>
<p>Часто функциональное тестирование проводится с помощью автоматизированных тестов — специальных программ, которые пишут разработчики и запускают в процессе разработки. Подробнее про автоматическое тестирование мы поговорим позже.</p>
<p>Когда основной функционал страницы протестирован, начинается этап <strong>нефункционального</strong> тестирования — проверка удобства и качества приложения.</p>
<p>В процессе изучения этого курса мы много раз сталкивались с нефункциональным тестированием, например:</p>
<ul>
<li>Проверка корректной адаптивности страницы</li>
<li>Проверка мультиязычности</li>
<li>Проверка безопасности полей ввода</li>
</ul>
<p>Эти тесты не влияют на функционал продукта, но являются их неотъемлемой частью. Если выделить категории, то нефункциональное тестирование рассматривает:</p>
<ul>
<li>Удобство использования</li>
<li>Корректную работу в разном окружении: операционные системы, браузеры, разные модели телефонов</li>
<li>Защищенность приложения</li>
<li>Производительность приложения</li>
</ul>
<p>Все тесты, которые проводились выше, называются динамическими. Разберем, что это такое, и как они отличаются от статичных тестов.</p>
<h2 id="heading-2-2">Статическое и динамическое тестирование</h2>
<p>В прошлом разделе все тесты назывались <strong>динамическими</strong> — тесты, которые выполняются на запущенном проекте. В случае с Хекслетом — на работающем сайте. Этот сайт находится в публичном доступе, как сейчас, или на специальном сервере. Доступ к этому серверу имеют только разработчики.</p>
<p>В противовес динамическому тестированию существует <strong>статическое</strong>. Его цель — проверка написанного кода без запуска приложения. В этот момент изучаются технические требования — код проверяется на явные логические ошибки. Это похоже на то, как наставники дают код-ревью и проверяют написанный студентами код.</p>
<p>Динамическое и статическое тестирование может проводиться в автоматическом и ручном режимах. Рассмотрим эти виды тестирования подробнее.</p>
<h2 id="heading-2-3">Автоматическое и ручное тестирование</h2>
<p>При прохождении этого курса мы просили открывать страницы и проверять их по разным пунктам: от проверки адаптивности до работы с безопасностью. Эти процессы делались непосредственно вами, то есть выполнялось <strong>ручное</strong> тестирование. А ответы в упражнениях проверялись с помощью скрипта без участия человека. Такое тестирование называется <strong>автоматическим</strong>.</p>
<p>Рассмотрим подробнее оба вида тестирования и их отличия друг от друга.</p>
<p>Ручным называется тестирование, при котором тестировщик вручную проверяет функционал страницы по заранее определенному техническому заданию. При таком типе тестирования тестировщик обычно проверяет участки, которые сложно проверить при автоматическом тестировании:</p>
<ul>
<li>Пользовательский интерфейс</li>
<li>Удобство использования</li>
<li>Проверка различных типов поведения пользователя</li>
</ul>
<p>При этом тестировщик может найти новые баги, которые не нашлись в процессе автоматического тестирования.</p>
<p>В ручном тестировании участвует человек, который подвержен внешним факторам: настроение, самочувствие, физическое состояние. Один и тот же сценарий ручного тестирования может различаться из-за этих факторов, что приведет к нахождению новых багов.</p>
<p>Например, мы тестируем кнопку заказа товара. В обычных сценариях мы вводим данные и нажимаем на кнопку «Заказать». Но нас могут отвлечь. За это время сайт может «выкинуть» нас из корзины и сбросить весь заказ из-за ошибки в коде. Так будет найден новый баг. Этот пример показывает, как человеческий фактор играет роль в тестировании.</p>
<p>При автоматическом тестировании все действия и ожидаемый результат записываются заранее. Например, разработчик создал калькулятор и проверяет, что выражение <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">2 + 2 * 2</code> вернет <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">6</code>, а не <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">8</code>. Он пишет тест вида:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">expect(calc('2 + 2 * 2')).toBe(6)</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>При каждом запуске тестов скрипт будет проверять, что пример возвращает <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">6</code> и логика работы не нарушена. Таких тестов может быть сотни. Зачастую они запускаются, когда создается новый функционал или выкладывается новая версия. Это гарантирует, что новые изменения не сломали уже работающий функционал.</p>
<p>Автоматическое тестирование не может заменить ручное. Последнее может быть полезным при проверке пользовательского интерфейса, а также при проверке сложных функций программы. Еще ручное тестирование может помочь выявить ошибки, которые могут быть упущены при автоматическом тестировании.</p>
<h2 id="heading-2-4">Выводы</h2>
<p>Тестирование включает в себя широкий спектр задач и подзадач, для которых требуются специалисты разных уровней и подготовки. Среди всех видов тестирования можно выделить несколько базовых групп:</p>
<ul>
<li>Функциональное и нефункциональное тестирование</li>
<li>Статическое и динамическое тестирование</li>
<li>Ручное и автоматизированное тестирование</li>
</ul>
<p>Функциональное тестирование направлено на тестирование заявленного функционала приложения. А нефункциональное тестирование направлено на тестирование вторичных вещей: удобство и качество.</p>
<p>В зависимости от того, где тестируется приложение, разделяют два вида тестов: статические и динамические. Динамические тесты используются на работающем приложении, а статические — определяют качество написанного кода и отсутствие логических ошибок в нем.</p>
<p>Почти все тесты можно сделать в автоматическом или ручном режиме. При ручном тестировании за тестирование отвечает специалист, который самостоятельно проверяет приложение по разным критериям. При автоматическом тестировании все тесты — это скрипты, которые пишут разработчики. После этого роль человека заканчивается и тесты проверяют всё автоматически.</p>
<p>Эти типы тестирования не могут заменить друг друга, а происходят параллельно. Это позволяет протестировать все области приложения в разных сценариях.</p></div><div style="margin-block:var(--mantine-spacing-xl)" class=""><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md)" class="m_8a5d1357 mantine-Title-root" data-order="2">Рекомендуемые программы</h2><style data-mantine-styles="inline">.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xs);--carousel-slide-size:70%;}@media(min-width: 36em){.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xl);--carousel-slide-size:50%;}}</style><div style="--carousel-control-size:calc(2.5rem * var(--mantine-scale));--carousel-controls-offset:var(--mantine-spacing-sm);margin-bottom:var(--mantine-spacing-lg);padding-block:var(--mantine-spacing-sm);background:var(--app-color-surface)" class="m_17884d0f mantine-Carousel-root responsiveClassName" data-orientation="horizontal" data-include-gap-in-size="true"><div class="m_39bc3463 mantine-Carousel-controls" data-orientation="horizontal"><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="previous" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="next" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div><div class="m_a2dae653 mantine-Carousel-viewport" data-type="media"><div class="m_fcd81474 mantine-Carousel-container __m__-_R_2mremqrdub_" data-orientation="horizontal"><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/qa-engineer?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">4 месяца</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Инженер по ручному тестированию</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Изучите виды тестирования, тест-кейсы, DevTools, Postman, SQL, Git и HTTP/HTTPS.</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzk1MCwicHVyIjoiYmxvYl9pZCJ9fQ==--4a16fe638654fb8d5ae09d7e8ab8e16ff228214f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Bug%20fixing-amico.png" alt="Инженер по ручному тестированию" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 3 368 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/testing-basics-free?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">1 месяц</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Основы тестирования</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root"></p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzkyOCwicHVyIjoiYmxvYl9pZCJ9fQ==--f60f9dfdd11bed62e5573394ea442764a862e2c8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Mobile%20testing-bro.png" alt="Основы тестирования" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Бесплатно</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md);font-size:var(--mantine-font-size-h3)" class="m_8a5d1357 mantine-Title-root" data-order="2" data-responsive="true">Каталог</h2><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Полный список доступных курсов по разным направлениям</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="/vite/assets/development-BVihs_d5.png" alt="Orientation"/></div></div></div></a></div></div></div></div></div></div></div></div></div><style data-mantine-styles="inline">.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:8.333333333333334%;--col-max-width:8.333333333333334%;}@media(min-width: 48em){.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem" class="m_96bdd299 mantine-Grid-col __m__-_R_1bdub_"><div style="margin-inline:var(--mantine-spacing-xs)" class="mantine-visible-from-sm"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-lg);text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/web-testing-basics/lessons/types-of-testing/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label"><span style="margin-inline-end:var(--mantine-spacing-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Дальше</span>→</span></span></a><a style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Навигация по теме</span><span class="m_57492dcc mantine-NavLink-description">Теория</span></div><span class="m_690090b5 mantine-NavLink-section" data-position="right"></span></a><div style="margin-block:var(--mantine-spacing-lg)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div><div style="margin-block:var(--mantine-spacing-lg)" class=""><div style="justify-content:space-between;margin-bottom:calc(0.1875rem * var(--mantine-scale));color:var(--mantine-color-dimmed);font-size:var(--mantine-font-size-xs)" class="m_8bffd616 mantine-Flex-root __m__-_R_qimrbdub_"><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Завершено</p><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">0 / 15</p></div><div style="--progress-size:var(--progress-size-sm)" class="m_db6d6462 mantine-Progress-root" data-size="sm"><div style="--progress-section-size:0%;--progress-section-color:var(--mantine-color-gray-filled)" class="m_2242eb65 mantine-Progress-section" role="progressbar" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-valuetext="0%"></div></div></div><button style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root" type="button"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Обсуждения (архив)</span><span class="m_57492dcc mantine-NavLink-description"></span></div></button><div style="--toc-bg:var(--mantine-color-blue-light);--toc-color:var(--mantine-color-blue-light-color);--toc-size:var(--mantine-font-size-sm);--toc-radius:var(--mantine-radius-sm);margin-top:var(--mantine-spacing-xl)" class="m_bcaa9990 mantine-TableOfContents-root" data-variant="light" data-size="sm"></div></div><div class="mantine-hidden-from-sm"><div style="--stack-gap:0rem;--stack-align:stretch;--stack-justify:flex-start" class="m_6d731127 mantine-Stack-root"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-xs);padding:0rem;text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/web-testing-basics/lessons/types-of-testing/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></a><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-Bukl1lYy.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-BrRXra1y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>