diff --git a/exts/yaxunit/src/CommonModules/ЮТИсполнитель/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТИсполнитель/Module.bsl
index bd89cdb8..39fc9d37 100644
--- a/exts/yaxunit/src/CommonModules/ЮТИсполнитель/Module.bsl
+++ b/exts/yaxunit/src/CommonModules/ЮТИсполнитель/Module.bsl
@@ -46,18 +46,30 @@
ЮТКонтекст.УстановитьГлобальныеНастройкиВыполнения(ЮТКонтекст.ГлобальныеНастройкиВыполнения());
ЮТКонтекст.УстановитьКонтекстИсполнения(ДанныеКонтекстаИсполнения());
+ ЮТСобытия.ПередЧтениеСценариев();
ТестовыеМодули = ЮТЧитатель.ЗагрузитьТесты(Параметры);
+ ЮТСобытия.ПослеЧтенияСценариев(ТестовыеМодули);
РезультатыТестирования = Новый Массив();
+ КоллекцияКатегорийНаборов = Новый Массив();
Для Каждого ТестовыйМодуль Из ТестовыеМодули Цикл
КатегорииНаборов = КатегорииНаборовТестовМодуля(ТестовыйМодуль);
+ КоллекцияКатегорийНаборов.Добавить(КатегорииНаборов);
- Результат = ВыполнитьГруппуНаборовТестов(КатегорииНаборов.Клиентские, ТестовыйМодуль);
+ КонецЦикла;
+
+ ЮТСобытия.ПослеФормированияИсполняемыхНаборовТестов(КоллекцияКатегорийНаборов);
+
+ Для Каждого КатегорииНаборов Из КоллекцияКатегорийНаборов Цикл
+
+ Результат = ВыполнитьГруппуНаборовТестов(КатегорииНаборов.Клиентские, КатегорииНаборов.ТестовыйМодуль);
ЮТОбщий.ДополнитьМассив(РезультатыТестирования, Результат);
- Результат = ЮТИсполнительСервер.ВыполнитьГруппуНаборовТестов(КатегорииНаборов.Серверные, ТестовыйМодуль);
+ Результат = ЮТИсполнительСервер.ВыполнитьГруппуНаборовТестов(КатегорииНаборов.Серверные, КатегорииНаборов.ТестовыйМодуль);
+ ЮТЛогирование.ВывестиСерверныеСообщения();
+
ЮТОбщий.ДополнитьМассив(РезультатыТестирования, Результат);
ЮТОбщий.ДополнитьМассив(РезультатыТестирования, КатегорииНаборов.Пропущенные);
@@ -186,6 +198,8 @@
Функция КатегорииНаборовТестовМодуля(ТестовыйМодуль)
+ КатегорииНаборов = ОписаниеКатегорияНабораТестов(ТестовыйМодуль);
+
ИсполняемыеТестовыеНаборы = Новый Массив;
Для Каждого ТестовыйНабор Из ТестовыйМодуль.НаборыТестов Цикл
@@ -228,11 +242,6 @@
КонецЦикла;
- КатегорииНаборов = Новый Структура();
- КатегорииНаборов.Вставить("Клиентские", Новый Массив());
- КатегорииНаборов.Вставить("Серверные", Новый Массив());
- КатегорииНаборов.Вставить("Пропущенные", Новый Массив());
-
КонтекстыПриложения = ЮТФабрика.КонтекстыПриложения();
КонтекстыМодуля = ЮТФабрика.КонтекстыМодуля(ТестовыйМодуль.МетаданныеМодуля);
КонтекстыИсполнения = ЮТФабрика.КонтекстыИсполнения();
@@ -328,6 +337,29 @@
КонецФункции
+// Описание категория набора тестов.
+//
+// Параметры:
+// ТестовыйМодуль - см. ЮТФабрика.ОписаниеТестовогоМодуля
+//
+// Возвращаемое значение:
+// Структура - Описание категория набора тестов:
+// * ТестовыйМодуль - см. ЮТФабрика.ОписаниеТестовогоМодуля
+// * Клиентские - Массив из ЮТФабрика.ОписаниеИсполняемогоНабораТестов
+// * Серверные - Массив из ЮТФабрика.ОписаниеИсполняемогоНабораТестов
+// * Пропущенные - Массив из ЮТФабрика.ОписаниеИсполняемогоНабораТестов
+Функция ОписаниеКатегорияНабораТестов(ТестовыйМодуль)
+
+ КатегорииНаборов = Новый Структура();
+ КатегорииНаборов.Вставить("ТестовыйМодуль", ТестовыйМодуль);
+ КатегорииНаборов.Вставить("Клиентские", Новый Массив());
+ КатегорииНаборов.Вставить("Серверные", Новый Массив());
+ КатегорииНаборов.Вставить("Пропущенные", Новый Массив());
+
+ Возврат КатегорииНаборов;
+
+КонецФункции
+
#Если Клиент Тогда
Процедура ПоказатьОтчет(РезультатыТестирования, Параметры)
diff --git a/exts/yaxunit/src/CommonModules/ЮТКонтекст/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТКонтекст/Module.bsl
index 1958b439..54351803 100644
--- a/exts/yaxunit/src/CommonModules/ЮТКонтекст/Module.bsl
+++ b/exts/yaxunit/src/CommonModules/ЮТКонтекст/Module.bsl
@@ -55,11 +55,21 @@
//
// Возвращаемое значение:
// Структура, Неопределено - Значение реквизита/вложенного контекста
-Функция ЗначениеКонтекста(ИмяРеквизита) Экспорт
+Функция ЗначениеКонтекста(ИмяРеквизита, ПолучитьССервера = Ложь) Экспорт
- ДанныеКонтекста = ДанныеКонтекста();
+#Если Клиент Тогда
+ Если ПолучитьССервера Тогда
+ Возврат ЮТКонтекстСервер.ЗначениеКонтекста(ИмяРеквизита);
+ КонецЕсли;
+#КонецЕсли
- Возврат ЮТОбщий.ЗначениеСтруктуры(ДанныеКонтекста, ИмяРеквизита);
+ Объект = ДанныеКонтекста();
+ Ключи = СтрРазделить(ИмяРеквизита, ".");
+ Для Инд = 0 По Ключи.Количество() - 2 Цикл
+ Объект = Объект[Ключи[Инд]];
+ КонецЦикла;
+
+ Возврат ЮТОбщий.ЗначениеСтруктуры(Объект, Ключи[Ключи.ВГраница()]);
КонецФункции
@@ -74,7 +84,13 @@
ДанныеКонтекста = ДанныеКонтекста();
- ДанныеКонтекста.Вставить(ИмяРеквизита, Значение);
+ Объект = ДанныеКонтекста;
+ Ключи = СтрРазделить(ИмяРеквизита, ".");
+ Для Инд = 0 По Ключи.Количество() - 2 Цикл
+ Объект = Объект[Ключи[Инд]];
+ КонецЦикла;
+
+ Объект.Вставить(Ключи[Ключи.ВГраница()], Значение);
#Если НЕ Сервер Тогда
Если УстановитьНаСервер Тогда
diff --git a/exts/yaxunit/src/CommonModules/ЮТКонтекстСервер/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТКонтекстСервер/Module.bsl
index 7969bcfb..26ad75ba 100644
--- a/exts/yaxunit/src/CommonModules/ЮТКонтекстСервер/Module.bsl
+++ b/exts/yaxunit/src/CommonModules/ЮТКонтекстСервер/Module.bsl
@@ -63,6 +63,12 @@
КонецПроцедуры
+Функция ЗначениеКонтекста(Знач ИмяРеквизита) Экспорт
+
+ Возврат ЮТКонтекст.ЗначениеКонтекста(ИмяРеквизита);
+
+КонецФункции
+
Функция КлючНастроекКонтекста() Экспорт
Возврат СтрШаблон("ЮТ%1.Контекста", НомерСеансаИнформационнойБазы());
diff --git a/exts/yaxunit/src/CommonModules/ЮТЛогирование/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТЛогирование/Module.bsl
new file mode 100644
index 00000000..34438c0a
--- /dev/null
+++ b/exts/yaxunit/src/CommonModules/ЮТЛогирование/Module.bsl
@@ -0,0 +1,373 @@
+//©///////////////////////////////////////////////////////////////////////////©//
+//
+// Copyright 2021-2022 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.
+//
+//©///////////////////////////////////////////////////////////////////////////©//
+
+#Область ПрограммныйИнтерфейс
+
+// Вывод отладочного сообщения в лог
+//
+// Параметры:
+// Сообщение - Строка - Сообщение
+Процедура Отладка(Сообщение) Экспорт
+
+ Записать("DBG", Сообщение, 0);
+
+КонецПроцедуры
+
+// Вывод информационного сообщения в лог
+//
+// Параметры:
+// Сообщение - Строка - Сообщение
+Процедура Информация(Сообщение) Экспорт
+
+ Записать("INF", Сообщение, 1);
+
+КонецПроцедуры
+
+// Вывод ошибки в лог
+//
+// Параметры:
+// Сообщение - Строка - Сообщение
+Процедура Ошибка(Сообщение) Экспорт
+
+ Записать("ERR", Сообщение, 2);
+
+КонецПроцедуры
+
+Процедура ВывестиСерверныеСообщения() Экспорт
+
+#Если Клиент Тогда
+ Контекст = Контекст();
+ Если Контекст = Неопределено ИЛИ НЕ Контекст.Включено ИЛИ Контекст.ДоступенНаСервере Тогда
+ Возврат;
+ КонецЕсли;
+
+ Сообщения = ЮТЛогированиеВызовСервера.НакопленныеСообщенияЛогирования(Истина);
+ ЗаписатьСообщения(Контекст.ФайлЛога, Сообщения);
+#Иначе
+ ВызватьИсключение "Метод вывода сервеных сообщений в лог должен вызываться с клиента"
+#КонецЕсли
+
+КонецПроцедуры
+
+Функция УровниЛога() Экспорт
+
+ Возврат Новый ФиксированнаяСтруктура("Отладка, Информация, Ошибка", "debug", "info", "error");
+
+КонецФункции
+
+#КонецОбласти
+
+#Область СлужебныеПроцедурыИФункции
+
+#Область ОбработчикиСобытий
+
+// Инициализация.
+//
+// Параметры:
+// ПараметрыЗапуска - см. ЮТФабрика.ПараметрыЗапуска
+Процедура Инициализация(ПараметрыЗапуска) Экспорт
+
+ ДанныеКонтекста = НовыйДанныеКонтекста();
+ ДанныеКонтекста.ФайлЛога = ПараметрыЗапуска.logging.file;
+
+ Если ПараметрыЗапуска.logging.enable = Неопределено Тогда
+ ДанныеКонтекста.Включено = ЗначениеЗаполнено(ДанныеКонтекста.ФайлЛога);
+ Иначе
+ ДанныеКонтекста.Включено = ПараметрыЗапуска.logging.enable;
+ КонецЕсли;
+
+ Если НЕ ДанныеКонтекста.Включено Тогда
+ ЮТКонтекст.УстановитьЗначениеКонтекста(ИмяКонтекстаЛогирования(), ДанныеКонтекста, Истина);
+ Возврат;
+ КонецЕсли;
+
+ УровениЛога = УровниЛога();
+
+ Если СтрСравнить(ПараметрыЗапуска.logging.level, УровениЛога.Ошибка) = 0 Тогда
+ ДанныеКонтекста.УровеньЛога = 2;
+ ИначеЕсли СтрСравнить(ПараметрыЗапуска.logging.level, УровениЛога.Информация) = 0 Тогда
+ ДанныеКонтекста.УровеньЛога = 1;
+ Иначе
+ ДанныеКонтекста.УровеньЛога = 0;
+ КонецЕсли;
+
+ ЗначениеПроверки = Строка(Новый УникальныйИдентификатор());
+ ЗаписатьСообщения(ДанныеКонтекста.ФайлЛога, ЮТОбщий.ЗначениеВМассиве(ЗначениеПроверки), Ложь);
+ ДанныеКонтекста.ДоступенНаСервере = ЮТЛогированиеВызовСервера.ФайлЛогаДоступенНаСервере(ДанныеКонтекста.ФайлЛога, ЗначениеПроверки);
+
+ ЮТКонтекст.УстановитьЗначениеКонтекста(ИмяКонтекстаЛогирования(), ДанныеКонтекста, Истина);
+
+ Разделитель = "------------------------------------------------------";
+ ЗаписатьСообщения(ДанныеКонтекста.ФайлЛога, ЮТОбщий.ЗначениеВМассиве(Разделитель), Ложь);
+ Информация("Старт");
+
+КонецПроцедуры
+
+// Обработка события "ПередЧтениеСценариев"
+Процедура ПередЧтениеСценариев() Экспорт
+
+ Информация("Загрузка сценариев");
+
+КонецПроцедуры
+
+// Перед чтением сценариев модуля.
+//
+// Параметры:
+// МетаданныеМодуля - см. ЮТФабрика.ОписаниеМодуля
+// ИсполняемыеСценарии - см. ЮТТесты.СценарииМодуля
+Процедура ПередЧтениемСценариевМодуля(МетаданныеМодуля, ИсполняемыеСценарии) Экспорт
+
+ Информация(СтрШаблон("Загрузка сценариев модуля `%1`", МетаданныеМодуля.Имя));
+
+КонецПроцедуры
+
+// Перед чтением сценариев модуля.
+//
+// Параметры:
+// МетаданныеМодуля - см. ЮТФабрика.ОписаниеМодуля
+// ИсполняемыеСценарии - см. ЮТТесты.СценарииМодуля
+Процедура ПослеЧтенияСценариевМодуля(МетаданныеМодуля, ИсполняемыеСценарии) Экспорт
+
+ Информация(СтрШаблон("Загрузка сценариев модуля завершена `%1`", МетаданныеМодуля.Имя));
+
+КонецПроцедуры
+
+// Обработка события "ПослеЧтенияСценариев"
+// Параметры:
+// Сценарии - Массив из см. ЮТФабрика.ОписаниеТестовогоМодуля - Набор описаний тестовых модулей, которые содержат информацию о запускаемых тестах
+Процедура ПослеЧтенияСценариев(Сценарии) Экспорт
+
+ Информация("Загрузка сценариев завершена.");
+
+КонецПроцедуры
+
+// Обработка события "ПослеФормированияИсполняемыхНаборовТестов"
+// Параметры:
+// КоллекцияКатегорийНаборов - Массив из см. ЮТИсполнитель.ОписаниеКатегорияНабораТестов - Набор исполняемых наборов
+Процедура ПослеФормированияИсполняемыхНаборовТестов(КоллекцияКатегорийНаборов) Экспорт
+
+ Количество = 0;
+
+ Для Каждого Наборы Из КоллекцияКатегорийНаборов Цикл
+
+ Для Каждого Набор Из Наборы.Клиентские Цикл
+ ЮТОбщий.Инкремент(Количество, Набор.Тесты.Количество());
+ КонецЦикла;
+
+ Для Каждого Набор Из Наборы.Серверные Цикл
+ ЮТОбщий.Инкремент(Количество, Набор.Тесты.Количество());
+ КонецЦикла;
+
+ КонецЦикла;
+
+ ЮТКонтекст.УстановитьЗначениеКонтекста(ИмяКонтекстаЛогирования() + ".ОбщееКоличествоТестов", Количество, Истина);
+
+КонецПроцедуры
+
+// Перед всеми тестами.
+//
+// Параметры:
+// ОписаниеСобытия - см. ЮТФабрика.ОписаниеСобытияИсполненияТестов
+Процедура ПередВсемиТестами(ОписаниеСобытия) Экспорт
+
+#Если Клиент Тогда
+ ПрогрессКлиент = Контекст().КоличествоВыполненныхТестов;
+ ПрогрессСервер = ЮТКонтекст.ЗначениеКонтекста(ИмяКонтекстаЛогирования() + ".КоличествоВыполненныхТестов", Истина);
+
+ Если ПрогрессКлиент < ПрогрессСервер Тогда
+ Контекст().КоличествоВыполненныхТестов = ПрогрессСервер;
+ КонецЕсли;
+#КонецЕсли
+ Информация(СтрШаблон("Запуск тестов модуля `%1`", ОписаниеСобытия.Модуль.МетаданныеМодуля.ПолноеИмя));
+
+КонецПроцедуры
+
+// Перед тестовым набором.
+//
+// Параметры:
+// ОписаниеСобытия - см. ЮТФабрика.ОписаниеСобытияИсполненияТестов
+Процедура ПередТестовымНабором(ОписаниеСобытия) Экспорт
+
+ Информация(СтрШаблон("Запуск тестов набора `%1`", ОписаниеСобытия.Набор.Имя));
+
+КонецПроцедуры
+
+// Перед каждым тестом.
+//
+// Параметры:
+// ОписаниеСобытия - см. ЮТФабрика.ОписаниеСобытияИсполненияТестов
+Процедура ПередКаждымТестом(ОписаниеСобытия) Экспорт
+
+ Информация(СтрШаблон("Запуск теста `%1`", ОписаниеСобытия.Тест.Имя));
+
+КонецПроцедуры
+
+// Перед каждым тестом.
+//
+// Параметры:
+// ОписаниеСобытия - см. ЮТФабрика.ОписаниеСобытияИсполненияТестов
+Процедура ПослеКаждогоТеста(ОписаниеСобытия) Экспорт
+
+ Контекст = Контекст();
+ ЮТОбщий.Инкремент(Контекст.КоличествоВыполненныхТестов);
+ Информация(СтрШаблон("%1 Завершен тест `%2`", Прогресс(), ОписаниеСобытия.Тест.Имя));
+
+КонецПроцедуры
+
+// Перед каждым тестом.
+//
+// Параметры:
+// ОписаниеСобытия - см. ЮТФабрика.ОписаниеСобытияИсполненияТестов
+Процедура ПослеТестовогоНабора(ОписаниеСобытия) Экспорт
+
+ Информация(СтрШаблон("Завершен тестый набор `%1`", ОписаниеСобытия.Набор.Имя));
+
+КонецПроцедуры
+
+// Перед каждым тестом.
+//
+// Параметры:
+// ОписаниеСобытия - см. ЮТФабрика.ОписаниеСобытияИсполненияТестов
+Процедура ПослеВсехТестов(ОписаниеСобытия) Экспорт
+
+#Если Клиент Тогда
+ Прогресс = Контекст().КоличествоВыполненныхТестов;
+ ЮТКонтекст.УстановитьЗначениеКонтекста(ИмяКонтекстаЛогирования() + ".КоличествоВыполненныхТестов", Прогресс, Истина);
+#КонецЕсли
+
+ Информация(СтрШаблон("Завершен модуль `%1`", ОписаниеСобытия.Модуль.МетаданныеМодуля.ПолноеИмя));
+
+КонецПроцедуры
+
+#КонецОбласти
+
+#Область Контекст
+
+// Контекст.
+//
+// Возвращаемое значение:
+// см. НовыйДанныеКонтекста
+Функция Контекст()
+
+ Возврат ЮТКонтекст.ЗначениеКонтекста(ИмяКонтекстаЛогирования());
+
+КонецФункции
+
+Функция ИмяКонтекстаЛогирования()
+
+ Возврат "КонтекстЛогирования";
+
+КонецФункции
+
+// Новый данные контекста.
+//
+// Возвращаемое значение:
+// Структура - Новый данные контекста:
+// * Включено - Булево - Логирование включено
+// * ФайлЛога - Неопределено - Файл вывода лога
+// * ДоступенНаСервере - Булево - Файл лога доступен на сервере
+// * НакопленныеЗаписи - Массив из Строка - Буфер для серверных сообщений
+// * ОбщееКоличествоТестов - Число
+// * КоличествоВыполненныхТестов - Число
+// * УровеньЛога - Число - Уровень логирования
+Функция НовыйДанныеКонтекста()
+
+ ДанныеКонтекста = Новый Структура();
+ ДанныеКонтекста.Вставить("Включено", Ложь);
+ ДанныеКонтекста.Вставить("ФайлЛога", Неопределено);
+ ДанныеКонтекста.Вставить("ДоступенНаСервере", Ложь);
+ ДанныеКонтекста.Вставить("НакопленныеЗаписи", Новый Массив());
+ ДанныеКонтекста.Вставить("ОбщееКоличествоТестов", 0);
+ ДанныеКонтекста.Вставить("КоличествоВыполненныхТестов", 0);
+ ДанныеКонтекста.Вставить("УровеньЛога", 0);
+
+ Возврат ДанныеКонтекста;
+
+КонецФункции
+
+#КонецОбласти
+
+#Область Запись
+
+Функция НакопленныеСообщенияЛогирования(Очистить = Ложь) Экспорт
+
+ Контекст = Контекст();
+
+ Сообщения = Контекст.НакопленныеЗаписи;
+
+ Если Очистить Тогда
+ Контекст.НакопленныеЗаписи = Новый Массив();
+ КонецЕсли;
+
+ Возврат Сообщения;
+
+КонецФункции
+
+Процедура Записать(УровеньЛога, Сообщение, Приоритет)
+
+ Контекст = Контекст();
+ Если Контекст = Неопределено ИЛИ НЕ Контекст.Включено ИЛИ Контекст.УровеньЛога > Приоритет Тогда
+ Возврат;
+ КонецЕсли;
+
+#Если Клиент Тогда
+ КонтекстИсполнения = "Клиент";
+#Иначе
+ КонтекстИсполнения = "Сервер";
+#КонецЕсли
+ Текст = СтрШаблон("%1 [%2][%3]: %4", ЮТОбщий.ПредставлениеУниверсальнойДата(), КонтекстИсполнения, УровеньЛога, Сообщение);
+#Если Клиент Тогда
+ ЗаписатьСообщения(Контекст.ФайлЛога, ЮТОбщий.ЗначениеВМассиве(Текст));
+#Иначе
+ Если Контекст.ДоступенНаСервере Тогда
+ ЗаписатьСообщения(Контекст.ФайлЛога, ЮТОбщий.ЗначениеВМассиве(Текст));
+ Иначе
+ Контекст.НакопленныеЗаписи.Добавить(Текст);
+ КонецЕсли;
+#КонецЕсли
+
+КонецПроцедуры
+
+Процедура ЗаписатьСообщения(ФайлЛога, Сообщения, Дописывать = Истина)
+
+#Если ВебКлиент Тогда
+ ВызватьИсключение "Метод записи лога не доступен в web-клиенте";
+#Иначе
+ Запись = Новый ЗаписьТекста(ФайлЛога, КодировкаТекста.UTF8, , Дописывать);
+
+ Для Каждого Сообщение Из Сообщения Цикл
+ Запись.ЗаписатьСтроку(Сообщение);
+ КонецЦикла;
+
+ Запись.Закрыть();
+#КонецЕсли
+
+КонецПроцедуры
+
+Функция Прогресс()
+
+ Контекст = Контекст();
+ Прогресс = Окр(100 * Контекст.КоличествоВыполненныхТестов / Контекст.ОбщееКоличествоТестов, 0);
+
+ Возврат СтрШаблон("%1%% (%2/%3)", Прогресс, Контекст.КоличествоВыполненныхТестов, Контекст.ОбщееКоличествоТестов);
+
+КонецФункции
+
+#КонецОбласти
+
+#КонецОбласти
diff --git a/exts/yaxunit/src/CommonModules/ЮТЛогирование/ЮТЛогирование.mdo b/exts/yaxunit/src/CommonModules/ЮТЛогирование/ЮТЛогирование.mdo
new file mode 100644
index 00000000..2acfa560
--- /dev/null
+++ b/exts/yaxunit/src/CommonModules/ЮТЛогирование/ЮТЛогирование.mdo
@@ -0,0 +1,11 @@
+
+
+ ЮТЛогирование
+
+ ru
+ Логгер
+
+ true
+ true
+ true
+
diff --git a/exts/yaxunit/src/CommonModules/ЮТЛогированиеВызовСервера/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТЛогированиеВызовСервера/Module.bsl
new file mode 100644
index 00000000..d5daa3ea
--- /dev/null
+++ b/exts/yaxunit/src/CommonModules/ЮТЛогированиеВызовСервера/Module.bsl
@@ -0,0 +1,47 @@
+//©///////////////////////////////////////////////////////////////////////////©//
+//
+// Copyright 2021-2022 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.
+//
+//©///////////////////////////////////////////////////////////////////////////©//
+
+/////////////////////////////////////////////////////////////////////////////////
+// Экспортные процедуры и функции для служебного использования внутри подсистемы
+/////////////////////////////////////////////////////////////////////////////////
+
+#Область СлужебныйПрограммныйИнтерфейс
+
+Функция НакопленныеСообщенияЛогирования(Знач Очистить = Ложь) Экспорт
+
+ Возврат ЮТЛогирование.НакопленныеСообщенияЛогирования(Очистить);
+
+КонецФункции
+
+Функция ФайлЛогаДоступенНаСервере(Знач ИмяФайла, Знач ЗначениеПроверки) Экспорт
+
+ Попытка
+
+ Чтение = Новый ЧтениеТекста(ИмяФайла);
+ Строка = Чтение.ПрочитатьСтроку();
+ Возврат Строка = ЗначениеПроверки;
+
+ Исключение
+
+ Возврат Ложь;
+
+ КонецПопытки;
+
+КонецФункции
+
+#КонецОбласти
diff --git a/exts/yaxunit/src/CommonModules/ЮТЛогированиеВызовСервера/ЮТЛогированиеВызовСервера.mdo b/exts/yaxunit/src/CommonModules/ЮТЛогированиеВызовСервера/ЮТЛогированиеВызовСервера.mdo
new file mode 100644
index 00000000..7f45fc7a
--- /dev/null
+++ b/exts/yaxunit/src/CommonModules/ЮТЛогированиеВызовСервера/ЮТЛогированиеВызовСервера.mdo
@@ -0,0 +1,10 @@
+
+
+ ЮТЛогированиеВызовСервера
+
+ ru
+ Логирование вызов сервера
+
+ true
+ true
+
diff --git a/exts/yaxunit/src/CommonModules/ЮТОбщий/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТОбщий/Module.bsl
index 2fa1bf55..8423e6ad 100644
--- a/exts/yaxunit/src/CommonModules/ЮТОбщий/Module.bsl
+++ b/exts/yaxunit/src/CommonModules/ЮТОбщий/Module.bsl
@@ -147,6 +147,19 @@
КонецФункции
+Функция ПредставлениеУниверсальнойДата(Знач УниверсальнаяДатаВМиллисекундах = Неопределено) Экспорт
+
+ Если УниверсальнаяДатаВМиллисекундах = Неопределено Тогда
+ УниверсальнаяДатаВМиллисекундах = ТекущаяУниверсальнаяДатаВМиллисекундах();
+ КонецЕсли;
+
+ Дата = '00010101' + УниверсальнаяДатаВМиллисекундах / 1000;
+ Дата = МестноеВремя(Дата);
+
+ Возврат СтрШаблон("%1.%2", Дата, Формат(УниверсальнаяДатаВМиллисекундах%1000, "ЧЦ=3; ЧН=000; ЧВН=; ЧГ=0;"));
+
+КонецФункции
+
#КонецОбласти
#Область Коллекции
@@ -162,7 +175,7 @@
// то возвращается значение по умолчанию
//
// Возвращаемое значение:
-// Произвольный -- Значение искомого поля структуры
+// Произвольный - Значение искомого поля структуры
Функция ЗначениеСтруктуры(Знач ИсходнаяСтруктура, ИмяПоля, Знач ЗначениеПоУмолчанию = Неопределено, ПроверятьЗаполненность = Ложь) Экспорт
Если ПустаяСтрока(ИмяПоля) Тогда
@@ -589,7 +602,24 @@
// Строка - Объединенный путь
Функция ОбъединитьПути(Путь1, Путь2) Экспорт
- Возврат ДобавитьСтроку(Путь1, Путь2, ПолучитьРазделительПути());
+ Результат = Неопределено;
+
+ Если ЗначениеЗаполнено(Путь1) И ЗначениеЗаполнено(Путь2) Тогда
+ Разделитель = ПолучитьРазделительПути();
+
+ Если НЕ СтрЗаканчиваетсяНа(Путь1, Разделитель) И НЕ СтрНачинаетсяС(Разделитель, Путь2) Тогда
+ Результат = СтрШаблон("%1%2%3", Путь1, Разделитель, Путь2);
+ Иначе
+ Результат = Путь1 + Путь2;
+ КонецЕсли;
+
+ ИначеЕсли ЗначениеЗаполнено(Путь1) Тогда
+ Результат = Путь1;
+ Иначе
+ Результат = Путь2;
+ КонецЕсли;
+
+ Возврат Результат;
КонецФункции
@@ -622,6 +652,7 @@
КонецФункции
#КонецОбласти
+
// МетодМодуляСуществует
// Проверяет существование публичного (экспортного) метода у объекта
//
@@ -632,7 +663,7 @@
// Кешировать - Булево - Признак кеширования результата проверки
//
// Возвращаемое значение:
-// Булево -- Метод найден
+// Булево - Метод найден
Функция МетодМодуляСуществует(ИмяМодуля, ИмяМетода, КоличествоПараметров = 0, Кешировать = Истина) Экспорт
Если Кешировать Тогда
diff --git a/exts/yaxunit/src/CommonModules/ЮТСобытия/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТСобытия/Module.bsl
index 6ca37f46..ecf889a2 100644
--- a/exts/yaxunit/src/CommonModules/ЮТСобытия/Module.bsl
+++ b/exts/yaxunit/src/CommonModules/ЮТСобытия/Module.bsl
@@ -143,6 +143,14 @@
#Область СобытияЗагрузкиТестов
+// Обработка события "ПередЧтениеСценариев"
+Процедура ПередЧтениеСценариев() Экспорт
+
+ Параметры = Новый Массив();
+ ВызватьОбработчикРасширения("ПередЧтениеСценариев", Параметры);
+
+КонецПроцедуры
+
// Обработчик события "ПередЧтениемСценариевМодуля"
// Позволяет настроить базовые параметры перед чтением настроек тестов модуля
// Параметры:
@@ -166,6 +174,26 @@
КонецПроцедуры
+// Обработка события "ПослеЧтенияСценариев"
+// Параметры:
+// Сценарии - Массив из см. ЮТФабрика.ОписаниеТестовогоМодуля - Набор описаний тестовых модулей, которые содержат информацию о запускаемых тестах
+Процедура ПослеЧтенияСценариев(Сценарии) Экспорт
+
+ Параметры = ЮТОбщий.ЗначениеВМассиве(Сценарии);
+ ВызватьОбработчикРасширения("ПослеЧтенияСценариев", Параметры);
+
+КонецПроцедуры
+
+// Обработка события "ПослеФормированияИсполняемыхНаборовТестов"
+// Параметры:
+// КоллекцияКатегорийНаборов - Массив из см. ЮТИсполнитель.ОписаниеКатегорияНабораТестов - Набор исполняемых наборов
+Процедура ПослеФормированияИсполняемыхНаборовТестов(КоллекцияКатегорийНаборов) Экспорт
+
+ Параметры = ЮТОбщий.ЗначениеВМассиве(КоллекцияКатегорийНаборов);
+ ВызватьОбработчикРасширения("ПослеФормированияИсполняемыхНаборовТестов", Параметры);
+
+КонецПроцедуры
+
#КонецОбласти
#КонецОбласти
diff --git a/exts/yaxunit/src/CommonModules/ЮТТесты/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТТесты/Module.bsl
index a738a15e..dfc9a06f 100644
--- a/exts/yaxunit/src/CommonModules/ЮТТесты/Module.bsl
+++ b/exts/yaxunit/src/CommonModules/ЮТТесты/Module.bsl
@@ -323,7 +323,7 @@
// МетаданныеМодуля - см. ЮТФабрика.ОписаниеМодуля
//
// Возвращаемое значение:
-// Структура -- Исполняемые сценарии::
+// Структура - Исполняемые сценарии:
// * ТестовыеНаборы - Массив из см. ЮТФабрика.ОписаниеТестовогоНабора - Тестовые наборы модуля
Функция ИсполняемыеСценарии(МетаданныеМодуля)
diff --git a/exts/yaxunit/src/CommonModules/ЮТФабрика/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТФабрика/Module.bsl
index 32203811..8eb7e83a 100644
--- a/exts/yaxunit/src/CommonModules/ЮТФабрика/Module.bsl
+++ b/exts/yaxunit/src/CommonModules/ЮТФабрика/Module.bsl
@@ -166,12 +166,12 @@
// Описание тестового модуля.
//
// Параметры:
-// МетаданныеМодуля - Структура из см. ЮТФабрика.ОписаниеМодуля
+// МетаданныеМодуля - см. ЮТФабрика.ОписаниеМодуля
// НаборыТестов - Массив из см. ЮТФабрика.ОписаниеТестовогоНабора
//
// Возвращаемое значение:
// Структура - Описание тестового модуля:
-// * МетаданныеМодуля - Структура из см. ЮТФабрика.ОписаниеМодуля
+// * МетаданныеМодуля - см. ЮТФабрика.ОписаниеМодуля
// * НаборыТестов - Массив из см. ЮТФабрика.ОписаниеТестовогоНабора
// * Ошибки - Массив из см. ЮТФабрика.ОписаниеВозникшейОшибки
Функция ОписаниеТестовогоМодуля(МетаданныеМодуля, НаборыТестов) Экспорт
@@ -340,11 +340,12 @@
// Структура - Параметры:
// * ВыполнятьМодульноеТестирование - Булево - Признак необходимости выполнения тестов
// * reportPath - Строка - Файл или каталог сохранения отчета о тестировании
-// * filter - Структура - Параметры отбора запускаемых тестов, см. ПараметрыФильтрации
+// * filter - см. ПараметрыФильтрации
// * settings - см. НастройкиВыполнения
// * closeAfterTests - Булево - Признак необходимости закрытия приложения по окончании прогона
// * reportFormat - Строка - Формат отчета о тестировании.
// Модули реализующие различные форматы отчетов собраны в подсистеме ЮТФормированиеОтчета
+// * logging - см. ПараметрыЛогирования
Функция ПараметрыЗапуска() Экспорт
Параметры = Новый Структура;
@@ -357,6 +358,7 @@
Параметры.Вставить("settings", НастройкиВыполнения());
Параметры.Вставить("reportFormat", "jUnit");
Параметры.Вставить("showReport", Ложь);
+ Параметры.Вставить("logging", ПараметрыЛогирования());
Возврат Параметры;
@@ -450,7 +452,7 @@
// Сообщение - Строка
//
// Возвращаемое значение:
-// Структура -- Описание возникшей ошибки::
+// Структура - Описание возникшей ошибки:
// * Сообщение - Строка - Описание возникшей ошибки
// * Стек - Строка - Стек возникшей ошибки
// * ТипОшибки - Строка - Тип возникшей ошибки. Доступные значения
@@ -473,7 +475,7 @@
//
// Возвращаемое значение:
// Структура - Описание события исполнения тестов:
-// * ИмяМодуля - Строка
+// * Модуль - см. ЮТФабрика.ОписаниеТестовогоМодуля
// * Набор - см. ЮТФабрика.ОписаниеИсполняемогоНабораТестов
// * Тест - см. ЮТФабрика.ОписаниеИсполняемогоТеста
Функция ОписаниеСобытияИсполненияТестов(Модуль, Набор = Неопределено, Тест = Неопределено) Экспорт
@@ -606,18 +608,25 @@
// Возвращает структуру отборов для поиска тестов
// Возвращаемое значение:
// Структура - Параметры фильтрации:
-// * extensions - Неопределено, Массив из Строка - Список тестовых расширений
-// * modules - Неопределено, Массив из Строка - Список тестовых модулей
-// * suites - Неопределено, Массив из Строка - Список тестовых наборов
-// * paths - Неопределено, Массив из Строка - Список путей до тестовых методов, путь может быть не полным.
+// * extensions - Неопределено - Нет фильтрации по расширениям
+// - Массив из Строка - Список тестовых расширений
+// * modules - Неопределено - Нет фильтрации по модулям
+// - Массив из Строка - Список тестовых модулей
+// * suites - Неопределено - Нет фильтрации по тестовым наборам
+// - Массив из Строка - Список тестовых наборов
+// * paths - Неопределено - Нет фильтрации по путям
+// - Массив из Строка - Список путей до тестовых методов, путь может быть не полным.
// Например:
// + tests - Ищем тесты в расширении tests
// + tests.ОМ_ОбщегоНазначения - Ищем тесты в модуле ОМ_ОбщегоНазначения расширения tests
// + tests.ОМ_ОбщегоНазначения.ПолучитьЗначениеРеквизита - указание конкретного теста
-// * tags - Неопределено, Массив из Строка - Список тэгов
-// * contexts - Неопределено, Массив из Строка - Список тестируемых контекстов
-// * tests - Неопределено, Массив из Строка - Список полных имен тестовых методов. ИмяМодуля.ИмяМетода{.Контекст}
-Функция ПараметрыФильтрации()
+// * tags - Неопределено - Нет фильтрации по тегам
+// - Массив из Строка - Список тэгов
+// * contexts - Неопределено - Нет фильтрации по контекстам
+// - Массив из Строка - Список тестируемых контекстов
+// * tests - Неопределено - Нет фильтрации по тестам
+// - Массив из Строка - Список полных имен тестовых методов. ИмяМодуля.ИмяМетода{.Контекст}
+Функция ПараметрыФильтрации() Экспорт
Параметры = Новый Структура;
Параметры.Вставить("extensions");
@@ -632,7 +641,7 @@
КонецФункции
-Функция НастройкиВыполнения()
+Функция НастройкиВыполнения() Экспорт
ПараметрыИсполнения = ПараметрыИсполненияТеста();
@@ -644,4 +653,15 @@
КонецФункции
+Функция ПараметрыЛогирования() Экспорт
+
+ Параметры = Новый Структура();
+ Параметры.Вставить("file", "");
+ Параметры.Вставить("enable", Неопределено);
+ Параметры.Вставить("level", ЮТЛогирование.УровниЛога().Отладка);
+
+ Возврат Параметры;
+
+КонецФункции
+
#КонецОбласти
diff --git a/exts/yaxunit/src/CommonModules/ЮТЧитатель/Module.bsl b/exts/yaxunit/src/CommonModules/ЮТЧитатель/Module.bsl
index 59dbb4f5..a987cb06 100644
--- a/exts/yaxunit/src/CommonModules/ЮТЧитатель/Module.bsl
+++ b/exts/yaxunit/src/CommonModules/ЮТЧитатель/Module.bsl
@@ -55,7 +55,7 @@
Результат.Добавить(ТестовыйМодуль);
КонецЦикла;
-
+
Возврат Результат;
КонецФункции
@@ -196,6 +196,7 @@
НаборыТестов = ИсполняемыеСценарииМодуля(Модуль);
ИначеЕсли Модуль.Сервер Тогда
НаборыТестов = ЮТЧитательСервер.ИсполняемыеСценарииМодуля(Модуль);
+ ЮТЛогирование.ВывестиСерверныеСообщения();
КонецЕсли;
#ИначеЕсли Сервер Тогда
Если Модуль.Сервер Тогда
@@ -208,6 +209,7 @@
НаборыТестов = ИсполняемыеСценарииМодуля(Модуль);
ИначеЕсли Модуль.Сервер Тогда
НаборыТестов = ЮТЧитательСервер.ИсполняемыеСценарииМодуля(Модуль);
+ ЮТЛогирование.ВывестиСерверныеСообщения();
КонецЕсли;
#КонецЕсли
diff --git a/exts/yaxunit/src/Configuration/Configuration.mdo b/exts/yaxunit/src/Configuration/Configuration.mdo
index 0263a449..ce2a9184 100644
--- a/exts/yaxunit/src/Configuration/Configuration.mdo
+++ b/exts/yaxunit/src/Configuration/Configuration.mdo
@@ -49,6 +49,8 @@
CommonModule.ЮТКонтекстКлиент
CommonModule.ЮТКонтекстСервер
CommonModule.ЮТКонтекстТеста
+ CommonModule.ЮТЛогирование
+ CommonModule.ЮТЛогированиеВызовСервера
CommonModule.ЮТМетаданныеСервер
CommonModule.ЮТОбщий
CommonModule.ЮТОбщийВызовСервера
diff --git a/exts/yaxunit/src/DataProcessors/ЮТЮнитТесты/Forms/СозданиеНастройки/Form.form b/exts/yaxunit/src/DataProcessors/ЮТЮнитТесты/Forms/СозданиеНастройки/Form.form
index 3cd19a59..5f94aa26 100644
--- a/exts/yaxunit/src/DataProcessors/ЮТЮнитТесты/Forms/СозданиеНастройки/Form.form
+++ b/exts/yaxunit/src/DataProcessors/ЮТЮнитТесты/Forms/СозданиеНастройки/Form.form
@@ -414,6 +414,104 @@
ГруппаПараметрыЗапуска
43
+
+ ОтобразитьОтчет
+ 69
+ true
+ true
+
+ true
+
+
+ ОтобразитьОтчет
+
+
+ ОтобразитьОтчетРасширеннаяПодсказка
+ 71
+ true
+ true
+
+ true
+
+ Label
+ true
+ true
+
+ Left
+
+
+
+ ОтобразитьОтчетКонтекстноеМеню
+ 70
+ true
+ true
+
+ true
+
+ true
+
+ CheckBoxField
+ Enter
+ true
+ Left
+ true
+
+
+
+ ВыводЛога
+ 66
+ true
+ true
+
+ true
+
+
+ ИмяФайлаЛога
+
+
+ ВыводЛогаРасширеннаяПодсказка
+ 68
+ true
+ true
+
+ true
+
+ Label
+ true
+ true
+
+ Left
+
+
+
+ ВыводЛогаКонтекстноеМеню
+ 67
+ true
+ true
+
+ true
+
+ true
+
+ InputField
+ Enter
+ true
+ Left
+ true
+
+
+ StartChoice
+ ВыводЛогаНачалоВыбора
+
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+
+
ФайлКонфигурации
55
@@ -824,6 +922,47 @@
ЗапускИзКонфигуратор
+
+ ИмяФайлаЛога
+
+ ru
+ Вывод отладочных сообщений в файл
+
+ 61
+
+ String
+
+
+
+ true
+
+
+ true
+
+
+ ИмяФайлаЛога
+
+
+
+ ОтобразитьОтчет
+
+ ru
+ Показать отчет после выполнения тестов
+
+ 63
+
+ Boolean
+
+
+ true
+
+
+ true
+
+
+ ОтобразитьОтчет
+
+
УстановитьФлажки
diff --git a/exts/yaxunit/src/DataProcessors/ЮТЮнитТесты/Forms/СозданиеНастройки/Module.bsl b/exts/yaxunit/src/DataProcessors/ЮТЮнитТесты/Forms/СозданиеНастройки/Module.bsl
index 9f8e788e..140540aa 100644
--- a/exts/yaxunit/src/DataProcessors/ЮТЮнитТесты/Forms/СозданиеНастройки/Module.bsl
+++ b/exts/yaxunit/src/DataProcessors/ЮТЮнитТесты/Forms/СозданиеНастройки/Module.bsl
@@ -21,6 +21,8 @@
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
+ ОтобразитьОтчет = Истина;
+
КонецПроцедуры
&НаКлиенте
@@ -55,6 +57,13 @@
КонецПроцедуры
+&НаКлиенте
+Процедура ВыводЛогаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
+
+ ВыбратьФайл("*.log|*.log|*.txt|*.txt|All files(*.*)|*.*", ИмяФайлаЛога, Новый ОписаниеОповещения("УстановитьИмяФайлаЛога", ЭтотОбъект));
+
+КонецПроцедуры
+
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормыДеревоТестов
@@ -298,16 +307,22 @@
#Иначе
Файл = "1cv8";
#КонецЕсли
- ПутьЗапускаемогоКлиента = КаталогПрограммы() + ПолучитьРазделительПути() + Файл;
+ ПутьЗапускаемогоКлиента = ЮТОбщий.ОбъединитьПути(КаталогПрограммы(), Файл);
Если СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86 Или СистемнаяИнформация.ТипПлатформы
= ТипПлатформы.Windows_x86_64 Тогда
ПутьЗапускаемогоКлиента = ПутьЗапускаемогоКлиента + ".exe";
КонецЕсли;
- ПараметрыЗапуска = СтрШаблон("""%1"" /N""%2"" /IBConnectionString ""%3"" /C""%4""",
+ Если ЗначениеЗаполнено(ИмяПользователя()) Тогда
+ Пользователь = СтрШаблон("/N""%1""", ИмяПользователя());
+ Иначе
+ Пользователь = "";
+ КонецЕсли;
+
+ ПараметрыЗапуска = СтрШаблон("""%1"" %2 /IBConnectionString ""%3"" /C""%4""",
ПутьЗапускаемогоКлиента,
- ИмяПользователя(),
+ Пользователь,
СтрЗаменить(СтрокаСоединенияИнформационнойБазы(), """", """"""),
ПараметрыЗапускаЮнитТестов);
#КонецЕсли
@@ -328,8 +343,19 @@
&НаКлиенте
Процедура УстановитьФайлКонфигурации(ВыбранныйФайл, ДополнительныеПараметры) Экспорт
- ФайлКонфигурации = ВыбранныйФайл;
- ОбновитьСтрокуЗапуска();
+ Если ВыбранныйФайл <> Неопределено Тогда
+ ФайлКонфигурации = ВыбранныйФайл;
+ ОбновитьСтрокуЗапуска();
+ КонецЕсли;
+
+КонецПроцедуры
+
+&НаКлиенте
+Процедура УстановитьИмяФайлаЛога(ВыбранныйФайл, ДополнительныеПараметры) Экспорт
+
+ Если ВыбранныйФайл <> Неопределено Тогда
+ ИмяФайлаЛога = ВыбранныйФайл;
+ КонецЕсли;
КонецПроцедуры
@@ -363,10 +389,12 @@
ВызватьИсключение "Сохранение конфигурации из веб-клиента не поддерживается";
#Иначе
Конфигурация = ЮТФабрика.ПараметрыЗапуска();
- Конфигурация.showReport = Истина;
+ Конфигурация.showReport = ОтобразитьОтчет;
Конфигурация.closeAfterTests = Истина;
Конфигурация.reportPath = ЮТОбщий.Каталог(ФайлКонфигурации);
Конфигурация.Удалить("ВыполнятьМодульноеТестирование");
+ Конфигурация.logging.enable = ЗначениеЗаполнено(ИмяФайлаЛога);
+ Конфигурация.logging.file = ИмяФайлаЛога;
Если НЕ (УстановленФильтрПоРасширению(Конфигурация) ИЛИ УстановленФильтрПоМодулям(Конфигурация)) Тогда
УстановитьФильтрПоТестам(Конфигурация);
diff --git a/exts/yaxunit/src/Subsystems/ЮТФункциональность/Subsystems/ЮТОбработчикиСобытий/ЮТОбработчикиСобытий.mdo b/exts/yaxunit/src/Subsystems/ЮТФункциональность/Subsystems/ЮТОбработчикиСобытий/ЮТОбработчикиСобытий.mdo
index f83fad12..e4e1e36f 100644
--- a/exts/yaxunit/src/Subsystems/ЮТФункциональность/Subsystems/ЮТОбработчикиСобытий/ЮТОбработчикиСобытий.mdo
+++ b/exts/yaxunit/src/Subsystems/ЮТФункциональность/Subsystems/ЮТОбработчикиСобытий/ЮТОбработчикиСобытий.mdo
@@ -10,5 +10,6 @@
CommonModule.МокитоСлужебный
CommonModule.ЮТТестовыеДанные
CommonModule.ЮТУтверждения
+ CommonModule.ЮТЛогирование
Subsystem.ЮТФункциональность