Recentemente, planejei um grande projeto de refatoração de CSS para fazer a transição de um grande site de comércio eletrônico de um design antiquado de 1024px para um design mais moderno e responsivo.
É claro que essa situação não é única. O design responsivo passou oficialmente dos blogs de experiência do usuário para o escritório da esquina – a Web será, a partir de agora, flexível.
Os perigos do desenvolvimento responsivo
À medida que entramos nessa era de construção para usabilidade em vários dispositivos, é importante mitigar as armadilhas comuns do desenvolvimento responsivo, que, entre outras, incluem:
-
O efeito multiplicador responsivo
Se antes o senhor achava que o CSS era peculiar, talvez queira se sentar para ver isso: O reequipamento do seu site com novos breakpoints responsivos multiplicará esse mistério por 2, 3 ou mais, especialmente se o senhor não puder usar uma estrutura testada em batalha, como Bootstrap, Foundation etc. -
Dragões adormecidos
Mesmo que o senhor se dê ao luxo de começar seu projeto css do zero, ao desenvolver seu css, os erros geralmente acontecem em pontos de interrupção que não podem ser vistos. Por exemplo, ao ajustar uma visualização móvel, a visualização de desktop pode sofrer uma regressão e, como os testes visuais exigem a manipulação física do tamanho e da posição de rolagem da janela de visualização do navegador, não é possível para um desenvolvedor detectar tudo. -
Morte por milhares de insetos
Se o senhor não estiver automatizando o teste de regressão visual, um grande trabalho de refatoração pode facilmente sobrecarregar um grupo de controle de qualidade com uma contagem desnecessariamente alta de bugs de CSS em um único sprint.
Respondendo ao desenvolvimento responsivo
A atitude responsável a ser tomada diante dessas exposições é atenuar os bugs visuais por meio de testes visuais automatizados, ou seja, nesse caso, comparar programaticamente as renderizações de conteúdo responsivo em diferentes tamanhos de viewport para garantir que as alterações feitas em um tamanho de tela não danifiquem o layout em outro tamanho de tela. Automatizar esse processo é fundamental, pois seu computador nunca se cansa de comparar o mesmo design repetidamente. Isso é fundamental para reduzir os bugs que vão para o processo de controle de qualidade ou, pior ainda, para a produção.
É aqui que o BackstopJS entra em cena. O BackstopJS é uma ferramenta simples, baseada em configuração, que facilita para o desenvolvedor automatizar o teste visual de vários URLs em vários tamanhos de tela. A ideia básica é a seguinte:
-
Primeiro, faça capturas de tela de referência
Depois que o senhor tiver uma implementação de CSS funcional, o BackstopJS obtém um conjunto de referência capturas de tela. Essas capturas de tela serão salvas para comparações posteriores. -
Teste seu CSS depois de fazer alterações:
Digamos que, na etapa 1 acima, o senhor tivesse uma visualização perfeita para desktop e, em seguida, começasse a trabalhar em uma visualização para celular. Depois de trabalhar na visualização móvel, o senhor pode executar um teste para garantir que nenhuma das alterações feitas na visualização móvel tenha prejudicado a visualização do desktop. -
Repetir
O senhor pode continuar repetindo o processo de referência/teste para garantir que esteja sempre avançando em todas as visualizações.
Essa abordagem se torna ainda mais eficaz ao fazer alterações em projetos existentes, nos quais o senhor deseja garantir que a adição de um novo recurso aos designs existentes não interromperá outras áreas.
O tempo é tudo
O caso de uso original do BackstopJS era testar várias páginas da Web estáticas, portanto, inicialmente, ele renderizava uma captura de tela logo após o carregamento de uma página solicitada. Isso funcionou muito bem para aplicativos grandes e principalmente estáticos do lado do servidor, mas e os aplicativos de página única e as páginas que usam aprimoramento progressivo? Nesses casos, precisamos informar explicitamente ao BackstopJS quando a página está pronta para o “close-up”.
Em sua versão mais recente (0.4.0), o BackstopJS aborda esse problema com duas novas opções de configuração: readyEvent
e delay
. Os readyEvent
especifica uma string (que é registrada no console pelo seu aplicativo) para aguardar antes de fazer uma captura de tela. O delay
especifica uma duração (em milissegundos) para aguardar antes de fazer uma captura de tela. Eles também podem ser usados juntos, caso em que o BackstopJS primeiro aguarda o readyEvent e depois aguarda a duração adicional do delay
para fazer a captura de tela.
Vamos ver isso em ação!
Um cenário óbvio em que o senhor gostaria de esperar antes de fazer uma captura de tela é quando está aguardando a conclusão de uma chamada ajax e o envio de informações para a exibição. Mas um cenário mais interessante (e possivelmente mais complicado) pode ser quando o senhor espera a conclusão de uma animação intersticial. Vamos dar uma olhada nesse caso…
Observação: este exercício requer a instalação do Node e do NPM, mais informações aqui
Preparei um aplicativo AngularJS simples para testarmos. Faça o download do arquivo myAngularProject.zip aqui e expanda o projeto em algum lugar em seu ambiente de desenvolvimento.
Vamos dar uma olhada no diretório do projeto:
Instalar o BackstopJS
Esse é o projeto AngularJS simples no qual trabalharemos. A próxima etapa é instalar o BackstopJS. Em seu terminal, cd
para seu ./myAngularProject
e execute
$ npm install backstopjs
O comando acima criará a estrutura de pastas ./node_modules/backstopjs
dentro do ./myAngularProject
como na figura abaixo.
Há três outras dependências para o BackstopJS. No momento, elas não estão incluídas no pacote BackstopJS.
Se o senhor ainda não tiver uma instância global atual do Gulp…
$ sudo npm install -g gulp
Se o senhor ainda não tiver uma instalação global atual do PhantomJS…
$ sudo npm install -g phantomjs
Se o senhor ainda não tiver uma instalação global atual do CasperJS…
$ sudo npm install -g casperjs
Revise nossos arquivos de projeto
Vamos dar uma olhada na página que vamos testar. Abra a página ./simple.html
.
Esse é o arquivo que usaremos em nossa demonstração de teste. Ele consiste em um título e duas caixas cinzas de conteúdo. Bastante simples…
Agora vamos examinar o arquivo de configuração do backstopjs. Abra o arquivo ./backstop.json
Esse é o arquivo de configuração que o BackstopJS procura ao executar testes em seu projeto. O primeiro nó: viewports
recebe uma lista de objetos de viewport que consiste em um nome e nas dimensões da viewport que estamos simulando – neste caso, estamos definindo três tamanhos. O segundo nó: scenarios
é uma lista de cenários para o teste em que especificamos o testName
, url
, DOM selectors
queremos testar e opcional readyEvent
e delay
parâmetros.
Observação: o parâmetro URL funciona como uma tag âncora href
propriedade. Se o senhor iniciar a string do caminho do arquivo com http://
o senhor obterá uma página em um domínio de Internet especificado. Se o senhor simplesmente digitar test/simple.html
o senhor estará fazendo uma solicitação de arquivo relativo que é relativo ao domínio ./node_modules/backstopjs/
por exemplo, ../../simple.html
refere-se ao arquivo na raiz do diretório myAngularProject
.
Portanto, com nosso projeto pronto e o BackstopJS carregado, vamos ao que interessa.
Execute nossos testes pela primeira vez
Primeiro, certifique-se de que seu diretório de trabalho seja ./myAngularProject/node_modules/backstopjs
Em seguida, crie arquivos de referência para o projeto…
$ gulp reference
…e imediatamente executar um teste:
$ gulp test
Quando a sequência de teste terminar, o BackstopJS deverá abrir os resultados no Chrome. Como não fizemos nenhuma alteração entre nossas telas de referência e nossas telas de teste, tudo deve passar…
Faça as alterações e teste novamente
Agora vamos fazer uma alteração. Abra o simple.html
novamente e descomente as linhas 30 a 38. Isso adicionará uma animação deslumbrante ao nosso aplicativo simples.
E o senhor deveria ver…
Eu sei. Deslumbrante, não é?
Então, vamos testar isto. Deveríamos obter um resultado muito diferente…
$ gulp test
Portanto, não entre em pânico – isso é totalmente esperado. Esses elementos estão faltando porque nossa captura de tela foi tirada assim que a página terminou de carregar. Mas precisamos esperar um pouco até que a animação esteja concluída para tirar as capturas de tela.
Aprimore as habilidades de comunicação de seu aplicativo
Então, quanto tempo devemos esperar? Na prática, com o desenvolvimento da Web, na maioria das vezes não sabemos. Normalmente, há todos os tipos de coisas assíncronas acontecendo na maioria dos aplicativos da Web e é realmente melhor se o aplicativo puder determinar quando toda a atividade dependente (por exemplo, chamadas ajax, animações, carregamento de fontes etc.) estiver concluída e, em seguida, enviar um sinal.
No nosso caso, isso já foi feito. Nosso aplicativo Angular está ouvindo o animationEnd
do segundo bloco de conteúdo e registrando o texto backstop.ready
no console.
Vamos tirar proveito disso e atualizar nosso backstop.json
para que o BackstopJS saiba quando o aplicativo é realmente pronto para ser avaliado.
Abrir ./backstop.json
novamente e altere o readyEvent
para "backstop.ready"
Agora vamos tentar novamente.
Primeiro, “abençoe” nossa alteração de configuração… (veja a nota abaixo sobre gulp bless
*)
$ gulp bless
E, em segundo lugar, execute novamente nosso teste novo e aprimorado…
$ gulp test
E Viola! (E com “Viola” quero dizer que todos os testes deveriam ter sido aprovados).
Em vez disso, poderíamos ter usado a propriedade delay – vá em frente e defina o readyEvent como nulo e altere o valor do delay para 2000. Veja o que acontece.
No final, o senhor pode preferir o método de evento ou o método de atraso ou ambos.
Resumindo
A esta altura, alguns dos senhores podem estar pensando, Ei, Garris, o BackstopJS é uma ferramenta legal e tudo mais, mas o senhor não mostrou como ele encontra bugs responsivos. A razão para isso é que já existem demonstrações por aí ilustrando esse assunto. Com essa demonstração, eu queria destacar as considerações especiais (e talvez não óbvias) sobre os testes visuais para aplicativos do lado do cliente (em oposição aos aplicativos do lado do servidor).
Essa técnica pode ser usada em todos os tipos de SPAs, cenários de aprimoramento progressivo e widgets de terceiros (por exemplo, Twitter, Facebook, ações, previsão do tempo, controles deslizantes de imagens de heróis etc.).
Como na maioria dos métodos de teste, é realmente útil ter stubs de dados para garantir que o senhor esteja sempre comparando maçãs com maçãs. Dito isso, para os casos em que isso não é possível, o BackstopJS também aceita uma lista negra de seletores DOM, de modo que o senhor pode optar por ignorar coisas como banners ou outros conteúdos dinâmicos. Mais informações na documentação.
O BackstopJS é otimizado para testar um grande número de páginas (ou estados de URL, se for um SPA). Em vez de buscar interações profundas, o BackstopJS foi concebido mais como uma verificação de sanidade que pode ser usada ativamente durante o desenvolvimento do CSS.
Para um teste visual mais profundo do aplicativo (incluindo estados intermediários e microinterações), recomendo que o senhor experimente o PhantomCSS ou escreva seus próprios scripts CasperJS. Se tiver seguido este tutorial, o senhor já tem muitas das ferramentas necessárias carregadas em seu computador.
Descobri que, depois que me acostumei a automatizar os testes visuais, é difícil iniciar um novo projeto grande sem isso.
Gostaria de saber se o senhor está usando o BackstopJS em seu grupo de desenvolvimento. Entre em contato comigo! @garris
* Na maioria dos casos, o senhor desejaria executar novamente o gulp reference
ao atualizar um arquivo de configuração. Para esta demonstração, estamos substituindo esse comportamento. Fazemos isso com o gulp bless
conforme mostrado acima.