Automação com Codeception + Gherkin + PageObject para os menores


Como não encontrei um único exemplo concreto de uma implementação Gherkin com um padrão de design de Objeto de Página para Codecepção na Internet , pensei que não seria impróprio informar a Internet sobre nossa própria implementação desse padrão.

Este artigo destina-se mais àqueles que já estão um pouco familiarizados com a codecepção ou estruturas semelhantes, mas ainda não sabem como usar o Objeto de Teste para tornar os testes mais legíveis, simplificar seu suporte e reduzir a quantidade de código extra. No entanto, tentei explicar passo a passo todos os pontos principais da montagem do projeto de automação do zero.

O modelo de objeto de página permite que você encapsule o trabalho com elementos de página, o que, por sua vez, permite reduzir a quantidade de código e simplificar seu suporte. Todas as alterações na interface do usuário são implementadas com facilidade e rapidez - basta atualizar a classe Objeto de Página que descreve esta página. Outra vantagem importante dessa abordagem arquitetônica é que ela permite que você não bagunce o script de teste HTML com detalhes, o que o torna mais compreensível e fácil de ler.

É assim que o teste se parece sem usar o Objeto de Página



Usando objeto de página



Não vou me deter na instalação do ambiente básico, darei meus dados iniciais:

  • Castor biônico do Ubuntu
  • PHP 7.1.19-1
  • Composer - gerenciador de gerenciamento de dependências para PHP, instalado globalmente
  • PhpStorm - ambiente de desenvolvimento

Para executar os testes, também precisamos de:


Expand Codecepção


Prossiga para instalar o Codeception:

Abrimos no terminal o diretório de que precisamos, onde coletamos o projeto ou criamos um diretório para o projeto e vamos a ele:

mkdir ProjectTutorial cd ProjectTutorial 

Instale a estrutura de codecepção e suas dependências:

 composer require codeception/codeception --dev 



O arquivo de instalação da dependência composer.json no projeto terá a seguinte aparência:

 { "require": { "php": ">=5.6.0 <8.0", "facebook/webdriver": ">=1.1.3 <2.0", "behat/gherkin": "^4.4.0", "codeception/phpunit-wrapper": "^6.0.9|^7.0.6" }, "require-dev": { "codeception/codeception": "^2.5", "codeception/base": "^2.5" } } 

Expanda o projeto:

 php vendor/bin/codecept bootstrap 



Mais informações sobre como instalar o projeto podem ser encontradas na documentação oficial .

Nesta fase, três conjuntos de testes são criados em nosso projeto. Por padrão, a codecepção os divide em aceitação, funcional e unidade. Para esses conjuntos, o Codeception também gera três arquivos yml. Nelas indicamos todas as configurações necessárias, conectamos os módulos e propriedades para executar nossos testes.

Esta lição é baseada no exemplo do teste de aceitação, portanto darei as configurações em Acceptance.suite.yml.

Abra nosso projeto no PHP Storm (ou outro ambiente de desenvolvimento favorito) e vá para Acceptance.suite.yml (por padrão, ele está na pasta tests / accept.suite.yml).
Anotamos as dependências mínimas necessárias e sempre prestamos atenção à formatação. Os módulos são separados por um sinal "-" e devem estar no mesmo nível, caso contrário, os erros serão gerados quando o teste for iniciado.

Acontece:

 actor: AcceptanceTester modules: enabled: - WebDriver: url: 'http://yandex.ru/' //    ,        browser: 'chrome' - \Helper\Acceptance //          gherkin: contexts: default: - AcceptanceTester 

E algum trabalho mais preparatório:

Crie um diretório separado na raiz do projeto (eu tenho lib).
Nesse diretório, crie o arquivo executável run.sh, que executará o Selenium e o Driver do Chrome.

Colocamos o Selenium e o Driver do Chrome aqui e escrevemos o comando run em run.sh:

 java -jar -Dwebdriver.chrome.driver=chromedriver_241 selenium-server-standalone-3.14.0.jar 

Como fica no projeto:



Retornamos ao console e alteramos os direitos de acesso:

 chmod +x ./run.sh 

(observação. Os nomes dos drivers que estão no diretório devem corresponder exatamente aos especificados no comando start).

Você pode iniciar o Selenium e o Webdriver agora mesmo para não voltar a isso. Para fazer isso, abra uma nova guia do terminal, vá para o diretório em que o arquivo run.sh está e escreva o comando de inicialização:

 ~/AutomationProjects/ProjectTutorial/lib$ ./run.sh 

Verifique se o servidor está em execução:



Deixamos em um estado de execução. Neste trabalho preparatório está concluído.

Escrevendo um script de teste


Continuamos a criar um arquivo de recurso para o nosso caso de teste. Para fazer isso, um comando especial é fornecido no Codeception, execute-o no console:

 cept g:feature acceptance check 

(observe "cheque" - o nome do meu teste)

Vemos o novo arquivo check.feature na pasta de aceitação.



Não precisamos do conteúdo padrão, nós o excluímos imediatamente e escrevemos nosso teste.

Para que o colecionador reconheça o alfabeto cirílico, não esqueça de iniciar o script com #language: ru.
Estamos escrevendo um script curto em russo. Lembro que cada frase deve começar com as palavras-chave: "Quando", "Então", "E", o símbolo "*" etc.

Para o meu exemplo, peguei o site Yandex, você pode pegar qualquer.



Para ver quais etapas existem no teste, executamos nosso script no terminal:

 cept dry-run acceptance check.feature 



As etapas do script são exibidas no console, mas sua implementação ainda não está disponível.

Em seguida, executamos um comando que irá gerar automaticamente modelos para implementar nossos métodos:

 cept gherkin:snippets acceptance 



Todos os nomes do script que estavam entre aspas são substituídos por variáveis: arg.
Nós os copiamos do terminal e os colamos no arquivo AcceptanceTester.php , onde estão os métodos para trabalhar com os elementos da página.



Renomeie os métodos para legíveis, refletindo sua essência (opcional) e escreva sua implementação.



Tudo é simples, mas ainda mais simples se você estiver trabalhando em um ambiente de desenvolvimento inteligente, como o Storm, que solicitará os comandos necessários da biblioteca:



Removemos o excesso e escrevemos os métodos:

 /** * @When      */ public function step_beingOnMainPage($page) { $this->amOnPage('/'); } /** * @Then    :element */ public function step_seeElement($element) { this->seeElement($element); } /** * @Then    :button */ public function step_clickOnButton($button) { $this->click($button); } /** * @Then    :field  :text */ public function step_fillField($field, $text) { $this->fillField($field, $text); } 

Vamos ver o que aconteceu. Lançamos uma equipe que nos mostrará quais métodos (etapa) agora temos uma implementação.

 cept gherkin:steps acceptance 



Sucesso!

Mas as etapas no arquivo de recurso ainda não são reconhecidas como métodos.



Para que o Storm entenda o que fazer com as etapas, faremos um truque ao implementar a interface Context a partir do namespace Gherkin Context.

 namespace Behat\Behat\Context { interface Context {} } 

Agrupe nossa classe AcceptanceTester no namespace e herda de Context

 implements \Behat\Behat\Context\Context 



Agora todas as etapas do arquivo de recurso estão vinculadas à sua implementação:



Para que o Webdriver entenda o que clicar e onde procurar, é necessário substituir os nomes dos elementos legíveis e os endereços das páginas pelos localizadores e URLs correspondentes, que serão incluídos nos métodos como argumentos.

Em seguida, fazemos um teste do formulário:



E você pode executar:

 cept run acceptance 



Aprovado

aprox. Se os elementos da página demorarem muito para carregar, você poderá adicionar a espera ao método desejado:

 $this->waitForElementVisible($element); 

Voltamos ao nosso cenário de teste. Estamos preocupados que toda a legibilidade do teste seja perdida devido ao fato de que, em vez dos nomes claros dos elementos e páginas, vemos os elementos HTML e o URL.

Se quisermos corrigir isso, é hora de seguir para a implementação do padrão Objeto de Página.

Ir para o objeto Página


No diretório _support, crie o diretório Page, onde colocaremos nossas páginas de classe:

 php vendor/bin/codecept generate:pageobject MainPage 

O primeiro Objeto de Página é a página principal do Yandex, vamos chamá-lo de MainPage, chamaremos a classe da mesma forma:



Aqui declaramos campos e métodos estáticos para que possam ser chamados sem criar um objeto.

Como nas configurações do Acceptance.suite.yml já especificamos a página inicial url: yandex.ru , para a página principal, basta especificar

 public static $URL = '/'; 

Em seguida, vem uma matriz de elementos da página. Descrevemos localizadores para vários elementos e damos a eles nomes claros e exclusivos.

Agora você precisa adicionar o método getElement, que retornará o localizador pelo nome do elemento da matriz.

Como resultado, temos:

 <?php //location: tests/_support/Page/MainPage.php namespace Page; /**   */ class MainPage { public static $URL = '/'; public static $elements = array( ' ' => "//*[@id='wd-wrapper-_afisha']", ' ' => "//*[@data-statlog='afisha.title.link']", ' ' => "//*[@class='weather__icon weather__icon_ovc']|//*[@class='weather__icon weather__icon_skc_d']", ); public static function getElement($name){ return self::$elements[$name]; } } 

Adicione algumas classes de página:

/ ** Pôster * /



/ ** Pôster - Resultados da pesquisa * /



Retornamos à classe AcceptanceTester.php , onde escrevemos nossos métodos.
Vamos criar nele uma matriz de classes PageObject, na qual atribuiremos os nomes às páginas e indicaremos seus nomes de classe no namespace:

  private $pages = array( " " => "\Page\MainPage", "" => "\Page\AfishaPage", " -  " => "\Page\AfishaResult" ); 

Cada novo PageObject é adicionado de maneira semelhante a essa matriz.

Em seguida, precisamos criar o campo currentPage, que armazenará o link no PageObject da página atual:

 private $currentPage; 

Agora, escreveremos um método, quando chamado, podemos obter currentPage e inicializar a classe PageObject de que precisamos.

É lógico dar um passo como esse usando o método "Quando o usuário navega para a página" Nome da página ". Em seguida, a maneira mais simples de inicializar a classe PageObject, sem verificações, seria assim:

 /** * @When     :page */ public function step_beingOn($page) { //   pageObject $this->currentPage = $this->pages[$page]; } 

Agora, escrevemos o método getPageElement, que nos permitirá obter o elemento, ou melhor, seu localizador na página atual:

 private function getPageElement($elementName) { //         $curPage = $this->currentPage; return $curPage::getElement($elementName); } 



Para métodos já implementados, é necessário substituir os argumentos que recebemos diretamente do texto do recurso no início pelos elementos do PageObject, ou seja:

 $arg 

vai assumir a forma

 getPageElement($arg)) 

Em seguida, nossos métodos assumirão a forma:

 /** * @When     :page */ public function step_beingOnMainPage($page) { //      pageObject $this->currentPage = $this->pages[$page]; $curPage = $this->currentPage; $this->amOnPage($curPage::$URL); } /** * @Then    :element */ public function step_seeElement($element) { $this->waitForElementVisible($this->getPageElement($element)); $this->seeElement($this->getPageElement($element)); } /** * @Then    :button */ public function step_clickOnButton($button) { $this->click($this->getPageElement($button)); } /** * @Then    :field  :text */ public function step_fillField($field, $text) { $this->fillField($this->getPageElement($field), $text); } /** * @Then      :field */ public function step_deleteText($field) { $this->clearField($this->getPageElement($field)); } 

Adicionado outro método para exibir os resultados da pesquisa pressionando Enter:

 /** * @Then    ENTER */ public function step_keyboardButton() { $this->pressKey('//input',WebDriverKeys::ENTER); } 

A última etapa é quando todos os métodos e PageObjects necessários são descritos, é necessário refatorar o teste em si. Adicione as etapas que inicializarão o PageObject ao acessar uma nova página. Temos este "* usuário foi para a página: página".

Para maior clareza, adicionarei mais algumas etapas. O resultado é este teste:

 #language: ru :     :   .    .   .      " "     " "     " "     " "      ""     " "  " "     ENTER      " -  "     "   "       " "     " "  ""     ENTER 

Esse cenário de teste é compreensível e legível para qualquer pessoa de fora.

Lançamento!

Para visualizar um resultado de execução mais detalhado, você pode usar o comando

 cept run acceptance --debug 

Nós olhamos para o resultado:



Portanto, o uso do padrão Objeto de Página permite separar todos os elementos da página dos scripts de teste e armazená-los em um diretório separado.

O projeto em si pode ser encontrado em https://github.com/Remneva/ProjectTutorial

Como engenheiro de automação iniciante, ficarei grato se você compartilhar suas idéias e, talvez, me dizer como transformar e simplificar mais logicamente a estrutura do projeto.

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


All Articles