Всем здравствуйте!
Цель:
Иметь возможность без связи с http сервисом на стороне, на своей стороне держать рабочие алгоритмы по работе с различными ответами со стороны.
Так же корректно обрабатывать наши запросы к ним, но через подготовленный МОК сервер согласно описанному интерфейсу взаимодействия. (какие договоренности передачи данных по тем или иным запросам.)
То есть мы независимо от другой стороны можем быть уверены в работе своей части.
Входные данные:
Конфигурация ERP, программа SoapUI, Мок сервер и скрипт, конфигурация "Тестирование 3.0".
Платформа 1с версии 8.3.14 и выше.
Кому может быть интересно:
Тем кто в своей работе разрабатывает http сервисы или взаимодействует с другими и хотел бы их покрыть автотестами.
И быть в курсе работоспособности своего продукта.
Практическая часть
Задача.
Существует набор REST-запросов, которые мы хотим проверить.
В нашем случае это url адреса с параметрами, по котороым мы ожидаем получить определенный ответ в формате json.
Пример запроса:
/api/receipts/4b558ad8-c4dd-11ea-b84e-00d8617b0c84/?testname=Test1in1
где параметр совпадает с именем теста. (?testname=Test1in1)
Пример ответа в формате json:
{
"code": "УП-34425",
"guid": "4b558ad8-c4dd-11ea-b84e-00d8617b0c84",
"buildingCode": "Склад основной(без ячеек)",
"typeCode": "1",
"expDate": "2020-07-13T00:00:00",
"supplier": "Комплектующие",
"notes": null,
"transportTask": "",
"lines": [
{
"productCode": "069000000009",
"lineNumber": "ca0bda06-79ce-4494-b078-08796038e83c",
"expQuantity": 5,
"actQuantity": 5,
"serial": "1112",
"details": null,
"prodDate": "2019-07-01T00:00:00"
}
{
"productCode": "069000000004",
"lineNumber": "10f05205-a1fb-40b5-85e3-49f5cda43c0e",
"expQuantity": 1,
"actQuantity":1,
"serial": "",
"details": null,
"prodDate": "0001-01-01T00:00:00"
}
]
}
1. Настраиваем проект в SoapUI. Мы организуем механизм обработки входной строки и подбора подходящего ответа. Сам алгоритм создания простого проекта смотрите по ссылке ( //infostart.ru/1c/articles/1182541/ ),
тут мы рассмотрим как выбрать необходимый ответ.
В SoapUI у нас хранится набор заданных ответов. Для того чтобы выбрать необходимый ответ и отправить пользователю мы используем код на языке "gerkin".
Текст кода приведен ниже. Он получает параметр из url строки и находит необходимый вариант ответа и отправляет его.
// Match based on query parameter
def queryString = mockRequest.getRequest().getQueryString() ?: "TestName=Test1in1"
TestName = queryString.substring(9);
log.info "TestName: " + TestName;
return TestName
2. Настраиваем в Тестировании 3.0
Фреймворк "Тестирование 3.0 (более подробное описание на https://testingtool.ru/)
Процедура создания задания в тестировании 3.0 следующая:
а) Создается новое задание и в нее последовательно добавляются три действия
б) Все действия с произвольным кодом на сервере 1С, тексты приведены ниже
Вот они 3 действия.
1. Запуск МОК сервера через набор команд.
2. Выполнение юнит тестов
3. Завершение мок сервера через килл процесса
1. Запуск МОК сервера через набор команд
По сути все сводится к запуску конкретного сохраненного проекта через mockservicerunner от soapui
// I) если открыт, то закроем
Сообщение = "";
PID = ПланировщикЗаданийСервер.ПолучитьЗначениеПользовательскойПеременной(Неопределено,"SoapUI MockServer");
Если НЕ PID=Неопределено Тогда
ПланировщикЗаданийКлиентСервер.ЗавершитьПроцессЛокально(PID,Сообщение);
КонецЕсли;
// II) запустить и сохранить в параметр
Сообщение = "";
ПутьККоманде = """C:\Program Files\SmartBear\SoapUI-5.3.0\bin\mockservicerunner.bat"" ""F:\Vissarov\git\erp-tests\WebServicesUnitTests\WMS\REST-WMS-soapui-project for unittest.xml""";
PID = ПланировщикЗаданийКлиентСервер.ЗапуститьПриложениеЛокально(ПутьККоманде,Сообщение);
Если PID>0 Тогда
ПланировщикЗаданийСервер.УстановитьЗначениеПользовательскойПеременной(Неопределено,"SoapUI MockServer",PID);
КонецЕсли;
2. Выполнение юнит тестов
Тут было принято решение разбить их на несколько обработок по структурным соображениям.
По видам запросов. И последовательно их запускать из определенной папки.
Команда так и называется "Все юнит-тесты из каталога UnitTest (WMS)".
В каждом тесте заводим тестовые случаи. И при падении теста мы точно знаем какой вариант теста не сработал из пройденных.
Вот как это выглядит:
Как результат теста сравниваем полученный документ и эталонный, который предварительно был выгружен в макет через обработку СериализаторMXL.epf (он еще известен по проекту https://github.com/xDrivenDevelopment/xUnitFor1C Аюханова Артура).
Правда в команде мы его доработали под свои нужды и служит для генерации первоначальных данных или эталонных макетов.
// создаем эталонный документ
СозданныеДанные = СериализаторMXL.СоздатьДанныеПоТабличномуДокументу(МакетДанные);
ПриходныйОрдер_Эталон = СозданныеДанные.ПриходныйОрдерНаТоварыУП_00034425От13_07_202010_48_52;
// проверяем результат работы алгоритма и подготовленный эталонный документ
УтвержденияПроверкаТаблиц.ПроверитьРавенствоТаблиц(
ПриходныйОрдер_Эталон.Товары.Выгрузить(,СтрокаНужныхКолонок),
ПриходныйОрдерТоварыПослеОбработки);
// переменные по данному тесту передаем в рабочую обработку, для того чтобы она поняла что это тестовый прогон
// и передала в адрес запрос нужный параметр.
ВнешняяОбработка.НастройкиОбменаWMS.Вставить("РежимТеста",Истина);
ВнешняяОбработка.НастройкиОбменаWMS.Вставить("ИмяПроверкиЮнитТеста",ИмяПроверкиЮнитТеста);
//Поменяем путь к МОК серверу.
//Исходный адрес вернется при откате транзакции
СтруктураЗаписи = Новый Структура;
СтруктураЗаписи.Вставить("Корреспондент",УзелWMS);
СтруктураЗаписи.Вставить("WSURLВебСервиса","http://SRV-msk-test1c1.ppl.loc:8098");
РегистрыСведений.НастройкиТранспортаОбменаДанными.ДобавитьЗапись(СтруктураЗаписи);
ГУИД_РО = "4b558ad8-c4dd-11ea-b84e-00d8617b0c84";
Ордер = Документы.ПриходныйОрдерНаТовары.ПолучитьСсылку(Новый УникальныйИдентификатор(ГУИД_РО));
КлючЗапроса = "/receiptUpdated/"+ГУИД_РО;
РезультатВыполнения = ВнешняяОбработка.ВыполнитьЮнитТест_ЗагрузкаИзWMSПоКлючОбъекта(КлючЗапроса, ТелоЗапроса);
//Часть кода добавленного в рабочем алгоритме для работы автотестов
Если НастройкиОбменаWMS.РежимТеста = Истина
И ЗначениеЗаполнено(НастройкиОбменаWMS.ИмяПроверкиЮнитТеста) Тогда
СтруктураПараметров.АдресРесурса = СтруктураПараметров.АдресРесурса +"/"+
СтрШаблон("?%1=%2", "TestName", НастройкиОбменаWMS.ИмяПроверкиЮнитТеста);
КонецЕсли;
// то есть получится на выходе примерно так
/api/receipts/4b558ad8-c4dd-11ea-b84e-00d8617b0c84/?TestName=Test1in1
3. Завершение мок сервера через килл процесса
Тут помогла статья от автора //infostart.ru/1c/articles/1014870/ Сергея Гарина. Но 1 в 1 не встали идеи.
Была изначально идея с завершением по PID, но там батник вызывает новый процесс и его PID отлавливать тоже задача.
Пришлось перейти на ком объект и вызов следующего метода.
Scr = Новый COMОбъект("MSScriptControl.ScriptControl");
Scr.Language = "vbscript";
Scr.AddCode("
Option Explicit
Dim objWMIService, objProcess, colProcess
Set objWMIService = GetObject(""winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2"")
Set colProcess = objWMIService.ExecQuery(""Select * from Win32_Process Where (CommandLine Like '%SoapUIMockServiceRunner%')"")
For Each objProcess in colProcess
objProcess.Terminate()
Next
");
Если инициализация com объекта не будет происходить, то нужно выполнить установку tsc64.dll
https://tablacus.github.io/scriptcontrol_en.html
По тестирование своего http есть хорошая статья:
//infostart.ru/1c/articles/1182541/
П.С.
Это моя первая статья, любую критику буду стараться принимать.