Como estruturar testes de unidade para um aplicativo GUI usando C # e NUnit


16

Me pediram para fazer um pequeno projeto paralelo para fornecer um aplicativo simples a um de nossos clientes. Normalmente, eu trabalhava no código de back-end em que todas as minhas necessidades de teste foram descobertas e ainda não tive o prazer duvidoso de escrever testes para a GUI, por isso não é claro para mim como devo configurar o código de teste e as ferramentas para um EXE.

Meu primeiro instinto foi simplesmente incluir os testes com o código do aplicativo, no entanto, isso exigiria o fornecimento de várias dependências específicas do teste, as quais fui instruído a não enviar especificamente para o cliente. Também não consigo extrair dinheiro para uma ferramenta de teste criada para fins específicos, por isso preciso usar as ferramentas que tenho em mãos ( StoryQ , RhinoMocks e NUnit), que realmente deve ser mais do que suficiente para testar o comportamento de um aplicativo GUI simples. Até onde eu posso ver, isso me deixa tentando encontrar um bom equilíbrio entre manter o design realmente simples, ou fazer uma engenharia de propósito intencional em prol dos testes. Parece que estou construindo o aplicativo com a lógica de negócios em uma biblioteca separada e testando-a como normalmente, ou encontrando algum outro mecanismo para permitir o executável sem quebrar módulos adicionais que o design do aplicativo não faz realmente preciso.

Edit:
Observe que esta pergunta é sobre como estruturar o relacionamento entre o NUnit e o meu executável - em oposição a uma DLL - e não sobre como separar a apresentação e a lógica de negócios.
/Editar

Então, minha pergunta é:

  1. Existe um método específico / recomendado para configurar um aplicativo GUI simples com testes de unidade para me permitir verificar adequadamente o estado e o comportamento, usando as ferramentas que tenho à mão e sem recorrer à engenharia em excesso?
  2. Perdi algo fundamental sobre a maneira como o NUnit deve ser chamado / configurado ao testar um EXE (em vez de uma DLL)?
  3. Você pode me fornecer ou apontar exemplos de como conseguir tudo isso?

Sei que pode haver mais de uma maneira de fazer isso, por isso estou procurando diretrizes de implementação específicas com base na sua experiência.


O NUnit não foi projetado para testar as GUIs diretamente. Você precisa separar sua camada de apresentação (ou seja, a visualização) dos dados e a lógica de negócios (ou seja, modelo) para poder testar o que entra na sua visualização sem usar a visualização.
Bernard

1
@ Bernard Esta questão não é sobre a criação de uma GUI para teste. Eu naturalmente coloco todos os meus aplicativos em camadas - mesmo os triviais - para que realmente não seja um problema para mim. Eu editei a pergunta para adequá-la e espero que ela esclareça quaisquer equívocos. :)
S.Robins

1
Não há nada terrivelmente complicado em coisas de teste de unidade nos EXE. Basta fazer com que a sua DLL de teste faça referência ao seu arquivo EXE e você estará pronto.
Whatsisname

Respostas:


3

Mencionei em um de meus comentários à resposta de simoraman que havia pensado em algumas maneiras de fazer isso. Uma das minhas opções era semelhante à sugestão na resposta de Jalayn de criar um projeto duplicado e gerar uma DLL, enquanto minha outra idéia era simplesmente vincular os arquivos no projeto em que havia o código que eu queria testar. Embora seja possível que ambas as opções funcionem, elas são inferiores ao ideal.

No segundo caso, eu teria uma confusão de dependências de unidade para gerenciar, a menos que eu pudesse separar a arquitetura para minimizar as dependências. Isso é bom para projetos menores, mas os maiores podem facilmente se tornar uma bagunça real de gerenciar. Minha maior resistência a essa opção, porém, é a pura deselegância dela. Claro que eu poderiafazê-lo funcionar, mas, ao fazer isso, eu preciso efetivamente quebrar o encapsulamento para testar os internos de um assembly diretamente via fonte, em vez de testar as interfaces públicas, o que, na minha opinião, é um grande não-não. Da mesma forma, ter um arquivo de projeto adicional significaria duplicar esforços em dois projetos por vez ou encontrar uma maneira de adicionar configurações de arquivo de projeto automaticamente a dois arquivos por vez ou lembrar-se de copiar e renomear o campo do projeto toda vez que eu criar. Talvez isso possa ser automatizado no servidor de compilação, mas seria uma tarefa difícil de gerenciar no IDE. Mais uma vez, pode funcionar, mas na melhor das hipóteses é um incômodo e, se você entender errado, é um incômodo.

A melhor maneira parece ser fazer o que está comentado na minha pergunta e simplesmente incluir o EXE como uma referência no projeto de teste. Acontece que um EXE é efetivamente tratado da mesma maneira que uma DLL nesse caso, e eu posso acessar todas as minhas classes em camadas para testar o que flutua no meu barco.


2

Eu penso isso:

  • Seu código de teste de negócios deve estar em um projeto separado, testando sua biblioteca de códigos de negócios.
  • Seu código de teste da GUI deve estar em um projeto separado, testando sua biblioteca da GUI. Agora, como criar uma biblioteca GUI em vez de um executável, tento responder mais tarde.
  • Se você possui um my.namespace.biz.MyClass, sua classe de teste deve ser my.namespace.biz.MyClassTest (ou MyClassTestCase).
  • Se você quiser testar o código encontrado no seu destino executável, deverá ter uma instalação que crie um EXE e outra que crie uma biblioteca (DLL), na qual você iniciará os testes.

Estas são as regras que eu gosto de seguir, seja Java ou C # (exceto que não há nenhum problema de EXE no Java, é claro :-))

Quanto a como configurar seu ambiente de teste, parece-me que você tem pelo menos essas duas opções:

Usando o MSBuild

Crie um clone do seu arquivo .proj (por exemplo, myproject-as-dll.proj ). Altere o OutputTypearquivo clonado de " EXE" para " Library". Agora, usando o comando MSBuild, você pode produzir uma biblioteca que pode ser definida como referência em seu projeto, contendo casos de teste do NUnit.

Parece-me possível, mas nunca o usei com tanta honestidade, por isso não tenho certeza. Além disso, você pode não ter o MSBuild no servidor de teste de integração e não sei se ele pode ser separado do Visual Studio ...

Usando NAnt

Se você não estiver familiarizado com o NAnt, precisará pesquisar no Google como configurar o seu projeto. Talvez verifique isso , é um pouco antigo, mas o autor comentou os arquivos NAnt e, se achar auto-explicativo ( Editar: examinando seu arquivo com mais detalhes, acho seu arquivo de configuração extremamente reutilizável ). Ele também faz muito mais do que apenas construir, pois executa casos de teste e lança ferramentas de cobertura de código. Agora, admito que nunca usei o NAnt, ao contrário do pai e do pai "Ant" de Java, que usei muito, mas vejo que é exatamente a mesma coisa e não acho difícil aprender isso.

Com essa ferramenta, você pode criar uma configuração que permita:

  • construa todos os seus projetos (lógica de negócios, GUI etc.) em bibliotecas separadas
  • construa seus projetos de teste
  • inicie os testes (essa parte específica é feita com a tarefa NUnit2 ).
  • examine sua cobertura de código com a tarefa NCover .

Com um pouco mais de código, você pode até:

  • execute implantações noturnas no servidor de integração
  • se o NAnt estiver disponível no servidor de integração, inicie os testes noturnos de integração com a ajuda de tarefas agendadas

Tudo é feito sem alterar nada nos arquivos do Visual Studio. E, na verdade, para mim não me parece excesso de engenharia, é apenas um arquivo. Pode levar um, talvez dois dias para fazer tudo funcionar, mas você terá, em minha opinião, uma boa configuração.

Por fim, daria ao cliente tudo o que é necessário para construir, testar e executar os projetos. Costumo pensar que isso mostra o seu profissionalismo e o fato de você escrever código com qualidade em sua mente (o que me parece que você faz desde que procura soluções elegantes)


0

Só porque o projeto é pequeno (inicialmente) não significa que a arquitetura adequada exagere na engenharia. O fato de você querer escrever testes informa que seu projeto não é um hack único e trivial.

Você não mencionou qual GUI-Framework você está usando. O WPF MVVM (Model-View-ViewModel) é bom e permite que você escreva testes para toda a lógica com bastante facilidade. Com o WinForms, ouvi coisas boas sobre o MVP (Model-View-Presenter)


Escrevo testes para todo o código que escrevo. Até as coisas que você pode achar trivial. A única vez em que não escrevo um teste é quando pico. Nesse caso, estou enviando uma utilidade única a um cliente; portanto, o teste é mais do que apenas um luxo, é um requisito para satisfazer nossos padrões de qualidade. Em termos de "excesso de engenharia", essa não é uma escolha entre arquitetura boa ou ruim, mas evita a necessidade de impor camadas adicionais que não são necessárias nesse caso, pois o aplicativo é de finalidade única com um ciclo de vida relativamente curto.
precisa saber é o seguinte

No que diz respeito à escolha do gui-framework, não vejo como isso afetará a maneira como o ambiente de teste é configurado. Estou procurando COMO especificamente implementar testes de unidade para a camada da GUI usando as ferramentas que tenho disponíveis. Essa resposta em particular não me diz nada sobre isso.
S.Robins

Simoraman - Se você retirasse o primeiro parágrafo bastante crítico, isso estaria chegando a uma resposta. Corrija isso e eu removerei meu -1. @ S.Robins note que o segundo parágrafo é relevante - embora não seja uma resposta completa, ajudaria. Se sua camada da GUI é fina, bem estruturada e óbvia, e toda a lógica de negócios é testada por testes de unidade no nível do Modelo, pode ser que você não precise passar pelo incômodo extra de testar explicitamente a UI.
Mark Booth

1
@ MarkBooth Layering não é realmente um problema. Como simiraman menciona, eu posso MVP, MVVM ou posso criar algo ainda mais fino. No entanto, tenho alguns elementos específicos da GUI que exigirão testes explícitos, motivo pelo qual decidi escrever isso como uma pergunta. Tenho algumas idéias e, se piorar, sei que, eventualmente, poderei resolver o problema e redigir uma resposta. No entanto, eu queria abrir isso para a comunidade, pois pensei que seria uma boa pergunta para o ProgrammersSE. ;-)
S.Robins

0

Dê uma olhada na minha resposta nesta pergunta: Como configurar o MVP para uma solução WinForms?

Na verdade, escrevi um aplicativo de exemplo que mostra como eu estrato e como testo minha GUI.

lendo sua edição: use um executor de teste que se integre ao seu ambiente de desenvolvimento. Eu uso o ReSharper.


Obrigado pela recomendação do ReSharper. Esta é uma ferramenta que eu uso no desenvolvimento. Infelizmente, isso não ajudará na execução dos testes no servidor de criação de integração. Também não me diz como configurar os testes da unidade para acessar o código em um exe durante o teste.
S.Robins

1
Informalmente, sim. O exe é apenas a visualização, que carrega o apresentador, modelos e modelos de visualização de uma biblioteca de classes como parte da inicialização do aplicativo. Pelo menos na minha solução, a exibição é burra o suficiente para que não a testemos com testes automatizados e apenas fazemos testes de aceitação para garantir que as coisas estejam corretas e os botões estejam onde deveriam estar. NUnit-testando uma DLL é muito fácil de fazer.
precisa saber é o seguinte

0

Eu havia escrito o Nunit WinForms há alguns anos (acho que há 6 anos). Uma coisa que me lembro especificamente é que, embora seja um caso de teste de unidade, ele também atua como um caso de teste de ponta a ponta. Às vezes, não há muito o que testar em um front end (um formulário simples). Portanto, mesmo que você esteja tentando testar uma caixa de mensagem aparecendo com o clique de um botão, você está involuntariamente testando vários outros métodos de outras camadas. Existem algumas coisas que você não pode automatizar também. A aparência, a sensação e a usabilidade não podem ser automatizadas usando o teste de unidade automatizado. Você precisará executar alguns testes manuais antes de liberar.


Se o seu cliente especificar que uma tela deve ter uma certa aparência ou mudar de uma certa maneira, você poderá testar essas coisas. Capturar especificações como testes é o cerne da metodologia BDD, e nunca encontrei uma situação em que você não pudesse - embora de forma criativa - encontrar um meio de automatizar um teste. A verdadeira questão é se os testes terão valor, se o aplicativo é fatorado o suficiente para permitir que você automatize todos os testes em primeiro lugar e se os testes serão rentáveis. Concordo, porém, que às vezes não são.
precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.