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:
- O teste deve ser marcado com o valor de metadados 'ProcessUnderTest'. Isso permite que a UMM identifique o processo que está sendo testado.
- 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;
- Se houver várias instâncias do processo nomeado em execução, a instância descoberta primeiro será usada.
- 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.
- 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:
- O teste é executado sem problemas. Este é o melhor resultado possível.
- 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'.
- 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.