Fixture "Webtest" para Fitnesse/Selenium

http://fitnesse.info/webtest/

Alguém esta usando ou experimentaram esta fixture para integrar o Fitnesse com o Selenium?
Caso sim, quais foram suas impressões?

Apesar de eu ter trabalhado com o autor dessa Fixture e até ter escrito alguns comandos que faltavam, eu não uso ela mais. Manter scripts de Selenium é um pé no saco, e FitNesse ajuda mas não resolve o problema.

O negócio é usar selenium-rc direto com Page Objects. Até escrevi um post sobre isso.

A idéia de PO é bem interessante e natural em projetos que são, por natureza, orientado a objetos. No entanto, algo que gosto do Fit(FitNesse) para os testes de aceitação é propiciar a colaboração e trazer isso em um ambiente informativo executável (colaborativo na visão do cliente + time de desenvolvimento).

Não sou fã tbm da idéia de sair rodando Selenium e capturando Scripts, isso seria uma mão inversa da idéia de acolher os critérios de aceitação “antes”.

Por isso, com a fixture do webtest não estou avaliando a utilização de PlainSeleniumTest, mas sim usar a DSL estendida da DoFixture, com o S-RC colaborando. Essas DSLs podem ser levantadas como critérios de aceite junto com o cliente (talvez nao em sua totalidade, mas as mais relevantes) e já estarem disponíveis para testar o comportamento da aplicação, sem precisar capturar script algum.

Na prática Ivan, você já enfrentou algum problema com isso?

Já encontrei vários problemas, não por causa do FitNesse, mas por causa de testar a partir da interface com o usuário: compatibilidade entre navegadores, tempo de execução dos testes, dificuldades para fazer setup/teardown em servidores remotos etc.

Hoje em dia eu tento me preocupar mais com regras de negócio do que interface com usuário. Nesse caso posso usar as classes do sistema diretamente nas minhas próprias Fixtures, rodando dentro de transações para facilitar o setup/teardown e tem funcionado que é uma beleza. Se a camada de apresentação não for a parte mais complicada do seu sistema, essa é uma ótima opção.

Ainda tenho testes em Selenium para validar workflows e coisas do tipo, mas tento mantê-los o mais light possível. Quanto mais eu puder evitá-los, melhor!

Sim, porém este é um ponto que nem mesmo Page Objects resolve, uma vez que se ele realizar chamadas ao Selenium-RC cai no mesmo problema. Esta é uma questão mais relacionadas com “o que testar”.

Encaro que os critérios de aceitação para as regras de negócio é super importante, porém a garantia que o resultado da regra (por exemplo) vai “sempre” ser exibido na interface conforme definido pelo cliente também é algo a se considerar. Se o cliente define que uma funcionalidade esta completa SE a página que exibe o cálculo da IRF exibe o resultado após a seleção via AJAX de um cpf … sendo que este DEVE aparecer em verde caso a restituição seja acima de R$100,00 e azul caso seja abaixo, é arriscado que isso não esteja coberto.

Caso o estado de alguns de seus objetos de negócios sejam conversacionais entre requisições web, por exemplo wizards, tbm acho prudente que a experiência via interface seja mantida (satisfazer um critério de aceitação para este caso “simulando” o ambiente talvez não seja justo).

[quote=Lezinho]Sim, porém este é um ponto que nem mesmo Page Objects resolve, uma vez que se ele realizar chamadas ao Selenium-RC cai no mesmo problema. Esta é uma questão mais relacionadas com “o que testar”.
[/quote]
Concordo. Page Object ajuda na hora escrever/manter os testes, mas não resolve todos os problemas.

[quote=Lezinho]
Encaro que os critérios de aceitação para as regras de negócio é super importante, porém a garantia que o resultado da regra (por exemplo) vai “sempre” ser exibido na interface conforme definido pelo cliente também é algo a se considerar. Se o cliente define que uma funcionalidade esta completa SE a página que exibe o cálculo da IRF exibe o resultado após a seleção via AJAX de um cpf … sendo que este DEVE aparecer em verde caso a restituição seja acima de R$100,00 e azul caso seja abaixo, é arriscado que isso não esteja coberto.

Caso o estado de alguns de seus objetos de negócios sejam conversacionais entre requisições web, por exemplo wizards, tbm acho prudente que a experiência via interface seja mantida (satisfazer um critério de aceitação para este caso “simulando” o ambiente talvez não seja justo).[/quote]

Nos dois exemplos que você deu a parte mais importante da história está na interface com usuário. Neste caso é sensato fazer os testes de aceitação cobrirem esta parte. Só que há muitos casos onde isso não é tão crítico.

Por exemplo, no caso do cálculo da restituição do IRF mesmo, o “como calcular” é definido no seu modelo, e não na interface. Neste caso eu usaria FitNesse para validar todas estas regras e Selenium apenas para ver se os resultados aparecem na hora e lugar certo.

Perceba que não estou dizendo que Selenium tem que ser abandonado e deve-se testar apenas regras de negócio com FitNesse. O que estou dizendo é que para muitos casos mesmo testes de aceitação não precisam ser feitos a partir da interface com o usuário.

Apropósito, uma abordagem que pode ser interessante é mesclar testes de interface e negócio em FitNesse. Neste caso ao invés de usar a fixture WebTest eu escreveria minhas próprias fixtures para atuarem como os Page Objects (usando selenium-rc por trás dos panos) para prover uma linguagem única na hora de escrever os testes de aceitação.

De fato o negócio merece, por si só, uma cobertura dedicada.
Separar os propósitos e finalidades de Acceptance Tests pode ser a fronteira sobre o domínio e a interface. Daí por diante, utilizar Page Objects ou DSLs vai depender de como a equipe esta fazendo o resto da cobertura.

[]'s

[quote=s4nchez]Apesar de eu ter trabalhado com o autor dessa Fixture e até ter escrito alguns comandos que faltavam, eu não uso ela mais. Manter scripts de Selenium é um pé no saco, e FitNesse ajuda mas não resolve o problema.

O negócio é usar selenium-rc direto com Page Objects. Até escrevi um post sobre isso.[/quote]

Gostei muito do post, mas queria fazer uma sugestão. No exemplo do Google, tem uma bola um pouco dividida de asserções entre o Page Object e o Teste. Você não acha que fica mais claro colocar todas as asserções no Teste?

Abraço,
Luiz

Nao entendi direito sua sugestao. Voce esta se referindo a esta checagem?

if (!"Google".equals(selenium.getTitle())) { throw new IllegalStateException("This is not the Google Home Page"); }

Neste caso eu prefiro lancar uma excecao porque nao estou na pagina que este Page Object representa. E eh melhor saber isso o mais cedo possivel, antes de comecar a usar o PO e ter que identificar todo tipo de comportamento estranho que os outros metodos vao ter se eu estiver na pagina errada.

De qualquer modo eu concordo contigo. Eh sempre melhor fazer o PO somente dar informacoes sobre a interface e encarregar os testes de verificarem estas informacoes.

+1 pra Page Objects. Trabalhava no mesmo projeto que o Simon Stewart quando a gente inventou esse treco, e ajuda MUITO a tornar os testes mais expressivos.

Estamos fazendo uma coisa igual em Ruby hoje em dia, e ta dando bem certo.

Uma unica armadilha que eh facil de cair eh desenhar os seus Page Objects pra so fazer uma coisinha de cada vez: eh facil ter uma pagina moderninha que usa AJAX e que pode estar em zilhoes de estados diferentes, e acabar com zilhoes de page objects diferentes pra representar as possiveis combinacoes. Eh uma armadilha dificil de identificar, mas que fica meio obvia depois que vc ve a explosao de classes no /spec/page :slight_smile:

Também concordo que os asserts tem que ficar no teste. Mas tem duas alternativas para isso.

@Test
public void criarUsuario() {
TelaUsuario tela = new TelaUsuario(selenium);
tela.criaUsuario("José");

// Usa direto o objeto do Selenium para verificar
selenium.assertTextPresent("Usuário Criado");

//ou

//Há um método no próprio PO que sabe verificar a mensagem.
tela.verificaMensagemDeUsuarioCriado();
}

O que vocês estão usando?

Eu usaria algo como:

assertEquals("Usuário Criado", tela.getResultado());
:wink: