Реальность фрагментации устройств
Updated Jul 2026
Масштаб проблемы
Прежде чем обсуждать инструменты и стратегии, необходимо осознать огромный масштаб фрагментации устройств. Этот контекст критически важен для принятия обоснованных решений по тестированию и для объяснения вашей стратегии на собеседованиях.
Фрагментация устройств в цифрах (2026)
| Измерение | Масштаб | Следствие для тестирования |
|---|---|---|
| Активно используемые версии Android | 6+ мажорных версий (10-15) | Каждая имеет свой WebView, уровни API, модели разрешений |
| Активно используемые версии iOS | 3-4 мажорные версии (15-18) | Быстрое принятие, но старые устройства отстают |
| Уникальные модели Android-устройств | 24 000+ | Размеры экранов от 4" до 13", вырезы, отверстия, складные |
| Уникальные разрешения экрана | 200+ распространённых | Тестирование контрольных точек не может покрыть каждую ширину в пикселях |
| Браузерные движки (мобильные) | 3 основных (Blink, WebKit, Gecko) | iOS заставляет все браузеры использовать WebKit (меняется с DMA в ЕС) |
| Сетевые условия | от 2G до 5G + WiFi | Производительность варьируется в 100 раз между лучшими и худшими |
| Доступная RAM | от 2 ГБ до 16 ГБ | Устройства с малой памятью агрессивно закрывают фоновые приложения |
| Архитектуры чипсетов | ARM, ARM64, x86 (редко) | Нативный код должен компилироваться для каждой архитектуры |
Почему это важно для QA
Каждое число в таблице выше представляет измерение вариативности, которое может вызывать баги. Вёрстка, которая работает на 6.1" iPhone 15, может переполниться на 5.4" iPhone 13 mini. Анимация, которая плавно работает с 12 ГБ RAM, может подтормаживать на устройстве с 3 ГБ. Сетевой запрос, который завершается за 200 мс по WiFi, может завершиться по таймауту на 3G-соединении в сельской Индии.
Вызов фрагментации Android
Фрагментация Android — доминирующая проблема в мобильном тестировании. В отличие от iOS, где Apple контролирует и оборудование, и ПО, Android работает на тысячах устройств от сотен производителей, каждый со своими настройками.
Распределение версий Android (приблизительно, 2026)
| Версия Android | Уровень API | Доля рынка | Заметные отличия |
|---|---|---|---|
| Android 15 | 35 | ~20% | Предиктивный «назад», язык для каждого приложения |
| Android 14 | 34 | ~30% | Типы foreground-сервисов, выбор фото |
| Android 13 | 33 | ~20% | Разрешение на уведомления, тематические иконки |
| Android 12 | 31-32 | ~15% | Material You, приблизительная геолокация |
| Android 11 | 30 | ~10% | Принудительное scoped-хранилище, одноразовые разрешения |
| Android 10 | 29 | ~5% | Тёмная тема, жестовая навигация |
Пользовательские оболочки производителей
Стоковый Android — это не то, что видит большинство пользователей. Samsung, Xiaomi, Huawei и другие производители накладывают собственные UI поверх Android:
| Производитель | Оболочка | Влияние на рынок | Особенность тестирования |
|---|---|---|---|
| Samsung (One UI) | ~30% Android-устройств | Пользовательские жесты, разделённый экран, боковые панели | Тестировать многооконный режим и боковые панели |
| Xiaomi (MIUI/HyperOS) | ~15% глобально | Агрессивная оптимизация батареи закрывает фоновые приложения | Тестировать выживание фоновых задач |
| Huawei (EMUI/HarmonyOS) | ~5% глобально (растёт в Китае) | Нет Google Play Services в новых моделях | Тестировать без Google API, использовать HMS |
| Oppo/OnePlus (ColorOS/OxygenOS) | ~10% глобально | Пользовательская обработка уведомлений | Тестировать крайние случаи доставки уведомлений |
| Google (Pixel) | ~3% глобально | Стоковый Android, самые быстрые обновления | Хорошее базовое референсное устройство |
Проблема WebView
На Android веб-контент в нативных приложениях отображается через компонент WebView, привязанный к системной версии Chrome. Разные версии Chrome на разных версиях Android дают разные результаты рендеринга. Это означает, что веб-страница, которая идеально выглядит в Chrome на вашей машине для разработки, может отображаться иначе внутри WebView на Samsung Galaxy A54 с Android 12.
# Check WebView version programmatically
def get_webview_version(driver):
"""Get the WebView engine version on the current device."""
info = driver.execute_script("return navigator.userAgent")
# Parse Chrome version from user agent
# Example: "Chrome/120.0.6099.230"
import re
match = re.search(r'Chrome/(\d+\.\d+\.\d+\.\d+)', info)
return match.group(1) if match else "unknown"
Фрагментация iOS (да, она существует)
Фрагментация iOS менее выражена, чем Android, но всё ещё значительна. Ключевые факторы:
Вариации экранов устройств
| Устройство | Размер экрана | Разрешение | Отступы Safe Area | Заметные особенности |
|---|---|---|---|---|
| iPhone SE (3-е поколение) | 4.7" | 750x1334 | Нет (кнопка Home) | Самый маленький текущий iPhone |
| iPhone 13 mini | 5.4" | 1080x2340 | Верхняя выемка + нижняя полоса | Ограничения компактной вёрстки |
| iPhone 15 | 6.1" | 1179x2556 | Dynamic Island + нижняя полоса | Стандартное референсное устройство |
| iPhone 15 Pro Max | 6.7" | 1290x2796 | Dynamic Island + нижняя полоса | Самый большой телефонный дисплей |
| iPhone 15 Plus | 6.7" | 1284x2778 | Dynamic Island + нижняя полоса | Тот же физический размер, другая PPI |
| iPad mini (6-е поколение) | 8.3" | 1488x2266 | Узкие рамки | Триггер планшетной вёрстки |
| iPad Pro 12.9" | 12.9" | 2048x2732 | ProMotion 120 Гц | Вёрстка десктопного класса |
Принятие версий iOS
Apple агрессивно продвигает обновления, но не все обновляются:
- ~75% iPhone используют последнюю мажорную версию в течение 3 месяцев
- ~15% используют предыдущую мажорную версию
- ~10% используют версию на два и более поколения назад (старые устройства, которые не могут обновиться)
Практический вывод: вы должны поддерживать как минимум iOS N и iOS N-1. Если ваша аудитория склоняется к старшему возрасту или корпоративному сектору, поддерживайте N-2.
Вариативность сетевых условий
Сетевые условия — наиболее недооценённое измерение фрагментации. Функция, которая отлично работает по WiFi, может быть неиспользуемой на перегруженном 3G-соединении.
| Условие | Типичная задержка | Типичная пропускная способность | Где встречается |
|---|---|---|---|
| WiFi (хороший) | 5-20 мс | 50-500 Мбит/с | Дом, офис |
| WiFi (перегруженный) | 50-200 мс | 1-10 Мбит/с | Кофейни, аэропорты |
| 5G | 10-30 мс | 100-500 Мбит/с | Городские районы |
| 4G/LTE | 30-50 мс | 10-50 Мбит/с | Пригороды, большинство районов |
| 3G | 100-500 мс | 0.5-5 Мбит/с | Сельская местность, развивающиеся рынки |
| 2G/Edge | 300-1000 мс | 0.05-0.2 Мбит/с | Удалённые районы, туннели |
| Офлайн | Бесконечность | 0 | Лифты, метро, авиарежим |
Тестирование сетевых условий
// Playwright: emulate network conditions
import { test } from '@playwright/test';
const networkProfiles = {
'4g': { download: 4_000_000, upload: 3_000_000, latency: 40 },
'3g': { download: 750_000, upload: 250_000, latency: 100 },
'slow3g': { download: 500_000, upload: 250_000, latency: 300 },
'offline': { download: 0, upload: 0, latency: 0 },
};
for (const [name, profile] of Object.entries(networkProfiles)) {
test(`app loads within budget on ${name}`, async ({ page, context }) => {
const cdp = await context.newCDPSession(page);
await cdp.send('Network.emulateNetworkConditions', {
offline: profile.download === 0,
downloadThroughput: profile.download / 8,
uploadThroughput: profile.upload / 8,
latency: profile.latency,
});
const start = Date.now();
await page.goto('/');
const loadTime = Date.now() - start;
// Set budget per network condition
const budgets: Record<string, number> = {
'4g': 3000,
'3g': 8000,
'slow3g': 15000,
};
if (budgets[name]) {
expect(loadTime).toBeLessThan(budgets[name]);
}
});
}
Ключевой вывод для собеседований
Реальность фрагментации — это не аргумент в пользу тестирования всего. Это аргумент в пользу стратегического тестирования. Когда вас спрашивают о мобильном тестировании на собеседовании, продемонстрируйте, что вы понимаете масштаб проблемы И основанный на данных подход к управлению ею. Фраза «мы тестируем на каждом устройстве» показывает наивность. Фраза «мы используем аналитику для построения многоуровневой матрицы устройств, покрывающей 90% пользователей 12 устройствами» показывает инженерную зрелость.