Сайты, как и другие источники информации в интернете, доступны только при наличии соединения с сетью. Выражение «соединение с сетью» достаточно сложное, так как есть разница между проводным соединением в квартире и мобильным соединением посреди леса. В последнем случае оно может быть или очень слабым, или совсем отсутствовать.
При разработке сайта важно понять, как ведет себя сайт или приложение при разных скоростях соединения.
В этом уроке разберем, что нам дает понимание скорости работы интернета, насколько 4G быстрее 3G и почему уже на этапе разработки необходимо учитывать различия в скорости соединения.
Скорость соединения
Представим, что мы переехали в новую квартиру и хотим подключить интернет. Один звонок провайдеру и заявка уже открыта. При этом нам говорят, что подключат к интернету со скоростью 100 мегабит в секунду — 100Мбит/с. Это и будет нашей скоростью соединения с интернетом.
Сразу сложно сказать много это или мало, также не понятно, что значат 100Мбит/с.
В компьютерах основная единица измерения — бит. Именно из них всё состоит. Мы можем вычислить скорость в мегабайт в секунду. Для этого нужно поделить количество мегабит на восемь, так как в одном байте 8 бит. Получится, что скорость соединения равна 12.5 мегабайт в секунду.
Например, одна минута видео, которая записана в разрешении 1920x1080 или FullHD, в среднем весит 30 мегабайт. Значит, с вычисленной скоростью можно смотреть видео без прерываний. Одну минуту такого видео наш интернет способен скачать за три секунды. Поэтому 12.5 мегабайт в секунду — это хорошая скорость, которая позволяет пользоваться интернетом без задержек.
Сайты весят значительно меньше, чем одно видео. Например, главная страница Хекслета на январь 2023 года весит 11.7 мегабайт. Получается, ее можно скачать на компьютере за одну секунду при скорости интернета в 100Мбит/с.
В мобильном интернете распространены два стандарта подключения к интернету:
Сравним их по скорости соединения с интернетом:
- 3G — в зависимости от подстандарта скорость может быть 14.4Мбит/с или 42Мбит/с. Если перевести в мегабайты, то максимальная скорость составит 5.25 мегабайта в секунду. Это в два раза меньше скорости при подключении интернета в квартире из примера выше
- 4G — максимальная скорость считается 1Гбит/с (один гигабит в секунду). Но в реальности скорость сопоставима со скоростью домашнего интернета и равняется 100Мбит/с
Основная проблема показателей скорости интернета в том, что это теоретические данные. То есть можно не получить заявленную скорость по разным причинам. Например:
- Удаление от мобильной станции
- Плохая погода
- Большое количество препятствий в виде домов, машин, деревьев, на пути от станции до вашего устройства
Эти факторы могут снизить скорость соединения или отключить от интернета. Поэтому скорость соединения в городе и в лесу различаются. Приложение должно учитывать это, особенно, если оно может помочь человеку в трудной ситуации. Например: карты, приложение для вызова помощи, мессенджер и так далее.
Загрузка сайта
На примере страницы Хекслета проверим, как загружается сайт при низкой скорости интернета. В дальнейшем разберем, как самостоятельно установить разные скорости соединения для тестирования.
Загрузка страницы — сложный процесс, который включает в себя множество понятий. Им можно посвятить целый курс. По этой причине опустим технические вещи и посмотрим на сайт с точки зрения простого пользователя с плохим интернетом.
Весь процесс загрузки страницы Хекслета можно разбить на три части:
- Загрузка тела страницы. Сюда входит текст, его расположение и расположение блоков:
- Загрузка скриптов и данных, таких как шрифты:
- Загрузка визуального оформления. Изображения и так далее:
С первого шага загрузки страницы доступен весь текст, его расположение и смысловое значение. То есть, если во время загрузки пропадет соединение с интернетом, то основной посыл страницы останется доступен пользователю для изучения.
То, как будет загружаться страница, отчасти зависит от разработчиков. Если выдать пользователю всё, что есть, то видимая загрузка может остановиться в начале и появиться в конце, когда все данные будут скачаны. Это плохой вариант, так как можно оставить пользователя на некоторое время перед белым экраном.
Такой порядок загрузки возникает из-за принципов работы браузеров. В обычной ситуации они анализируют HTML сверху вниз. Во время анализа может встретиться ссылка на ресурс, например, изображение, стили или код на JavaScript. В этом случае анализ прекращается до тех пор, пока не будет обработан ресурс.
Представьте, что в начале страницы находится большой код на JavaScript. Тогда браузер не будет ничего загружать до тех пор, пока не обработает и не выполнит весь код. Это может занимать четверть секунды, а может и несколько секунд — всё зависит от сложности и объема кода.
Чтобы избежать такой блокировки загрузки, используется техника, которая называется асинхронной загрузкой. Браузер знает, что ему нужно загрузить и выполнить код, но делает это не вместо загрузки страницы, а вместе с дальнейшей загрузкой.
Именно так загрузится страница Хекслета при плохом соединении с интернетом. На самом деле и при хорошем соединении процесс не изменится, только он произойдет за очень короткое время. Мы даже не успеваем увидеть все стадии загрузки.
Тестирование скорости
В инструментах разработчика браузеров есть функция, которая позволяет эмулировать разную скорость соединения с интернетом. То есть искусственно ограничить скорость, чтобы протестировать приложение. Разберем функцию на примере инструмента разработчика в Firefox.
Чтобы открыть инструмент разработчика, нужно воспользоваться комбинацией клавиш Ctrl + Shift + I или клавишей F12. Затем нужно перейти во вкладку Network.
В этой вкладке доступно всё, что связано с загрузкой нашего проекта: тип информации, его адрес, вес и время загрузки:
Попробуйте изучить эту информацию на любом сайте.
Чтобы изменить скорость загрузки, воспользуемся выпадающим списком в правой части вкладки. По умолчанию на ней написано «No Throttling» — «Без ограничений» или «Без регулировки». Если открыть этот список, то можно увидеть предустановленные варианты для разных типов соединения:
- GPRS: 50 Кбит/с (загрузка), 20 Кбит/с (отправка), 500 мс (задержка)
- Regular 2G: 250 Кбит/с (загрузка), 50 Кбит/с (отправка), 300 мс (задержка)
- Good 2G: 450 Кбит/с (загрузка), 150 Кбит/с (отправка), 150 мс (задержка)
- Regular 3G: 750 Кбит/с (загрузка), 250 Кбит/с (отправка), 100 мс (задержка)
- Good 3G: 1.5 Мбит/с (загрузка), 750 Кбит/с (отправка), 40 мс (задержка)
- Regular 4G/LTE: 4 Мбит/с (загрузка), 3 Мбит/с (отправка), 20 мс (задержка)
- DSL: 2 Мбит/с (загрузка), 1 Мбит/с (отправка), 5 мс (задержка)
- Wi-Fi: Не имеет строго определённых параметров в DevTools по умолчанию, поскольку скорость Wi-Fi может сильно варьироваться в зависимости от спецификаций, но для эмуляции можно использовать значения, близкие к реальным условиям использования, например, 30-50 Мбит/с для загрузки и 10-30 Мбит/с для отправки, с относительно низкой задержкой.
Чтобы изменить скорость, выполните два действия:
- Выберите нужный вариант скорости соединения
- Перезагрузите страницу. Для этого можно использовать клавишу F5
Сценарий тестирования зависит от приложения и технического задания. Если это приложение помогает людям ориентироваться в пространстве или обмениваться сообщениями, то оно должно достаточно быстро работать даже при нестабильном соединен��и. Это связано с тем, что такие приложения могут использоваться в критической ситуации. К такому же принципу могут относиться банковские приложения и карты.
Если технического задания нет, то можно проверить следующие пункты:
- Страница отображает текст еще до загрузки изображений или видео
- Никакой из компонентов страницы не ругается на отсутствие соединения, если оно есть
- Отсутствуют ошибки в JavaScript, которые не появляются при обычном соединении. Это можно увидеть на вкладке Console
Выводы
В этом уроке мы узнали, что помимо корректного отображения страницы на разных устройствах важно тестировать поведение сайта или приложения при разных скоростях соединения. Скорость соединения — количество информации в секунду, которую можно получить или отправить в интернете.
Так же мы рассмотрели загрузку одной из страниц Хекслета при низкой скорости соединения. Мы выяснили, что один из главных факторов при низкой скорости — быстрая отрисовка текста и его расположения. Это позволяет даже при обрыве соединения прочитать информацию.
В качестве инструмента тестирования можно использовать инструменты разработчика. В нем есть специальная вкладка Network, которая позволяет проанализировать количество скачиваемого контента, его вес и время загрузки. Так же на этой вкладке можно установить тип соединения для тестирования соединения.
<!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 16:45:04 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="Ggnjfu1XqcFrJtEoGzrdtb3pH018ovtCm4owN-TlWnn12ChJHykEod1l9bAXNS3CfeAy53SVBeAmaqpjtuK9Fw";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="Скорость соединения / Введение в тестирование веб-приложений: Изучаем, как скорость загрузки страницы влияет на приложение">
<link rel="canonical" href="https://ru.hexlet.io/courses/web-testing-basics/lessons/connection-speed/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Скорость соединения">
<meta property="og:title" content="Введение в тестирование веб-приложений">
<meta property="og:description" content="Скорость соединения / Введение в тестирование веб-приложений: Изучаем, как скорость загрузки страницы влияет на приложение">
<meta property="og:url" content="https://ru.hexlet.io/courses/web-testing-basics/lessons/connection-speed/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="L4eqIiskFOVaUzkHmy2iVKwQBoAjbryeXaEE445HXavAVmEV2Vq5hewQHZ-XIlIjbBkrKitZQjzgQZ633EC6xQ" />
<script src="/vite/assets/inertia-INZxX8jp.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-nkZBEvfU.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-6pOtQ3OW.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-26T16:45:04.275Z","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":"XvTZJN9Vi2vYSEybb0wuqvfa6yzjC8mrGwaruuUcGE-xJRITLSsmC24LaANjQ97dN9PGhus8Nwmm5jHutxv_IQ","topics":[{"id":105473,"title":"Здравствуйте. А я решила и ответ был принят. а в навигации решение не зафиксировано","plain_title":"Здравствуйте. А я решила и ответ был принят. а в навигации решение не зафиксировано ","creator":{"public_name":"Оля","id":909134,"is_tutor":false},"comments":[{"creator":{"public_name":"Оля","id":909134,"is_tutor":false},"id":198122,"body":"Уже все хорошо ","topic_id":105473},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":198121,"body":"**Оля**, здравствуйте. Урок вообще никак не отмечен, то есть показывает, что не пройден?","topic_id":105473}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}},{"id":87167,"title":"Застряла на таком вопросе, уже наугад пытаюсь выбрать ответы.\nДля каких веб-приложений важна скорость и стабильность соединения с интернетом?\nпо теории, и по логике, это приложения, которые в критической ситуации позволяют выйти на связь... так какие же по ответам должны быть?","plain_title":"Застряла на таком вопросе, уже наугад пытаюсь выбрать ответы. Для каких веб-приложений важна скорость и стабильность соединения с интернетом? по теории, и по логике, это приложения, которые в критической ситуации позволяют выйти на связь... так какие же по ответам должны быть? ","creator":{"public_name":"Екатерина","id":632813,"is_tutor":false},"comments":[{"creator":{"public_name":"Maksim Litvinov","id":198906,"is_tutor":true},"id":174836,"body":"Приветствую, Екатерина! А как вы считаете, для стриминговых сервисов важно быстрое и стабильное соединение? Или для динамичных онлайн игр, когда секундная задержка стоит игроку победы?","topic_id":87167}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}},{"id":85196,"title":"Здравствуйте! Не смогла выполнить упражнение. Посмотрела решение - такого сообщения нигде не видела. Делала сначала в Хроме, у меня там вариантов только 4: no throttling, fast 3g, slow 3g and offline. Выбираю, жму F5, сообщения из решения не было. Потом попробовала в Файрфоксе, там больше вариантов есть (2g, 3g etc.), но там при нажатии f5 страница просто грузится, белый экран. Что я сделала не так?","plain_title":"Здравствуйте! Не смогла выполнить упражнение. Посмотрела решение - такого сообщения нигде не видела. Делала сначала в Хроме, у меня там вариантов только 4: no throttling, fast 3g, slow 3g and offline. Выбираю, жму F5, сообщения из решения не было. Потом попробовала в Файрфоксе, там больше вариантов есть (2g, 3g etc.), но там при нажатии f5 страница просто грузится, белый экран. Что я сделала не так? ","creator":{"public_name":"Anna Gurina","id":600902,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":172066,"body":"**Anna**, здравствуйте. Вы можете добавить свой профиль нажав \"add\". Откроется окно создания профиля, там вы можете задать любую скорость соединения и указать имя профиля. После этого он появится в списке и вы сможете его выбрать.","topic_id":85196},{"creator":{"public_name":"Anna Gurina","id":600902,"is_tutor":false},"id":177035,"body":"Сообщение о медленном соединении никаким образом не появлялось при смене скоростей до тех пор, пока я не отметила галочку 'disable cache'. Может, кому-нибудь поможет.","topic_id":85196},{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":177074,"body":"**Anna G**, да, действительно, кэш нужно сбрасывать. Это можно делать при перезагрузке страницы. Когда открыт devtools, то если нажать правой кнопкой на иконку перезагрузки, там будет такая функция. Спасибо, что обратили на это внимание. Добавил подсказку в упражнение.","topic_id":85196}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}},{"id":88864,"title":"[Intervention] Slow network is detected. See https://www.chromestatus.com/feature/5636954674692096 for more details. Fallback font will be used while loading: https://web-web-testing-basics-connection-speed-5630332.evaluator7-5.hexlet.io/assets/fonts/OnestRegular.woff \nУ меня выдает это сообщение, но тест не проходит, что не так?","plain_title":"[Intervention] Slow network is detected. See https://www.chromestatus.com/feature/5636954674692096 for more details. Fallback font will be used while loading: https://web-web-testing-basics-connection-speed-5630332.evaluator7-5.hexlet.io/assets/fonts/OnestRegular.woff У меня выдает это сообщение, но тест не проходит, что не так? ","creator":{"public_name":"Марина Клыкова","id":543318,"is_tutor":false},"comments":[{"creator":{"public_name":"Aleksandr Litvinov","id":117182,"is_tutor":true},"id":177498,"body":"Должно появится сообщение-ошибка в самом верху страницы. Попробуйте выбрать более медленный вид интернета и обновить страницу с очищением кеша (Ctrl + Shift + R)","topic_id":88864}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}},{"id":90643,"title":"В тексте, Good 3G cкорость меньше, чем Good 2G, уверен это опечатка.","plain_title":"В тексте, Good 3G cкорость меньше, чем Good 2G, уверен это опечатка. ","creator":{"public_name":"Владимир Ш.","id":600167,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":179791,"body":"**Владимир Ш.**, спасибо! Поправил.","topic_id":90643}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}},{"id":94160,"title":"и всё таки выскажусь, тест имеет не корректный ответ = я категорически против, что менеджер задач не требует стабильного соединения \n\"Инструмент нужен, чтобы не было хаоса в работе\" и что?, по причине того, что задача не была скорректирована своевременно, может вся группа уйти не в ту сторону","plain_title":"и всё таки выскажусь, тест имеет не корректный ответ = я категорически против, что менеджер задач не требует стабильного соединения \"Инструмент нужен, чтобы не было хаоса в работе\" и что?, по причине того, что задача не была скорректирована своевременно, может вся группа уйти не в ту сторону ","creator":{"public_name":"Ростислав Марковский","id":123413,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":184475,"body":"**Ростислав Марковский**, здравствуйте. Обычно подобные приложения могут работать без постоянного соединения с сервером. Если соединение на некоторое время пропадет, то приложение подгрузит данные с небольшой задержкой, ничего критичного в этом не будет. В то же время, есть приложения, для которых любая задержка в соединении является критичной. Например, просмотр видео с постоянными \"заиканиями\" принесет значительный дискомфорт.\n\nТут важно не путать нестабильное соединение и отсутствие соединения вообще. Если нет соединения длительное время, за которое группа ушла не в ту сторону, как в вашем примере, то в данном случае это не нестабильное соединение. Это уже отсутствие соединения длительное время. Нестабильное соединение подразумевает, что соединение есть, но с небольшими задержками или теряется часть пакетов данных.","topic_id":94160}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}},{"id":98009,"title":"Вопрос по скорости разных типов соединения:\nВ таблице в статье указана примерная скорость разных типов соединения:\n\n> * Regular 3G. Скорость скачивания: 750 килобайт в секунду\n> * Good 3G. Скорость скачивания: 1 мегабайт в секунду\n> * Regular 4G / LTE. Скорость скачивания: 500 килобайт в секунду\n> * DSL. Скорость скачивания: 250 килобайт в секунду\n\n\nЭто не ошибка? На Regular 4G скорость скачивания ниже, чем на Regular 3G? \n\n","plain_title":"Вопрос по скорости разных типов соединения: В таблице в статье указана примерная скорость разных типов соединения: Regular 3G. Скорость скачивания: 750 килобайт в секунду Good 3G. Скорость скачивания: 1 мегабайт в секунду Regular 4G / LTE. Скорость скачивания: 500 килобайт в секунду DSL. Скорость скачивания: 250 килобайт в секунду Это не ошибка? На Regular 4G скорость скачивания ниже, чем на Regular 3G? ","creator":{"public_name":"Ольга Шкорубская","id":724465,"is_tutor":false},"comments":[{"creator":{"public_name":"Elena Gromova","id":548102,"is_tutor":true},"id":189325,"body":"**Ольга Шкорубская**, да, действительно ошибка. Исправили)","topic_id":98009}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}},{"id":98718,"title":"Когда сам написал(Скорость соединения слишком мала. Обратитесь в поддержку Hexlet) не приняло ответ, когда скопировал приняло)) выходит так все задачи работаю?)","plain_title":"Когда сам написал(Скорость соединения слишком мала. Обратитесь в поддержку Hexlet) не приняло ответ, когда скопировал приняло)) выходит так все задачи работаю?) ","creator":{"public_name":"Виктор","id":798625,"is_tutor":false},"comments":[{"creator":{"public_name":"Elena Gromova","id":548102,"is_tutor":true},"id":190118,"body":"**Виктор**, добрый день! В таких заданиях важно написать предложение слово в слово, символ в символ. Возможно когда вы самостоятельно прописали предложение, то где-то ошиблись в символах, вот оно и не прошло","topic_id":98718}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}},{"id":104498,"title":"\"Если выдать пользователю всё, что есть, то видимая загрузка может остановиться в начале и появиться в конце, когда все данные будут скачаны\" - можно ли подробнее объяснить этот момент? Не поняла, что значит \"загрузка может остановиться в начале и появиться в конце\"\n","plain_title":"\"Если выдать пользователю всё, что есть, то видимая загрузка может остановиться в начале и появиться в конце, когда все данные будут скачаны\" - можно ли подробнее объяснить этот момент? Не поняла, что значит \"загрузка может остановиться в начале и появиться в конце\" ","creator":{"public_name":"Наталья Чернышова","id":908608,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Gagarinov","id":75907,"is_tutor":true},"id":197074,"body":"**Наталья**, дальше по тексту идет пояснение с примером. Такое бывает, если например встречается код. Код начинает выполняться, и браузер ждет завершения выполнения.","topic_id":104498}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Скорость соединения","entity_url":null,"active":true}}],"lesson":{"exercise":{"id":2116,"slug":"web_testing_basics_connection_speed_exercise","name":null,"state":"active","kind":"exercise","language":"javascript","locale":"ru","has_web_view":true,"has_test_view":false,"reviewable":true,"readme":"Если скорость соединения недостаточна для комфортного использования приложения, то разработчик может написать об этом пользователю.\n\nВ этом задании разработчик реализовал механизм, при котором появляется сообщение о плохом соединении, если страница грузится больше четырех секунд.\n\nПротестируйте функционал с помощью инструментов DevTools и воспроизведите ошибку.\n\n## solution\n\nВ качестве ответа напишите сообщение, которое выводится пользователю, если страница грузится дольше положенного. Тесты чувствительны к регистру букв и символам, поэтому самый простой вариант — скопировать сообщение со страницы.\n\n## Подсказки\n\n* Чтобы файлы заново загружались, нужно сбрасывать кэш\n","prepared_readme":"Если скорость соединения недостаточна для комфортного использования приложения, то разработчик может написать об этом пользователю.\n\nВ этом задании разработчик реализовал механизм, при котором появляется сообщение о плохом соединении, если страница грузится больше четырех секунд.\n\nПротестируйте функционал с помощью инструментов DevTools и воспроизведите ошибку.\n\n## solution\n\nВ качестве ответа напишите сообщение, которое выводится пользователю, если страница грузится дольше положенного. Тесты чувствительны к регистру букв и символам, поэтому самый простой вариант — скопировать сообщение со страницы.\n\n## Подсказки\n\n* Чтобы файлы заново загружались, нужно сбрасывать кэш\n","has_solution":true,"entity_name":"Скорость соединения"},"units":[{"id":7281,"name":"theory","url":"/courses/web-testing-basics/lessons/connection-speed/theory_unit"},{"id":7489,"name":"quiz","url":"/courses/web-testing-basics/lessons/connection-speed/quiz_unit"},{"id":7349,"name":"exercise","url":"/courses/web-testing-basics/lessons/connection-speed/exercise_unit"}],"links":[{"id":423063,"name":"Что влияет на работу беспроводных сетей Wi-Fi","url":"https://help.keenetic.com/hc/ru/articles/213968709-Что-влияет-на-работу-беспроводных-сетей-Wi-Fi-Что-может-являться-источником-помех-и-каковы-их-возможные-причины-"}],"ordered_units":[{"id":7281,"name":"theory","url":"/courses/web-testing-basics/lessons/connection-speed/theory_unit"},{"id":7489,"name":"quiz","url":"/courses/web-testing-basics/lessons/connection-speed/quiz_unit"},{"id":7349,"name":"exercise","url":"/courses/web-testing-basics/lessons/connection-speed/exercise_unit"}],"id":3272,"slug":"connection-speed","state":"approved","name":"Скорость соединения","course_order":360,"goal":"Изучаем, как скорость загрузки страницы влияет на приложение","self_study":null,"theory_video_provider":"vimeo","theory_video_uid":"773469410","theory":"Сайты, как и другие источники информации в интернете, доступны только при наличии соединения с сетью. Выражение «соединение с сетью» достаточно сложное, так как есть разница между проводным соединением в квартире и мобильным соединением посреди леса. В последнем случае оно может быть или очень слабым, или совсем отсутствовать.\n\nПри разработке сайта важно понять, как ведет себя сайт или приложение при разных скоростях соединения.\n\nВ этом уроке разберем, что нам дает понимание скорости работы интернета, насколько 4G быстрее 3G и почему уже на этапе разработки необходимо учитывать различия в скорости соединения.\n\n## Скорость соединения\n\nПредставим, что мы переехали в новую квартиру и хотим подключить интернет. Один звонок провайдеру и заявка уже открыта. При этом нам говорят, что подключат к интернету со скоростью 100 мегабит в секунду — 100Мбит/с. Это и будет нашей скоростью соединения с интернетом.\n\nСразу сложно сказать много это или мало, также не понятно, что значат 100Мбит/с.\n\nВ компьютерах основная единица измерения — бит. Именно из них всё состоит. Мы можем вычислить скорость в мегабайт в секунду. Для этого нужно поделить количество мегабит на восемь, так как в одном байте 8 бит. Получится, что скорость соединения равна 12.5 мегабайт в секунду.\n\nНапример, одна минута видео, которая записана в разрешении 1920x1080 или FullHD, в среднем весит 30 мегабайт. Значит, с вычисленной скоростью можно смотреть видео без прерываний. Одну минуту такого видео наш интернет способен скачать за три секунды. Поэтому 12.5 мегабайт в секунду — это хорошая скорость, которая позволяет пользоваться интернетом без задержек.\n\nСайты весят значительно меньше, чем одно видео. Например, главная страница Хекслета на январь 2023 года весит 11.7 мегабайт. Получается, ее можно скачать на компьютере за одну секунду при скорости интернета в 100Мбит/с.\n\nВ мобильном интернете распространены два стандарта подключения к интернету:\n\n* 3G\n* 4G\n\nСравним их по скорости соединения с интернетом:\n\n* 3G — в зависимости от подстандарта скорость может быть 14.4Мбит/с или 42Мбит/с. Если перевести в мегабайты, то максимальная скорость составит 5.25 мегабайта в секунду. Это в два раза меньше скорости при подключении интернета в квартире из примера выше\n* 4G — максимальная скорость считается 1Гбит/с (один гигабит в секунду). Но в реальности скорость сопоставима со скоростью домашнего интернета и равняется 100Мбит/с\n\nОсновная проблема показателей скорости интернета в том, что это теоретические данные. То есть можно не получить заявленную скорость по разным причинам. Например:\n\n* Удаление от мобильной станции\n* Плохая погода\n* Большое количество препятствий в виде домов, машин, деревьев, на пути от станции до вашего устройства\n\nЭти факторы могут снизить скорость соединения или отключить от интернета. Поэтому скорость соединения в городе и в лесу различаются. Приложение должно учитывать это, особенно, если оно может помочь человеку в трудной ситуации. Например: карты, приложение для вызова помощи, мессенджер и так далее.\n\n## Загрузка сайта\n\nНа примере страницы [Хекслета](https://ru.hexlet.io/webinars) проверим, как загружается сайт при низкой скорости интернета. В дальнейшем разберем, как самостоятельно установить разные скорости соединения для тестирования.\n\nЗагрузка страницы — сложный процесс, который включает в себя множество понятий. Им можно посвятить целый курс. По этой причине опустим технические вещи и посмотрим на сайт с точки зрения простого пользователя с плохим интернетом.\n\nВесь процесс загрузки страницы Хекслета можно разбить на три части:\n\n* Загрузка тела страницы. Сюда входит текст, его расположение и расположение блоков:\n\n\n\n* Загрузка скриптов и данных, таких как шрифты:\n\n\n\n* Загрузка визуального оформления. Изображения и так далее:\n\n\n\nС первого шага загрузки страницы доступен весь текст, его расположение и смысловое значение. То есть, если во время загрузки пропадет соединение с интернетом, то основной посыл страницы останется доступен пользователю для изучения.\n\nТо, как будет загружаться страница, отчасти зависит от разработчиков. Если выдать пользователю всё, что есть, то видимая загрузка может остановиться в начале и появиться в конце, когда все данные будут скачаны. Это плохой вариант, так как можно оставить пользователя на некоторое время перед белым экраном.\n\nТакой порядок загрузки возникает из-за принципов работы браузеров. В обычной ситуации они анализируют HTML сверху вниз. Во время анализа может встретиться ссылка на ресурс, например, изображение, стили или код на JavaScript. В этом случае анализ прекращается до тех пор, пока не будет обработан ресурс.\n\nПредставьте, что в начале страницы находится большой код на JavaScript. Тогда браузер не будет ничего загружать до тех пор, пока не обработает и не выполнит весь код. Это может занимать четверть секунды, а может и несколько секунд — всё зависит от сложности и объема кода.\n\nЧтобы избежать такой блокировки загрузки, используется техника, которая называется асинхронной загрузкой. Браузер знает, что ему нужно загрузить и выполнить код, но делает это не вместо загрузки страницы, а вместе с дальнейшей загрузкой.\n\nИменно так загрузится страница Хекслета при плохом соединении с интернетом. На самом деле и при хорошем соединении процесс не изменится, только он произойдет за очень короткое время. Мы даже не успеваем увидеть все стадии загрузки.\n\n## Тестирование скорости\n\nВ инструментах разработчика браузеров есть функция, которая позволяет эмулировать разную скорость соединения с интернетом. То есть искусственно ограничить скорость, чтобы протестировать приложение. Разберем функцию на примере инструмента разработчика в Firefox.\n\nЧтобы открыть инструмент разработчика, нужно воспользоваться комбинацией клавиш <kbd>Ctrl + Shift + I</kbd> или клавишей <kbd>F12</kbd>. Затем нужно перейти во вкладку _Network_.\n\nВ этой вкладке доступно всё, что связано с загрузкой нашего проекта: тип информации, его адрес, вес и время загрузки:\n\n\n\nПопробуйте изучить эту информацию на любом сайте.\n\nЧтобы изменить скорость загрузки, воспользуемся выпадающим списком в правой части вкладки. По умолчанию на ней написано «No Throttling» — «Без ограничений» или «Без регулировки». Если открыть этот список, то можно увидеть предустановленные варианты для разных типов соединения:\n\n\n\n* GPRS: 50 Кбит/с (загрузка), 20 Кбит/с (отправка), 500 мс (задержка)\n* Regular 2G: 250 Кбит/с (загрузка), 50 Кбит/с (отправка), 300 мс (задержка)\n* Good 2G: 450 Кбит/с (загрузка), 150 Кбит/с (отправка), 150 мс (задержка)\n* Regular 3G: 750 Кбит/с (загрузка), 250 Кбит/с (отправка), 100 мс (задержка)\n* Good 3G: 1.5 Мбит/с (загрузка), 750 Кбит/с (отправка), 40 мс (задержка)\n* Regular 4G/LTE: 4 Мбит/с (загрузка), 3 Мбит/с (отправка), 20 мс (задержка)\n* DSL: 2 Мбит/с (загрузка), 1 Мбит/с (отправка), 5 мс (задержка)\n* Wi-Fi: Не имеет строго определённых параметров в DevTools по умолчанию, поскольку скорость Wi-Fi может сильно варьироваться в зависимости от спецификаций, но для эмуляции можно использовать значения, близкие к реальным условиям использования, например, 30-50 Мбит/с для загрузки и 10-30 Мбит/с для отправки, с относительно низкой задержкой.\n\nЧтобы изменить скорость, выполните два действия:\n\n1. Выберите нужный вариант скорости соединения\n2. Перезагрузите страницу. Для этого можно использовать клавишу <kbd>F5</kbd>\n\nСценарий тестирования зависит от приложения и технического задания. Если это приложение помогает людям ориентироваться в пространстве или обмениваться сообщениями, то оно должно достаточно быстро работать даже при нестабильном соединении. Это связано с тем, что такие приложения могут использоваться в критической ситуации. К такому же принципу могут относиться банковские приложения и карты.\n\nЕсли технического задания нет, то можно проверить следующие пункты:\n\n1. Страница отображает текст еще до загрузки изображений или видео\n2. Никакой из компонентов страницы не ругается на отсутствие соединения, если оно есть\n3. Отсутствуют ошибки в JavaScript, которые не появляются при обычном соединении. Это можно увидеть на вкладке Console\n\n## Выводы\n\nВ этом уроке мы узнали, что помимо корректного отображения страницы на разных устройствах важно тестировать поведение сайта или приложения при разных скоростях соединения. Скорость соединения — количество информации в секунду, которую можно получить или отправить в интернете.\n\nТак же мы рассмотрели загрузку одной из страниц Хекслета при низкой скорости соединения. Мы выяснили, что один из главных факторов при низкой скорости — быстрая отрисовка текста и его расположения. Это позволяет даже при обрыве соединения прочитать информацию.\n\nВ качестве инструмента тестирования можно использовать инструменты разработчика. В нем есть специальная вкладка Network, которая позволяет проанализировать количество скачиваемого контента, его вес и время загрузки. Так же на этой вкладке можно установить тип соединения для тестирования соединения.\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/connection-speed/theory_unit","version":"0b0c6d4ebbd40fd58630a0dd89cc25544ccdf24e","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/773469410" loading="lazy" allowFullScreen="" title="video"></iframe></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><p>Сайты, как и другие источники информации в интернете, доступны только при наличии соединения с сетью. Выражение «соединение с сетью» достаточно сложное, так как есть разница между проводным соединением в квартире и мобильным соединением посреди леса. В последнем случае оно может быть или очень слабым, или совсем отсутствовать.</p>
<p>При разработке сайта важно понять, как ведет себя сайт или приложение при разных скоростях соединения.</p>
<p>В этом уроке разберем, что нам дает понимание скорости работы интернета, насколько 4G быстрее 3G и почему уже на этапе разработки необходимо учитывать различия в скорости соединения.</p>
<h2 id="heading-2-1">Скорость соединения</h2>
<p>Представим, что мы переехали в новую квартиру и хотим подключить интернет. Один звонок провайдеру и заявка уже открыта. При этом нам говорят, что подключат к интернету со скоростью 100 мегабит в секунду — 100Мбит/с. Это и будет нашей скоростью соединения с интернетом.</p>
<p>Сразу сложно сказать много это или мало, также не понятно, что значат 100Мбит/с.</p>
<p>В компьютерах основная единица измерения — бит. Именно из них всё состоит. Мы можем вычислить скорость в мегабайт в секунду. Для этого нужно поделить количество мегабит на восемь, так как в одном байте 8 бит. Получится, что скорость соединения равна 12.5 мегабайт в секунду.</p>
<p>Например, одна минута видео, которая записана в разрешении 1920x1080 или FullHD, в среднем весит 30 мегабайт. Значит, с вычисленной скоростью можно смотреть видео без прерываний. Одну минуту такого видео наш интернет способен скачать за три секунды. Поэтому 12.5 мегабайт в секунду — это хорошая скорость, которая позволяет пользоваться интернетом без задержек.</p>
<p>Сайты весят значительно меньше, чем одно видео. Например, главная страница Хекслета на январь 2023 года весит 11.7 мегабайт. Получается, ее можно скачать на компьютере за одну секунду при скорости интернета в 100Мбит/с.</p>
<p>В мобильном интернете распространены два стандарта подключения к интернету:</p>
<ul>
<li>3G</li>
<li>4G</li>
</ul>
<p>Сравним их по скорости соединения с интернетом:</p>
<ul>
<li>3G — в зависимости от подстандарта скорость может быть 14.4Мбит/с или 42Мбит/с. Если перевести в мегабайты, то максимальная скорость составит 5.25 мегабайта в секунду. Это в два раза меньше скорости при подключении интернета в квартире из примера выше</li>
<li>4G — максимальная скорость считается 1Гбит/с (один гигабит в секунду). Но в реальности скорость сопоставима со скоростью домашнего интернета и равняется 100Мбит/с</li>
</ul>
<p>Основная проблема показателей скорости интернета в том, что это теоретические данные. То есть можно не получить заявленную скорость по разным причинам. Например:</p>
<ul>
<li>Удаление от мобильной станции</li>
<li>Плохая погода</li>
<li>Большое количество препятствий в виде домов, машин, деревьев, на пути от станции до вашего устройства</li>
</ul>
<p>Эти факторы могут снизить скорость соединения или отключить от интернета. Поэтому скорость соединения в городе и в лесу различаются. Приложение должно учитывать это, особенно, если оно может помочь человеку в трудной ситуации. Например: карты, приложение для вызова помощи, мессенджер и так далее.</p>
<h2 id="heading-2-2">Загрузка сайта</h2>
<p>На примере страницы <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.hexlet.io/webinars" rel="noopener noreferrer" target="_blank">Хекслета</a> проверим, как загружается сайт при низкой скорости интернета. В дальнейшем разберем, как самостоятельно установить разные скорости соединения для тестирования.</p>
<p>Загрузка страницы — сложный процесс, который включает в себя множество понятий. Им можно посвятить целый курс. По этой причине опустим технические вещи и посмотрим на сайт с точки зрения простого пользователя с плохим интернетом.</p>
<p>Весь процесс загрузки страницы Хекслета можно разбить на три части:</p>
<ul>
<li>Загрузка тела страницы. Сюда входит текст, его расположение и расположение блоков:</li>
</ul>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjM1OSwicHVyIjoiYmxvYl9pZCJ9fQ==--cf30ff6225a0fb237457dae62aa10bcd94455516/hexlet-speed-1.jpg" alt="Загрузка страницы в интернете" loading="lazy"/></p>
<ul>
<li>Загрузка скриптов и данных, таких как шрифты:</li>
</ul>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjM2MCwicHVyIjoiYmxvYl9pZCJ9fQ==--a81e9073ae8c3c526ff18746e53e99acb873bc50/hexlet-speed-2.jpg" alt="Загрузка страницы в интернете" loading="lazy"/></p>
<ul>
<li>Загрузка визуального оформления. Изображения и так далее:</li>
</ul>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjM2MywicHVyIjoiYmxvYl9pZCJ9fQ==--283f041dd4977113ca8c704d2bb152c677b0a5d5/hexlet-speed-3.jpg" alt="Загрузка страницы в интернете" loading="lazy"/></p>
<p>С первого шага загрузки страницы доступен весь текст, его расположение и смысловое значение. То есть, если во время загрузки пропадет соединение с интернетом, то основной посыл страницы останется доступен пользователю для изучения.</p>
<p>То, как будет загружаться страница, отчасти зависит от разработчиков. Если выдать пользователю всё, что есть, то видимая загрузка может остановиться в начале и появиться в конце, когда все данные будут скачаны. Это плохой вариант, так как можно оставить пользователя на некоторое время перед белым экраном.</p>
<p>Такой порядок загрузки возникает из-за принципов работы браузеров. В обычной ситуации они анализируют HTML сверху вниз. Во время анализа может встретиться ссылка на ресурс, например, изображение, стили или код на JavaScript. В этом случае анализ прекращается до тех пор, пока не будет обработан ресурс.</p>
<p>Представьте, что в начале страницы находится большой код на JavaScript. Тогда браузер не будет ничего загружать до тех пор, пока не обработает и не выполнит весь код. Это может занимать четверть секунды, а может и несколько секунд — всё зависит от сложности и объема кода.</p>
<p>Чтобы избежать такой блокировки загрузки, используется техника, которая называется асинхронной загрузкой. Браузер знает, что ему нужно загрузить и выполнить код, но делает это не вместо загрузки страницы, а вместе с дальнейшей загрузкой.</p>
<p>Именно так загрузится страница Хекслета при плохом соединении с интернетом. На самом деле и при хорошем соединении процесс не изменится, только он произойдет за очень короткое время. Мы даже не успеваем увидеть все стадии загрузки.</p>
<h2 id="heading-2-3">Тестирование скорости</h2>
<p>В инструментах разработчика браузеров есть функция, которая позволяет эмулировать разную скорость соединения с интернетом. То есть искусственно ограничить скорость, чтобы протестировать приложение. Разберем функцию на примере инструмента разработчика в Firefox.</p>
<p>Чтобы открыть инструмент разработчика, нужно воспользоваться комбинацией клавиш <kbd>Ctrl + Shift + I</kbd> или клавишей <kbd>F12</kbd>. Затем нужно перейти во вкладку <em>Network</em>.</p>
<p>В этой вкладке доступно всё, что связано с загрузкой нашего проекта: тип информации, его адрес, вес и время загрузки:</p>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjM2NCwicHVyIjoiYmxvYl9pZCJ9fQ==--490aa61b5d4c1bb4a276790f65c339239ff626a4/devtools-network-1.jpg" alt="Вкладка Network в DevTools" loading="lazy"/></p>
<p>Попробуйте изучить эту информацию на любом сайте.</p>
<p>Чтобы изменить скорость загрузки, воспользуемся выпадающим списком в правой части вкладки. По умолчанию на ней написано «No Throttling» — «Без ограничений» или «Без регулировки». Если открыть этот список, то можно увидеть предустановленные варианты для разных типов соединения:</p>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NjM2NywicHVyIjoiYmxvYl9pZCJ9fQ==--f59f18805def6650c6034bdbee0d52d5b70e7ed3/devtools-network-2.jpg" alt="Вкладка Network в DevTools" loading="lazy"/></p>
<ul>
<li>GPRS: 50 Кбит/с (загрузка), 20 Кбит/с (отправка), 500 мс (задержка)</li>
<li>Regular 2G: 250 Кбит/с (загрузка), 50 Кбит/с (отправка), 300 мс (задержка)</li>
<li>Good 2G: 450 Кбит/с (загрузка), 150 Кбит/с (отправка), 150 мс (задержка)</li>
<li>Regular 3G: 750 Кбит/с (загрузка), 250 Кбит/с (отправка), 100 мс (задержка)</li>
<li>Good 3G: 1.5 Мбит/с (загрузка), 750 Кбит/с (отправка), 40 мс (задержка)</li>
<li>Regular 4G/LTE: 4 Мбит/с (загрузка), 3 Мбит/с (отправка), 20 мс (задержка)</li>
<li>DSL: 2 Мбит/с (загрузка), 1 Мбит/с (отправка), 5 мс (задержка)</li>
<li>Wi-Fi: Не имеет строго определённых параметров в DevTools по умолчанию, поскольку скорость Wi-Fi может сильно варьироваться в зависимости от спецификаций, но для эмуляции можно использовать значения, близкие к реальным условиям использования, например, 30-50 Мбит/с для загрузки и 10-30 Мбит/с для отправки, с относительно низкой задержкой.</li>
</ul>
<p>Чтобы изменить скорость, выполните два действия:</p>
<ol>
<li>Выберите нужный вариант скорости соединения</li>
<li>Перезагрузите страницу. Для этого можно использовать клавишу <kbd>F5</kbd></li>
</ol>
<p>Сценарий тестирования зависит от приложения и технического задания. Если это приложение помогает людям ориентироваться в пространстве или обмениваться сообщениями, то оно должно достаточно быстро работать даже при нестабильном соединении. Это связано с тем, что такие приложения могут использоваться в критической ситуации. К такому же принципу могут относиться банковские приложения и карты.</p>
<p>Если технического задания нет, то можно проверить следующие пункты:</p>
<ol>
<li>Страница отображает текст еще до загрузки изображений или видео</li>
<li>Никакой из компонентов страницы не ругается на отсутствие соединения, если оно есть</li>
<li>Отсутствуют ошибки в JavaScript, которые не появляются при обычном соединении. Это можно увидеть на вкладке Console</li>
</ol>
<h2 id="heading-2-4">Выводы</h2>
<p>В этом уроке мы узнали, что помимо корректного отображения страницы на разных устройствах важно тестировать поведение сайта или приложения при разных скоростях соединения. Скорость соединения — количество информации в секунду, которую можно получить или отправить в интернете.</p>
<p>Так же мы рассмотрели загрузку одной из страниц Хекслета при низкой скорости соединения. Мы выяснили, что один из главных факторов при низкой скорости — быстрая отрисовка текста и его расположения. Это позволяет даже при обрыве соединения прочитать информацию.</p>
<p>В качестве инструмента тестирования можно использовать инструменты разработчика. В нем есть специальная вкладка Network, которая позволяет проанализировать количество скачиваемого контента, его вес и время загрузки. Так же на этой вкладке можно установить тип соединения для тестирования соединения.</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/connection-speed/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/connection-speed/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-CdBlNCiQ.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-nkZBEvfU.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>