Partilhar via


Monitor do Modo de Usuário

O Monitor do Modo de Usuário permite que os testes obtenham mais contexto sobre a execução do "processo em teste" para obter mais contexto para investigar falhas de teste ou para habilitar uma melhor verificação de testes existentes. A implementação atual do Monitor do Modo de Usuário fornece uma implementação básica, com mais personalização e configuração chegando em versões subsequentes.

Introdução

O UMM (Monitor de Modo de Usuário) usa API do Windows de baixo nível para ser notificado de todos os eventos de "depurador" originados de um determinado processo – início e parada de thread, carregamento de módulo, falhas e exceções tratadas para citar apenas alguns. Ao receber um evento de depurador, o código UMM pode executar uma das várias ações, incluindo registrar comentários em log, registrar erros (para falhar em um teste) ou até mesmo fazer um minidespejo do processo em teste.

Habilitando o Monitor do Modo de Usuário

Para habilitar o UMM para um determinado caso de teste, você precisa fornecer duas partes de configuração:

  1. O teste deve ser marcado com o valor de metadados 'ProcessUnderTest'. Isso permite que a UMM identifique o processo que está sendo testado.
  2. A linha de comando Te.exe deve incluir '/userModeMonitor' para ativar a funcionalidade UMM.

Os pontos a seguir devem ser levados em conta ao usar o código UMM;

  1. Se houver várias instâncias do processo nomeado em execução, a instância descoberta primeiro será usada.
  2. O usuário que está executando a automação de teste deve ter permissão suficiente para receber eventos do depurador do Processo em Teste.
  3. O código UMM será 'anexado' ao Processo em Teste após a execução de todos os acessórios de instalação e 'desanexar' antes que os acessórios de limpeza sejam executados. Isso permite que os acessórios de instalação de um teste iniciem o Processo em Teste e executem qualquer inicialização necessária para se preparar para o teste.

Monitor de modo de usuário com suporte 'Actions'

O Monitor do Modo de Usuário tem um conjunto de "Ações" que pode ser usado quando um determinado evento de depurador ocorre no processo monitorado. Na implementação atual, um determinado evento invocará apenas sua ação padrão; atualmente, não há suporte para configuração.

Ação Descrição
LogComment Adiciona um comentário ao log, com informações contextuais do evento.
LogError Registra um erro no log, o que falhará no teste atual.
Minidespejo Grava um minidespejo e salva-o no Log.
Ignorar Não faz nada.

Monitor de modo de usuário com suporte 'Eventos'

O Monitor do Modo de Usuário exibe "eventos" que podem aplicar uma das "ações" listadas acima. A tabela a seguir mostra a lista atual de eventos relatados, juntamente com a Ação padrão que será executada quando o evento for recebido.

Evento Ação padrão (ação padrão de segunda chance)
Criar thread Ignorar
Sair do thread Ignorar
Criar processo Ignorar
Processo de saída LogError
Carregar módulo LogComment
Descarregar módulo Ignorar
Erro de sistema Ignorar
Ponto de interrupção inicial LogError
Carregamento inicial do módulo Ignorar
Saída de depuração LogComment
Violação de acesso LogError (LogError)
falha de asserção LogError (LogError)
Travamento do aplicativo LogError (LogError)
Exceção de instrução de interrupção LogError
Exceção de instrução de interrupção continuar Ignorar
Exceção de EH do C++ LogError (LogError)
Exceção CLR LogError (LogError)
Exceção de notificação CLR LogError (Ignorar)
Control-LogError exceção LogError
Control-LogError exceção continuar Ignorar
Exceção Control-C LogError
A exceção Control-C continua Ignorar
Dados desalinhados LogError (LogError)
Exceção de comando do depurador Ignorar
Violação de página de proteção LogError (LogError)
Instrução ilegal LogError (LogError)
Erro de E/S na página LogError (LogError)
Integer divide-by-zero LogError (LogError)
Estouro de inteiro LogError (LogError)
Identificador inválido LogError
Continuar identificador inválido LogError
Sequência de bloqueio inválida LogError (LogError)
Chamada de sistema inválida LogError (LogError)
Porta desconectada LogError (LogError)
Travamento do serviço LogError (LogError)
Exceção de etapa única LogError
A exceção de etapa única continua Ignorar
Estouro de buffer da pilha LogError (LogError)
Estouro de pilha LogError (LogError)
Parada do verificador LogError (LogError)
Exceção do Visual C++ Ignorar (Ignorar)
Depurador de ativação LogError (LogError)
Ponto de interrupção WOW64 LogError (Ignorar)
Exceção de etapa única WOW64 LogError (Ignorar)
Outra exceção LogError (LogError)

Exemplo

Para ilustrar o uso da funcionalidade UMM, vamos dar uma olhada em um exemplo (ligeiramente inventado) de um teste que automatiza '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;
    }
}

Aqui está um detalhamento rápido da estrutura do teste:

  • O teste 'SimpleInteraction' representa um teste que interage com um aplicativo baseado em interface do usuário - nesse caso, é "MSPaint.exe". Observe que os metadados "ProcessUnderTest" foram aplicados para chamar que esse teste está testando o processo de "mspaint.exe".
  • O teste tem uma instalação que garante que não há instâncias pré-existentes em execução e inicia uma única instância para testar.
  • O teste também tem um acessório de limpeza que fecha a instância que foi iniciada no acessório de instalação.

O "teste" é muito direto, vamos examinar os possíveis resultados:

  1. O teste é executado sem problemas. Este é o melhor resultado possível.
  2. Sem o UMM habilitado, um usuário fecha a instância do MSPaint durante a execução. Nesse caso, o teste será aprovado, mas a limpeza falhará com 'InvalidOperationException'.
  3. Com o UMM habilitado, um usuário fecha a instância do MSPaint durante a execução. Nesse caso, o código UMM registrará um erro mostrando que o processo foi fechado falhando no teste. A limpeza falha como no caso (2).

Com o UMM habilitado, o comportamento errante é relatado imediatamente e afeta diretamente o resultado do teste. Esse é um padrão de teste muito melhor, pois os erros são relatados o mais cedo possível e o contexto extra é fornecido para ajudar na depuração ou no entendimento de falhas de teste.