UI-тест без UI-потока: зелёная галочка, которой нельзя верить

MSTest 4.5 и MTP 2.5 запускают тесты WinUI 3 и UWP в UI-потоке приложения. Почему STA мало и как проверить свои тесты.

  • Что произошло
  • Что сообщила Microsoft
  • Почему STA-потока недостаточно
  • Что это значит для бизнеса

Что произошло

Команда .NET опубликовала в блоге Microsoft DevBlogs разбор UI-тестов для UWP и WinUI 3 на MSTest. Тезис: тест десктопного приложения должен идти через настоящий диспетчер UI этого приложения, а одного потока в режиме STA для этого мало. Тест, который проверяет приложение вне условий его реальной работы, даёт руководителю ложное чувство безопасности.

По нашему опыту, такая уверенность обходится дороже, чем честное отсутствие тестов: на неё опираются при решении о релизе.

Что сообщила Microsoft

  1. Начиная с MSTest 4.5 и Microsoft.Testing.Platform (MTP) 2.5 один и тот же подход к тестированию в UI-потоке работает для UWP и WinUI 3. В материале перечислены поддерживаемые модели приложений: классическое и современное UWP, а также упакованные варианты.

  2. Перечень в доступном нам фрагменте обрывается, поэтому полный список сверяйте по первоисточнику. В примере из статьи тест помечен атрибутом `[UITestMethod]`.

  3. Он асинхронный, делает `await Task.Yield()`, создаёт `Grid` и проверяет `grid.DispatcherQueue.HasThreadAccess`.

  4. Установка теста, асинхронный код внутри него и очистка выполняются с доступом к UI-потоку.

Почему STA-потока недостаточно

STA (single-threaded apartment) задаёт модель потоков для COM: объект живёт в одном потоке, и обращаться к нему нужно из этого же потока.

Наличие такого потока ещё не означает, что у него есть диспетчер, который принимает задачи интерфейса так, как это делает приложение. В WinUI 3 элементы управления привязаны к `DispatcherQueue`.

Если тест создаёт `Grid` в произвольном потоке, он проверяет другую систему: в проде есть очередь сообщений и определённый порядок выполнения, а в таком тесте их нет.

Практический эффект бывает двух видов

В первом тест проходит на чистом STA-потоке, а в приложении тот же код падает с ошибкой доступа из чужого потока.

Во втором тесты краснеют из-за особенностей окружения, и команда привыкает их игнорировать. В обоих случаях цвет результата перестаёт что-либо сообщать.

Что это значит для бизнеса

  1. Основные потери времени и денег приходятся на промежуток между «написал код» и «работает в проде».

  2. Автотесты нужны, чтобы сократить его и сделать предсказуемым.

  3. Время до результата (TTU, time to use) измеряется тем, как быстро изменение дошло до пользователя и ничего не сломало по дороге.

  4. Если UI-тесты запускаются в условиях, непохожих на боевые, релиз приходится проверять руками, а сами тесты остаются формальностью. У настольных приложений на WinUI 3 и UWP это заметнее: интерфейс меняется часто, асинхронного кода много, а ошибки потоков проявляются нерегулярно.

  5. Такие дефекты команды нередко ищут неделями, потому что их трудно воспроизвести.

  6. Тест в правильном потоке делает их воспроизводимыми.

Разобрать ваш контур интеграции

Как это устроено технически

  1. За простым атрибутом стоит нетривиальная инженерия.

  2. Раннер должен: - поднять окружение приложения и его диспетчер; - перенести выполнение теста в нужный поток; - сохранить асинхронную семантику, чтобы после `await` код продолжал работать в том же потоке; - выполнить инициализацию и очистку в том же контексте.

  3. Эту часть берёт на себя Microsoft Testing Platform, и разработчик пишет тест, который выглядит как обычный модульный.

  4. Простой интерфейс здесь стоит на сложной работе под капотом, и платить за неё приходится либо временем своих инженеров, либо зависимостью от готовой библиотеки.

Что делать командам на C# / .NET

  1. Мы работаем с C# / .NET и регулярно видим одни и те же ошибки в тестовых контурах. Вот проверка, которая быстро показывает, на чём стоит ваш набор тестов:

  2. Возьмите три самых болезненных дефекта за последний квартал, связанных с потоками или интерфейсом.

  3. Для каждого выясните, поймал бы его существующий автотест. Если нет, определите причину: окружение теста или отсутствие самого теста.

  4. Если причина в окружении, перенесите такие тесты в UI-поток приложения и сравните долю падений до и после. Это гипотеза, и проверять её нужно на своём коде.

Источник

не приводит цифр по сокращению дефектов, и мы их не обещаем. Подобные проверки мы встраиваем в контур разработки на проектах интеграции. В AI-native development они нужны особенно: когда код пишет и меняет ИИ-ассистент, тесты в боевых условиях остаются единственным независимым арбитром. Автор правок не может сам решать, достаточно ли написанного.

Вывод

Тест, запущенный вне среды работы приложения, проверяет вымышленную систему.

Поэтому метрика покрытия без вопроса «в каком окружении» говорит о качестве очень мало.

Спросите у своей команды, какая доля тестов идёт в условиях, повторяющих прод.

По ответу видно, чем заняты ваши инженеры: поставляют результат или поддерживают зелёную галочку.

Источник

«UWP and WinUI 3 apps: UI testing with MSTest», команда .NET, Microsoft DevBlogs: https://devblogs.microsoft.com/dotnet/testing-uwp-and-winui-3-apps-with-mstest/. Права на материал принадлежат автору; здесь он использован как повод для разбора.

Обсудить статью: UI-тест без UI-потока: зелёная галочка,…

Укажите email или телефон, чтобы мы могли вам ответить.

Отправить через: