Como posso testar uma unidade GUI?

154

Os cálculos no meu código são bem testados, mas como há muito código da GUI, minha cobertura geral é menor do que eu gostaria. Existem diretrizes sobre o código da GUI de teste de unidade? Isso faz algum sentido?

Por exemplo, existem gráficos no meu aplicativo. Não consegui descobrir como automatizar o teste dos gráficos. É preciso um olho humano, AFAIK, para verificar se o gráfico está correto.

(Estou usando o Java Swing)

Steve McLeod
fonte
1
Há um ótimo artigo sobre diferentes arquiteturas de GUI de Martin Fowler ( martinfowler.com/eaaDev/uiArchs.html ). Ele descreve as compensações da arquitetura da GUI em termos de teste de unidade.
Roman Hwang
1
Atualmente, essa pergunta seria melhor feita em programmers.stackexchange.com (e provavelmente está fora de tópico no Stack Overflow, por ser muito ampla), mas as perguntas antigas não podem ser migradas. A questão de saber se pertence aqui de lado, o problema permanece interessante e difícil.
Mark # Amery #
1
Seria ótimo ter exemplo com algum código GUI e JUnit.
Witold Kaczurba 27/10
1
Eu diria apenas relaxe e não se incomode. O esforço realizado em testes de unidade nem sempre acaba sendo produtivo.
codeulike
Ainda questão antiga, você pode testar o fluxo na GUI usando Jubula
Abi

Respostas:

68

Projetos como MVP e MVC geralmente tentam abstrair o máximo de lógica possível da GUI real. Um artigo muito popular sobre isso é "The Humble Dialog Box", de Michael Feathers. Pessoalmente, tive experiências variadas com a tentativa de mover a lógica para fora da interface do usuário - às vezes funcionou muito bem e, outras vezes, tem sido mais problemas do que vale a pena. É um pouco fora da minha área de especialização.

Jon Skeet
fonte
??? "às vezes funcionou muito bem, e outras vezes tem sido mais problemático do que vale a pena" Muito estranho, porque a maioria das novas linguagens tende a ser orientada para MVC ... o que é uma lógica fora do gui (modelo-visual) ...
Patrick Desjardins
14
Ainda assim, a lógica de apresentação estará na GUI. Às vezes, isso pode estar longe de ser trivial.
Andrea
Tratamento de Martin Fowler do conceito (no caso de sua rede, como o meu, filtra archive.org): martinfowler.com/eaaDev/uiArchs.html#HumbleView
Christopher Berman
@ c24w obrigado por puxar o espelho, você é o verdadeiro MVP :)
John Baker
38

Obviamente, a resposta é usar o MVC e mover o máximo de lógica possível da GUI.

Dito isto, ouvi de um colega de trabalho há muito tempo que, quando a SGI estava portando o OpenGL para um novo hardware, eles fizeram vários testes de unidade que atraíam um conjunto de primitivos para a tela e depois computavam uma soma MD5 do buffer de quadros. Esse valor pode ser comparado aos bons valores de hash conhecidos para determinar rapidamente se a API é precisa por pixel.

dicroce
fonte
3
Eu gosto dessa abordagem. Difícil de configurar e manter, mas me daria os recursos de teste de regressão necessários.
Steve McLeod
7
danatel você perdeu o ponto. OpenGL é uma API de renderização gráfica de pixels com precisão. As estruturas de aplicativos da GUI, como o Qt, serão altamente dependentes do cromo do sistema, portanto, hash do buffer de quadros não é uma boa abordagem.
21720 Bob Somers
1
Um MD5? O que um hash criptográfico tem a ver com isso? Como a segurança está envolvida? Um hash, OK, é uma ótima idéia para gráficos perfeitos em pixels, mas um hash criptográfico? Você pode usar hashes mais rápidos que não são criptográficos e cuja probabilidade de colisão é insignificante. Você tem certeza de que era um hash criptográfico e não simplesmente um hash? (para além de que, nos dias de idade de computação paralela, algoritmo de hashing [utilizados para fins não-criptográficas] que não podem ser paralelizadas deve ser encarado com suspeita)
SyntaxT3rr0r
24
@ SyntaxT3rr0r: Que função de hash você recomendaria neste tipo de aplicativo não relacionado à segurança e que nível de ganho de desempenho se poderia esperar em comparação ao MD5?
Lèse majesté
1
Você responde significa "nunca crie sua GUI e, portanto, não a teste". Legal.
Dims
10

Você pode experimentar o UISpec4J é uma biblioteca de código-fonte funcional e / ou de testes de unidade para aplicativos Java baseados em Swing ...

CMS
fonte
2
Comecei a usar o UISpec4J por um mês ou mais para realizar testes de validação de requisitos nas GUIs do Java Swing. Eu tenho gostado muito até agora.
Bassam
O github.com/UISpec4J/UISpec4J afirma que seu link é o site oficial, mas não me parece oficial. Tudo o que vejo é um blog sobre vlogging
lucidbrot
7

Existe o Selenium RC , que automatizará o teste de uma interface do usuário baseada na Web. Ele gravará ações e as reproduzirá novamente. Você ainda precisará percorrer as interações com sua interface do usuário, portanto isso não ajudará na cobertura, mas pode ser usado para compilações automatizadas.

David Robbins
fonte
7

Você pode tentar usar o Cucumber e o Swinger para escrever testes de aceitação funcional em inglês simples para aplicativos da GUI Swing. O Swinger usa a biblioteca Jemmy do Netbeans sob o capô para dirigir o aplicativo.

Pepino permite que você escreva testes como este:

 Scenario: Dialog manipulation
    Given the frame "SwingSet" is visible
    When I click the menu "File/About"
    Then I should see the dialog "About Swing!"
    When I click the button "OK"
    Then I should not see the dialog "About Swing!"

Dê uma olhada nesta demonstração em vídeo do Swinger para vê-la em ação.

Dema
fonte
6

Aqui estão algumas dicas:

Tente remover o máximo de código possível da GUI (possui controlador e objeto de modelo) dessa maneira, para poder testá-los sem a GUI.

Para o gráfico, você deve testar o valor que você fornece ao código que gera o gráfico.

Patrick Desjardins
fonte
6

Testar é uma forma de arte. Concordo que a lógica deve ser removida a GUI, tanto quanto possível. Podemos então focar nossos testes de unidade lá. Como qualquer outra coisa, testar é reduzir riscos. Você nem sempre precisa testar tudo, mas muitas vezes a melhor coisa é dividir os diferentes testes em diferentes áreas.

A outra pergunta é o que você realmente está tentando testar na camada da interface do usuário. O teste da interface do usuário é o teste mais caro, porque geralmente leva mais tempo para criar, manter e é o mais frágil. Se você testar a lógica para saber se as coordenadas estão corretas antes de tentar desenhar a linha, o que você está testando especificamente? Se você deseja testar um gráfico com uma linha vermelha, é desenhado. Você pode definir coordenadas pré-determinadas e testar se certos pixels são vermelhos ou não vermelhos? Conforme sugerido acima, as comparações de bitmap funcionam, mas o Selenium, mas meu foco principal, é não testar a GUI, mas testar a lógica que ajudará a criar a interface do usuário e, em seguida, focar em qual parte da interface do usuário é interrompida ou suspeita e focar alguns testes. há.

Charles Smith
fonte
3

Você pode usar o JFCUnit para testar sua GUI, mas os gráficos podem ser mais desafiadores. Em algumas ocasiões, tirei instantâneos da minha GUI e a comparei automaticamente com uma versão anterior. Embora isso não forneça um teste real, ele alerta se uma construção automática falha ao produzir a saída esperada.

Steve Moyer
fonte
3

O que eu deduzo da sua pergunta é que você está procurando uma maneira automatizada de testar o comportamento da GUI em detalhes; o exemplo que você dá é testar se uma curva é realmente desenhada corretamente.

As estruturas de teste de unidade fornecem uma maneira de realizar testes automatizados, mas acho que o tipo de teste que você deseja fazer é um teste de integração complicado que verifica o comportamento correto de várias classes, entre as quais as classes do seu kit / biblioteca de GUI, que você não deve querer testar.

Suas opções dependem muito de quais plataformas / kits de ferramentas / estruturas você usa: por exemplo, um aplicativo usando o Qt como sua estrutura da GUI pode usar o Squish para automatizar seus testes. Você verifica os resultados dos seus testes uma vez e os testes executados automaticamente subsequentes comparam os resultados com os resultados verificados.

andreas buykx
fonte
2

Janela Licker para Swing & Ajax

robi-y
fonte
2

Minha abordagem ao teste de GUI está evoluindo, assim como o consenso do setor. Mas acho que algumas técnicas importantes estão começando a surgir.

Eu uso uma ou mais dessas técnicas, dependendo da situação (por exemplo, que tipo de GUI é, com que rapidez precisa ser criada, quem será o usuário final etc.).

  1. Teste manual. Você sempre tem a GUI em execução enquanto trabalha no código e garante que ela esteja sincronizada com o código. Você testa e testa manualmente novamente a parte em que trabalha, alternando entre o código e o aplicativo em execução. Toda vez que você conclui uma parte significativa do trabalho, você faz um teste geral para toda a tela ou área do aplicativo, para garantir que não haja regressões.

  2. Teste de unidade. Você escreve testes para funções ou pequenas unidades de comportamento da GUI. Por exemplo, seus gráficos podem precisar calcular diferentes tons de uma cor com base em uma cor 'base'. Você pode extrair esse cálculo para uma função e escrever um teste de unidade para ele. Você pode procurar por uma lógica como essa na GUI (especialmente lógica reutilizável) e extraí-la em funções discretas, que podem ser mais facilmente testadas em unidade. Mesmo comportamentos complexos podem ser extraídos e testados dessa maneira - por exemplo, uma sequência de etapas em um assistente pode ser extraída para uma função e um teste de unidade pode verificar se, dada uma entrada, a etapa correta é retornada.

  3. Explorador de componentes. Você cria uma tela 'explorer' cuja única função é mostrar cada um dos componentes reutilizáveis ​​que compõem sua GUI. Essa tela fornece uma maneira rápida e fácil de verificar visualmente que cada componente tem a aparência e a sensação corretas. O explorador de componentes é mais eficiente do que passar manualmente por todo o aplicativo, porque A) você só precisa verificar cada componente uma vez e B) não precisa navegar profundamente no aplicativo para ver o componente, basta visualizar e verifique imediatamente.

  4. Teste de automação. Você escreve um teste que interage com a tela ou componente, simulando cliques do mouse, entrada de dados etc., afirmando que o aplicativo funciona corretamente, dadas essas manipulações. Isso pode ser útil como um teste de backup extra, para capturar possíveis erros que outros testes podem perder. Costumo reservar testes de automação para as partes da GUI mais propensas a quebrar e / ou altamente críticas. Peças onde eu quero saber o mais cedo possível se algo quebrou. Isso pode incluir componentes interativos altamente complexos, vulneráveis ​​a interrupções ou telas principais importantes.

  5. Teste de diferença / instantâneo. Você escreve um teste que simplesmente captura a saída como uma captura de tela ou como código HTML e a compara com a saída anterior. Dessa forma, você será alertado sempre que a saída for alterada. Testes difíceis podem ser úteis se o aspecto visual da sua GUI for complexo e / ou sujeito a alterações; nesse caso, você deseja obter um feedback rápido e visual sobre o impacto de uma determinada alteração na GUI como um todo.

Em vez de usar intensamente todos os tipos de testes possíveis, prefiro escolher a técnica de teste com base no tipo de coisa em que estou trabalhando. Então, em um caso, extrairei uma função simples e a testo na unidade, mas em outro caso, adicionarei um componente ao explorador de componentes, etc. Depende da situação.

Não achei a cobertura de código uma métrica muito útil, mas outros podem ter encontrado um uso para ela.

Eu acho que a primeira medida é o número e a gravidade dos bugs. Sua primeira prioridade é provavelmente ter um aplicativo que funcione corretamente. Se o aplicativo funcionar corretamente, deve haver poucos ou nenhum erro. Se houver muitos ou graves erros, presumivelmente, você não está testando ou seus testes não são eficazes.

Além de reduzir bugs, existem outras medidas, como desempenho, usabilidade, acessibilidade, capacidade de manutenção, extensibilidade etc. Elas diferem dependendo do tipo de aplicativo que você está construindo, dos negócios, do usuário final etc.

Tudo isso é baseado em minha experiência e pesquisa pessoal, além de uma excelente descrição dos testes de interface do usuário de Ham Vocke .

Jonathan
fonte
1

Pelo que sei, isso é bastante complicado e depende muito do idioma - vários idiomas têm seu próprio modo de testar a GUI, mas se você realmente precisa testar a GUI (em oposição à interação modelo / GUI), geralmente precisa simule um usuário real clicando nos botões. Por exemplo, a estrutura SWT usada no Eclipse fornece SWTBot , o JFCUnit já foi mencionado, a Mozilla tem sua própria maneira de simular isso no XUL (e pelo que li em seus blogs, esses testes parecem bastante frágeis).

Às vezes, é necessário fazer uma captura de tela e testar a renderização perfeita em pixels (acredito que o Mozilla faz isso para verificar se há páginas renderizadas corretamente) - isso requer uma configuração mais longa, mas pode ser o que você precisa para os gráficos. Dessa forma, quando você atualiza seu código e um teste é interrompido, você deve verificar manualmente a imagem se a falha foi real ou aprimorou o código de renderização do gráfico para gerar gráficos mais bonitos e precisa atualizar as capturas de tela.

Kim Sullivan
fonte
0

Se você estiver usando o Swing, o FEST-Swing é útil para direcionar sua GUI e testar as asserções. Torna bastante simples testar coisas como "se eu clicar no botão A, a caixa de diálogo B deve ser exibida" ou "se eu selecionar a opção 2 no menu suspenso, todas as caixas de seleção serão desmarcadas" .

O cenário gráfico que você mencionou não é tão fácil de testar. É muito fácil obter cobertura de código para componentes da GUI apenas criando e exibindo-os (e talvez direcionando-os com o FEST). No entanto, fazer afirmações significativas é a parte mais difícil (e a cobertura do código sem afirmações significativas é um exercício de auto-engano). Como você testa se o gráfico não foi desenhado de cabeça para baixo ou muito pequeno?

Eu acho que você só precisa aceitar que alguns aspectos das GUIs não podem ser testados efetivamente por testes de unidade automatizados e que você precisará testá-los de outras maneiras.

Dan Dyer
fonte
0

Não é seu trabalho testar a biblioteca da GUI. Portanto, você pode evitar a responsabilidade de verificar o que é realmente desenhado na tela e, em vez disso, verificar as propriedades dos widgets, confiando na biblioteca que eles representam com precisão o que é desenhado.

ivan_pozdeev
fonte