E2E Testing In Angular 2 From Zero To Hero (Final Part)
Dear futuros Mestres do Angular 2 E2E Testing.
É isto. Ao final desta lição você finalmente terá todas as ferramentas para criar testes funcionais para suas aplicações de Angular 2. Sem mais desculpas: Você tem o poder!
Primeiro vamos nos familiarizar com Locators, depois veremos como os Page Objects podem ser fantásticos, seguidos de como lidar com a assincronia e finalmente a parte mais fácil que está desencadeando as Actions.
Se você não tem o básico certo, vá para lá, senão você estará um pouco perdido.
Locators
Uma das coisas mais importantes no teste E2E é encontrar os elementos que você quer testar na sua visão. Na maioria das vezes, você vai se perguntar “por que não consigo encontrar este elemento ****?” seguido por um “oooohhhhh”.
Você tem muitas maneiras de fazer isso. A maioria delas depende da sua aplicação. Para obter seus elementos, você usará uma série de Localizadores. Na maioria das vezes, você pode encontrar seus elementos por:
- Nome da classe.
- Id.
- Modelo.
- Binding.
Para os próximos testes, nós usaremos este template.html:
<div class="parent2"> <div class="parent1"> <div class="nested-class" style="color:blue;"> I am a nested element </div> </div></div>
Sejamos focados nested-class e nested-id.
Por classe:
Aprovamos aqui o nosso elemento usando elemento(by.css(selector)) então testamos se ele está presente ou não.
Por Id:
it("should find the nested id", () => { let elem = element(by.id("nested-id")); expect(elem.getText()).toBe("I am a nested element");});
Pegamos aqui o nosso elemento usando elemento(by.id(elem-id)) então testamos se ele está presente ou não.
Os seguintes localizadores são muito úteis em AngularJS mas ainda não implementados em Angular 2 então apenas mantenha-os de lado por enquanto.
Por Modelo:
it("should find the model", () => { let elem = element(by.model("modelToFind")); expect(elem.isPresent()).toBeTruthy();});
Por Bindings:
it("should find the binding", () => { let elem = element(by.model("bindingToFind")); expect(elem.isPresent()).toBeTruthy();});
Para depurar seus testes, você pode simplesmente adicionar “browser.pause()” em seu teste, você será capaz de executar todas as instruções anteriores e parar onde você quiser.
Após chegar à sua pausa, você terá uma tela semelhante a esta:
Como você pode ver nesta imagem, para entrar no banco do motorista você precisa digitar repl.
Agora vamos dizer que você não tem nenhum teste e você só quer brincar com o Protractor. Você pode apenas digitar no seu terminal:
protractor --elementExplorer
Se você tiver alguns problemas com o seu caminho, você pode digitar:
./node_modules/protractor/bin/elementexplorer.js
Não é necessário digitar repl desta vez, basta usar o objeto do navegador e você está pronto para navegar!
Page Objects
E se você tiver testes que compartilham o mesmo cenário? Você vai copiar colar seu código em qualquer lugar? E se este cenário mudar? Agora você tem que percorrer todos os arquivos e fazer as modificações.
É aí que as Páginas Objetos se tornam muito úteis. Write Once, Share Everywhere!
Um Page Object é um objeto que contém os elementos e cenários relativos a uma página.
Primeiro um Page Object muito simples:
export class HomePage { nestedClass; constructor() { this.nestedClass = element(by.css(".nested-class")); }}
Então usamos no nosso teste:
Importamos o Page Object, criamos uma instância e depois usamos a sua propriedade.
As Aventuras Assíncronas
Agora meus amigos, vocês podem aceder a qualquer elemento da vossa página! Quero dizer quase :).
Haverá alguns casos especiais.
Se você teve (des)sorte de trabalhar com jQuery, você deve estar familiarizado com document.ready().
Pela natureza assíncrona do JavaScript, haverá casos em que você tentará acessar um elemento antes que ele ainda não tenha aparecido na página.
Para lidar com isso, você terá que usar um recurso do Protractor para esperar que seu elemento esteja pronto antes de procurá-lo.
Aqui está um exemplo mostrando um botão após um timeout expirar.
Primeiro a classe que contém o timeout:
export class Home { isHidden = true; triggerTimeOut = ((){ setTimeout(() => this.isHidden = false, 2250) })}
Então o template.html:
Temos aqui um botão que irá acionar nosso timeout, uma vez que o timeout expira, o texto é exibido.
Aqui estão os testes.
Encontramos o nosso botão, clicamos nele, tentamos encontrar o nosso texto MAS esperamos que ele não esteja presente.
E aqui está a forma como lidamos com este caso ;).
Usamos “browser.wait” combinado com “browser.isElementPresent” testando o nosso Locator. Após 5 segundos, o resto do código é executado. Não se esqueça de colocar um temporizador aqui, caso contrário seus testes serão bloqueados para sempre!
Então se um de seus elementos é suposto estar aqui mas você não pode obtê-lo, seu instinto instintivo deve dizer-lhe para lembrar o que você acabou de ler aqui.
Ações
Agora que você tem o seu elemento precioso, você fez 90% do trabalho!
>
Se você não conseguir encontrá-lo, é que sua aplicação não funciona como deveria (é por isso que fazemos testes) ou você precisa melhorar nos testes e passar menos tempo no Pokemon GO caçando dratinis perto de um rio à uma da manhã (todos nós já estivemos lá …).
>
Vamos continuar com as ações que você pode usar em um elemento. Aqui estão:
Estamos usando o Protractor que depende do WebDriver. Se você precisar de ações mais sofisticadas, você pode dar uma olhada no que está disponível aqui.
Vamos testar algumas delas.
Para o template.html:
<input type="text" />
Vamos jogar um pouco com a entrada de texto. Teste rápido, o que faz este teste (não leia a descrição)?
Solução: Nós recebemos nossa entrada, digitamos “Algum texto” dentro, testamos se temos o valor definido, limpamos e finalmente testamos se o valor está vazio.
Legisamente podemos nos perguntar qual é a melhor maneira de acionar as ações? Este link aqui mostra uma das falhas de usar JavaScript em vez de WebDriver.
A escrita segura em JavaScript é muito mais compacta mas vem com alguns riscos!
Você pode fazer o que quiser com um elemento. A melhor maneira de testá-lo é usar os combinadores que estão disponíveis. Porquê? Porque eles são elegantes e próximos à linguagem humana, exemplo:
expect(apples.length !== 0).toBe(true);
expect(apples).not.toBeEmpty();
Conclusion
Este foi o post final desta série, neste momento você tem 90% das habilidades para testar suas aplicações Angular 2. Você terá os outros 10% por experiência. Lembre-se, primeiro pegue seus elementos usando Locators, depois coloque aquele que pode ser replicado em um Page Object, se você não consegue encontrar seu elemento e tem certeza que ele está aqui, pode ser porque ele ainda não apareceu e você precisa lidar com a assincronia. Finalmente teste o **** a partir dos seus elementos com Actions.