Добрый день!

В третьей части этой серии статей мы добавили нативную поддержку тестирования API в нашу платформу автоматизации тестирования. В этой статье мы организуем нашу тестовую среду для размещения объектной модели страницы, также известной как POM, для веб-элементов пользовательского интерфейса.
Allons-y!

Что такое объектная модель страницы?

Объектная модель страницы (POM) – это широко используемый в автоматизации тестирования шаблон проектирования, который создает репозиторий объектов для элементов веб-интерфейса. Преимущество модели в том, что она уменьшает дублирование кода и улучшает сопровождение тестов.

Согласно этой модели, для каждой веб-страницы в приложении должен быть соответствующий класс страницы. Этот класс Page идентифицирует веб-элементы этой веб-страницы, а также содержит методы страницы, которые выполняют операции с этими веб-элементами. Имя этим методам должно быть дано в соответствии с выполняемой ими задачей, т. е. если загрузчик ожидает появления платежного шлюза, имя метода POM может быть 'waitForPaymentScreenDisplay()'.[1]

Преимущества POM

  1. Шаблон Page Object Pattern говорит, что операции и потоки в пользовательском интерфейсе должны быть отделены от проверки. Эта концепция делает наш код чище и проще для понимания.
  2. Вторым преимуществом является то, что репозиторий объектов не зависит от тестовых случаев, поэтому мы можем использовать один и тот же репозиторий объектов для разных целей с помощью разных инструментов. Например, мы можем интегрировать POM с TestNG/JUnit для функционального тестирования и одновременно с JBehave/Cucumber для приемочного тестирования.
  3. Код становится меньше, оптимизирован и прост в обслуживании благодаря многократно используемым методам страницы в классах POM.
  4. Методы получают более реалистичные имена, которые можно легко сопоставить с операцией, происходящей в пользовательском интерфейсе. т. е. если после нажатия на кнопку мы попадаем на домашнюю страницу, имя метода будет выглядеть как ‘gotoHomePage()’.

Интеграция объектной модели страницы

Чтобы добавить объекты Page в нашу существующую структуру, нам не нужны никакие дополнительные функции Cypress или внешние библиотеки JS. Все, что нам нужно сделать, это немного изменить структуру нашего проекта, чтобы включить классы страниц и добавить соответствующие элементы и действия в так называемые "Страницы".

Давайте начнем немного расширять наш тестовый пример пользовательского интерфейса, так как он проверяет только заголовок, поэтому веб-элементы не используются.

Добавление новых тестовых шагов для ввода поискового запроса и последующей проверки первого результата поиска на Google.com.

//Updated Test Case
@UI
Feature: Navigating to Google.com and verifying title and match result keyword
    @smoke @test
    Scenario: Perform Search
        Given I open the Google web url
        Then I verify title of web page as 'Google'
        When I provide search query as "Pokemon"
        Then Verify first search result to match "Pokemon" keyword

Теперь добавьте новую папку в /integration с именем pages:

Теперь, когда мы будем вводить ключевое слово для поиска в поле ввода на главной странице Google, а затем проверять результат на странице результатов поиска. Таким образом, мы можем сказать, что у нас есть 2 страницы, и мы должны хранить элементы и действия для этих 2 страниц.

Теперь мы создадим 2 папки для страниц HomePage и ResultPage соответственно.
Как мне нравится группировать элементы и действия на странице; Я создаю 2 отдельных файла JS, по одному для элементов и действий Cypress. Так, например, в папке HomePage elements.js хранит веб-элементы, а HomePage.js хранит действия Cypress.

Элементы домашней страницы — это простой файл module.exports, который содержит объект HOMEPAGE для хранения своих веб-элементов:

//elements.js for HomePage
module.exports = {
    HOMEPAGE:{
        SEARCH_TXTBOX: "input[name='q']"
    } 
}

Аналогично для элементов ResultPage:

//elements.js for HomePage
module.exports = {
    RESULTPAGE:{
        SEARCH_RESULT_FIRST: "div.rc"
    } 
}

На основе этих элементов мы напишем наши действия для HomePage:

//HomePage.js
var elements = require('./elements')
class HomePage {
  clickSearchTxtBox() {
    return cy.get(elements.HOMEPAGE.SEARCH_TXTBOX).click();
  }

  typeInSearchTxtBox(value) {
    return cy.get(elements.HOMEPAGE.SEARCH_TXTBOX).type(value);
  }

  submitSearchQuery() {
  //press enter after query is provided, for submission
    return cy.get(elements.HOMEPAGE.SEARCH_TXTBOX).type('{enter}');
  }

  }
  export default HomePage;

и действия ResultPage:

//ResultPage.js
var elements = require('./elements')
class ResultPage {
  
    verifyFirstResult(search_keyword) {    
        //matches partial text of result string
        return cy.get(elements.RESULTPAGE.SEARCH_RESULT_FIRST).first().text().then(value => {
          cy.log("Text is :", value);
          expect(value).to.include(search_keyword);
          
        });
      }
  
  }
  export default ResultPage;

Одна важная вещь: функция cypress text() отсутствует по умолчанию, мы должны написать пользовательскую команду в файле /support/command.js следующим образом:

Cypress.Commands.add("text", { prevSubject: true }, (subject, options) =› { return subject.text();
});

Теперь, когда у нас есть наша объектная модель страницы, мы можем добавить ее к нашим шагам BDD.

Шаги BDD с объектной моделью страницы:

Чтобы использовать Page Classed в нашем проекте, нам нужно сначала импортировать его в файл Step-Definition commonStep.js, используя оператор импорта.

//Page imports into commonStep.js file
import HomePage from '../../../pages/HomePage/HomePage';
import ResultPage from '../../../pages/ResultPage/ResultPage';

const homePage = new HomePage();
const resultPage = new ResultPage();
...

и шаги BDD будут выглядеть так:

//BDD Steps in commonSteps.js
Given('I open the Google web url', () => {
    cy.visit('https://www.google.com');
    
  });
  
Then(
    'I verify title of web page as {string}',
    (title) => {
        cy.title().should('include', title);
    }
  );

When(
    'I provide search query as {string}',
    (query) => {
      homePage.clickSearchTxtBox();
      homePage.typeInSearchTxtBox(query);
      homePage.submitSearchQuery();
    }
  );

Then(
    'Verify first search result to match {string} keyword',
    (search_keyword) => {
      let result = resultPage.verifyFirstResult(search_keyword);
    }
  );

Это все. Все, что нам нужно сделать, это запустить этот тест, используя следующую команду:

npx cypress run --env TAGS="@UI"

или через интерфейс Cypress:

npx cypress open

— env TAGS="@UI" обеспечивает запуск только теста пользовательского интерфейса, пропуская выполнение теста API

Результат теста:

ИЛИ, используя интерфейс Cypress:

Вот и все, мы интегрировали POM в нашу структуру.

Если вы хотите увидеть все видео тестового прогона; вы можете просто перейти в следующую папку: cypress\videos\features\UI, и там вы найдете Test1.js.mp4, в котором будет записано полное выполнение тестового запуска.

Увидимся в следующий раз, когда мы увидим добавление некоторых других интересных вещей в наши фреймворки, таких как отчеты, поддержка нескольких сред и т. д. Так что следите за обновлениями. Часть 5 теперь доступна.

До свидания!

Репозиторий GitHub: https://github.com/far11ven/Cypress-TestFramework/tree/develop/Part 04

Первоначально опубликовано на https://kushalbhalaik.xyz/blog 4 октября 2020 г.