Приемочные испытания используются для определения соответствия требованиям спецификации. Он должен работать в среде, максимально похожей на рабочую. Поэтому, если ваше приложение развернуто в Openshift, вам потребуется параллельная учетная запись с учетной записью, используемой в производстве для запуска тестов. В этом посте мы собираемся написать приемочный тест для приложения, развернутого в Openshift, которое использует MongoDb в качестве базы данных.

Развернутое приложение — очень простая библиотека, которая возвращает все книги, доступные для кредитования. Это приложение использует MongoDb для хранения всей информации, связанной с книгами.
Итак, давайте начнем с описания цели, функции, пользовательской истории и критериев принятия для предыдущего приложения.
Цель : расширение лекции для большинства людей.
Особенность : Показать доступные книги.
История пользователя : Просмотр каталога -> Чтобы найти книги, которые я хотел бы позаимствовать, как пользователь, я хочу иметь возможность просматривать все книги.
Критерии приемки : должны видеть все доступные книги.
Сценарий:
Учитывая, что я хочу взять книгу
Когда я нахожусь на странице каталога
Тогда я должен увидеть доступную информацию о книгах: Повелитель Банок — 1299 — LOTRCoverUrl, Хоббит — 293 — HobbitCoverUrl
Обратите внимание, что это очень простое приложение, поэтому критерии принятия тоже просты.
Для этого примера нам понадобятся две тестовые среды: первая для написания и запуска приемочных тестов, а другая для управления бэкэндом NoSQL . В этом посте мы собираемся использовать Thucydides для ATDD и NoSQLUnit для работы с MongoDb .
Приложение уже развернуто в Openshift , и вы можете взглянуть на https://books-lordofthejars.rhcloud.com/GetAllBooks
Thucydides — это инструмент, разработанный для облегчения написания автоматизированных приемочных и регрессионных тестов.
Thucydides использует API WebDriver для доступа к элементам HTML- страницы. Но также помогает вам организовать ваши тесты и пользовательские истории с помощью конкретной модели программирования, создавать отчеты о выполненных тестах и, наконец, также измерять функциональное покрытие.
Чтобы написать приемочные тесты с Thucydides следующие шаги должны быть выполнены.
- Прежде всего выберите пользовательскую историю одной из ваших функций.
- Затем реализуйте класс PageObject . PageObject — это шаблон, который моделирует элементы пользовательского интерфейса веб-приложения как объекты, поэтому тесты могут взаимодействовать с ними программно. Обратите внимание, что в этом случае мы кодируем «как» мы получаем доступ к html- странице.
- Следующим шагом является реализация библиотеки шагов. Этот класс будет содержать все шаги, необходимые для выполнения действия. Например, для создания новой книги необходимо открыть страницу addnewbook , вставить новые данные и нажать кнопку «Отправить». В этом случае мы кодируем «что» нам нужно для реализации критериев приемлемости.
- И, наконец, кодирование выбранной пользовательской истории в соответствии с определенными критериями принятия и использованием предыдущих классов шагов.
NoSQLUnit — это расширение JUnit, которое нацелено на управление жизненным циклом необходимого движка NoSQL , помогает нам поддерживать базу данных в известном состоянии и стандартизировать способ написания тестов для приложений NoSQL .
NoSQLUnit состоит из двух групп правил JUnit и двух аннотаций. В текущем случае нам не нужно управлять жизненным циклом движка NoSQL , потому что он управляется внешним объектом ( Openshift ).
Итак, давайте приступим к работе:
Первое, что мы собираемся сделать, это создать класс объектов, который не содержит тестовый код; он используется как способ представления структуры требований.
|
1
2
3
4
5
6
7
8
|
public class Application { @Feature public class Books { public class ListAllBooks {} }} |
Обратите внимание, что каждая реализованная функция должна содержаться в классе с аннотацией @Feature . Каждый метод избранного класса представляет пользовательскую историю.
Следующим шагом является создание класса PageObject. Помните, что шаблон PageObject моделирует пользовательский интерфейс веб-приложения как объект. Итак, давайте посмотрим html- файл, чтобы проверить, какие элементы должны отображаться.
|
1
2
3
4
5
6
7
8
9
|
<table id='listBooks' cellspacing='0' cellpadding='5'> <caption>List of Available Books<caption> <tr> <th>Title<th> <th>Number Of Pages<th> <th>Cover<th> <tr> .....<table> |
Здесь самое важное, что табличный тег имеет идентификатор listBooks, который будет использоваться в классе PageObject для получения ссылки на его параметры и данные. Давайте напишем объект страницы:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
@DefaultUrl('http:books-lordofthejars.rhcloud.comGetAllBooks')public class FindAllBooksPage extends PageObject { @FindBy(id = 'listBooks') private WebElement tableBooks; public FindAllBooksPage(WebDriver driver) { super(driver); } public TableWebElement getBooksTable() { Map<String, List<String>> tableValues = new HashMap<String, List<String>>(); tableValues.put('titles', titles()); tableValues.put('numberOfPages', numberOfPages()); tableValues.put('covers', coversUrl()); return new TableWebElement(tableValues); } private List<String> titles() { List<WebElement> namesWebElement = tableBooks.findElements(By.className('title')); return with(namesWebElement).convert(toStringValue()); } private List<String> numberOfPages() { List<WebElement> numberOfPagesWebElement = tableBooks.findElements(By.className('numberOfPages')); return with(numberOfPagesWebElement).convert(toStringValue()); } private List<String> coversUrl() { List<WebElement> coverUrlWebElement = tableBooks.findElements(By.className('cover')); return with(coverUrlWebElement).convert(toImageUrl()); } private Converter<WebElement, String> toImageUrl() { return new Converter<WebElement, String>() { @Override public String convert(WebElement from) { WebElement imgTag = from.findElement(By.tagName('img')); return imgTag.getAttribute('src'); } }; } private Converter<WebElement, String> toStringValue() { return new Converter<WebElement, String>() { @Override public String convert(WebElement from) { return from.getText(); } }; }} |
Используя @DefaultUrl, мы устанавливаем, какой URL отображается, с помощью @FindBy мы отображаем веб-элемент с помощью id listBooks и, наконец, получаем метод getBooksTable (), который возвращает содержимое сгенерированной HTML- таблицы.
Следующее, что нужно сделать, это реализовать класс steps; в этом простом случае нам нужно всего два шага: первый, который открывает страницу GetAllBooks , и другой, который утверждает, что таблица содержит ожидаемые элементы.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public class EndUserSteps extends ScenarioSteps { public EndUserSteps(Pages pages) { super(pages); } private static final long serialVersionUID = 1L; @Step public void should_obtain_all_inserted_books() { TableWebElement booksTable = onFindAllBooksPage().getBooksTable(); List<String> titles = booksTable.getColumn('titles'); assertThat(titles, hasItems('The Lord Of The Rings', 'The Hobbit')); List<String> numberOfPages = booksTable.getColumn('numberOfPages'); assertThat(numberOfPages, hasItems('1299', '293')); List<String> covers = booksTable.getColumn('covers'); assertThat(covers, hasItems('http:upload.wikimedia.orgwikipediaen662Jrrt_lotr_cover_design.jpg', 'http:upload.wikimedia.orgwikipediaen44aTheHobbit_FirstEdition.jpg')); } @Step public void open_find_all_page() { onFindAllBooksPage().open(); } private FindAllBooksPage onFindAllBooksPage() { return getPages().currentPageAt(FindAllBooksPage.class); }} |
И, наконец, класс для проверки критериев приемлемости:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@Story(Application.Books.ListAllBooks.class)@RunWith(ThucydidesRunner.class)public class FindBooksStory { private final MongoDbConfiguration mongoDbConfiguration = mongoDb() .host('127.0.0.1').databaseName('books') .username(MongoDbConstants.USERNAME) .password(MongoDbConstants.PASSWORD).build(); @Rule public final MongoDbRule mongoDbRule = newMongoDbRule().configure( mongoDbConfiguration).build(); @Managed(uniqueSession = true) public WebDriver webdriver; @ManagedPages(defaultUrl = 'http:books-lordofthejars.rhcloud.com') public Pages pages; @Steps public EndUserSteps endUserSteps; @Test @UsingDataSet(locations = 'books.json', loadStrategy = LoadStrategyEnum.CLEAN_INSERT) public void finding_all_books_should_return_all_available_books() { endUserSteps.open_find_all_page(); endUserSteps.should_obtain_all_inserted_books(); }} |
Есть несколько вещей, которые следует рассмотреть в предыдущем классе:
- @Story должен получить класс, определенный с помощью аннотации @Feature , чтобы Thucydides мог правильно создать отчет.
- Мы используем MongoDbRule для установления соединения с удаленным экземпляром MongoDb . Обратите внимание, что мы можем использовать адрес localhost из-за возможности переадресации портов Openshift , поэтому, хотя localhost используется, мы действительно управляем удаленным экземпляром MongoDb .
- Использование @Steps Thucydides создаст экземпляр библиотеки предыдущего шага.
- И, наконец, аннотация @UsingDataSet для заполнения данных в базе данных MongoDb перед запуском теста.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
{ 'book':[ { 'title': 'The Lord Of The Rings', 'numberOfPages': '1299', 'cover': 'http:upload.wikimedia.orgwikipediaen662Jrrt_lotr_cover_design.jpg' }, { 'title': 'The Hobbit', 'numberOfPages': '293', 'cover': 'http:upload.wikimedia.orgwikipediaen44aTheHobbit_FirstEdition.jpg' } ]} |
Обратите внимание, что NoSQLUnit поддерживает базу данных в известном состоянии, очищая базу данных перед каждым выполнением теста и заполняя ее известными данными, определенными в файле json .
Также имейте в виду, что этот пример очень прост, поэтому было показано только небольшое подмножество возможностей Thucydides и NoSQLUnit . Следите за обоими сайтами: http://thucydides.info и https://github.com/lordofthejars/nosql-unit.
Ссылка: Написание приемочных тестов для приложений Openshift + MongoDb от нашего партнера JCG Алекса Сото в блоге One Jar To Rule All .


