Выбирайте самый простой уровень, который наблюдает реальное поведение. Не нужно для каждого релиза проверять каждую функцию на четырёх устройствах, без причины повторять CI локально или вести отдельные отчёты ревизий в репозитории. Исторические release notes сохраняются. Существенные ошибки и границы проверки указывайте в соответствующем PR/релизе, без секретов и личных capture.
| Изменение | Проверка |
|---|---|
| Только документация / графика | Локальные ссылки, картинки, согласованность EN/RU и соответствие коду; без сборки APK |
| Kotlin/UI/конфигурация | Во время работы — затронутые JVM/Robolectric тесты; перед передачей — bundle exec fastlane android android_checks |
| Go transport/DNS | bundle exec fastlane android native_tests; для dialer/auth/trust/совместимости серверов добавить native_integration |
| Python/автоматизация | bundle exec fastlane android python_checks (stdlib runtime, закреплённые style/test tools; Node.js для workflow JS) |
| TUN/JNI/service/permissions/Keystore/SAF | Существующие интеграционные наборы API 26/35 в CI; локальный одноразовый эмулятор — для воспроизведения |
| Общая сборка / широкое изменение | Все затронутые lanes; test не включает Python, Docker integration и устройства |
Парсеры, форматирование, полнота ресурсов, навигация и переходы состояния остаются в детерминированных
JVM/Go тестах. Compose взаимодействия используют существующий Robolectric harness с подставными
platform operations и Keystore; записанный service intent не доказывает работу сервиса/JNI.
Дождитесь очереди записи конфигурации и проверьте ошибку, а не только pending == 0.
Native-тесты используют управляемые серверы, не личные/публичные прокси. Не нужны тесты, просто
повторяющие тривиальный код отображения.
При изменении потоков нужен тест с управляемым медленным worker, подтверждающий отзывчивость главного потока, в том числе при остановке JNI и планировании подписок. Фоновые callbacks сервиса сохраняют порядок команд и сессий. UI-автоматизация ждёт обновления accessibility-дерева Compose, прежде чем решать, нужна ли прокрутка: изменение runtime-состояния ещё не означает отрисовку кнопки.
- Для PR каждый набор сравнивается с последним успешно проверенным предком в том же PR/base. Ошибка, отмена и пропуск не продвигают покрытие. При отсутствии истории/ошибке API берётся весь diff PR; неизвестные пути и общие build inputs включают всё. Ошибка diff останавливает выбор.
- Документация пропускает тестовые задания. Только Python запускает Python, только Go-тесты — Go.
Native production и Android включают Android и оба device-набора. Точные пути:
scripts/ci_changes.py. - Каждый push в
mainи каждый релизный PR запускает всё. Полный rerun повторяет Change scope и принудительно включает все наборы; failed-only сохраняет scope, пока сам Change scope не повторён. - Обязательны
Change scope,Python tests and style,Native Go tests,Android tests and checks,Android emulator API 26/35 / Device tests. Native включает race и реальные GOST/OpenSSH в Docker. Android включает JVM, lint, debug и unsigned release. - API 26/35 независимы, Ubuntu 24.04 с KVM, cold boot без snapshot cache. Без software fallback и повторов ошибок runner/тестов. Установка SDK и старт эмулятора могут повториться один раз до начала тестов. Ошибка скачивания до runner — сбой инфраструктуры, не результат теста; перед ручным повтором изучите причину. Не отключайте проверку checksum/сертификатов ради зелёного CI.
- JUnit публикуется отдельно по завершении набора. Отсутствие отчёта или пропуск не означает PASS. Публикация повторяет только обновление того же Check при 404: дважды через 1 и 3 секунды, без перезапуска тестов и создания нового Check. После исчерпания повторов публикация падает. Релизные секреты недоступны PR. Команды, артефакты и требования эмулятора: Fastlane.
Device-наборы проверяют реальный TUN/JNI TCP/UDP, HTTPS/SOCKS5/MASQUE, HTTPS preference/fallback, все четыре сочетания HTTP/3 у Jump, QUIC presets/размеры/auth/trust, split routing, failover, stop/restart и остановку при запуске SSH, VPN/notification permissions, реальный Keystore с новым процессом, хранение подписки и системный DocumentsUI. Каждый сценарий запускается отдельным instrumentation-процессом; Keystore seed/verify должны оставаться раздельными. Это не доказывает работу physical network handover, OEM power policy, всех Always-on/lockdown режимов и реального IPv6 uplink.
Одноразовый эмулятор отключает публичные проверки captive portal, переподключает Wi-Fi на API 35 (клиент svc wifi API 26 завершается с кодом 137) и ждёт, пока она станет подтверждённой сетью по умолчанию. До VPN-сценариев он должен получить баннер локального SSH-стенда через 10.0.2.2; при отказе сохраняется диагностика сети, а набор останавливается без повторения тестов.
Перед каждым сценарием runner ждёт завершения предыдущего процесса и Activity, читает точное время собственной уникальной метки в Logcat, не очищая общие буферы. Вывод успешных и упавших сценариев содержит обезличенный хвост диагностического журнала (до 64 KiB), собранный после остановки VPN. Ошибки подготовки, самого теста и cleanup сохраняют доказательства; ошибка их сбора не скрывает исходную. Локальная TCP/UDP-фикстура повторяет только выбор занятого порта, до запуска контейнеров и тестов.
Зафиксируйте точный commit, версию/ABI, SHA-256 и подпись APK. Нужен полный успешный CI кандидата; пропущенный набор PR недостаточен. Debug instrumentation поддерживает, но не заменяет smoke подписанного APK. Публикация/подпись/VirusTotal — отдельные релизные операции.
Обычный ручной smoke планируется примерно на 20–30 минут на одном подходящем телефоне; это бюджет, а не срок, после которого отсутствие доказательств превращается в PASS. Минимальный API и API 35 покрывает CI. Дополнительные телефоны/API нужны для platform-specific изменений и воспроизведения.
| Область | Что требуется наблюдать |
|---|---|
| Каждый релиз | Установка/обновление того же подписанного варианта без удаления; сохраняются профили/секреты/routing. Подключение, реальные данные обычного приложения, Stop и reconnect. Изменённый экран; ошибки/crash/ANR приложения. |
| Routing, DNS, IPv6 или VPN lifecycle | Включённый/исключённый UID обычных приложений, global/split и синхронность переключателя MegaProxy со списком; LAN bypass. Контролируемые DNS/UDP с положительным/отрицательным контролем и origin/capture. Stop при старте/failover не оживляет VPN. Реальные IPv6, handover и Always-on/lockdown — в подходящей дополнительной среде при затронутой логике. |
| Transport/auth/trust | Только затронутые transports/hops: двоичный round trip, верные/неверные/восстановленные credentials, hostname/CA/SSH pin rejection, EOF/half-close, timeout/cancel и fallback. Нет прямого обхода отказавшего hop. Сохраняются известные ограничения GOST по размеру/IPv6/half-close. |
| Хранение/подписки/import/export | Upgrade или затронутая миграция, omitted/empty secrets, отменённый/упавший перенос без усечения файла, свежая подписка при открытом редакторе, process death/Keystore failure при затронутой логике. Повреждённые/нечитаемые данные сохраняются; восстановление явное. Секреты не попадают в saved-state bundles. |
| Тест / Скорость / Видимость VPN | Выходной IP/страна и независимые UDP-статусы с a11y; копирование IP. Скорость основной сети/VPN: постепенные результаты/прогресс, флаг/код, HTTP и TLS на отдельных строках, download/upload и лог. Для smoke — 10 MB, h3→h2→h1 fallback только где разрешён; Back отменяет, Home продолжает. Задержка здесь — медиана TTFB трёх запросов, не пассивный RTT прокси. Daily-limit/failure/cache ProxyCheck проверяются фикстурами, без расхода живой квоты unit-тестами. |
| UI/accessibility | Изменённые экраны EN/RU при ширине 320 dp и 1280 dp, в том числе со шрифтом 200%; читаемые действия баннера, switches и multi-select checkboxes по назначению, TalkBack-статусы, копирование/выделение и рабочие ссылки. Полный перебор тем/ориентаций/устройств — только для соответствующего дефекта. |
| Обновления/релизы | Затронутые выбор источника/согласие/подпись/ABI/версия, отмена скачивания и результат установщика; некорректные metadata/APK — на фикстурах. При публикации — tag/merge tree, hashes APK и завершённые VirusTotal-отчёты. F-Droid recipe/reproducibility — при изменении соответствующего рецепта/релиза. |
Используйте синтетические профили и одноразовые фикстуры. Сохраните и восстановите исходные данные, сеть, разрешения и Always-on телефона; разрушительные сценарии — на одноразовых эмуляторах. Успешная сеть требует ответа и доказательств origin, а не надписи «Подключено». Отрицательным тестам нужны рабочие контроли до/после. Опасные пути, которые нельзя безопасно воспроизвести на личном телефоне, проверяйте по коду и регрессионными тестами. Результаты: PASS, FAIL, BLOCKED, NOT TESTED, N/A с причиной; не подменяйте запуск на устройстве чтением исходников.
Остановите приёмку при необъяснённом crash, потере данных, обходе auth/trust, неверной подписи/ABI, неработающем forwarding или непроверенной затронутой migration/lockdown. Сохраните исходный отказ, исправьте общую причину с регрессионным тестом, повторите воспроизведение и соседние затронутые пути. Восстановите устройства и удалите временный доступ/файлы даже после сбоя. Отдельный каталог отчётов не нужен.
Обычный smoke подписанного APK планируйте на 20–30 минут: обновление с сохранением настроек, реальный трафик, Stop/reconnect, изменённый экран и просмотр crash/ANR. Это бюджет, а не разрешение пропустить упавшую или заблокированную критическую проверку.
- Один подходящий телефон. Дополнительное устройство/API — только для затронутого platform-specific пути.
- Только затронутые строки таблицы; только соответствующие transports/hops вместо полного cross-product.
- Используйте CI точного кандидата для детерминированной логики, transport matrices и интеграции API 26/35; вручную не повторяйте их без конкретного пробела или воспроизведения ошибки.
- Для smoke скорости — 10 MB, для quota/error — синтетические фикстуры. Не нужны повторные публичные замеры скорости/репутации ради заполнения отчёта. Длительная работа и физические переключения сети — только при изменениях, которые могут их затронуть.
- При воспроизводимом отказе остановитесь, сохраните доказательства и разберите причину. После исправления повторите воспроизведение и соседние затронутые пути, а не всю ручную матрицу.
- Отдельный committed report и инвентаризация четырёх устройств не нужны. В соответствующем PR/релизе укажите проверенную область, ошибки и существенные ограничения; устройство обязательно восстановите.
CI не меняется: сохраняются все наборы, scope rules и независимые API-проверки.
KeyboardInsetsDeviceTest проверяет геометрию полей с настоящей клавиатурой.
Он отказывается работать с net.megaproxy487: сначала соберите отдельное приложение
net.megaproxy487.keyboardreview. В нём используются тестовые профили, VPN не запускается.
Эти проверки конфигураций UI остаются локальными и не входят в интеграционные VPN-сценарии CI.
Перед запуском разблокируйте телефоны. Тестовая Activity удерживает экран включённым, не меняя системный тайм-аут.
bundle exec fastlane run gradle tasks:"assembleDebug assembleDebugAndroidTest" flags:"--no-daemon -I scripts/keyboard-review.gradle"
adb -s SERIAL install app/build/outputs/apk/debug/app-debug.apk
adb -s SERIAL install app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
adb -s SERIAL shell am instrument -w -r -e class net.megaproxy487.KeyboardInsetsDeviceTest -e language ru -e orientation landscape -e fontScale 2.0 net.megaproxy487.keyboardreview.test/androidx.test.runner.AndroidJUnitRunnerПроверьте эмуляторы API 26/35 и подключённые телефоны с их обычными клавиатурами:
портретную и альбомную ориентации, затем альбомную со шрифтом 200%; включите EN/RU.
Проверки охватывают поиск приложений, DoH, ошибочный порт с сообщением проверки,
интервал подписки и многострочный приватный ключ. Они требуют открытия настоящей
клавиатуры, достаточной высоты поля над ней и восстановления навигации после закрытия клавиатуры.
Также осмотрите ввод, видимость курсора и прокрутку. В коротком окне панель заголовка
скрывается на время ввода, а сообщения переходят в прокручиваемую форму. Аргументы ориентации и шрифта
влияют только на тестовую Activity. После проверки удалите только net.megaproxy487.keyboardreview.test
и net.megaproxy487.keyboardreview.
При изменении строгой проверки источника проверьте сохранение opt-in и статус до переподключения, недоступность на API 26 и реальный TCP/UDP/DNS через JNI на API 35 для обоих уровней. Блокировку неизвестного/устаревшего UID, повторное использование UDP-порта (немедленный отказ на расширенном уровне, фиксированное окно 1 секунду без продления на стандартном), Echo обоих семейств и сохранение ошибок MTU проверяют детерминированные native/JVM-тесты. Выключенный режим не устанавливает фильтрующие обёртки. Статус видимости не заменяет тест обхода другим UID; для ручного воспроизведения используйте контролируемое исключённое приложение.