From 6a0906661e6389786688a3c2a4f857e7174d367d Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 27 Aug 2026 14:04:01 +0200 Subject: [PATCH 1/4] =?UTF-8?q?=D0=9A=D0=B0=D1=82=D0=B0=D0=BB=D0=BE=D0=B3?= =?UTF-8?q?=20=D1=8F=D0=B4=D1=80=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B3=D0=BE?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=91=D1=82=D1=81=D1=8F?= =?UTF-8?q?=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=BE=D0=BC?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BF=D1=83=D1=81=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ядро дочернего прогона всегда бралось рядом с построителем точки входа. Приложению, которое поставляет OneUnit внутри себя, но прогоняет чужие тесты, это навязывает своё ядро вместо того, на которое рассчитан тестируемый проект. Передать проектное ядро через ПараметрыЗапуска.Импорты нельзя: отложенные импорты попадают в тело сценария и загружаются после того, как ядро подключено директивой в шапке и поделка уже собрана. Прогон при этом завершается успешно, поэтому подмена выглядит сработавшей, хотя ею не является. Параметр КаталогЯдра со значением по умолчанию сохраняет прежнее поведение. Изолированные прогоны наследуют выбор сами: ИсполнительИзоляции подключает shared относительно себя, то есть той же копии OneUnit, что и ядро прогона. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CP3TEtTKWGE2wxRjEDwVRV --- ...20\262\320\260\320\275\320\270\321\217.os" | 5 ++ ...20\222\321\205\320\276\320\264\320\260.os" | 27 ++++++- ...20\266\320\265\320\275\320\270\320\265.os" | 73 +++++++++++++++++++ 3 files changed, 102 insertions(+), 3 deletions(-) diff --git "a/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\227\320\260\320\277\321\203\321\201\320\272\320\260\321\202\320\265\320\273\321\214\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217.os" "b/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\227\320\260\320\277\321\203\321\201\320\272\320\260\321\202\320\265\320\273\321\214\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217.os" index 3c2a2a4..3eea215 100644 --- "a/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\227\320\260\320\277\321\203\321\201\320\272\320\260\321\202\320\265\320\273\321\214\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217.os" +++ "b/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\227\320\260\320\277\321\203\321\201\320\272\320\260\321\202\320\265\320\273\321\214\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217.os" @@ -28,6 +28,10 @@ // исполняется в прогоне с захватом экземпляра набора, поднятого // напрямую через Новый, пустая строка - совет по умолчанию // * РаскладкаЛога - Строка - Раскладка лога прогона, по умолчанию JSONРаскладкаСообщения +// * КаталогЯдра - Строка - Каталог ядра, которым выполняется прогон, пустое значение - +// ядро, поставляемое с текущим экземпляром OneUnit. Нужен приложениям, +// которые поставляют OneUnit внутри себя, но прогоняют чужие тесты: +// тесты проекта тогда выполняются тем ядром, на которое проект рассчитан // Функция ПараметрыЗапуска() Экспорт @@ -42,6 +46,7 @@ Параметры.Вставить("Импорты", Новый Массив); Параметры.Вставить("ЛямбдаСовета", ""); Параметры.Вставить("РаскладкаЛога", "JSONРаскладкаСообщения"); + Параметры.Вставить("КаталогЯдра", ""); Возврат Параметры; diff --git "a/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\276\321\201\321\202\321\200\320\276\320\270\321\202\320\265\320\273\321\214\320\242\320\276\321\207\320\272\320\270\320\222\321\205\320\276\320\264\320\260.os" "b/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\276\321\201\321\202\321\200\320\276\320\270\321\202\320\265\320\273\321\214\320\242\320\276\321\207\320\272\320\270\320\222\321\205\320\276\320\264\320\260.os" index e36e3cc..ef23013 100644 --- "a/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\276\321\201\321\202\321\200\320\276\320\270\321\202\320\265\320\273\321\214\320\242\320\276\321\207\320\272\320\270\320\222\321\205\320\276\320\264\320\260.os" +++ "b/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\276\321\201\321\202\321\200\320\276\320\270\321\202\320\265\320\273\321\214\320\242\320\276\321\207\320\272\320\270\320\222\321\205\320\276\320\264\320\260.os" @@ -36,9 +36,9 @@ Лог.Отладка("Импорты считанные из тестов (Импорт=ПодключаетсяПоПути): %1", Импорты); - КаталогПриложения = ФС.НормализоватьПуть( - ОбъединитьПути(ОбъединитьПути(ТекущийСценарий().Каталог, "..", ".."), "core") - ); + КаталогПриложения = КаталогЯдра(ПараметрыЗапуска); + + Лог.Отладка("Ядро прогона: %1", КаталогПриложения); ПостроительСценария = Новый ПостроительДекоратора() .Импорт(Новый Импорт(КаталогПриложения).ТипПодключения(ТипыПодключенияБиблиотек.ПоПути)); @@ -356,8 +356,29 @@ ПараметрыЗапуска.Вставить("РаскладкаЛога", "JSONРаскладкаСообщения"); КонецЕсли; + Если Не ПараметрыЗапуска.Свойство("КаталогЯдра") Тогда + ПараметрыЗапуска.Вставить("КаталогЯдра", ""); + КонецЕсли; + КонецПроцедуры +// Каталог ядра, которым будет выполнен дочерний прогон. +// +// По умолчанию берётся ядро, лежащее рядом с этим классом. Указать другое нужно тем, +// кто поставляет OneUnit внутри себя, но прогоняет чужие тесты: иначе тесты проекта +// выполнялись бы ядром вызывающего приложения, а не тем, на которое проект рассчитан. +Функция КаталогЯдра(ПараметрыЗапуска) + + Если ЗначениеЗаполнено(ПараметрыЗапуска.КаталогЯдра) Тогда + Возврат ФС.НормализоватьПуть(ПараметрыЗапуска.КаталогЯдра); + КонецЕсли; + + Возврат ФС.НормализоватьПуть( + ОбъединитьПути(ОбъединитьПути(ТекущийСценарий().Каталог, "..", ".."), "core") + ); + +КонецФункции + Функция КонфигурационныйФайл(Детальки, МенеджерВременныхФайлов, Лог) ПутиККонфигурационнымФайлам = Новый СписокМассив; diff --git "a/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" "b/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" index ea3eba7..3acd021 100644 --- "a/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" +++ "b/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" @@ -208,6 +208,60 @@ КонецПроцедуры +&Тест +Процедура ПрогонВыполняетсяЯдромРядомСПостроителем() Экспорт + + МенеджерВременныхФайлов = Новый МенеджерВременныхФайлов(); + МенеджерВременныхФайлов.БазовыйКаталог = МенеджерВременныхФайлов.СоздатьКаталог(); + + Построитель().СоздатьТочкуВхода( + Детальки(Массивы.ИзЭлементов("./tests/fixtures"), Новый Массив), + МенеджерВременныхФайлов, + Логирование.ПолучитьЛог("oscript.lib.oneunit.тесты"), + "// тестовая команда" + ); + + Ожидаем.Что(СтрНайти(СценарийПрогона(МенеджерВременныхФайлов), КаталогЯдраПоУмолчанию()), "Ядро по умолчанию") + .Больше(0); + + МенеджерВременныхФайлов.Удалить(); + +КонецПроцедуры + +&Тест +Процедура ЯдроПрогонаЗадаетсяПараметром() Экспорт + + // Приложению, которое поставляет OneUnit внутри себя, но прогоняет чужие тесты, + // нужно выполнять их ядром того проекта, а не своим + + МенеджерВременныхФайлов = Новый МенеджерВременныхФайлов(); + МенеджерВременныхФайлов.БазовыйКаталог = МенеджерВременныхФайлов.СоздатьКаталог(); + + КаталогЯдра = ФС.НормализоватьПуть(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures")); + + Параметры = Запускатель().ПараметрыЗапуска(); + Параметры.КаталогЯдра = КаталогЯдра; + + Построитель().СоздатьТочкуВхода( + Детальки(Массивы.ИзЭлементов("./tests/fixtures"), Новый Массив), + МенеджерВременныхФайлов, + Логирование.ПолучитьЛог("oscript.lib.oneunit.тесты"), + "// тестовая команда", + Параметры + ); + + ТекстСценария = СценарийПрогона(МенеджерВременныхФайлов); + + Ожидаем.Что(СтрНайти(ТекстСценария, КаталогЯдра), "Указанное ядро") + .Больше(0); + + Ожидаем.Что(СтрНайти(ТекстСценария, КаталогЯдраПоУмолчанию()), "Ядро по умолчанию не используется") + .Равно(0); + + МенеджерВременныхФайлов.Удалить(); + +КонецПроцедуры + #КонецОбласти #Область ТестыЗапускателяТестирования @@ -442,4 +496,23 @@ КонецФункции +Функция КаталогЯдраПоУмолчанию() + + Возврат ФС.НормализоватьПуть(ОбъединитьПути(ТекущийКаталог(), "src", "core")); + +КонецФункции + +// Точка входа загружает отдельный сценарий, в котором подключается ядро и запускается прогон. +Функция СценарийПрогона(МенеджерВременныхФайлов) + + Тексты = Новый Массив(); + + Для Каждого Файл Из НайтиФайлы(МенеджерВременныхФайлов.БазовыйКаталог, "*.os") Цикл + Тексты.Добавить(ПрочитатьФайл(Файл.ПолноеИмя)); + КонецЦикла; + + Возврат СтрСоединить(Тексты, Символы.ПС); + +КонецФункции + #КонецОбласти From 6c10a3c518198c38d7deabe5e6b2d60dfec82df8 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 27 Aug 2026 14:16:02 +0200 Subject: [PATCH 2/4] =?UTF-8?q?=D0=92=D0=B5=D1=80=D1=81=D0=B8=D1=8F=200.5.?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Параметр КаталогЯдра расширяет программный интерфейс запуска прогонов, поведение по умолчанию не меняется. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CP3TEtTKWGE2wxRjEDwVRV --- ...\320\273\320\276\320\266\320\265\320\275\320\270\321\217.os" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/src/cli/internal/isolated/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\277\320\270\321\201\320\260\320\275\320\270\320\265\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\263\320\276\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\321\217.os" "b/src/cli/internal/isolated/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\277\320\270\321\201\320\260\320\275\320\270\320\265\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\263\320\276\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\321\217.os" index a65b388..2449d87 100644 --- "a/src/cli/internal/isolated/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\277\320\270\321\201\320\260\320\275\320\270\320\265\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\263\320\276\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\321\217.os" +++ "b/src/cli/internal/isolated/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\277\320\270\321\201\320\260\320\275\320\270\320\265\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\263\320\276\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\321\217.os" @@ -12,5 +12,5 @@ КонецФункции Функция ВерсияПриложения() Экспорт - Возврат "0.4.1"; + Возврат "0.5.0"; КонецФункции From 485160bf1f79436e72fa66e1e920158e77e2fd09 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 27 Aug 2026 16:17:01 +0200 Subject: [PATCH 3/4] =?UTF-8?q?=D0=A2=D0=B5=D1=81=D1=82:=20=D1=8F=D0=B4?= =?UTF-8?q?=D1=80=D0=BE=20=D0=BF=D0=BE=20=D1=83=D0=BC=D0=BE=D0=BB=D1=87?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8E=20=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=81=D0=B8=D1=82=20=D0=BE=D1=82=20=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=83=D1=89=D0=B5=D0=B3=D0=BE=20=D0=BA=D0=B0=D1=82=D0=B0=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Умолчание отсчитывается от каталога построителя, а не от текущего каталога. На этом держится изоляция: изолированный набор прогоняется дочерним процессом уже внутри выбранного ядра, и своё ядро тот определяет по умолчанию. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01PpvuJYLbttUBC1ufRmU1JN --- ...20\266\320\265\320\275\320\270\320\265.os" | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git "a/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" "b/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" index 3acd021..572b309 100644 --- "a/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" +++ "b/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" @@ -262,6 +262,48 @@ КонецПроцедуры +&Тест +Процедура ЯдроПоУмолчаниюНеЗависитОтТекущегоКаталога() Экспорт + + // Ядро по умолчанию отсчитывается от каталога построителя, а не от текущего каталога. + // На этом держится изоляция: изолированный набор прогоняется дочерним процессом уже + // внутри выбранного ядра, и своё ядро тот определяет по умолчанию - то есть тем же + // ядром, которым запущен сам. Текущий каталог там - каталог тестируемого проекта, + // и отсчёт от него увёл бы изолированный прогон на несуществующее ядро + + МенеджерВременныхФайлов = Новый МенеджерВременныхФайлов(); + МенеджерВременныхФайлов.БазовыйКаталог = МенеджерВременныхФайлов.СоздатьКаталог(); + + ИсходныйКаталог = ТекущийКаталог(); + КаталогиТестов = Массивы.ИзЭлементов( + ФС.НормализоватьПуть(ОбъединитьПути(ИсходныйКаталог, "tests", "fixtures")) + ); + + УстановитьТекущийКаталог(МенеджерВременныхФайлов.БазовыйКаталог); + + Попытка + + Построитель().СоздатьТочкуВхода( + Детальки(КаталогиТестов, Новый Массив), + МенеджерВременныхФайлов, + Логирование.ПолучитьЛог("oscript.lib.oneunit.тесты"), + "// тестовая команда" + ); + + Исключение + УстановитьТекущийКаталог(ИсходныйКаталог); + ВызватьИсключение; + КонецПопытки; + + УстановитьТекущийКаталог(ИсходныйКаталог); + + Ожидаем.Что(СтрНайти(СценарийПрогона(МенеджерВременныхФайлов), КаталогЯдраПоУмолчанию()), "Ядро по умолчанию") + .Больше(0); + + МенеджерВременныхФайлов.Удалить(); + +КонецПроцедуры + #КонецОбласти #Область ТестыЗапускателяТестирования From ba4ed1a66603798a7c13c20459c72ca9353743ac Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Fri, 28 Aug 2026 21:29:54 +0200 Subject: [PATCH 4/4] =?UTF-8?q?=D0=97=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D1=83=20=D1=8F=D0=B4=D1=80=D0=B0?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B3=D0=BE=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Тест на заданное ядро проверял путь из проекта, который попадает в сценарий импортами самих тестов, - утверждение прошло бы и при проигнорированном параметре. Теперь ядро подставляется пустым временным каталогом. Относительный каталог ядра разворачивается до перехода в рабочий каталог прогона: иначе тот же путь означал бы каталог рядом с чужими тестами. Несуществующий каталог ядра отклоняется сразу, а не дочерним процессом сообщением о несуществующей библиотеке. В документации параметра описано, что развязка частичная: точку входа строит построитель вызывающего приложения, а дерево зависимостей остаётся прежним. --- ...20\262\320\260\320\275\320\270\321\217.os" | 23 +++++++++-- ...20\222\321\205\320\276\320\264\320\260.os" | 27 ++++++++++--- ...20\266\320\265\320\275\320\270\320\265.os" | 40 ++++++++++++++++++- 3 files changed, 80 insertions(+), 10 deletions(-) diff --git "a/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\227\320\260\320\277\321\203\321\201\320\272\320\260\321\202\320\265\320\273\321\214\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217.os" "b/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\227\320\260\320\277\321\203\321\201\320\272\320\260\321\202\320\265\320\273\321\214\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217.os" index 3eea215..9c39de7 100644 --- "a/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\227\320\260\320\277\321\203\321\201\320\272\320\260\321\202\320\265\320\273\321\214\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217.os" +++ "b/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\227\320\260\320\277\321\203\321\201\320\272\320\260\321\202\320\265\320\273\321\214\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217.os" @@ -28,10 +28,18 @@ // исполняется в прогоне с захватом экземпляра набора, поднятого // напрямую через Новый, пустая строка - совет по умолчанию // * РаскладкаЛога - Строка - Раскладка лога прогона, по умолчанию JSONРаскладкаСообщения -// * КаталогЯдра - Строка - Каталог ядра, которым выполняется прогон, пустое значение - -// ядро, поставляемое с текущим экземпляром OneUnit. Нужен приложениям, -// которые поставляют OneUnit внутри себя, но прогоняют чужие тесты: -// тесты проекта тогда выполняются тем ядром, на которое проект рассчитан +// * КаталогЯдра - Строка - Каталог ядра (core чужой поставки, рядом обязан лежать +// shared), которым выполняется прогон. Пустое значение - ядро, поставляемое +// с текущим экземпляром OneUnit. Нужен приложениям, которые поставляют +// OneUnit внутри себя, но прогоняют чужие тесты: тесты проекта тогда +// выполняются тем ядром, на которое проект рассчитан. +// Развязка при этом частичная. Точку входа строит по-прежнему построитель +// вызывающего приложения, а он завязан на состав ядра: имена желудей, +// имена деталек, настройки лога. Лишнюю детальку старое ядро пропустит, +// а вот ядру новее построителя нужной детальки никто не запишет. +// Дерево зависимостей прогона тоже остаётся прежним: lib.system +// и lib.additional собираются из окружения вызывающего процесса +// и oscript.cfg каталогов тестов // Функция ПараметрыЗапуска() Экспорт @@ -255,6 +263,13 @@ ФормироватьПокрытие = ЗначениеЗаполнено(Параметры.ПутьКОтчетуGenericCoverage) ИЛИ ЗначениеЗаполнено(Параметры.ПутьКОтчетуCobertura); + // Относительный каталог ядра разворачивается здесь, пока текущий каталог - каталог + // вызывающего. Дальше прогон переходит в РабочийКаталог, и тот же путь означал бы + // уже другой каталог - зависящий от того, где лежат чужие тесты + Если Параметры.Свойство("КаталогЯдра") И ЗначениеЗаполнено(Параметры.КаталогЯдра) Тогда + Параметры.КаталогЯдра = ФС.НормализоватьПуть(Параметры.КаталогЯдра); + КонецЕсли; + МенеджерВременныхФайлов = Новый МенеджерВременныхФайлов(); МенеджерВременныхФайлов.БазовыйКаталог = МенеджерВременныхФайлов.СоздатьКаталог(); diff --git "a/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\276\321\201\321\202\321\200\320\276\320\270\321\202\320\265\320\273\321\214\320\242\320\276\321\207\320\272\320\270\320\222\321\205\320\276\320\264\320\260.os" "b/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\276\321\201\321\202\321\200\320\276\320\270\321\202\320\265\320\273\321\214\320\242\320\276\321\207\320\272\320\270\320\222\321\205\320\276\320\264\320\260.os" index ef23013..d7a9f83 100644 --- "a/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\276\321\201\321\202\321\200\320\276\320\270\321\202\320\265\320\273\321\214\320\242\320\276\321\207\320\272\320\270\320\222\321\205\320\276\320\264\320\260.os" +++ "b/src/shared/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\276\321\201\321\202\321\200\320\276\320\270\321\202\320\265\320\273\321\214\320\242\320\276\321\207\320\272\320\270\320\222\321\205\320\276\320\264\320\260.os" @@ -362,15 +362,32 @@ КонецПроцедуры -// Каталог ядра, которым будет выполнен дочерний прогон. +// Возвращает каталог ядра, которым будет выполнен дочерний прогон. +// +// Параметры: +// ПараметрыЗапуска - Структура - Параметры запуска прогона, см. ЗапускательТестирования.ПараметрыЗапуска +// +// Возвращаемое значение: +// Строка - Каталог ядра. По умолчанию - ядро, лежащее рядом с этим классом +// +// Указанный каталог - это каталог core чужой поставки, и рядом с ним обязан лежать +// shared: ядро подключает его относительным путём, и на этом же держится наследование +// ядра изолированными прогонами. // -// По умолчанию берётся ядро, лежащее рядом с этим классом. Указать другое нужно тем, -// кто поставляет OneUnit внутри себя, но прогоняет чужие тесты: иначе тесты проекта -// выполнялись бы ядром вызывающего приложения, а не тем, на которое проект рассчитан. Функция КаталогЯдра(ПараметрыЗапуска) Если ЗначениеЗаполнено(ПараметрыЗапуска.КаталогЯдра) Тогда - Возврат ФС.НормализоватьПуть(ПараметрыЗапуска.КаталогЯдра); + + Каталог = ФС.НормализоватьПуть(ПараметрыЗапуска.КаталогЯдра); + + // Иначе о промахе сказал бы дочерний процесс - и сказал бы про несуществующую + // библиотеку, а не про параметр, которым эту библиотеку выбрали + Если Не ФС.КаталогСуществует(Каталог) Тогда + ВызватьИсключение СтрШаблон("Каталог ядра прогона не найден: %1", Каталог); + КонецЕсли; + + Возврат Каталог; + КонецЕсли; Возврат ФС.НормализоватьПуть( diff --git "a/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" "b/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" index 572b309..b37a1be 100644 --- "a/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" +++ "b/tests/\320\232\320\276\320\275\321\201\320\276\320\273\321\214\320\275\320\276\320\265\320\237\321\200\320\270\320\273\320\276\320\266\320\265\320\275\320\270\320\265.os" @@ -237,7 +237,10 @@ МенеджерВременныхФайлов = Новый МенеджерВременныхФайлов(); МенеджерВременныхФайлов.БазовыйКаталог = МенеджерВременныхФайлов.СоздатьКаталог(); - КаталогЯдра = ФС.НормализоватьПуть(ОбъединитьПути(ТекущийКаталог(), "tests", "fixtures")); + // Каталог намеренно пустой и временный. Путь из проекта - те же tests/fixtures - + // попадает в сценарий импортами самих тестов, и утверждение проходило бы + // даже при полностью проигнорированном параметре + КаталогЯдра = ФС.НормализоватьПуть(МенеджерВременныхФайлов.СоздатьКаталог()); Параметры = Запускатель().ПараметрыЗапуска(); Параметры.КаталогЯдра = КаталогЯдра; @@ -304,6 +307,41 @@ КонецПроцедуры +&Тест +Процедура НесуществующееЯдроОтклоняетсяСразу() Экспорт + + // Промах в каталоге ядра иначе виден только дочернему процессу, а тот жалуется + // на несуществующую библиотеку - по такому сообщению до параметра не добраться + + МенеджерВременныхФайлов = Новый МенеджерВременныхФайлов(); + МенеджерВременныхФайлов.БазовыйКаталог = МенеджерВременныхФайлов.СоздатьКаталог(); + + Параметры = Запускатель().ПараметрыЗапуска(); + Параметры.КаталогЯдра = ОбъединитьПути(МенеджерВременныхФайлов.БазовыйКаталог, "ядра-тут-нет"); + + Описание = ""; + + Попытка + + Построитель().СоздатьТочкуВхода( + Детальки(Массивы.ИзЭлементов("./tests/fixtures"), Новый Массив), + МенеджерВременныхФайлов, + Логирование.ПолучитьЛог("oscript.lib.oneunit.тесты"), + "// тестовая команда", + Параметры + ); + + Исключение + Описание = ОписаниеОшибки(); + КонецПопытки; + + Ожидаем.Что(СтрНайти(Описание, "Каталог ядра прогона не найден"), "Сообщение об ошибке") + .Больше(0); + + МенеджерВременныхФайлов.Удалить(); + +КонецПроцедуры + #КонецОбласти #Область ТестыЗапускателяТестирования