Интеграционное тестирование¶
Интеграционное тестирование, оно же e2e-тестирование, подразумевает комплексное тестирование модулей через интерфейс приложения.
Применительно к Angular приложению e2e тесты используются для проверки корректности взаимодействия между собой компонентов, которые в совокупности представляют функциональную единицу.
Если unit-тестирование нацелено на проверку атомарных частей кода, например, метода, то интеграционные тесты проверяют взаимодействие этих частей между собой.
Управление e2e тестами и их запуск в браузере осуществляет библиотека Protractor
, а сам код написан с использованием Jasmine
.
Конфигурационный файл protractor.conf.js
находится в директории e2e
, а сами файлы тестов - в директории e2e/src
.
Запуск тестирования осуществляется командой:
ng e2e
Интеграционное тестирование начинается с создания классов Page Object, каждый из которых описывает логику одной конкретной страницы приложения. Например, содержит методы навигации на другие страницы или методы, возвращающие HTML-элементы или значения их свойств.
export class Page {
url: string = 'http://localhost:4200'
getTextByElement(selector) {
return element(by.css(selector)).getText()
}
clickByElement(selector) {
element(by.css(selector)).click()
}
getElement(selector) {
return element(by.css(selector))
}
}
Взаимодействие с интерфейсом обеспечивают три основных инструмента библиотеки Protractor
:
browser
— глобальный объект, который предоставляет API команд браузера;element
— функция, осуществляющая поиск HTML-элементов в пределах текущей страницы по заданному критерию;by
— объект с набором методов, которые возвращают понятный для функцииelement()
критерий поиска;expectedConditions
— класс, предоставляющий API для проверки выполнения определенных условий.
Методы browser
используются для навигации по приложению, эмуляции событий и т. д. Основные из них:
get()
— переходит на переданный URL-адрес, выполнение следующего за вызовом метода кода выполняется после завершения перехода, вторым аргументом принимает время в миллисекундах, в течение которого будет ожидаться завершение перехода (по умолчанию 10 секунд);getTitle()
— возвращает значение тега<title>
getLocationAbsUrl()
— возвращает текущий URL-адрес;navigate().forward()
— переходит на следующий URL-адрес в истории;navigate().back()
— переходит на предыдущий URL-адрес в истории;wait()
— приостанавливает процесс тестирования, пока не будет выполнена переданныйPromise
, вторым параметром можно передать время ожидания в миллисекундах (по умолчанию 30 секунд);actions()
— позволяет инициировать пользовательские события в пределах всего браузера (движение курсора или клик мыши, нажатие клавиши и др.). Функции действий:mouseDown()
— нажатие и удержание левой кнопки мыши;mouseUp()
— отпустить нажатую левую кнопку мыши;mouseMove(element | {x: number, y: number})
— перемещение курсора мыши на элемент или по координатам;doubleClick()
— двойное нажатие левой кнопки мыши;dragAndDrop()
— событие DragAndDrop.
Пример использования метода actions()
:
browser
.actions()
.mouseMove({ x: 300, y: 250 })
.doubleClick()
.perform()
Здесь курсор мыши сдвигается на 300 пикселей вправо и на 250 пикселей вниз, а затем выполняется двойной клик мыши по месту, соответствующему заданным координатам. Отсчет начинается с левого верхнего угла. Для выполнения действий в конце всегда нужно вызывать метод perform()
.
Методы объекта by
весьма разнообразны. Каждый из них возвращает критерий поиска, который используется для нахождения HTML-элементов функцией element()
:
by.css()
— находит элементы по заданному селектору (#id
,.class
);by.id()
— находит элемент поid
;by.className()
— находит элементы по имени css-класса;by.tagName()
— находит элементы по имени HTML-тега;by.input()
— возвращает все input-элементы;by.linkText()
— находит все ссылки, текстовое значение которых равно переданной строке;by.partialLinkText()
— находит все ссылки, в текстовом значение которых содержится переданная строка.
Функция element()
по умолчанию возвращает первый найденный элемент, соответствующий заданному критерию поиска. Для нахождения всех элементов используется метод element.all()
:
element.all(by.css('p'))
А получение одного элемента из массива, возвращаемого element.all()
, обеспечивает метод get()
.
let pEls = element.all(by.css('p'))
let firstP = pEls.get(0)
Для манипуляции отдельным элементом также имеется API.
Получение текстового значения:
element(by.id('title')).getText()
Клик по элементу:
element(by.buttonText('Submit')).click()
Эмуляция нажатия клавиши, например, в поле формы:
element(by.input('login')).sendKeys('d')
element(by.input('login')).sendKeys(protractor.Key.TAB)
Сброс значения:
element(by.input('login')).clear()
Проверка наличия элемента в DOM-дереве:
element(by.tagName('nav')).isPresent()
Проверка видимости элемента:
element(by.tagName('sidebar')).isVisible()
Получение габаритных размеров:
element(by.input('login'))
.getSize()
.then(function (size) {
console.log('Width: ' + size.width)
console.log('Height: ' + size.height)
})
Теперь рассмотрим подробнее методы класса ExpectedConditions
. Абсолютно все методы возвращают объект Promise
, поэтому следует их использовать совместно с методом browser.wait()
.
Проверка кликабельности элемента:
let EC = protractor.expectedConditions
let btn = element(by.id('confirm'))
browser.wait(EC.elementToBeClickable(btn))
Проверка содержания строки в текстовом значении элемента:
let EC = protractor.expectedConditions
let btn = element(by.id('confirm'))
browser.wait(EC.textToBePresentInElement(btn, 'Confirm'))
Проверка значения элемента <title>
страницы:
let EC = protractor.expectedConditions
browser.wait(EC.titleIs('Home'))
Также проверки ожидаемых результатов могут быть скомбинированы оператором or
или and
:
let EC = protractor.expectedConditions
let btn = element(by.id('confirm'))
let textContain = EC.textToBePresentInElement(
btn,
'Confirm'
)
let titleCheck = EC.titleIs('Home')
browser.wait(EC.and(textContain, titleCheck))
С полным API можно ознакомиться на официальном сайте Protractor.