Поделиться через


Монитор пользовательского режима

Монитор пользовательского режима позволяет тестам получать больше контекста о выполнении тестируемых процессов, чтобы получить больше контекста для исследования сбоев тестов или для обеспечения более эффективной проверки из существующих тестов. Текущая реализация монитора пользовательского режима предоставляет базовую реализацию с дополнительными настройками и конфигурацией, которые будут доступны в последующих выпусках.

Введение

Монитор пользовательского режима (UMM) использует низкоуровневые api Windows для уведомления обо всех событиях "отладчика", которые происходят из заданного процесса: запуск и остановка потока, загрузка модуля, сбои и обработанные исключения. После получения события отладчика код UMM может выполнить одно из нескольких действий, включая ведение журнала комментариев, ведение журнала ошибок (для того, чтобы не выполнить тест) или даже выполнить минидамп тестируемого процесса.

Включение монитора пользовательского режима

Чтобы включить UMM для конкретного тестового случая, необходимо предоставить два элемента конфигурации:

  1. Тест должен быть помечен значением метаданных ProcessUnderTest. Это позволяет UMM определить тестируемый процесс.
  2. Командная строка Te.exe должна включать "/userModeMonitor", чтобы включить функцию UMM.

При использовании кода UMM следует учитывать следующие моменты.

  1. Если запущено несколько экземпляров именованного тестового процесса, будет использоваться экземпляр, обнаруженный первым.
  2. Пользователь, выполняющий автоматизацию тестирования, должен иметь достаточные разрешения на получение событий отладчика из тестируемой обработки.
  3. Код UMM будет "присоединяться" к тестируемой процедуре после выполнения всех установочных приспособлений и "отсоединять" перед выполнением очисточных приспособлений. Это позволяет средствам настройки теста запустить тестируемый процесс и выполнить любую необходимую инициализацию для подготовки к тесту.

Поддерживаемый монитор "Действия" в пользовательском режиме

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

Действие Описание
LogComment Добавляет комментарий в журнал с контекстной информацией из события.
LogError Записывает ошибку в журнал, что приведет к сбою текущего теста.
Минидампа Записывает минидамп и сохраняет его в журнале.
Игнорировать Не выполняет никаких действий.

Поддерживаемый монитор пользовательского режима "События"

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

Событие Действие по умолчанию (второе действие по умолчанию)
Создание потока Игнорировать
Выход из потока Игнорировать
Процесс создания Игнорировать
Процесс выхода LogError
Загрузка модуля LogComment
Выгрузка модуля Игнорировать
Системная ошибка Игнорировать
Начальная точка останова LogError
Начальная загрузка модуля Игнорировать
Выходные данные отладчика LogComment
Нарушение прав доступа LogError (LogError)
Сбой проверочного утверждения LogError (LogError)
Зависание приложения LogError (LogError)
Исключение инструкции break LogError
Продолжение исключения инструкции break Игнорировать
Исключение C++ EH LogError (LogError)
Исключение CLR LogError (LogError)
Исключение уведомления CLR LogError (игнорировать)
исключение Control-LogError LogError
Control-LogError продолжение исключения Игнорировать
Исключение Control-C LogError
Продолжение исключения Control-C Игнорировать
Неправильное сопоставление данных LogError (LogError)
Исключение команды отладчика Игнорировать
Нарушение страницы "Защита" LogError (LogError)
Недопустимая инструкция LogError (LogError)
Ошибка страничного ввода-вывода LogError (LogError)
Целочисленное деление на ноль LogError (LogError)
Переполнение целых чисел LogError (LogError)
Недопустимый дескриптор LogError
Недопустимое продолжение дескриптора LogError
Недопустимая последовательность блокировки LogError (LogError)
Недопустимый системный вызов LogError (LogError)
Порт отключен LogError (LogError)
Зависание службы LogError (LogError)
Одношаговая исключение LogError
Продолжение одношагового исключения Игнорировать
Stack buffer overflow; LogError (LogError)
Stack Overflow LogError (LogError)
Остановка проверяющего средства LogError (LogError)
Исключение Visual C++ Игнорировать (игнорировать)
Отладчик пробуждения LogError (LogError)
Точка останова WOW64 LogError (игнорировать)
Одношаговая исключение WOW64 LogError (игнорировать)
Другое исключение LogError (LogError)

Примере

Чтобы проиллюстрировать использование функций UMM, давайте рассмотрим (слегка придуманные) пример теста, который автоматизирует MSPaint:

namespace UserModeMonitorExample
{
    using System;
    using System.Diagnostics;
    using System.Threading;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using WEX.Logging.Interop;
    using WEX.TestExecution;

    [TestClass]
    public class BasicExample
    {
        [TestInitialize]
        public void TestInitialize()
        {
            Process[] runningPaintInstances = Process.GetProcessesByName("mspaint.exe");

            Verify.IsTrue(runningPaintInstances.Length == 0, "There are no running instances of mspaint.exe");

            this.mspaintUnderTest = Process.Start("mspaint.exe");
        }

        [TestCleanup]
        public void TestCleanup()
        {
            // Close the 'mspaint under test' - if it's already gone, this will throw, but that's no big deal.
            this.mspaintUnderTest.CloseMainWindow();
        }

        [TestMethod]
        [TestProperty("ProcessUnderTest", "mspaint.exe")]
        [TestProperty("Description", "Shows how a test can be failed if the UI is closed from underneath the test.")]
        public void SimpleInteraction()
        {
            Log.Comment("If the 'user mode monitor' is enabled and mspaint.exe is closed,");
            Log.Comment("then this test will be failed.");
            Log.Comment("Sleeping for 5 seconds");

            Thread.Sleep(TimeSpan.FromSeconds(5));
        }

        private Process mspaintUnderTest;
    }
}

Ниже приведена краткая разбивка структуры теста.

  • Тест SimpleInteraction представляет собой тест, взаимодействующий с приложением на основе пользовательского интерфейса. В данном случае это "MSPaint.exe". Обратите внимание, что метаданные ProcessUnderTest были применены для вызова того, что этот тест тест тестирует процесс "mspaint.exe".
  • Тест содержит средство настройки, которое гарантирует отсутствие существующих экземпляров, и запускает один экземпляр для тестирования.
  • Тест также содержит средство очистки, которое закрывает экземпляр, запущенный в программе установки.

"Тест" очень прямой, давайте рассмотрим возможные результаты:

  1. Тест выполняется без проблем. Это наилучший возможный результат.
  2. Без включения UMM пользователь закрывает экземпляр MSPaint во время выполнения. В этом случае тест будет пройден, но очистка завершится ошибкой с ошибкой InvalidOperationException.
  3. При включенной UMM пользователь закрывает экземпляр MSPaint во время выполнения. В этом случае код UMM зановит в журнал ошибку, показывающую, что процесс завершился сбоем теста. Очистка завершается ошибкой в случае (2).

Если UMM включена, поведение с ошибками немедленно сообщается и напрямую влияет на результат теста. Это гораздо лучший шаблон тестирования, так как ошибки отображаются как можно раньше, и предоставляется дополнительный контекст для отладки или понимания сбоев тестов.