Um dia na vida da automação de controle de qualidade

Como tive que me tornar um pouco de automação de qa: o que senti, sobrevivi e a maravilhosa arquitetura e infraestrutura de testes automáticos através dos olhos de um desenvolvedor que passava.


1. Introdução


Como se costuma dizer, eu não sou ginecologista, apenas passei e decidi procurar. Portanto, para começar, vou falar sobre os motivos da escrita. Parece-me que um especialista lidaria com o problema em uma ordem de magnitude mais rápida e não coletaria tantos ancinhos no caminho. Mas ele não estaria tão interessado quanto eu, e você não teria nada para ler.


Outro motivo que me levou a escrever: por um bom tempo, não entendi o que havia de tão especial na infraestrutura de autotestes. Além disso, muitos gerentes da PM e superiores também não entendiam completamente o que é tão cósmico lá e por que os desenvolvedores escrevem testes de unidade para um ou dois eles mesmos, e para os phycestests, indivíduos individuais são contratados, que escrevem testes mais lentamente, reparam constantemente algo e a chance de passar todas as especificações financeiras é estritamente menor que 100%, desde que a amostra seja grande o suficiente.


O problema


No terceiro dia, as especificações da questão do projeto ferroviário caíram. Cerca de uma semana antes, nosso único engenheiro de automação decidiu trabalhar em Chicago e ainda não encontramos um novo especialista. Portanto, tive que arregaçar as mangas e fingir que estava no controle de qualidade. Sobre como foi e tente contar.


O problema parece bastante inofensivo. Mas, para começar, um pouco de histórico e descrição do ambiente. Temos muitos seletores de endereço em nossa plataforma. Honestamente, essa é uma das principais entidades da plataforma. Os seletores acessam a API do Google para obter dados. Nos autotestes, todas as solicitações são interrompidas para economizar dinheiro e acelerar os testes. Além disso, um pouco de lógica foi adicionada para fornecer aproximadamente a mesma linha de endereço solicitada sem precisar ir a serviços externos.


O que foi quebrado: inserimos o endereço desejado na barra de endereços, uma caixa suspensa aparece com várias opções, selecionamos o desejado e ... o valor do elemento vizinho é inserido na entrada. Sempre.


Um longo caminho para a verdade


Primeiras hipóteses e abordagem ingênua


Sem mais delongas, fiz o teste de queda mais próximo, encontrei a linha na qual o endereço foi selecionado e comecei a examiná-lo cuidadosamente e aos vizinhos. A linha parece inofensiva: new_order_page.destination_address.select(baker_street) . Mas entendemos que por trás de um código bonito há sempre um monte de pequenos desenhos estranhos e entranhas desagradáveis.


Lembrei rapidamente que toda essa economia funciona no SitePrism . Isso possibilita agrupar a página e os elementos nela nos métodos de classe e classe, respectivamente. Por cliques e outras ações, a Capivara e o RSpec são responsáveis. Mas eles não têm dúvida, são confiáveis, como toda a frota civil. E, nesse caso, a primeira hipótese imediatamente se sugere: alguém escreveu mal seletores para o prisma ou alguém torceu o layout na frente.


A primeira parte da hipótese desapareceu rapidamente, os seletores são escritos perfeitamente. Nenhum xpath com a escolha do terceiro li dentro do elemento foi encontrado lá e o próprio código não foi alterado no ano passado.


No entanto, na área do método de select , amontoou a lógica com regexps para selecionar a opção desejada na lista suspensa. É claro que fico com raiva dos regexps e vou checá-los. Passo meia hora e entendo que tudo funciona bem. Exatamente a linha necessária é selecionada. click é chamado nele. E tudo deve funcionar. Ou seja, a segunda parte da hipótese de layout também desaparece. Mas o pensamento aparece sobre a curva js . Afinal, o elemento na página que temos é personalizado, js em ordem e, além disso, nesse js acabamos de mexer com ele recentemente.


Js é o culpado


Esse é o motivo padrão para todos os problemas obscuros. Algo como "vá para js , porque ele já está em choque". E, parece, no meu caso, também não poderia prescindir de js . Em geral, sem pensar duas vezes, corro para a equipe de front-end e aponto o dedo para os testes de queda, afirmando "tudo funciona do nosso lado, por favor, repare o seu lado".


Mas os caras do dândi não são uma falta, eles andam por aí por algumas horas, encontram alguns bugs que não estão relacionados à narrativa e dizem que js não js culpado! Ao mesmo tempo, eles lançam informações interessantes de que uma solicitação para o select não é suficiente e ele faz outra, cuja resposta corresponde exatamente ao conteúdo incorreto da entrada.


Eu não esperava essa virada. Temos que voltar e descobrir como a simulação de pedidos funciona para nós.


Abordagem abrangente


Portanto, não há outro lugar para esperar ajuda, Moscou está atrás de nós e coisas assim.


Primeiro, analisamos as formas de solicitações da Moka para o Google. Mais precisamente, primeiro procuramos onde isso acontece. Esta não é uma tarefa trivial. Acontece que temos todo um módulo MockServices::Base , responsável pela simulação de diferentes solicitações usando o videocassete . Ele está astuciosamente ajoelhado no controlador de base e apenas por causa do nome do serviço responsável por solicitações externas, ele não pode ser encontrado.


Ok, encontrei o moki. Agora, olhamos para a implementação deles. O primeiro pedido é molhado simplesmente: as informações dos params são obtidas e substituídas no modelo pela resposta. Por precaução, verifiquei o conteúdo dos params e, como esperado, tudo vem como deveria.


O método moka da próxima solicitação é mais interessante. Algum tipo de mock_data aparece lá. Estes não são params e precisamos descobrir de onde vem essa data. Depois de ter caído cinco vezes, é revelado que esses dados são obtidos do RequestStore usando a chave x_mock_data . Já é mais interessante.


Voltamos ao teste original e observamos que existe uma coisa set_mock_header que, após uma análise mais detalhada, adiciona alguns dados ao mesmo RequestStore . Mais interessante!


Em algum momento neste momento, ocorre uma dissonância cognitiva na cabeça: por um lado, é a provável causa do problema, as variáveis ​​globais que a solicitação lateral nos dá quebraram. Mas há uma nuance: o servidor para as especificações financeiras e as próprias especificações financeiras são dois processos independentes (na verdade, o servidor tem pelo menos três processos); portanto, um débito com crédito não pode convergir de forma alguma, porque ainda não foram trazidas para o mundo nenhuma variável global entre os processos. E com um servidor web multiencadeado, será um jogo feroz, que não funcionará fisicamente. Significa que oco alguma coisa e é necessário pesquisar.


Nós olhamos mais longe e encontramos um certo bm , ao qual os cabeçalhos colocam. Vá em frente e perceba que o bm é o BrowserMob . Então fiquei um pouco preocupado, pois é um proxy em Java em um invólucro de rubi. Apenas um piano nos arbustos.


Começamos a escolher mais e entendemos que, para as variáveis ​​"globais" entre o cliente com rspec e o servidor com o aplicativo (por exemplo, puma ), os mesmos cabeçalhos X-Mock-Data na solicitação são usados. O problema é que o aplicativo não deve saber nada sobre esses leitores. Apenas para isso, você precisa de um proxy através do qual todas as solicitações voem e que cuidem da configuração dos cabeçalhos. Astuciosamente, você não dirá nada.


Vamos testar e descobrir que apenas isso não funciona. Os cabeçalhos não são vistos em lugar algum: nem em solicitações nem em respostas. Mas o RequestStore é preenchido no lado do rspec e vazio no lado do servidor da web. Isso significa com certeza - está no proxy.


No meio, verifica-se que não temos apenas testes com endereços set_mock_header , mas também tudo o que usa o set_mock_header acima.


Ótimo. Resta entender como consertar isso.


Lidamos com um proxy


Omitimos os pontos de escavação na região onde o arquivo jar é iniciado e o controlamos através do Ruby. É melhor prestar atenção à maneira como o proxy do navegador é especificado. Usamos o Chrome e passamos informações de proxy em um dos muitos argumentos da linha de comando quando ela é iniciada. O recurso de proxy é que usamos o arquivo pac que geramos a partir do modelo para impedir o tráfego de soquetes da web por meio do proxy.


Em algum lugar aqui, há um desejo de ir e pesquisar no google o que há no chrome com a configuração do proxy. Acontece que você não precisa ir muito longe e, na versão 72+, os caras "terminaram" o trabalho dele. Nesta ocasião, eles até trouxeram um bug separado . Meu comentário favorito:


"Você pode parar de REMOVER a funcionalidade?"

A tristeza é que isso é considerado uma característica e, no futuro, eles prometem ainda mais em termos de "sigilo".


Em resumo, o Chrome não oferece mais suporte ao file: protocol no argumento proxy-pac-url . As soluções são melhores que as outras:


  • passe o argumento js , que lerá o arquivo pac e o transformará em base64: --proxy-pac-url='data:application/x-javascript-config;base64,'$(base64 -w0 /path/to/pac/script) ;
  • aumente seu servidor da Web em python para distribuir um arquivo de acordo com um protocolo mais "correto", suportado no argumento para pac proxy;
  • desative o NetworkService e, em seguida, o protocolo file: deve funcionar, mas eles prometem que também será "corrigido" no futuro.

As duas primeiras opções certamente não me inspiraram, e a terceira, curiosamente, ajudou.


Alegria de curta duração


Alegrando-me por ter sido encontrada uma conexão complicada entre suspensos inativos e o Chrome atualizado, não fiquei feliz por muito tempo. Acontece que nosso IC atualizou não apenas o chrome, mas também todos os pacotes adjacentes, e agora temos ainda mais testes Selenium::WebDriver::Error::NoSuchDriverError devido a um erro desconhecido Selenium::WebDriver::Error::NoSuchDriverError , que, curiosamente, não está relacionado ao chromedriver , mas está relacionado com uma configuração do chrome, versões da biblioteca e execução de especificações paralelas.


Mas esta é a tarefa para o próximo dia útil ...


Olhando para o futuro: o argumento disable-dev-shm-usage ajudou lá.


Conclusões


Não repreenda a automação. Ele parece sofrer mais com circunstâncias externas independentes dele.


É melhor fazer um amigo do engenheiro de automação com os desenvolvedores, para que eles organizem sua infraestrutura com preferência e cortesãs com versões fixas e um ambiente de teste controlado. Para mim, isso é melhor do que sofrer com o IC proprietário, cada um com muletas e bancos subaquáticos muito sofisticados, sobre os quais você aprenderá somente após uma forte integração de seu aplicativo e testes com o ambiente de outra pessoa.

Source: https://habr.com/ru/post/pt451558/


All Articles