1
0
mirror of https://github.com/bia-technologies/yaxunit.git synced 2025-03-17 20:48:01 +02:00

Merge pull request #321 from bia-technologies/feature/314

314 / Механизм зависимостей тестов
This commit is contained in:
Koryakin Aleksey 2024-04-02 14:54:20 +03:00 committed by GitHub
commit b3bbf387e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 1236 additions and 66 deletions

View File

@ -0,0 +1,72 @@
# Зависимости
Предположим у вас есть набор серверных тестов, которые требуют наличия файлов хранящихся в репозитории на клиенте.
Для выполнения этих тестов вам необходимо передать файлы на сервер перед выполнением. В дополнение, передачу необходимо выполнить только один раз и только если выполняются тесты, для которых файлы нужны.
В решении этой проблемы может помочь механизм зависимостей, который:
* Позволяет указывать зависимости тестов
* Для разрешения зависимостей используется код 1с, вызываемый с клиента
* Разрешение зависимостей выполняется единожды и результат может быть переиспользован в различных тестах
* Если по какой-то причине не удалось разрешить зависимость, то зависимые тесты не будут выполнятся.
* YAxUnit на данный момент реализует зависимость от файлов проекта, которая проверяет наличие нужных файлов и переносит их на сервер.
Например, вам необходимо проверить, что файл `.gitignore` содержит исключение для `ConfigDumpInfo.xml`.
```bsl
Процедура ИсполняемыеСценарии() Экспорт
ЮТТесты.
.ДобавитьТест("ПроверитьДанныеGitIgnore")
.ЗависитОт().ФайлыПроекта(".gitignore"); // Указываем зависимость
КонецПроцедуры
Процедура ПроверитьДанныеGitIgnore() Экспорт
ПолноеИмяФайла = ЮТест.Зависимость(ЮТЗависимости.ФайлыПроекта(".gitignore")).ПолноеИмя; // Получаем результат работы зависимости
ЮТест.ОжидаетЧто(ЮТФайлы.Существует(ПолноеИмяФайла), "Файл каталога проекта не существует")
.ЭтоИстина();
Данные = ЮТОбщий.ДанныеТекстовогоФайла(ПолноеИмяФайла);
ЮТест.ОжидаетЧто(Данные, "Содержимое файла")
.Содержит("ConfigDumpInfo.xml");
КонецПроцедуры
```
В примере движок проверит наличие файла `.gitignore` в каталоге проекта и перенесет его на сервер и сохранит в контексте путь к у файлу (причем, для сервера и клиент будут сохранены разные пути).
Другой пример, в своих тестах мы добавили зависимость для создания `ФабрикаXDTO` из файлов:
```bsl
Процедура ИсполняемыеСценарии() Экспорт
ЮТТесты.
.ДобавитьТест("ВыполнитьОбмен")
.ЗависитОт().ФабрикаСбора();
КонецПроцедуры
Процедура ВыполнитьОбмен() Экспорт
Фабрика = ЮТест.Зависимость(ЮТЗависимости.ФабрикаСбора()).Фабрика; // Получаем результат работы зависимости
...
КонецПроцедуры
```
Здесь для тестирования различных обменов мы создаем, на основании файлов хранящихся в репозитории, фабрику XDTO. При этом фабрика создается только один раз и доступна во всех серверных тестах.
## Зачем нужны зависимости
Основной целью создания зависимостей было предоставление единого механизма для работы с "тяжелыми" и часто используемыми зависимостями тестов. В большинстве случаев достаточно создать общий метод и вызывать его в тестах или событиях и таким образом готовить контекст теста. Но в некоторых случаях, таких как использование "клиентских" файлов в серверных тестах, этот вариант не подходит. Чтобы избежать костылей в подобных ситуациях и были добавлены зависимости.
## Принцип работы
1. В своих тестах вы указываете зависимости для тестов (наборов или модулей).
2. При запуске, YAxUnit анализирует какие тесты вы хотите запустить и собирает по ним реестр зависимостей.
3. Движок обрабатывает реестр зависимостей:
* вызывает методы реализующие зависимости
* сохраняет признак успешности обработки зависимости
* сохраняет данные, которые сформировала зависимость.
4. Тесты связанные с неразрешенными зависимостями переводятся в статус "Пропущен" и не вызываются при прогоне.
5. После этого происходит запуск тестов.
6. Любой тест может обратиться к результатам обработки зависимостей используя `ЮТест.Зависимость`

View File

@ -0,0 +1,41 @@
//©///////////////////////////////////////////////////////////////////////////©//
//
// Copyright 2021-2024 BIA-Technologies Limited Liability Company
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//
#Область ПрограммныйИнтерфейс
// Указывает зависимость теста (набора или модуля) от файлов проекта.
// Гарантирует доступность файлов как на клиенте, так и на сервере.
//
// Параметры:
// ПутьКФайлам - Строка - Относетельный путь к файлу проекта (относительно настройки projectPath)
//
// Возвращаемое значение:
// CommonModule.ЮТТесты - Файлы проекта
Функция ФайлыПроекта(ПутьКФайлам) Экспорт
ОписаниеЗависимости = ЮТФабрика.НовоеОписаниеЗависимости();
ОписаниеЗависимости.Идентификатор = "ФайлыПроекта";
ОписаниеЗависимости.МетодРеализации = "ЮТРазрешениеЗависимостейСлужебныйКлиент.ФайлыПроекта";
ОписаниеЗависимости.Параметры.Добавить(ПутьКФайлам);
ОписаниеЗависимости.Асинхронный = Истина;
Возврат ЮТЗависимостиСлужебный.ДобавитьЗависимостьПриРегистрации(ОписаниеЗависимости);
КонецФункции
#КонецОбласти

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="d19d3945-b2a8-459e-a7bd-e0a2e2d62974">
<name>ЮТЗависимости</name>
<synonym>
<key>ru</key>
<value>Зависимости</value>
</synonym>
<clientManagedApplication>true</clientManagedApplication>
<server>true</server>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -0,0 +1,145 @@
//©///////////////////////////////////////////////////////////////////////////©//
//
// Copyright 2021-2024 BIA-Technologies Limited Liability Company
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//
#Область СлужебныйПрограммныйИнтерфейс
Функция ДанныеЗависимости(ОписаниеЗависимости) Экспорт
КлючЗависимости = КлючЗависимости(ОписаниеЗависимости);
Результаты = ЮТКонтекстСлужебный.ЗначениеКонтекста(ИмяКонтекстаДанныеЗависимостей());
ДанныеЗависимости = Результаты[КлючЗависимости];
Если ДанныеЗависимости = Неопределено И НЕ ЗависимостьРазрешена(КлючЗависимости) Тогда
ВызватьИсключение СтрШаблон("Не указана или не разрешена зависимость `%1`", ПредставлениеЗависимости(ОписаниеЗависимости));
КонецЕсли;
Возврат ДанныеЗависимости;
КонецФункции
// Служебный метод, используется только в модуле см. ЮТЗависимости.
//
// Параметры:
// ОписаниеЗависимости - см. ЮТФабрика.НовоеОписаниеЗависимости
//
// Возвращаемое значение:
// CommonModule.ЮТТесты
Функция ДобавитьЗависимостьПриРегистрации(ОписаниеЗависимости) Экспорт
Если ЮТКонтекстСлужебный.КонтекстИсполнения() <> Неопределено Тогда
Возврат ОписаниеЗависимости;
Иначе
ЮТТестыСлужебный.ДобавитьЗависимость(ОписаниеЗависимости);
Возврат ЮТТесты;
КонецЕсли;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция КлючЗависимости(ОписаниеЗависимости) Экспорт
Идентификатор = ВРег(ОписаниеЗависимости.Идентификатор);
Если ЗначениеЗаполнено(ОписаниеЗависимости.Параметры) Тогда
Возврат ЮТОбщий.СтрокаJSON(Новый Структура("Идентификатор, Параметры", Идентификатор, ОписаниеЗависимости.Параметры));
Иначе
Возврат Идентификатор;
КонецЕсли;
КонецФункции
Функция ПредставлениеЗависимости(ОписаниеЗависимости) Экспорт
Если ЗначениеЗаполнено(ОписаниеЗависимости.Параметры) Тогда
Возврат ОписаниеЗависимости.Идентификатор + ЮТКоллекции.ПредставлениеМассива(ОписаниеЗависимости.Параметры);
Иначе
Возврат ОписаниеЗависимости.Идентификатор;
КонецЕсли;
КонецФункции
Функция УникальнаяЗависимость(Зависимости, ОписаниеЗависимости) Экспорт
КлючЗависимости = КлючЗависимости(ОписаниеЗависимости);
УникальнаяЗависимость = Зависимости[КлючЗависимости];
Если УникальнаяЗависимость <> Неопределено Тогда
Возврат УникальнаяЗависимость;
КонецЕсли;
Копия = ЮТКоллекции.СкопироватьСтруктуру(ОписаниеЗависимости);
Копия.Параметры = Новый ФиксированныйМассив(ОписаниеЗависимости.Параметры);
Копия.Ключ = КлючЗависимости;
УникальнаяЗависимость = Новый ФиксированнаяСтруктура(Копия);
Зависимости.Вставить(КлючЗависимости, УникальнаяЗависимость);
Возврат УникальнаяЗависимость;
КонецФункции
Функция РезультатРазрешенияЗависимости(КлючЗависимости)
ДанныеКонтекста = КонтекстРазрешенныеЗависимости();
Возврат ДанныеКонтекста[КлючЗависимости];
КонецФункции
Функция ЗависимостьРазрешена(КлючЗависимости)
Результат = РезультатРазрешенияЗависимости(КлючЗависимости);
Возврат Результат <> Неопределено И Результат.Успешно;
КонецФункции
#Область Контексты
Процедура ИнициализацияКонтекста(ДанныеКонтекста) Экспорт
ДанныеКонтекста.Вставить(ИмяКонтекстаДанныеЗависимостей(), Новый Соответствие());
ДанныеКонтекста.Вставить(ИмяКонтекстаРазрешенныеЗависимости(), Новый Соответствие());
КонецПроцедуры
Функция КонтекстРазрешенныеЗависимости() Экспорт
Возврат ЮТКонтекстСлужебный.ЗначениеКонтекста(ИмяКонтекстаРазрешенныеЗависимости());
КонецФункции
Функция ИмяКонтекстаРазрешенныеЗависимости() Экспорт
Возврат "КонтекстРазрешенныеЗависимости";
КонецФункции
Функция ИмяКонтекстаДанныеЗависимостей() Экспорт
Возврат "КонтекстДанныеЗависимостей";
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="006d4dd3-e4fb-4003-8485-809dd7d9ac69">
<name>ЮТЗависимостиСлужебный</name>
<synonym>
<key>ru</key>
<value>Зависимости служебный</value>
</synonym>
<clientManagedApplication>true</clientManagedApplication>
<server>true</server>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -0,0 +1,320 @@
//©///////////////////////////////////////////////////////////////////////////©//
//
// Copyright 2021-2024 BIA-Technologies Limited Liability Company
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//
#Область СлужебныйПрограммныйИнтерфейс
// Разрешить зависимости.
//
// Параметры:
// ТестовыеМодули - Массив из см. ЮТФабрикаСлужебный.ОписаниеИсполняемогоТестовогоМодуля
// Обработчик - ОписаниеОповещения
Процедура РазрешитьЗависимости(ТестовыеМодули, Обработчик) Экспорт
Зависимости = СобратьЗависимости(ТестовыеМодули);
Если НЕ ЗначениеЗаполнено(Зависимости) Тогда
ЮТЛогирование.Отладка("Обработка зависимостей: нет зависимостей");
ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьОбработчик(Обработчик);
Возврат;
КонецЕсли;
ПараметрыИсполнения = ЮТАсинхроннаяОбработкаСлужебныйКлиент.ЦепочкаАсинхроннойОбработки();
ПараметрыИсполнения.Вставить("ТестовыеМодули", ТестовыеМодули);
Для Каждого ОписаниеЗависимости Из Зависимости Цикл
Параметры = Новый Структура("ОписаниеЗависимости, ПараметрыИсполнения", ОписаниеЗависимости, ПараметрыИсполнения);
Если ОписаниеЗависимости.Асинхронный Тогда
Загрузчик = Новый ОписаниеОповещения("РазрешитьЗависимостьАсинхронно", ЭтотОбъект, Параметры);
Иначе
Загрузчик = Новый ОписаниеОповещения("РазрешитьЗависимость", ЭтотОбъект, Параметры);
КонецЕсли;
ПараметрыИсполнения.Цепочка.Добавить(Загрузчик);
КонецЦикла;
ПараметрыИсполнения.Цепочка.Добавить(Новый ОписаниеОповещения("ПослеОбработкиЗависимостей", ЭтотОбъект, ПараметрыИсполнения));
ПараметрыИсполнения.Цепочка.Добавить(Обработчик);
ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьСледующийОбработчик(ПараметрыИсполнения);
КонецПроцедуры
// Дедупликация зависимостей.
//
// Параметры:
// РезультатЧтенияТестов - Массив из см. ЮТФабрикаСлужебный.ОписаниеТестовогоМодуля - Набор описаний тестовых модулей, которые содержат информацию о запускаемых тестах
Процедура ДедупликацияЗависимостей(РезультатЧтенияТестов) Экспорт
Зависимости = Новый Соответствие();
Для Каждого ТестовыйМодуль Из РезультатЧтенияТестов Цикл
ДедупликацияЗависимостейОбъекта(Зависимости, ТестовыйМодуль);
Для Каждого ТестовыйНабор Из ТестовыйМодуль.НаборыТестов Цикл
ДедупликацияЗависимостейОбъекта(Зависимости, ТестовыйНабор);
Для Каждого Тест Из ТестовыйНабор.Тесты Цикл
ДедупликацияЗависимостейОбъекта(Зависимости, Тест);
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
#Область РазрешениеЗависимостей
Функция СобратьЗависимости(ТестовыеМодули)
Зависимости = Новый Массив();
ДобавленныеЗависимости = Новый Соответствие();
Для Каждого ТестовыйМодуль Из ТестовыеМодули Цикл
СобратьЗависимостиОбъекта(ТестовыйМодуль, Зависимости, ДобавленныеЗависимости);
Для Каждого Набор Из ТестовыйМодуль.НаборыТестов Цикл
СобратьЗависимостиОбъекта(Набор, Зависимости, ДобавленныеЗависимости);
Для Каждого Тест Из Набор.Тесты Цикл
СобратьЗависимостиОбъекта(Тест, Зависимости, ДобавленныеЗависимости);
КонецЦикла;
КонецЦикла;
КонецЦикла;
Возврат Зависимости;
КонецФункции
Процедура СобратьЗависимостиОбъекта(Объект, Зависимости, ДобавленныеЗависимости)
Для Каждого Зависимость Из Объект.Зависимости Цикл
Если ДобавленныеЗависимости[Зависимость.Ключ] = Неопределено Тогда
Зависимости.Добавить(Зависимость);
ДобавленныеЗависимости.Вставить(Зависимость.Ключ, Истина);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура РазрешитьЗависимостьАсинхронно(Результат, Параметры) Экспорт
ОписаниеЗависимости = Параметры.ОписаниеЗависимости;
ЮТЛогирование.Отладка("Обработка зависимостей: асинхронная обработка зависимости " + ЮТЗависимостиСлужебный.ПредставлениеЗависимости(ОписаниеЗависимости));
Обработчик = Новый ОписаниеОповещения("ОбработатьРезультатРазрешенияЗависимости", ЭтотОбъект, Параметры);
ИмяМетода = ОписаниеЗависимости.МетодРеализации;
ПараметрыМетода = ЮТКоллекции.СкопироватьМассив(ОписаниеЗависимости.Параметры);
ПараметрыМетода.Добавить(Обработчик);
Ошибка = ЮТМетодыСлужебный.ВыполнитьМетод(ИмяМетода, ПараметрыМетода);
Если Ошибка <> Неопределено Тогда
РезультатРазрешения = ЮТФабрикаСлужебный.РезультатРазрешенияЗависимости();
РезультатРазрешения.Ошибка = Ошибка;
ОбработатьРезультатРазрешенияЗависимости(РезультатРазрешения, Параметры);
КонецЕсли;
КонецПроцедуры
Процедура ОбработатьРезультатРазрешенияЗависимости(Результат, Параметры) Экспорт
ОписаниеЗависимости = Параметры.ОписаниеЗависимости;
ПредставлениеЗависимости = ЮТЗависимостиСлужебный.ПредставлениеЗависимости(ОписаниеЗависимости);
ЮТЛогирование.Отладка("Обработка зависимостей: заврешена обработка зависимости " + ПредставлениеЗависимости);
ПараметрыИсполнения = Параметры.ПараметрыИсполнения;
Если НЕ Результат.Успешно Тогда
Сообщение = СтрШаблон("Не удалось разрешить зависимость `%1`", ПредставлениеЗависимости);
Результат.Ошибка = ОписаниеОшибкиПропуска(Сообщение, Результат.Ошибка);
ЮТЛогирование.Ошибка(Результат.Ошибка.Сообщение);
КонецЕсли;
СохранитьРезультатРазрешенияЗависимости(ОписаниеЗависимости.Ключ, Результат);
ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьСледующийОбработчик(ПараметрыИсполнения);
КонецПроцедуры
Процедура РазрешитьЗависимость(Результат, Параметры) Экспорт
ОписаниеЗависимости = Параметры.ОписаниеЗависимости;
Попытка
РезультатРазрешения = ЮТМетодыСлужебный.ВызватьФункцию(ОписаниеЗависимости.МетодРеализации, ОписаниеЗависимости.Параметры);
Исключение
РезультатРазрешения = ЮТФабрикаСлужебный.РезультатРазрешенияЗависимости();
РезультатРазрешения.Ошибка = ИнформацияОбОшибке();
КонецПопытки;
ОбработатьРезультатРазрешенияЗависимости(РезультатРазрешения, Параметры);
КонецПроцедуры
Процедура СохранитьРезультатРазрешенияЗависимости(КлючЗависимости, Результат) Экспорт
ИмяКонтекстаДанныеЗависимостей = ЮТЗависимостиСлужебный.ИмяКонтекстаДанныеЗависимостей();
КонтекстРазрешенныеЗависимости = ЮТЗависимостиСлужебный.КонтекстРазрешенныеЗависимости();
КонтекстРазрешенныеЗависимости.Вставить(КлючЗависимости, Результат);
ПередаваемыеЗначения = Новый Соответствие();
Если Результат.СохраняемыйКонтекст <> Неопределено Тогда
ПередаваемыеЗначения.Вставить(КлючЗависимости, Результат.СохраняемыйКонтекстСервер);
ЮТКонтекстСлужебный.ВставитьЗначениеКонтекста(ИмяКонтекстаДанныеЗависимостей, ПередаваемыеЗначения);
ЮТКонтекстСлужебный.ВставитьЗначениеКонтекста(ИмяКонтекстаДанныеЗависимостей, ПередаваемыеЗначения, Истина);
КонецЕсли;
Если Результат.СохраняемыйКонтекстСервер <> Неопределено Тогда
ПередаваемыеЗначения.Вставить(КлючЗависимости, Результат.СохраняемыйКонтекстСервер);
ЮТКонтекстСлужебный.ВставитьЗначениеКонтекста(ИмяКонтекстаДанныеЗависимостей, ПередаваемыеЗначения, Истина);
КонецЕсли;
Если Результат.СохраняемыйКонтекстКлиент <> Неопределено Тогда
ПередаваемыеЗначения.Вставить(КлючЗависимости, Результат.СохраняемыйКонтекстКлиент);
ЮТКонтекстСлужебный.ВставитьЗначениеКонтекста(ИмяКонтекстаДанныеЗависимостей, ПередаваемыеЗначения);
КонецЕсли;
КонецПроцедуры
Процедура ПослеОбработкиЗависимостей(Результат, ПараметрыИсполнения) Экспорт
РазрешенныеЗависимости = ЮТЗависимостиСлужебный.КонтекстРазрешенныеЗависимости();
Статусы = ЮТФабрика.СтатусыИсполненияТеста();
Для Каждого ТестовыйМодуль Из ПараметрыИсполнения.ТестовыеМодули Цикл
РезультатРазрешенияЗависимостей = ПроверкаРазрешенныхЗависимостей(ТестовыйМодуль, РазрешенныеЗависимости);
Если НЕ РезультатРазрешенияЗависимостей.Успешно Тогда
УстановитьОшибкиВ(ТестовыйМодуль.НаборыТестов, РезультатРазрешенияЗависимостей.Ошибка);
Прервать;
КонецЕсли;
Для Каждого Набор Из ТестовыйМодуль.НаборыТестов Цикл
РезультатРазрешенияЗависимостей = ПроверкаРазрешенныхЗависимостей(Набор, РазрешенныеЗависимости);
Если НЕ РезультатРазрешенияЗависимостей.Успешно Тогда
УстановитьОшибкиВ(Набор.Тесты, РезультатРазрешенияЗависимостей.Ошибка);
Набор.Ошибки.Добавить(РезультатРазрешенияЗависимостей.Ошибка);
Набор.Выполнять = Ложь;
Продолжить;
КонецЕсли;
Для Каждого Тест Из Набор.Тесты Цикл
РезультатРазрешенияЗависимостей = ПроверкаРазрешенныхЗависимостей(Тест, РазрешенныеЗависимости);
Если НЕ РезультатРазрешенияЗависимостей.Успешно Тогда
Тест.Ошибки.Добавить(РезультатРазрешенияЗависимостей.Ошибка);
Тест.Статус = Статусы.Пропущен;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЦикла;
ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьСледующийОбработчик(ПараметрыИсполнения);
КонецПроцедуры
Функция ОписаниеОшибкиПропуска(Описание, ИнформацияОбОшибке = Неопределено)
Ошибка = ЮТФабрикаСлужебный.ОписаниеОшибкиПропуска(Описание);
Если ИнформацияОбОшибке = Неопределено Тогда
Возврат Ошибка;
КонецЕсли;
ТипОшибки = ТипЗнч(ИнформацияОбОшибке);
Если ТипОшибки = Тип("Структура") Тогда
ЗаполнитьЗначенияСвойств(Ошибка, ИнформацияОбОшибке, , "ТипОшибки, Сообщение");
Ошибка.Сообщение = ЮТСтроки.ДобавитьСтроку(Описание, ИнформацияОбОшибке.Сообщение, Символы.ПС);
ИначеЕсли ТипОшибки = Тип("ИнформацияОбОшибке") Тогда
Ошибка.Стек = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
ИначеЕсли ТипОшибки = Тип("Строка") Тогда
Ошибка.Сообщение = ЮТСтроки.ДобавитьСтроку(Описание, ИнформацияОбОшибке, Символы.ПС);
КонецЕсли;
Возврат Ошибка;
КонецФункции
Функция УстановитьОшибкиВ(Объекты, Ошибка)
Для Каждого Объект Из Объекты Цикл
Объект.Ошибки.Добавить(Ошибка);
Объект.Выполнять = Ложь;
КонецЦикла;
Возврат Ошибка;
КонецФункции
Функция ПроверкаРазрешенныхЗависимостей(Объект, РазрешенныеЗависимости)
Для Каждого ОписаниеЗависимости Из Объект.Зависимости Цикл
Результат = РазрешенныеЗависимости[ОписаниеЗависимости.Ключ];
Если Результат = Неопределено Тогда
Результат = ЮТФабрикаСлужебный.РезультатРазрешенияЗависимости();
Сообщение = СтрШаблон("Нет информации о зависимости `%1`, что-то пошло не так", ЮТЗависимостиСлужебный.ПредставлениеЗависимости(ОписаниеЗависимости));
Результат.Ошибка = ОписаниеОшибкиПропуска(Сообщение);
КонецЕсли;
Если НЕ Результат.Успешно Тогда
Возврат Результат;
КонецЕсли;
КонецЦикла;
Возврат Новый Структура("Успешно", Истина);
КонецФункции
#КонецОбласти
Процедура ДедупликацияЗависимостейОбъекта(Зависимости, Объект)
Для Инд = 0 По Объект.Зависимости.ВГраница() Цикл
Объект.Зависимости[Инд] = ЮТЗависимостиСлужебный.УникальнаяЗависимость(Зависимости, Объект.Зависимости[Инд]);
КонецЦикла;
КонецПроцедуры
#КонецОбласти

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="8742463f-e915-43d3-b7bd-aaeedff6df08">
<name>ЮТЗависимостиСлужебныйКлиент</name>
<synonym>
<key>ru</key>
<value>Зависимости служебный клиент</value>
</synonym>
<clientManagedApplication>true</clientManagedApplication>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -28,6 +28,7 @@
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикПодключитьКомпоненты");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикИнициализация");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикЗагрузитьТесты");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикРазрешитьЗависимости");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикВыполнитьТестирование");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикСохранитьОтчет");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикСохранитьКодВозврата");
@ -44,6 +45,7 @@
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикИнициализация");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикЗагрузитьТесты");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикРазрешитьЗависимости");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикВыполнитьТестирование");
ПараметрыИсполнения.Цепочка.Добавить(ОбработчикЗавершения);
@ -189,6 +191,14 @@
КонецПроцедуры
Процедура ОбработчикРазрешитьЗависимости(Результат, ДополнительныеПараметры) Экспорт
Обработчик = ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(ДополнительныеПараметры);
ЮТЗависимостиСлужебныйКлиент.РазрешитьЗависимости(ДополнительныеПараметры.ИсполняемыеТестовыеМодули, Обработчик);
КонецПроцедуры
Процедура ОбработчикВыполнитьТестирование(Результат, ДополнительныеПараметры) Экспорт
ЮТСобытияСлужебный.ПередВыполнениемТестов(ДополнительныеПараметры.ИсполняемыеТестовыеМодули);

View File

@ -78,7 +78,7 @@
//@skip-check constructor-function-return-section
Возврат ЮТКоллекции.ЗначениеСтруктуры(Объект, Ключи[Ключи.ВГраница()]);
КонецФункции
// УстановитьЗначениеКонтекста
@ -108,6 +108,30 @@
КонецПроцедуры
// УстановитьЗначениеКонтекста
// Устанавливает значение вложенного контекста, вложенного реквизита контекста
//
// Параметры:
// ИмяРеквизита - Строка - Имя реквизита/вложенного контекста
// Значения - Структура, Соответствие из Произвольный - Набор устанавливаемых значений контекста
// УстановитьНаСервер - Булево - Установить также на сервер
Процедура ВставитьЗначениеКонтекста(Знач ИмяРеквизита, Знач Значения, Знач УстановитьНаСервер = Ложь) Экспорт
#Если НЕ Сервер Тогда
Если УстановитьНаСервер Тогда
ЮТКонтекстСлужебныйВызовСервера.ВставитьЗначениеКонтекста(ИмяРеквизита, Значения);
Возврат;
КонецЕсли;
#КонецЕсли
ДанныеКонтекста = ЗначениеКонтекста(ИмяРеквизита);
Для Каждого Элемент Из Значения Цикл
ДанныеКонтекста.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЦикла;
КонецПроцедуры
// КонтекстТеста
// Возвращает структуру, в которой можно хранить данные используемые в тесте
// Данные живут в рамках одного теста, но доступны в обработчиках событий `ПередКаждымТестом` и `ПослеКаждогоТеста`
@ -242,6 +266,8 @@
Описание = Новый Структура;
ЮТСобытияСлужебный.ИнициализацияКонтекста(Описание);
Возврат Описание;
КонецФункции

View File

@ -52,6 +52,18 @@
КонецПроцедуры
// УстановитьЗначениеКонтекста
// Устанавливает значение вложенного контекста, вложенного реквизита контекста
//
// Параметры:
// ИмяРеквизита - Строка - Имя реквизита/вложенного контекста
// Значения - Структура, Соответствие - Новое значение реквизита/вложенного контекста
Процедура ВставитьЗначениеКонтекста(Знач ИмяРеквизита, Знач Значения) Экспорт
ЮТКонтекстСлужебный.ВставитьЗначениеКонтекста(ИмяРеквизита, Значения, Ложь);
КонецПроцедуры
Функция ЗначениеКонтекста(Знач ИмяРеквизита) Экспорт
Возврат ЮТКонтекстСлужебный.ЗначениеКонтекста(ИмяРеквизита);

View File

@ -102,23 +102,7 @@
#Если ВебКлиент Тогда
ВызватьИсключение ЮТИсключения.МетодНеДоступен("ЮТОбщий.ВыполнитьМетод");
#Иначе
Если СтрЗаканчиваетсяНа(ПолноеИмяМетода, ")") Тогда
Алгоритм = ПолноеИмяМетода;
ИначеЕсли НЕ ЗначениеЗаполнено(Параметры) Тогда
Алгоритм = ПолноеИмяМетода + "()";
ИначеЕсли ТипЗнч(Параметры) = Тип("Массив") Тогда
Алгоритм = СтрШаблон("%1(%2)", ПолноеИмяМетода, СтрокаПараметровМетода(Параметры, "Параметры"));
Иначе
ВызватьИсключение СтрШаблон("Не верный тип параметров `%1` для вызова метода, должен быть массив", ТипЗнч(Параметры));
КонецЕсли;
Алгоритм = СтрокаВызоваМетода(ПолноеИмяМетода, Параметры, "Параметры");
Попытка
//@skip-check server-execution-safe-mode
@ -132,6 +116,22 @@
КонецФункции
Функция СтрокаВызоваМетода(ПолноеИмяМетода, Параметры, ИмяМассиваПараметров = "Параметры") Экспорт
Если СтрЗаканчиваетсяНа(ПолноеИмяМетода, ")") Тогда
Алгоритм = ПолноеИмяМетода;
ИначеЕсли НЕ ЗначениеЗаполнено(Параметры) Тогда
Алгоритм = ПолноеИмяМетода + "()";
ИначеЕсли ТипЗнч(Параметры) = Тип("Массив") Тогда
Алгоритм = СтрШаблон("%1(%2)", ПолноеИмяМетода, СтрокаПараметровМетода(Параметры, ИмяМассиваПараметров));
Иначе
ВызватьИсключение СтрШаблон("Не верный тип параметров `%1` для вызова метода, должен быть массив", ТипЗнч(Параметры));
КонецЕсли;
Возврат Алгоритм;
КонецФункции
Функция ВычислитьБезопасно(Выражение) Экспорт
#Если НЕ ВебКлиент И НЕ ТонкийКлиент Тогда
@ -152,6 +152,32 @@
КонецФункции
Функция ВызватьФункцию(ПолноеИмяМетода, Параметры, Безопасно = Истина) Экспорт
Выражение = СтрокаВызоваМетода(ПолноеИмяМетода, Параметры);
#Если НЕ ВебКлиент И НЕ ТонкийКлиент Тогда
Если Безопасно Тогда
УстановитьБезопасныйРежим(Истина);
Попытка
Значение = Вычислить(Выражение);
Исключение
УстановитьБезопасныйРежим(Ложь);
ВызватьИсключение;
КонецПопытки;
УстановитьБезопасныйРежим(Ложь);
Иначе
//@skip-check server-execution-safe-mode
Значение = Вычислить(Выражение);
КонецЕсли;
#Иначе
Значение = Вычислить(Выражение);
#КонецЕсли
Возврат Значение;
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@ -179,7 +179,9 @@
Процедура ЗаписатьОшибку(ЗаписьXML, ОписаниеОшибки)
Сообщение = СообщениеОбОшибке(ОписаниеОшибки);
ЗаписьXML.ЗаписатьНачалоЭлемента("error");
ЗаписьXML.ЗаписатьАтрибут("message", Сообщение);
Если Сообщение <> Неопределено Тогда
ЗаписьXML.ЗаписатьАтрибут("message", Сообщение);
КонецЕсли;
Если ЗначениеЗаполнено(ОписаниеОшибки.ТипОшибки) Тогда
ЗаписьXML.ЗаписатьАтрибут("type", XMLСтрока(ОписаниеОшибки.ТипОшибки));

View File

@ -0,0 +1,63 @@
//©///////////////////////////////////////////////////////////////////////////©//
//
// Copyright 2021-2024 BIA-Technologies Limited Liability Company
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//
#Область СлужебныйПрограммныйИнтерфейс
// Поместить файлы в рабочий каталог.
//
// Параметры:
// ПереданныеФайлы - Массив Из ОписаниеПереданногоФайла
//
// Возвращаемое значение:
//
Функция ПоместитьФайлыВРабочийКаталог(Знач ПереданныеФайлы) Экспорт
Контекст = Новый Структура();
Контекст.Вставить("РабочийКаталог", ФайлыПроектаРабочийКаталог());
ЮТФайлы.СоздатьКаталогРекурсивно(Контекст.РабочийКаталог);
КаталогПроекта = ЮТНастройкиВыполнения.КаталогПроекта();
Для Каждого Файл Из ПереданныеФайлы Цикл
ИмяВКаталоге = СтрЗаменить(Файл.ПолноеИмя, КаталогПроекта, "");
ПолноеИмя = ЮТФайлы.ОбъединитьПути(Контекст.РабочийКаталог, ИмяВКаталоге);
ЮТФайлы.СоздатьРодительскийКаталог(ПолноеИмя);
ПолучитьИзВременногоХранилища(Файл.Хранение).Записать(ПолноеИмя);
КонецЦикла;
Возврат Контекст;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ФайлыПроектаРабочийКаталог()
КлючБазы = ЮТОбщий.ХешMD5(СтрокаСоединенияИнформационнойБазы());
Возврат ЮТФайлы.ОбъединитьПути(КаталогВременныхФайлов(), КлючБазы, "КаталогПроекта");
КонецФункции
#КонецОбласти

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="4309409f-4ac1-4838-8843-dbf3bcaf0da8">
<name>ЮТРазрешениеЗависимостейСлужебныйВызовСервера</name>
<synonym>
<key>ru</key>
<value>Разрешение зависимостей служебный вызов сервера</value>
</synonym>
<server>true</server>
<serverCall>true</serverCall>
</mdclass:CommonModule>

View File

@ -0,0 +1,136 @@
//©///////////////////////////////////////////////////////////////////////////©//
//
// Copyright 2021-2024 BIA-Technologies Limited Liability Company
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//
#Область СлужебныйПрограммныйИнтерфейс
Процедура ФайлыПроекта(ПутьКФайлуПроекта, Обработчик) Экспорт
ПолныйПуть = ПутьКФайламПроекта(ПутьКФайлуПроекта);
ПараметрыИсполнения = ЮТАсинхроннаяОбработкаСлужебныйКлиент.ЦепочкаАсинхроннойОбработки();
ПараметрыИсполнения.Вставить("ФинальныйОбработчик", Обработчик);
ПараметрыИсполнения.Вставить("ПолныйПуть", ПолныйПуть);
ПараметрыИсполнения.Вставить("ПутьКФайлуПроекта", ПутьКФайлуПроекта);
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикПроверкиСуществования");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикПроверкиКаталога");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикРезультатовПоиска");
ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикПеремещения");
ПараметрыИсполнения.Цепочка.Добавить(Обработчик);
ЮТФайлы.Существует(ПолныйПуть, ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(ПараметрыИсполнения));
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
#Область ФайлыПроекта
Процедура ОбработчикПроверкиСуществования(Существует, Параметры) Экспорт
Если НЕ Существует Тогда
Сообщение = СтрШаблон("Файл/каталог проекта `%1` не существует", Параметры.ПутьКФайлуПроекта);
ПрерватьОбработку(Сообщение, Параметры);
Возврат;
КонецЕсли;
ЮТФайлы.ЭтоКаталог(Параметры.ПолныйПуть, ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(Параметры));
КонецПроцедуры
Процедура ОбработчикПроверкиКаталога(ЭтоКаталог, Параметры) Экспорт
Обработчик = ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(Параметры);
Если ЭтоКаталог Тогда
НачатьПоискФайлов(Обработчик, Параметры.ПолныйПуть, "*.*", Истина);
Иначе
НачатьПоискФайлов(Обработчик, Параметры.ПолныйПуть);
КонецЕсли;
КонецПроцедуры
Процедура ОбработчикРезультатовПоиска(НайденныеФайлы, Параметры) Экспорт
Если НЕ ЗначениеЗаполнено(НайденныеФайлы) Тогда
Сообщение = СтрШаблон("Не удалось найти файлы каталога проекта по пути `%1`", Параметры.ПутьКФайлуПроекта);
ПрерватьОбработку(Сообщение, Параметры);
Возврат;
КонецЕсли;
ФайлыДляПеремещения = Новый Массив();
Для Каждого Файл Из НайденныеФайлы Цикл
ФайлыДляПеремещения.Добавить(Новый ОписаниеПередаваемогоФайла(Файл.ПолноеИмя));
КонецЦикла;
Обработчик = ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(Параметры);
НачатьПомещениеФайлов(Обработчик, ФайлыДляПеремещения, , Ложь);
КонецПроцедуры
Процедура ОбработчикПеремещения(ПомещенныеФайлы, Параметры) Экспорт
Если НЕ ЗначениеЗаполнено(ПомещенныеФайлы) Тогда
Сообщение = СтрШаблон("Не удалось передать на сервер файлы проекта из каталога `%1`", Параметры.ПутьКФайлуПроекта);
ПрерватьОбработку(Сообщение, Параметры);
Возврат;
КонецЕсли;
РезультатПередачиФайлов = ЮТРазрешениеЗависимостейСлужебныйВызовСервера.ПоместитьФайлыВРабочийКаталог(ПомещенныеФайлы);
Результат = ЮТФабрикаСлужебный.РезультатРазрешенияЗависимости();
Результат.Успешно = РезультатПередачиФайлов <> Неопределено;
Если Результат.Успешно Тогда
Результат.СохраняемыйКонтекстКлиент = Новый Структура("РабочийКаталог, ПолноеИмя", ЮТНастройкиВыполнения.КаталогПроекта(), Параметры.ПолныйПуть);
Результат.СохраняемыйКонтекстСервер = РезультатПередачиФайлов;
Результат.СохраняемыйКонтекстСервер.Вставить("ПолноеИмя", ЮТФайлы.ОбъединитьПути(Результат.СохраняемыйКонтекстСервер.РабочийКаталог, Параметры.ПутьКФайлуПроекта));
КонецЕсли;
ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьСледующийОбработчик(Параметры, Результат);
КонецПроцедуры
Процедура ПрерватьОбработку(Ошибка, Параметры)
Обработчик = Параметры.ФинальныйОбработчик;
Результат = ЮТФабрикаСлужебный.РезультатРазрешенияЗависимости();
Результат.Ошибка = Ошибка;
ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьОбработчик(Обработчик, Результат);
КонецПроцедуры
Функция ПутьКФайламПроекта(ИмяФайла) Экспорт
Возврат ЮТФайлы.ОбъединитьПути(ЮТНастройкиВыполнения.КаталогПроекта(), ИмяФайла);
КонецФункции
#КонецОбласти
Процедура ДобавитьОбработчикЦепочки(ПараметрыИсполнения, ИмяМетода)
Обработчик = Новый ОписаниеОповещения(ИмяМетода, ЭтотОбъект, ПараметрыИсполнения);
ПараметрыИсполнения.Цепочка.Добавить(Обработчик);
КонецПроцедуры
#КонецОбласти

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="1ecac783-e788-42f4-a1ef-c716246b09c7">
<name>ЮТРазрешениеЗависимостейСлужебныйКлиент</name>
<synonym>
<key>ru</key>
<value>Разрешение зависимостей служебный клиент</value>
</synonym>
<clientManagedApplication>true</clientManagedApplication>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -487,7 +487,7 @@
Сообщение = СтрСоединить(Детали, Символы.ПС);
КонецЕсли;
ДанныеОшибки = ЮТФабрикаСлужебный.ОписаниеВозникшейОшибки(ТипОшибки + ": " + Сообщение);
ДанныеОшибки = ЮТФабрикаСлужебный.ОписаниеОшибкиПропуска(ТипОшибки + ": " + Сообщение);
Если Ошибка <> Неопределено Тогда
ДанныеОшибки.Стек = СтекОшибки(Ошибка);

View File

@ -25,6 +25,13 @@
КонецПроцедуры
Процедура ИнициализацияКонтекста(ДанныеКонтекста) Экспорт
Параметры = ЮТКоллекции.ЗначениеВМассиве(ДанныеКонтекста);
ВызватьОбработчикРасширения("ИнициализацияКонтекста", Параметры);
КонецПроцедуры
#Область СобытияИсполненияТестов
// Обработчик события "ПередВсемиТестамиМодуля"

View File

@ -350,4 +350,15 @@
КонецФункции
// Возволяет выполнить настройку зависимостей теста, тестового набора или модуля.
// Возвращает модуль установки зависимостей теста.
//
// Возвращаемое значение:
// CommonModule
Функция ЗависитОт() Экспорт
Возврат ЮТЗависимости;
КонецФункции
#КонецОбласти

View File

@ -86,6 +86,18 @@
КонецПроцедуры
Процедура ДобавитьЗависимость(ОписаниеЗависимости) Экспорт
Контекст = Контекст();
Если Контекст.ТекущийЭлемент = Неопределено Тогда
ВызватьИсключение "Не инициализированы настройки регистрации тестов";
КонецЕсли;
Контекст.ТекущийЭлемент.Зависимости.Добавить(ОписаниеЗависимости);
КонецПроцедуры
Процедура СПараметрами(Параметры, Знач НовыеКонтексты) Экспорт
Контекст = Контекст();
@ -148,10 +160,23 @@
// Описание сценариев модуля
//
// Возвращаемое значение:
// Структура - см. ИсполняемыеСценарии
// см. ИсполняемыеСценарии
Функция СценарииМодуля() Экспорт
Возврат Контекст().ИсполняемыеСценарии;
СценарииМодуля = Контекст().ИсполняемыеСценарии;
Результат = Новый Структура("ТестовыеНаборы, НастройкиВыполнения, Зависимости");
Результат.ТестовыеНаборы = СценарииМодуля.ТестовыеНаборы;
// TODO Нужен рефакторинг
Результат.НастройкиВыполнения = ЮТКоллекции.СкопироватьРекурсивно(СценарииМодуля.НастройкиВыполнения);
Результат.Зависимости = ЮТКоллекции.СкопироватьРекурсивно(СценарииМодуля.Зависимости);
СценарииМодуля.НастройкиВыполнения.Очистить(); // Костыль. Очистка первого набора, тк перенесено в модуль
СценарииМодуля.Зависимости.Очистить(); // Костыль. Очистка первого набора, тк перенесено в модуль
//@skip-check constructor-function-return-section
Возврат Результат;
КонецФункции
@ -191,15 +216,19 @@
// Возвращаемое значение:
// Структура - Исполняемые сценарии:
// * ТестовыеНаборы - Массив из см. ЮТФабрикаСлужебный.ОписаниеТестовогоНабора - Тестовые наборы модуля
// * НастройкиВыполнения- Структура - Настройки исполнения теста
// * НастройкиВыполнения - Структура - Настройки исполнения тестов модуля
// * Зависимости - Массив Из см. ЮТФабрика.НовоеОписаниеЗависимости - Зависимости тестового модуля
Функция ИсполняемыеСценарии(МетаданныеМодуля)
Структура = Новый Структура;
Структура.Вставить("ТестовыеНаборы", Новый Массив());
Структура.Вставить("НастройкиВыполнения", Новый Структура());
Структура.Вставить("ТестовыеНаборы", Новый Массив);
Структура.Вставить("НастройкиВыполнения", Новый Структура);
Структура.Вставить("Зависимости", Новый Массив);
Набор = ЮТФабрикаСлужебный.ОписаниеТестовогоНабора(МетаданныеМодуля.Имя);
Набор.НастройкиВыполнения = Структура.НастройкиВыполнения; // Общие настройки с набором по умолчанию
Набор.Зависимости = Структура.Зависимости; // Общие зависимости с набором по умолчанию
Структура.ТестовыеНаборы.Добавить(Набор);
Возврат Структура;

View File

@ -218,6 +218,19 @@
КонецФункции
Функция НовоеОписаниеЗависимости() Экспорт
Описание = Новый Структура;
Описание.Вставить("Идентификатор", "");
Описание.Вставить("МетодРеализации", "");
Описание.Вставить("Параметры", Новый Массив);
Описание.Вставить("Ключ", Неопределено);
Описание.Вставить("Асинхронный", Ложь);
Возврат Описание;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции

View File

@ -88,13 +88,13 @@
// * НаборыТестов - Массив из см. ЮТФабрикаСлужебный.ОписаниеТестовогоНабора
// * Ошибки - Массив из см. ЮТФабрикаСлужебный.ОписаниеВозникшейОшибки
// * НастройкиВыполнения- Структура - Настройки исполнения теста
// * Зависимости- Массив Из см. ЮТФабрика.НовоеОписаниеЗависимости - Зависимости тестового модуля
Функция ОписаниеТестовогоМодуля(МетаданныеМодуля, НаборыТестов) Экспорт
Описание = Новый Структура;
Описание = БазовоеОписаниеРегистрируемогоОбъекта();
Описание.Вставить("МетаданныеМодуля", МетаданныеМодуля);
Описание.Вставить("НаборыТестов", НаборыТестов);
Описание.Вставить("Ошибки", Новый Массив);
Описание.Вставить("НастройкиВыполнения", Новый Структура());
Возврат Описание;
@ -115,15 +115,15 @@
// * Тесты - Массив из см. ОписаниеТеста - Коллекция тестов набора, см. ОписаниеТеста
// * Ошибки - Массив из см. ЮТФабрикаСлужебный.ОписаниеВозникшейОшибки - Описания ошибок регистрации тестов
// * НастройкиВыполнения- Структура - Настройки исполнения теста
// * Зависимости- Массив Из см. ЮТФабрика.НовоеОписаниеЗависимости - Зависимости тестового набора
Функция ОписаниеТестовогоНабора(Имя, ТегиСтрокой = "") Экспорт
Описание = Новый Структура;
Описание = БазовоеОписаниеРегистрируемогоОбъекта();
Описание.Вставить("Имя", Строка(Имя));
Описание.Вставить("Представление", Строка(Имя));
Описание.Вставить("Теги", СтрРазделить(ТегиСтрокой, ", ", Ложь));
Описание.Вставить("Тесты", Новый Массив);
Описание.Вставить("Ошибки", Новый Массив);
Описание.Вставить("НастройкиВыполнения", Новый Структура());
Возврат Описание;
@ -147,18 +147,19 @@
// * НастройкиВыполнения- Структура - Настройки исполнения теста
// * Параметры - Неопределено, Массив из Произвольный - Параметры теста
// * НомерВНаборе - Число - Порядковый номер теста в наборе
// * Зависимости- Массив Из см. ЮТФабрика.НовоеОписаниеЗависимости - Зависимости теста
// * Ошибки - Массив из см. ЮТФабрикаСлужебный.ОписаниеВозникшейОшибки - Описания ошибок регистрации тестов
Функция ОписаниеТеста(Имя, Представление, КонтекстыВызова, Знач ТегиСтрокой = "") Экспорт
Если ТегиСтрокой = Неопределено Тогда
ТегиСтрокой = "";
КонецЕсли;
Описание = Новый Структура();
Описание = БазовоеОписаниеРегистрируемогоОбъекта();
Описание.Вставить("Имя", Строка(Имя));
Описание.Вставить("Представление", Строка(Представление));
Описание.Вставить("Теги", СтрРазделить(ТегиСтрокой, ", ", Ложь));
Описание.Вставить("КонтекстВызова", КонтекстыВызова);
Описание.Вставить("НастройкиВыполнения", Новый Структура());
Описание.Вставить("Параметры", Неопределено);
Описание.Вставить("НомерВНаборе", 0);
@ -177,14 +178,13 @@
// * НаборыТестов - Массив из см. ЮТФабрикаСлужебный.ОписаниеИсполняемогоНабораТестов
// * Ошибки - Массив из см. ЮТФабрикаСлужебный.ОписаниеВозникшейОшибки
// * НастройкиВыполнения- Структура - Настройки исполнения теста
// * Зависимости- Массив Из см. ЮТФабрика.НовоеОписаниеЗависимости - Зависимости тестового модуля
Функция ОписаниеИсполняемогоТестовогоМодуля(ТестовыйМодуль) Экспорт
Описание = Новый Структура;
Описание = БазовоеОписаниеИсполняемогоОбъекта(ТестовыйМодуль);
Описание.Вставить("МетаданныеМодуля", ТестовыйМодуль.МетаданныеМодуля);
Описание.Вставить("НаборыТестов", Новый Массив);
Описание.Вставить("Ошибки", ЮТКоллекции.СкопироватьМассив(ТестовыйМодуль.Ошибки));
Описание.Вставить("НастройкиВыполнения", ЮТКоллекции.СкопироватьСтруктуру(ТестовыйМодуль.НастройкиВыполнения));
Возврат Описание;
@ -211,14 +211,14 @@
// * Длительность - Число - Продолжительность выполнения набора
// * НастройкиВыполнения - Структура - Настройки исполнения теста
// * ТестовыйМодуль - См. ОписаниеТестовогоМодуля
// * Зависимости- Массив Из см. ЮТФабрика.НовоеОписаниеЗависимости - Зависимости тестового набора
Функция ОписаниеИсполняемогоНабораТестов(НаборТестов, ТестовыйМодуль) Экспорт
Описание = Новый Структура();
Описание = БазовоеОписаниеИсполняемогоОбъекта(НаборТестов);
Описание.Вставить("Имя", НаборТестов.Имя);
Описание.Вставить("Представление", НаборТестов.Представление);
Описание.Вставить("Теги", НаборТестов.Теги);
Описание.Вставить("Ошибки", ЮТКоллекции.СкопироватьМассив(НаборТестов.Ошибки));
Описание.Вставить("Режим", "");
Описание.Вставить("ТестовыйМодуль", ТестовыйМодуль);
Описание.Вставить("МетаданныеМодуля", ТестовыйМодуль.МетаданныеМодуля);
@ -226,7 +226,6 @@
Описание.Вставить("Выполнять", Описание.Ошибки.Количество() = 0);
Описание.Вставить("ДатаСтарта", 0);
Описание.Вставить("Длительность", 0);
Описание.Вставить("НастройкиВыполнения", НаборТестов.НастройкиВыполнения);
Возврат Описание;
@ -255,27 +254,26 @@
// * НастройкиВыполнения- Структура - Настройки исполнения теста
// * Параметры - Неопределено, Массив из Произвольный - Набор параметров теста
// * НомерВНаборе - Число - Порядковый номер теста в наборе
// * Зависимости- Массив Из см. ЮТФабрика.НовоеОписаниеЗависимости - Зависимости теста
Функция ОписаниеИсполняемогоТеста(Тест, Режим, ТестовыйМодуль) Экспорт
ПолноеИмяМетода = СтрШаблон("%1.%2", ТестовыйМодуль.МетаданныеМодуля.Имя, Тест.Имя);
Представление = ПредставлениеТеста(Тест);
ОписаниеТеста = Новый Структура;
ОписаниеТеста.Вставить("Имя", Представление);
ОписаниеТеста.Вставить("Метод", Тест.Имя);
ОписаниеТеста.Вставить("ПолноеИмяМетода", ПолноеИмяМетода);
ОписаниеТеста.Вставить("Теги", Тест.Теги);
ОписаниеТеста.Вставить("Режим", Режим);
ОписаниеТеста.Вставить("ДатаСтарта", 0);
ОписаниеТеста.Вставить("Длительность", 0);
ОписаниеТеста.Вставить("Статус", ЮТФабрика.СтатусыИсполненияТеста().Ожидание);
ОписаниеТеста.Вставить("Ошибки", Новый Массив);
ОписаниеТеста.Вставить("НастройкиВыполнения", Тест.НастройкиВыполнения);
ОписаниеТеста.Вставить("Параметры", Тест.Параметры);
ОписаниеТеста.Вставить("НомерВНаборе", Тест.НомерВНаборе);
Описание = БазовоеОписаниеИсполняемогоОбъекта(Тест);
Описание.Вставить("Имя", Представление);
Описание.Вставить("Метод", Тест.Имя);
Описание.Вставить("ПолноеИмяМетода", ПолноеИмяМетода);
Описание.Вставить("Теги", Тест.Теги);
Описание.Вставить("Режим", Режим);
Описание.Вставить("ДатаСтарта", 0);
Описание.Вставить("Длительность", 0);
Описание.Вставить("Статус", ЮТФабрика.СтатусыИсполненияТеста().Ожидание);
Описание.Вставить("Параметры", Тест.Параметры);
Описание.Вставить("НомерВНаборе", Тест.НомерВНаборе);
//@skip-check constructor-function-return-section
Возврат ОписаниеТеста;
Возврат Описание;
КонецФункции
@ -465,6 +463,23 @@
КонецФункции
#Область Зависимости
Функция РезультатРазрешенияЗависимости() Экспорт
Результат = Новый Структура();
Результат.Вставить("Успешно", Ложь);
Результат.Вставить("Ошибка", Неопределено);
Результат.Вставить("СохраняемыйКонтекст", Неопределено);
Результат.Вставить("СохраняемыйКонтекстКлиент", Неопределено);
Результат.Вставить("СохраняемыйКонтекстСервер", Неопределено);
Возврат Результат;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область КонструкторыКонтекстов
@ -505,7 +520,7 @@
Описание = Новый Структура();
Описание.Вставить("Сообщения", Новый Массив);
Описание.Вставить("Успешно", Истина);
Описание.Вставить("Успешно", Успешно);
Возврат Описание;
@ -677,8 +692,31 @@
Возврат Описание;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция БазовоеОписаниеРегистрируемогоОбъекта()
Описание = Новый Структура();
Описание.Вставить("НастройкиВыполнения", Новый Структура());
Описание.Вставить("Зависимости", Новый Массив());
Описание.Вставить("Ошибки", Новый Массив);
Возврат Описание;
КонецФункции
Функция БазовоеОписаниеИсполняемогоОбъекта(РегистрируемыйОбъекта)
Описание = Новый Структура();
Описание.Вставить("Ошибки", ЮТКоллекции.СкопироватьМассив(РегистрируемыйОбъекта.Ошибки));
Описание.Вставить("НастройкиВыполнения", ЮТКоллекции.СкопироватьСтруктуру(РегистрируемыйОбъекта.НастройкиВыполнения));
Описание.Вставить("Зависимости", ЮТКоллекции.СкопироватьМассив(РегистрируемыйОбъекта.Зависимости));
Возврат Описание;
КонецФункции
#КонецОбласти

View File

@ -148,6 +148,32 @@
КонецПроцедуры
Процедура СоздатьКаталогРекурсивно(Путь) Экспорт
Файл = Новый Файл(Путь);
Если Файл.Существует() Тогда
Возврат;
КонецЕсли;
СоздатьКаталогРекурсивно(Файл.Путь);
СоздатьКаталог(Файл.ПолноеИмя);
КонецПроцедуры
Процедура СоздатьРодительскийКаталог(Путь) Экспорт
Файл = Новый Файл(Путь);
Если Файл.Существует() Тогда
Возврат;
КонецЕсли;
СоздатьКаталогРекурсивно(Файл.Путь);
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции

View File

@ -18,6 +18,7 @@
#Область СлужебныйПрограммныйИнтерфейс
#Если Клиент Тогда
// ЗагрузитьТесты
// Читает наборы тестов (тестовые модули) из расширений
// Параметры:
@ -43,9 +44,12 @@
КонецЦикла;
ЮТЗависимостиСлужебныйКлиент.ДедупликацияЗависимостей(Результат);
Возврат Результат;
КонецФункции
#КонецЕсли
// ПрочитатьНаборТестов
// Читает набор тестов из модуля
@ -91,10 +95,9 @@
ЮТТестыСлужебный.ПослеЧтенияСценариевМодуля();
Сценарии = ЮТТестыСлужебный.СценарииМодуля();
УдалитьНастройкиМодуляИзПервогоНабора(Сценарии); // TODO Нужен рефакторинг
ОписаниеТестовогоМодуля.НаборыТестов = ЮТФильтрацияСлужебный.ОтфильтроватьТестовыеНаборы(Сценарии.ТестовыеНаборы, МетаданныеМодуля);
ОписаниеТестовогоМодуля.НастройкиВыполнения = Сценарии.НастройкиВыполнения;
ОписаниеТестовогоМодуля.Зависимости = Сценарии.Зависимости;
Иначе
@ -222,14 +225,4 @@
КонецФункции
Процедура УдалитьНастройкиМодуляИзПервогоНабора(СценарииМодуля)
НастройкиВыполнения = ЮТКоллекции.СкопироватьРекурсивно(СценарииМодуля.НастройкиВыполнения);
СценарииМодуля.НастройкиВыполнения.Очистить();
СценарииМодуля.НастройкиВыполнения = НастройкиВыполнения;
КонецПроцедуры
#КонецОбласти

View File

@ -203,4 +203,21 @@
КонецПроцедуры
// Возвращает данные зависимость.
// Результат зависит от реализации зависимости.
// Для указания зависимости используйте методы модуля `ЮТЗависимости`, необходимо указывать туже зависимость, что указана при регистрации.
//
// Параметры:
// ОписаниеЗависимости - см. ЮТФабрика.НовоеОписаниеЗависимости
//
// Возвращаемое значение:
// Произвольный
// Пример:
// ПолноеИмяФайла = ЮТест.Зависимость(ЮТЗависимости.ФайлыПроекта(".gitignore")).ПолноеИмя;
Функция Зависимость(ОписаниеЗависимости) Экспорт
Возврат ЮТЗависимостиСлужебный.ДанныеЗависимости(ОписаниеЗависимости);
КонецФункции
#КонецОбласти

View File

@ -61,6 +61,9 @@
<commonModules>CommonModule.МокитоСлужебный</commonModules>
<commonModules>CommonModule.ЮТАсинхроннаяОбработкаСлужебныйКлиент</commonModules>
<commonModules>CommonModule.ЮТест</commonModules>
<commonModules>CommonModule.ЮТЗависимости</commonModules>
<commonModules>CommonModule.ЮТЗависимостиСлужебный</commonModules>
<commonModules>CommonModule.ЮТЗависимостиСлужебныйКлиент</commonModules>
<commonModules>CommonModule.ЮТЗапросы</commonModules>
<commonModules>CommonModule.ЮТЗапросыСлужебныйВызовСервера</commonModules>
<commonModules>CommonModule.ЮТЗапросыСлужебныйКлиентСервер</commonModules>
@ -108,6 +111,8 @@
<commonModules>CommonModule.ЮТПредикатыСлужебныйКлиентСервер</commonModules>
<commonModules>CommonModule.ЮТПреобразованияСлужебный</commonModules>
<commonModules>CommonModule.ЮТПроверкиСлужебный</commonModules>
<commonModules>CommonModule.ЮТРазрешениеЗависимостейСлужебныйВызовСервера</commonModules>
<commonModules>CommonModule.ЮТРазрешениеЗависимостейСлужебныйКлиент</commonModules>
<commonModules>CommonModule.ЮТРасширенияСлужебный</commonModules>
<commonModules>CommonModule.ЮТРегистрацияОшибок</commonModules>
<commonModules>CommonModule.ЮТРегистрацияОшибокСлужебный</commonModules>

View File

@ -11,6 +11,8 @@
<value>Сервисная функциональность работы движка</value>
</explanation>
<content>CommonModule.ЮТАсинхроннаяОбработкаСлужебныйКлиент</content>
<content>CommonModule.ЮТЗависимости</content>
<content>CommonModule.ЮТЗависимостиСлужебный</content>
<content>CommonModule.ЮТИсключения</content>
<content>CommonModule.ЮТКомпоненты</content>
<content>CommonModule.ЮТКомпонентыСлужебныйВызовСервера</content>
@ -26,6 +28,8 @@
<content>CommonModule.ЮТОбщийСлужебныйВызовСервера</content>
<content>CommonModule.ЮТОтчетСлужебный</content>
<content>CommonModule.ЮТПроверкиСлужебный</content>
<content>CommonModule.ЮТРазрешениеЗависимостейСлужебныйВызовСервера</content>
<content>CommonModule.ЮТРазрешениеЗависимостейСлужебныйКлиент</content>
<content>CommonModule.ЮТРасширенияСлужебный</content>
<content>CommonModule.ЮТРегистрацияОшибок</content>
<content>CommonModule.ЮТРегистрацияОшибокСлужебный</content>

View File

@ -11,6 +11,7 @@
<value>Подключаемые обработчики событий тестов</value>
</explanation>
<content>CommonModule.МокитоСлужебный</content>
<content>CommonModule.ЮТЗависимостиСлужебный</content>
<content>CommonModule.ЮТИсполнительСлужебныйКлиент</content>
<content>CommonModule.ЮТЛогированиеСлужебный</content>
<content>CommonModule.ЮТТестовыеДанныеСлужебный</content>

View File

@ -19,6 +19,7 @@
<content>CommonModule.МокитоПерехват</content>
<content>CommonModule.МокитоПроверки</content>
<content>CommonModule.ЮТест</content>
<content>CommonModule.ЮТЗависимости</content>
<content>CommonModule.ЮТЗапросы</content>
<content>CommonModule.ЮТИсключения</content>
<content>CommonModule.ЮТКоллекции</content>

View File

@ -0,0 +1,112 @@
//©///////////////////////////////////////////////////////////////////////////©//
//
// Copyright 2021-2024 BIA-Technologies Limited Liability Company
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//
#Область СлужебныйПрограммныйИнтерфейс
Процедура ИсполняемыеСценарии() Экспорт
ЮТТесты.ЗависитОт().ФайлыПроекта(".gitignore")
.ДобавитьТест("УникальнаяЗависимость")
.ДобавитьТест("ДанныеЗависимости").ЗависитОт().ФайлыПроекта(".gitignore")
.ДобавитьТест("ДанныеЗависимости_Каталог").ЗависитОт().ФайлыПроекта(".github")
.ДобавитьТест("ДанныеЗависимости_НеизвестныйФайл").ЗависитОт().ФайлыПроекта("НеизвестныйФайл")
;
КонецПроцедуры
Процедура УникальнаяЗависимость() Экспорт
Зависимости = Новый Соответствие();
Зависимость1 = ЮТЗависимостиСлужебный.УникальнаяЗависимость(Зависимости, НоваяЗависимость("Зависимость 1"));
Зависимость2 = ЮТЗависимостиСлужебный.УникальнаяЗависимость(Зависимости, НоваяЗависимость("ЗавИсимость 1"));
Зависимость3 = ЮТЗависимостиСлужебный.УникальнаяЗависимость(Зависимости, НоваяЗависимость("ЗависИМОСТЬ 1", "Модуль.Метод"));
Зависимость4 = ЮТЗависимостиСлужебный.УникальнаяЗависимость(Зависимости, НоваяЗависимость("Зависимость 1", , "Строка 1"));
Зависимость5 = ЮТЗависимостиСлужебный.УникальнаяЗависимость(Зависимости, НоваяЗависимость("Зависимость 1", , "Строка 1"));
ЮТест.ОжидаетЧто(Зависимости)
.ИмеетДлину(2);
ЮТест.ОжидаетЧто(Зависимость1)
.ИмеетТип("ФиксированнаяСтруктура")
.Равно(Зависимость2)
.Равно(Зависимость3)
.НеРавно(Зависимость4);
ЮТест.ОжидаетЧто(Зависимость4, "Зависимость с параметром")
.ИмеетТип("ФиксированнаяСтруктура")
.Равно(Зависимость5)
КонецПроцедуры
Процедура ДанныеЗависимости() Экспорт
ПолноеИмяФайла = ЮТест.Зависимость(ЮТЗависимости.ФайлыПроекта(".gitignore")).ПолноеИмя;
ЮТест.ОжидаетЧто(ЮТФайлы.Существует(ПолноеИмяФайла), "Файл каталога проекта не существует")
.ЭтоИстина();
Данные = ЮТОбщий.ДанныеТекстовогоФайла(ПолноеИмяФайла);
ЮТест.ОжидаетЧто(Данные, "Содержимое файла")
.Содержит("ConfigDumpInfo.xml");
КонецПроцедуры
Процедура ДанныеЗависимости_НеизвестныйФайл() Экспорт
ВызватьИсключение "Тест не должен быть вызван";
КонецПроцедуры
Процедура ДанныеЗависимости_Каталог() Экспорт
ПолноеИмя = ЮТест.Зависимость(ЮТЗависимости.ФайлыПроекта(".github")).ПолноеИмя;
ЮТест.ОжидаетЧто(ЮТФайлы.Существует(ПолноеИмя), "Каталог проекта не доступен")
.ЭтоИстина();
ЮТест.ОжидаетЧто(ЮТФайлы.ЭтоКаталог(ПолноеИмя), "Это не каталог")
.ЭтоИстина();
ЮТест.ОжидаетЧто(ЮТФайлы.Существует(ЮТФайлы.ОбъединитьПути(ПолноеИмя, "workflows", "main-build.yml")), "Файл проекта не доступен")
.ЭтоИстина();
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция НоваяЗависимость(Идентификатор, Метод = Неопределено, Параметр1 = Неопределено, Параметр2 = Неопределено)
Описание = ЮТФабрика.НовоеОписаниеЗависимости();
Описание.Идентификатор = Идентификатор;
Описание.МетодРеализации = ?(Метод = Неопределено, Идентификатор, Метод);
Если Параметр1 <> Неопределено Тогда
Описание.Параметры.Добавить(Параметр1);
КонецЕсли;
Если Параметр2 <> Неопределено Тогда
Описание.Параметры.Добавить(Параметр2);
КонецЕсли;
Возврат Описание;
КонецФункции
#КонецОбласти

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="05b8dd54-4615-4c44-a350-178b8ba9eb79">
<name>ОМ_ЮТЗависимостиСлужебный</name>
<clientManagedApplication>true</clientManagedApplication>
<server>true</server>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>

View File

@ -35,6 +35,7 @@
<commonModules>CommonModule.ОМ_ОшибкаЗагрузкиСценариев</commonModules>
<commonModules>CommonModule.ОМ_ЮТест</commonModules>
<commonModules>CommonModule.ОМ_ЮТестПереопределяемый</commonModules>
<commonModules>CommonModule.ОМ_ЮТЗависимостиСлужебный</commonModules>
<commonModules>CommonModule.ОМ_ЮТЗапросы</commonModules>
<commonModules>CommonModule.ОМ_ЮТИсполнительСлужебныйКлиент</commonModules>
<commonModules>CommonModule.ОМ_ЮТИсполнительСлужебныйКлиентСервер</commonModules>