Создание фреймворка для регрессионного тестирования

Всем привет!
Создал данную тему, поскольку считаю, что здесь наилучший сайт для получения реальных практических советов.

Что нужно: создать демо-версию авто-теста для регрессионного тестирования.
Кратко суть регрессионного тестирования: есть определенная услуга (сервис), для которой создан регресс-сет, который, обычно, прогоняется в ручную.
Детально об процессе тестирования:

  1. Подготовка тестовых данных – внесение нужных записей в таблицы БД для разных вариантов проверок (т.е. простые insert, update, delete).
  2. Подача HTTP-запроса в браузер с нужными параметрами (одни параметры – статические (не меняются), другие параметры – динамические (изменяются))
  3. Получение XML-ответа в браузере (т.е. в зависимости от внесенных параметров в п.1 и от входящих параметров в п.2, мы получаем некий XML-ответ).
  4. Анализ данного XML-ответа (по сути парсинг; в этом ответе нужны только пару значений (тегов); мы смотрим, что ожидаемый результат действительно совпадает с актуальным результатом).
  5. Просмотр и анализ лог-файла на Linux сервере (т.е. после шага 2, после обработки HTTP-запроса, мы открываем лог-файл на линух-сервере и смотрим нужную для нас информацию и сравниваем её с ожидаемой; ожидаемая информация у меня есть, она определена заранее)
  6. Просмотр изменений в БД (например, какае-то запись создалась, где-то удалилась, где-то изменилась и т.д.; т.е. это обычные select-запросы).
    Тест завершен.

Я новичок в этой теме (был опыт только с написанием несложных авто-тестов для web).
Хотелось бы получить от вас практические советы, направить меня, так сказать, в правильное русло. С чего начать, чем пользоваться, как именно это имплементировать?

Мои предпочтения: язык - Java, среда для разработки - Ecplipse, использование библиотек Selenium, TestNG, подход PageObject.
Мои примечания: пункт 1й - на мой взгляд можно и не автоматизировать, поскольку по данному пункту уже написаны соответствующие запросы на sql (pl/sql), т.е. достаточно открыть файл и запустить на выполнение. Больший интерес представляет пункты 2-5.

Спасибо всем, кто поможет, проконсультирует, даст полезные советы!

Всю дополнительную информацию и все детали, которые нужны будут для уточнения, - предоставлю.

1 лайк

На сколько я понял, вам нужно протестировать некое API, т.е. подавать запросы на некий урл с разными вариантами параметров и получать ответ в виде xml, который необходимо потом распарсить. Если так, то в этом случае вам не нужен Selenuim и PageObject паттерн тем более, вам вообще не нужен браузер.
Если java, то используйте HttpUrlConnection или Apache HttpClient для создания HTTP-запрсов (POST, GET и т.д., что вам там надо), получаете ответ. Для работы с xml в java могу посоветовать либу Simple (сам ее юзаю - очень удобна для сериализации\десериализации) - Simple 2.7.1

1 лайк

Да, sergey_ ivanich, примерно так.
Правильно ли я понимаю, что HttpUrlConnection (Apache HttpClient) - это библиотеки?

HttpUrlConnection - это класс из java net библиотеки, который используется для создания HTTP-соединения.
В принцыпе, для создания несложного запроса мне, например, хватает следующих импортов из net

import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

HttpClient - библиотека от Apache Software Foundation. Почитать\скачать можно здесь Apache HttpComponents – Apache HttpComponents

Для демо вполне хватит о чем писали. Но намешали, имхо, много всего в кучу.
Ниже я допускаю, что сервисы, также разрабатываются в java стэке.

Лучше заавтоматизировать и п.1. Просто из некоторого prepare_db.bat/prepare_db.sh вызвать ваши скрипты против нужной бд.

2-4, если используется, что-то специфичное, тот же wsdl, то eclipse (или другое) поможет вам получить красивые обвертки.

_5. не уверен, о каких логах идет речь. но лучше подобное тестировать интеграционными тестами. Например запускать сервер в cargo maven, и прямо локально смотреть что логи такие как ожидаются.

_6. для регрессии, опять же, лучше интеграционные, юнит тесты.

  • юнит тесты - что dao вызывается при соответствующих действиях, с ожидаемыми параметрами
  • интгерационные тесты - проверочные селекты к in memory db (если что-то сложное, то к реально бд) в результате действий тестов.

P.S. поменяйте категорию, или уточните почему webdriver

dmakhno, по поводу 2-4 не совсем понял о каких обертках идет речь, можно в явном виде?
По поводу 5: речь идет о лагах некого сервера, который обрабатывает запросы и выдает ответ. Абсолютно вся инфа логируется в специальный лог-файл.txt на линукс-сервере, файл этот один, и в него постоянно дописывается информация. Из него мне и нужно выбирать определенную нужную информацию.

Спасибо.

1,5) Если в дальнейшем планируете развивать направление работы с БД, можно подключить Hibernate ORM.
2-3) Если серверная часть использует веб-сервисы, можно написать простенький REST клиент. Как вариант - Jersey.
4) Парсить xml можно чем угодно. Как вариант - JAXB.
5) Можно написать простенькую серверную часть, к примеру, используя Jetty. И запросить лог файл для дальнейшего анализа. Ну или послать ожидаемый результат, проанализировать его прямо на сервере и вернуть какой-нибудь true/false. Как послать? При помощи того же рест клиента.

ArtOfLife,
по 1,5) - в принципе да, поскольку везде и всегда будут нужны обращения к БД. Hibernate ORM - это библиотека, которая содержит набор необх. методов для работы с БД? А можно реальный пример кода.
2-3), опять таки, это приятно, что вы советуете, но для меня это лишь всего unknown-названия…Можете конкретные примере навести или где найти?
5) спасибо за идеи, буду понемногу разбираться.

если нужно тестирование REST, могу посоветовать Java либу resty, как по мне, очень простая в использовании
dependency для maven:

<dependency>
  <groupId>us.monoid.web</groupId>
  <artifactId>resty</artifactId>
  <version>0.3.2</version>
</dependency>

По хибернейту - пример простой сущности:

@Entity
@Table(name = "User")
public class User
{

	@Id
	@GeneratedValue
	@Column(name = "Id")
	private Integer id;

	@Column(name = "UserName")
	private String userName;

	@Column(name = "UserPassword")
	private String userPassword;

	@Column(name = "UserFullName")
	private String userFullName;

	public Integer getId()
	{
		return id;
	}

	public String getUserName()
	{
		return userName;
	}

	public String getUserPassword()
	{
		return userPassword;
	}

	public String getUserFullName()
	{
		return userFullName;
	}

	public void setId(Integer id)
	{
		this.id = id;
	}

	public void setUserName(String userName)
	{
		this.userName = userName;
	}

	public void setUserPassword(String userPassword)
	{
		this.userPassword = userPassword;
	}

	public void setUserFullName(String userFullName)
	{
		this.userFullName = userFullName;
	}

	public String toString()
	{
		return "[name : " + getUserName() +
				"; password : " + getUserPassword() +
				"; full name : " + getUserFullName() + "]";
	}
}

Помимо этого необходимо подготовить инициализатор сессий и конфигурационный файл хибернейта. Но суть в том, что не нужно изобретать велосипеды. Ваша БД сущность будет представлена в виде класса с аннотированными полями / методами. Посредством конфиг файла хибернейт узнает, где искать ваш класс, и как парсить поля нужной таблицы.
Конечно, чтобы все было красиво, можно вставить вычитывание данных из БД в DataProvider, который вернет вам вашу сущность, заполненную данными из таблицы.

Простенький Jersey REST client будет представлять из себя всего 1 класс. Приведу пример клиентской части Sikuli:

    private Client client;
private WebTarget service;

public RemoteScreen(String ip, int port)
{
	client = ClientBuilder.newBuilder()
			.register(ObjectMapperProvider.class)
			.register(JacksonFeature.class).build();

	service = client.target("http://" + ip + ":" + port + "/sikuli");
}

public boolean click(IImageElement image, int timeout)
{
	return service.path("image")
			.path("click")
			.queryParam("timeout", timeout)
			.request(MediaType.APPLICATION_JSON)
			.post(Entity.json(image))
			.getStatus() == Response.Status.OK.getStatusCode();
}

При этом, серверная часть, а именно вэб-сервис, будет представлять из себя нечто вроде:

@Path("/image")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ImageService
{
	@POST
	@Path("/click")
	public Response click(IImageElement image, @QueryParam("timeout") int timeout)
	{
		return Response.status(
				image != null ? (new RemoteDesktop().click(image, timeout) ?
						Response.Status.OK : Response.Status.NOT_FOUND) :
						Response.Status.BAD_REQUEST)
				.build();
	}
}

В любом случае вам придется почитать гайды на офф сайте Jersey (на текущий момент последняя версия 2.7). Они там достаточно хорошие. Но реализация простенького рест клиента + примитивного сервера решит вашу проблему с анализом удаленных логов. А в случае, если бэкэнд вашего приложение использует вэб-вервисы, вам достаточно будет узнать у разработчиков адрес сервиса и параметры запроса, чтобы отправить туда нужный request при помощи самописного рест клиента, и получить xml response.

ИМХО, использование Hibernate (и ему подобных ORM) для автотестов - это оверхед. 95% его функционала не будет использоваться, при этом на обеспечение его работоспособности будет уходить много времени.

Достаточно JDBC и простых запросов. Не надо усложнять фреймворк без необходимости.

Задача ORM - упрощать разработку приложения: при необходимости вносить изменения, делать это в одном-двух местах. У тестов задачи совершенно другие. Поэтому прежде чем решаться на использование ORM в автотестах, необходимо тщательно продумать для чего это делается.

Правильно, надо всегда все тщательно продумывать.
А если у вас стоит задача масштабирования ваших тестов? А если взаимодействие может осуществляться с несколькими совершенно разными БД (к примеру, тестовые данные будут лежать в MySQL, а апликейшен БД - в MS SQL)? А что если вам нужен параллельный доступ к обоим БД в одном тесте (к примеру, осуществить восстановление пасворда юзеру из аппликейшен БД)? А что, если понадобятся не только селекты? А что если данные не только String? А как насчет join’ов таблиц? Это самые банальные примеры, когда простой JDBC вскоре превратится в толстую проблему. Подключив Hibernate, я теряю около 7-10 сек на thread-safe конекшен с тремя БД. Но это абсолютно безболезненные затраты на фоне остальных его плюсов.

Возможно для автора подойдет и более простой вариант. Никто ж не спорит. Но в свое время я сам прошел через JDBC и знаю, насколько может усложниться жизнь при определенных условиях. И когда я понял, что все сводится к изобретению велосипедов, наиболее простым как раз оказалось - взять готовый.

Вывод: подход всегда должен подбираться под конкретную задачу. Но не следует также забывать и том, что может быть в будущем, тщательно продумывая архитектуру заранее.

  1. у меня данные для тестов лежат в SQLite, а БД приложения MSSQL
  2. доступ к обеим базам делается в ходе одного теста
  3. join-ы присутствуют
  4. всё работает через JDBC. Никакой проблемы с этим нет.

Просто не надо в тесте напрямую обращаться в БД, надо сделать абстрагирующий слой. Тогда в будущем можно будет спокойно и безболезненно перелезть с JDBC на ORM. Если понадобится.

P.S. Мне просто интересно стало: что у тебя делают тесты, которые в несколько потоков изменяют данные в БД? Что они тестируют?

@ArtOfLife, пошарьте больше инфы о том что у вас за система. Я затрудняюсь представить всю картину. :smile:

“А что если, а как на счет” я обычно решаю рефакторингом… Плохо задизайнил - рефакторю все нах и громко ругаюсь, хорошо - быстро. При том если я переписал все, но это всего - 100 строчек кода - хороший дизайн имхо, не жалко выбросить.

Сам сторонник декомпозиции (да “покрытие интеграции” меньше)… только один раз приходилось вставлять в бд огромный кусок данных для очень спечифического теста. Во всех остальных проектах, данные хранились в тесте, максимум “excel/xml”.

Пардон, но кто говорил о прямом обращении к БД из теста?

Если вы дошли до создания обертки над JDBC, в чем собственно профит над ОРМ? В меньшем использовании ресурсов? Так уж извольте, на дворе 21й век, железки сейчас достаточно мощные. Или может создание доп. уровня абстракции уже не требует времени? Суть мысли заключалась в том, что с Hibernate не нужно изобретать велосипедов, а не в том, что это панацея от всего. Если вы изобрели свой и считаете, что новичку будет это сделать так же просто, - позволю тут не согласиться.

В итоге он пройдет через все те же грабли, на которые в свое время наступал каждый из нас, потратив в десяток раз больше времени, нежели разобраться с готовым продуктом, имеющим хорошую документацию. Напрашивается вопрос - кто ему выделит столько времени? А что насчет саппорта, допиливания новых API? Кто этим будет заниматься? Используя готовый продукт, мы как минимум избавляем себя от головной боли по причине технического брака в стиле: “ой, забыл предусмотреть”, “ой, эксепшен”, “ой, неправильный конвершен данных” и т.п. Что позволяет нам концентрироваться на решении конкретных задач. Сейчас вся моя работа с БД заключается лишь в создании новых таблиц с тестовыми данными и соответствующих сущностей в коде для их маппинга. Все остальное делает Hibernate.

Касательно многопоточности вопрос не в том, что тестируют тесты, а в том, как вернуть систему в исходное состояние после их выполнения. Все же мы помним теорию тестирования, ведь так? Выше был приведен пример с ресетом пасворда юзера, когда нам предварительно нужно залогиниться в систему, перейти в профиль и сделать ресет. Все это происходит на копии реальной продакшн БД (в добавок к новой разрабатываемой), которая была интегрирована из другого уже существующего продукта на QA окружение. Т.е. помимо чтения тестовых данных для прогона самого теста, нам нужно еще и апликейшен БД возвращать в исходное состояние, ибо нельзя ресетнуть пасворд, не заходя в профиль. Возвращать исходные данные посредством UI - не вариант, ибо во-первых, долго, во-вторых, если тест упадет, то данные все равно не вернутся. Изменять до теста? Нет никакой разницы с точки зрения факта наличия операции записи в апликейшен базу. На вопрос - почему бы нам не забить на рестор системы и не накатить девственный снепшот БД перед запуском тестов - ответ: нецелесообразно с точки зрения временных затрат. Фул БД апдейт занимает около 2 часов по причине ее размера и удаленности серверов US-UK.

Клауд пейментс с числом будущих потребителей, измеряющимся в сотнях тысячах человек - по предварительной оценке на основании статистики использования предыдущих продуктов этой серии.

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

Спасибо, точка зрения ясна. Респект Вашей позиции и Вашему опыту!

Уйду в сторону от топигка, вечерком можно и флудануть…

Метафора в связи с “велосипедом”.

Когда нужно забить одни гвоздь - беру молоток за "1р50к". Но при этом знаю что есть пневмомолоток, и задумываюсь, а не шуруп ли тут лучше вообще крутить...
Когда проффесионально строю, кручу, пилю... то осваиваю инструменты по полной, ну или "бригадир"-level.
В любом случае движем "эффективностью"... и тут различаю нужно быть эффективным _сегодня и сейчас_ и нужно быть эффективным _завтра и через год_.

фигасе, и выкинул велосипед, сел на танк. :wink:
в любой момент jdbc - выкинул, взял - hibernate. Статистика, к сожалению такова, что люди выбрав инструмент, боятся (жалко, страшно, не хотят и т.п) его и весь код рядом “выкинуть”… и тут умирает котенок и рождается новый велосипед.

Возможно со своей колокольни.

Если вы делаете подобное с продакшином или стейджингом проверяя функционал. То лично для меня это “странно”.

Почему не поднять “песочничу” где этот кусок можно проверить все “локально”.

Если вы проверяете, что деплоймент прошел правильно (конфиг логирования сформирован и работает как пологается), то для меня странно видеть это в контексте других кейсов.

По поводу 2-4, не эксперт java-stack. Но например Eclipse WSDL2Java plugin видимо формирует обвертки для взаимодействия с сервисами. Делал подобное в стэке .net x-лет назад.

Я не спорю, что могут быть кейсы, когда использование Hibernate в автотест-фреймворке будет оправдано. Несмотря на то, что я такого не встречал.

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

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

2 лайка

SOAP UI в помощь