Тестирование, при помощи SoapUI, веб-сервиса, возвращающего список элементов

в 15:42, , рубрики: soapui, Песочница, тестирование, метки: ,
SoapUI — нужен help

Примерно с полгода назад поручили мне провести тестирование (заодно и автоматизировать его) проекта, активно использующему сервисы, отвечающие по SOAP-протоколу. Показали такую классную программу как SoapUI. То какая замечательная эта программа, какой у нее интутивно понятный интерфейс и интуитивно понятный онлайн-хэлп (soapui.org), мы оставим за рамками статьи.

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

Короче!

Сегодня мы решим конкретную прикладную задачу: а именно автоматизацию тестирования сервиса, который возвращает нам список из вот таких вот элементов:
<item>
<FeedbackId>357</FeedbackId>
<RequestDate>2012-04-08T00:48:49.493</RequestDate>
<FeedbackStatusName>Отправлено</FeedbackStatusName>
<FeedbackTypeName>Ошибка</FeedbackTypeName>
<AuthorFullName>Сидоров Иван Петрович</AuthorFullName>
<FeedbackStatusId>1</FeedbackStatusId>
<FeedbackTypeId>1</FeedbackTypeId>
<AuthorUserId>69</AuthorUserId>
</item>

Когда встала передо мной подобная задача, я трусливо проверил руками (поставил xpath-проверки) и отрапортавал что дело сделано (продукт я не знал, а лишнего времени много никогда не бывает...). Сейчас я готов исправиться, а заодно рассказать всем как это можно сделать. Сразу оговорюсь, что мой способ всего лишь один из нескольких, не претендующий на идеальность или оптимальность. И я таки надеюсь узнать и другие способы — рассчитываю на ваши идеи, опыт, фантазии…

Если вы читаете эту статью, я надеюсь, что у вас уже есть работающий сервис, который возвращает подобный список и база, из которой он черпает данные. И вы умеете написать такой селект, чтобы результат совпадал с тем что возвращает сервис.
image
На рисунке проект, который получился у меня: у нас есть xml-ка, полученная в ответ от сервиса, у нас есть результаты из базы. Они немного не совпадают, потому что мне лень сейчас дописывать join’ы и прочую муру (уже неактуально).

Теперь вкусненькое:

понятно что мышкой и готовыми проверками тут уже ничего не сделаешь — надо программировать. Программировать в SoapUI надо на Groovy. Java код является корректным Groovy-кодом, так что учить ничего не надо (я, вот, например Groovy не знаю)).
Вернемся к задаче: я вижу 2 способа решения: можно сделать Script Assertion в шаге JDBC Request, а можно вынести в отдельный шаг.
Я вынес. Дальше код, ради него все и затевалось. Думаю что тот, кто сможет поменять его под свою задачу, сможет разобраться и по тем комментам, которые есть, так что дальше слова излишни…

import com.eviware.soapui.support.XmlHolder;

boolean b = true;
def soapRequest = testRunner.testCase.getTestStepAt(0);
//Найдем кол-во item'ов в ответе
XmlHolder response = new XmlHolder( soapRequest.getProperty('Response').getValue() );
int numberOfItems = response.getXmlObject().selectPath('//item').size();

if (numberOfItems != 0)
{
XmlHolder row, item;
for (int i=1; i<=numberOfItems; i++) {
row = new XmlHolder( context.expand ( '${JDBC Request#ResponseAsXml#//Row['+i+']}' ));
item = new XmlHolder( context.expand ( '${GetFeedbackList#Response#//item['+i+']}' ));
//compareItemWithRow - функция, смотри ниже
if (!compareItemWithRow (item, row) ) {
b = false;
//выходим при первой ошибке
break;
}
}
}
else {
//удостоверимся что и в базе нет данных
def jdbcRequest = testRunner.testCase.getTestStepAt(1);
response = new XmlHolder( jdbcRequest.getProperty('ResponseAsXml').getValue() )
if (response.getXmlObject().selectPath('//item').size() != 0) {
log.error "There was no items in response but I found a few in database! WTF?!"
assert false;
}
}
assert b;
return;

/**сравнивает 2 XmlHolder'а по определенным полям, если что-то не так - пишет в лог ошибки и возвращает false*/
private boolean compareItemWithRow (XmlHolder item, XmlHolder row) {
boolean b = true;

if (!item.getNodeValue('//FeedbackId').equals( row.getNodeValue('//FEEDBACKID') )) {
log.error ('''FeedbackId doesn't corresponds database! Here could be your advertisment...'''
+ item.getNodeValue('//FeedbackId') + ' != ' + row.getNodeValue('//FEEDBACKID') +
'!!!ITEM: '+ item.getXml()+
' !!!ROW: '+ row.getXml());
b=false;
}
if (!item.getNodeValue('//RequestDate').equals( row.getNodeValue('//DATEINXML') )) {
log.error ('''RequestDate doesn't corresponds database! Here could be your advertisment... "'''
+ item.getNodeValue('//RequestDate') + '" != "' + row.getNodeValue('//DATEINXML') +
'" !!!ITEM: '+ item.getXml()+
' !!!ROW: '+ row.getXml());
b=false;
}
if (!item.getNodeValue('//AuthorUserId').equals( row.getNodeValue('//REQUESTUSERID') )) {
log.error ('''AuthorUserId doesn't corresponds database! Here could be your advertisment... "'''
+ item.getNodeValue('//AuthorUserId') + '" != "' + row.getNodeValue('//REQUESTUSERID') +
'" !!!ITEM: '+ item.getXml()+
' !!!ROW: '+ row.getXml());
b=false;
}
//...
return b;
}

Автор: astafev

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js