Разработка автоматизированного тестирования на основании настольного приложения при помощи платформы 1С: Предприятие 8.3 (версия 01.12)

23.11.22

Разработка - Тестирование QA

В данной статье я подробно разберу процесс создания автоматизированного тестирования для приложения на базе 1С: Предприятие 8.3.

В рамках этой статьи хотел бы подробно разобрать процесс создания автоматизированного тестирования для приложения, разработанного на базе 1С: Предприятие 8.3.

Возможно, где-то буду описывать крайне подробно, как может показаться опытным программистам, но делаю я это в первую очередь для себя и для того, чтобы это можно было повторить даже совсем начинающим программистам.
 

Шаг 1. 

Создаём новую информационную базу. Я её назвал "МенеджерТестирования" для понятности. Также немаловажно указать понятный путь.

Шаг 2. 

Переходим в конфигурацию. Далее во вкладку Сервис -> Параметры -> Запуск 1С: Предприятия -> Дополнительные -> Запускать как менеджер тестирования.

Шаг 3.

Теперь необходимо создать новую обработку (в панели объектов конфигурации, слева). Я назвал её "ЗапускТестов".

Внутри неё создаём новую форму (обработки).

В этой форме в окне реквизитов создаём два новых реквизита: Платформа и ПутьКБазе. Перетаскиваем их на форму.

В завершении, каждому из добавленных реквизитов в свойствах переходим в пункт Использование -> Кнопка выбора -> "Да".

Далее, не выходя из формы, добавляем новую команду - "ТестовыйСценарий". Перетаскиваем её на форму.

Теперь вернёмся к нашим полям путей. В свойствах поля "Платформа" переходим в События -> Начало выбора и теперь жмём на лупу и создаём новую процедуру на клиенте.

Открывается модуль, внутри которого должен лежать следующий код:

&НаКлиенте
Процедура ПлатформаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	  СтандартнаяОбработка = Ложь;
	  Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
	  Диалог.Заголовок = "Выберите файл базы 1С";
	  Диалог.ПредварительныйПросмотр = Ложь;
	  Диалог.МножественныйВыбор = Ложь;
	  Диалог.ПроверятьСуществованиеФайла = Истина;
	  Диалог.Каталог = "c:\";
	  Если Диалог.Выбрать() Тогда
		  Платформа = Диалог.ПолноеИмяФайла;
	  КонецЕсли;
КонецПроцедуры

 

Теперь пропишем процедуру для пути к базе. Переходим в свойства поля "ПутьКБазе" -> События -> НачалоВыбора -> Создаём процедуру на клиенте.

Туда мы пропишем следующий код:

&НаКлиенте
Процедура ПутьКБазеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	  СтандартнаяОбработка = Ложь;
	  Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	  Диалог.Заголовок = "Выберите путь к базе для тестирования";
	  Диалог.МножественныйВыбор = Ложь;
	  Диалог.Каталог = "";
	  Если Диалог.Выбрать() Тогда
		  ПутьКБазе = Диалог.Каталог;
	  КонецЕсли;
КонецПроцедуры

Чтобы у нас всё заработало, необходимо перейти в свойства всей конфигурации и в пункте "Совместимость" найти поле "Режим использования синхронных вызовов..." -> ставим Использовать.

 


Примерно так будет выглядеть окно

 

Проверяем! Указываем необходимые пути и если ошибок не возникает - идём дальше.
 

Шаг 4.

Теперь пропишем сценарий для кнопки.

Выбираем команду -> Свойства -> Действие -> На клиенте

Внутри пропишем следующий код:

&НаКлиенте
Процедура ТестовыйСценарий(Команда)
	ЗапуститьСистему("""Платформа"" ENTERPRISE /F " + ПутьКБазе + " /TESTCLIENT");
	ТестируемоеПриложение = Новый ТестируемоеПриложение();
	МаксИтераций = 10;
	Для Счетчик = 1 По МаксИтераций Цикл
		Попытка
			ТестируемоеПриложение.УстановитьСоединение();
			Прервать;
		Исключение
			Если Счетчик = МаксИтераций Тогда
				Сообщить(ОписаниеОшибки());
			КонецЕсли;
		КонецПопытки;
	КонецЦикла;
КонецПроцедуры

 

Шаг 5.

Переходим в конфигурацию основного, тестируемого приложения. Запускаем специальную отладку: Сервис -> "Запустить для записи журнала действий пользователя".

Запустится программа, в верхнем левом углу которой появятся необходимые нам дополнительные кнопки.

 

 

Для записи действий нажимаем кнопку "Начать".

После нажатия, совершаем тестируемое действие (например, заносим новые данные в Номенклатуру).

Важно! Если происходит запись данных через форму элемента, то там необходимо переключаться на новые поля не при помощи курсора, а клавиши Tab.

После выполнения необходимых действий тестирования, нажимаем на кнопку "Завершить запись журнала действий пользователя". Потом отобразится журнал - страница с кучей англоязычного кода. Нам необходимо весь этот текст необходимо сохранить в текстовый файл, чтобы не потерять.

 

Шаг 6.

Возвращаемся в менеджер тестирования.

Жмём ПКМ по Обработкам -> Вставить внешнюю обработку -> В диалоговом окне выбираем файл "ULogToScript". Я буду работать с этой наработкой.

Запускаем менеджер тестирования. Далее переключаемся на вкладку "Преобразование журнала действий пользователя".

Мы попадаем на новое для нас окно преобразования. Здесь нужно поставить две галочки, а также вставить ранее сохранённый нами журнал действий пользователя (который на английском). Жмём на красивую кнопку "Преобразовать".

Должно выглядеть так:

 


Преобразование журнала действий пользователя

 

В окне сценарий появился необходимый преобразованный код. Копируем его или сохраняем в файл и идём дальше.

Переходим в конфигуратор. Открываем форму ЗапускТестов и переходим в модуль. Открываем процедуру кнопки тестового сценария и добавляем в конец следующие строки:

ГлавноеОкноФормы = ТестируемоеПриложение.НайтиОбъект(Тип("ТестируемоеОкноКлиентскогоПриложения"));
КомандныйИнтерфейсГлавногоОкна = ГлавноеОкноФормы.ПолучитьКомандныйИнтерфейс();

И после процедуры, в которой мы это прописали, вставляем целиком весь преобразованный русскоязычный журнал действий.
Чтобы обратиться к нему, после тех двух строчек, что написаны выше, необходимо вызвать процедуру журнала, передав в параметр наше тестируемое приложение.

По итогу, модуль формы ЗапускТестов должен хранить в себе примерно такой код:

&НаКлиенте
Процедура ПлатформаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	  СтандартнаяОбработка = Ложь;
	  Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
	  Диалог.Заголовок = "Выберите файл базы 1С";
	  Диалог.ПредварительныйПросмотр = Ложь;
	  Диалог.МножественныйВыбор = Ложь;
	  Диалог.ПроверятьСуществованиеФайла = Истина;
	  Диалог.Каталог = "c:\";
	  Если Диалог.Выбрать() Тогда
		  Платформа = Диалог.ПолноеИмяФайла;
	  КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПутьКБазеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	  СтандартнаяОбработка = Ложь;
	  Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	  Диалог.Заголовок = "Выберите путь к базе для тестирования";
	  Диалог.МножественныйВыбор = Ложь;
	  Диалог.Каталог = "";
	  Если Диалог.Выбрать() Тогда
		  ПутьКБазе = Диалог.Каталог;
	  КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ТестовыйСценарий(Команда)
	ЗапуститьСистему("""Платформа"" ENTERPRISE /F " + ПутьКБазе + " /TESTCLIENT");
	ТестовоеПриложение = Новый ТестируемоеПриложение();
	МаксИтераций = 10;
	Для Счетчик = 1 По МаксИтераций Цикл
		Попытка
			ТестовоеПриложение.УстановитьСоединение();
			Прервать;
		Исключение
			Если Счетчик = МаксИтераций Тогда
				Сообщить(ОписаниеОшибки());
			КонецЕсли;
		КонецПопытки;
	КонецЦикла;  
	
	// Вставляем тесты
	ГлавноеОкноФормы = ТестовоеПриложение.НайтиОбъект(Тип("ТестируемоеОкноКлиентскогоПриложения"));
	КомандныйИнтерфейсГлавногоОкна = ГлавноеОкноФормы.ПолучитьКомандныйИнтерфейс(); 
	
	ТестовыйСценарий_22_11_2022(ТестовоеПриложение);
	
КонецПроцедуры       

&НаКлиенте
Процедура ТестовыйСценарий_22_11_2022(ТестовоеПриложение)

	ОкноПриложенияОсновноеКнопкаКомандногоИнтерфейсаНоменклатураНажать(ТестовоеПриложение);
	ОкноПриложенияНоменклатураКнопкаСоздатьНажать(ТестовоеПриложение);
	ОкноПриложенияНоменклатураСозданиеПолеНаименованиеПерейтиКСледующемуЭлементу(ТестовоеПриложение);
	ОкноПриложенияНоменклатураСозданиеКнопкаЗаписатьИЗакрытьНажать(ТестовоеПриложение);

КонецПроцедуры

&НаКлиенте
Процедура ОкноПриложенияОсновноеКнопкаКомандногоИнтерфейсаНоменклатураНажать(ТестовоеПриложение)
	
	ОкноПриложенияОсновное = Неопределено;
	КлиентсткиеОкнаТестируемогоПриложения = ТестовоеПриложение.ПолучитьПодчиненныеОбъекты();
	Для Каждого ТестируемоеОкно Из КлиентсткиеОкнаТестируемогоПриложения Цикл
		Если ТестируемоеОкно.Основное Тогда
			ОкноПриложенияОсновное = ТестируемоеОкно;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	ОкноПриложенияОсновноеCommandInterface = ОкноПриложенияОсновное.ПолучитьКомандныйИнтерфейс();
	ГруппаКомандногоИнтерфейсаПанельФункцийТекущегоРаздела = ОкноПриложенияОсновноеCommandInterface.НайтиОбъект(Тип("ТестируемаяГруппаКомандногоИнтерфейса"), "Панель функций текущего раздела");
	КнопкаКомандногоИнтерфейсаНоменклатура = ГруппаКомандногоИнтерфейсаПанельФункцийТекущегоРаздела.НайтиОбъект(Тип("ТестируемаяКнопкаКомандногоИнтерфейса"), "Номенклатура");
	КнопкаКомандногоИнтерфейсаНоменклатура.Нажать();

КонецПроцедуры

&НаКлиенте
Процедура ОкноПриложенияНоменклатураКнопкаСоздатьНажать(ТестовоеПриложение)

	ОкноПриложенияНоменклатура = ТестовоеПриложение.НайтиОбъект(Тип("ТестируемоеОкноКлиентскогоПриложения"), "Номенклатура", , 30);
	ОкноПриложенияНоменклатураФормаНоменклатура = ОкноПриложенияНоменклатура.НайтиОбъект(Тип("ТестируемаяФорма"), "Номенклатура");
	ГруппаКоманднаяПанель = ОкноПриложенияНоменклатураФормаНоменклатура.НайтиОбъект(Тип("ТестируемаяГруппаФормы"), "Командная панель");
	КнопкаСоздать = ГруппаКоманднаяПанель.НайтиОбъект(Тип("ТестируемаяКнопкаФормы"), "Создать");
	КнопкаСоздать.Нажать();

КонецПроцедуры

&НаКлиенте
Процедура ОкноПриложенияНоменклатураСозданиеПолеНаименованиеПерейтиКСледующемуЭлементу(ТестовоеПриложение)

	ОкноПриложенияНоменклатураСоздание = ТестовоеПриложение.НайтиОбъект(Тип("ТестируемоеОкноКлиентскогоПриложения"), "Номенклатура (создание)", , 30);
	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание = ОкноПриложенияНоменклатураСоздание.НайтиОбъект(Тип("ТестируемаяФорма"), "Номенклатура (создание)");
	ПолеНаименование = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемоеПолеФормы"), "Наименование");
	ПолеНаименование.ВвестиТекст("Номенклатура3");

	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.ПерейтиКСледующемуЭлементу();

КонецПроцедуры

&НаКлиенте
Процедура ОкноПриложенияНоменклатураСозданиеКнопкаЗаписатьИЗакрытьНажать(ТестовоеПриложение)

	ОкноПриложенияНоменклатураСоздание = ТестовоеПриложение.НайтиОбъект(Тип("ТестируемоеОкноКлиентскогоПриложения"), "Номенклатура (создание) *", , 30);
	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание = ОкноПриложенияНоменклатураСоздание.НайтиОбъект(Тип("ТестируемаяФорма"), "Номенклатура (создание) *");
	ПолеЕдиницаИзмерения = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемоеПолеФормы"), "Единица измерения");
	ПолеЕдиницаИзмерения.ОткрытьВыпадающийСписок();

	ПолеЕдиницаИзмерения.ОжидатьФормированияВыпадающегоСписка();

	ПолеЕдиницаИзмерения.ВыполнитьВыборИзСпискаВыбора("шт");

	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.ПерейтиКСледующемуЭлементу();

	ПолеДлинаМ = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемоеПолеФормы"), "Длина, м");
	ПолеДлинаМ.ВвестиТекст("1,00");

	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.ПерейтиКСледующемуЭлементу();

	ПолеКоличество = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемоеПолеФормы"), "Количество");
	ПолеКоличество.ВвестиТекст("1");

	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.ПерейтиКСледующемуЭлементу();

	ПолеТипНоменклатуры = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемоеПолеФормы"), "Тип номенклатуры");
	ПолеТипНоменклатуры.ОткрытьВыпадающийСписок();

	ПолеТипНоменклатуры.ОжидатьФормированияВыпадающегоСписка();

	ПолеТипНоменклатуры.ВыполнитьВыборИзСпискаВыбора("Материалы");

	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.ПерейтиКСледующемуЭлементу();

	ПолеТипМатериалаФурнитуры = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемоеПолеФормы"), "Тип материала/фурнитуры");
	ПолеТипМатериалаФурнитуры.ВвестиТекст("Новый тип");

	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.ПерейтиКСледующемуЭлементу();

	ПолеЦена = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемоеПолеФормы"), "Цена");
	ПолеЦена.ВвестиТекст("366,00");

	ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.ПерейтиКСледующемуЭлементу();

	ПолеКачество = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемоеПолеФормы"), "Качество");
	ПолеКачество.ОткрытьВыпадающийСписок();

	ПолеКачество.ОжидатьФормированияВыпадающегоСписка();

	ПолеКачество.ВыполнитьВыборИзСпискаВыбора("Средняя");

	ГруппаКоманднаяПанель = ОкноПриложенияНоменклатураСозданиеФормаНоменклатураСоздание.НайтиОбъект(Тип("ТестируемаяГруппаФормы"), "Командная панель");
	КнопкаЗаписатьИЗакрыть = ГруппаКоманднаяПанель.НайтиОбъект(Тип("ТестируемаяКнопкаФормы"), "Записать и закрыть");
	КнопкаЗаписатьИЗакрыть.Нажать();

КонецПроцедуры

Обратите внимание! Из-за возникновения неполадок этот листинг немного отличается от предыдущих тем, что ТестируемоеПриложение заменено на ТестовоеПриложение.

 

Проверяем модуль на наличие возможных синтаксических ошибок и запускаем наш менеджер тестирования.

Выбираем необходимые пути и выполняем тестовый сценарий.

Если всё правильно, то можно успеть заметить ускоренный автоматический процесс заполнения данных. После завершения можем увидеть в нашем справочнике/документе новые данные.

Тестирование прошло успешно!

Вступайте в нашу телеграмм-группу Инфостарт

Конфигурация тестирование автоматизация автоматическое

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Тестирование QA 1С 8.3 1С 8.5 1C:Бухгалтерия 1С:ERP Управление предприятием 2 1С:Зарплата и кадры государственного учреждения 3 1С:Управление торговлей 11 1С:Управление холдингом Абонемент ($m)

Обработка «Изменения движений» проверяет, меняются ли движения документов после перепроведения — без изменения данных в базе (перепроведение в транзакции с откатом). Удобна после обновления конфигурации, рефакторинга проведения и для регрессии доработок, в том числе сгенерированных ИИ. Можно запускать из формы или программно (регламент, HTTP-сервис, автотесты): задаёте период, виды документов и регистров, лимит выборки — получаете отчёт и таблицу расхождений.

10 стартмани

17.09.2026    248    1    MaxxiMiliSan    0    

0

DevOps и автоматизация разработки Тестирование QA Групповая разработка (Git, хранилище) Программист 1С:Предприятие 8 Бесплатно (free)

Четыре года в интеграторе я работал с git и EDT. Git после хранилища полюбил сразу: видно, кто и что менял. С EDT сложнее: тормозит, ошибки при обновлении ERP, автономный сервер внутри него работает только с файловой базой. На новой работе команда захотела перейти на git, я развернул EDT, и оно на второй день разрушило проект при загрузке расширения. Тогда я решил дать команде git с привычным Конфигуратором и инструмент, который за минуту доносит коммит до базы через ibcmd, вместо получасовой загрузки из файлов. На новой работе разрешили ИИ, и я написал это приложение с его помощью: от чтения документации и первого ТЗ до идей в электричке. Впервые за годы снова почувствовал себя творцом, а не закрывателем задач. По дороге приросли выгрузка, объединение и проверка конфигурации по коммитам, YAxUnit и режим MCP-сервера. В статье: схемы, скриншоты, грабли и честный список ограничений. Ссылки пока нет: хочу понять, нужно ли это кому-то, кроме меня.

03.09.2026    10759    KatanaDragon511    28    

40

Инструменты администратора БД Инструментарий разработчика Тестирование QA Системный администратор Программист Стажер 1С:Предприятие 8 Бесплатно (free)

В экосистеме 1С давно живут сотни инструментов: от Конфигуратора и Хранилища до систем тестирования, мониторинга, интеграции и CI/CD. Я собрал их в Ландшафт технологий, а теперь добавляю данные о реальном использовании. Рассказываю, как устроена карта, что показал первый опрос и почему в новой волне особенно нужны администраторы, аналитики и тестировщики.

01.09.2026    2247    mrXoxot    6    

25

DevOps и автоматизация разработки Мониторинг Тестирование QA Программист 1С:Предприятие 8 Бесплатно (free)

Платформа 1С давно вышла за рамки учетных систем. Сегодня это полноценная среда для создания сложных, высоконагруженных и распределенных приложений. А значит, и стек технологий современного разработчика кардинально изменился. Систематизируем весь инструментарий, который превращает 1С-программиста в инженера: от EDT и Git до автотестов на YAxUnit, контейнеризации приложений в Docker, мониторинга в Prometheus и организации шины данных на Kafka. Разберемся, зачем каждый инструмент нужен, как он вписывается в жизненный цикл разработки и с чего начать его внедрение.

25.08.2026    21483    mrXoxot    53    

83

HighLoad оптимизация Тестирование QA Программист 1С 8.3 Бесплатно (free)

Шесть внешних отчётов на боевой базе крупной сети переписали за неделю. По секундомеру ускорились четыре, в акт пошли три: у одного отчёта минус тринадцать процентов оказались выбросом нагрузки прода, а не эффектом кода. Поймал это чередующийся замер до/после в одном окне, обычные три прогона с метрикой "минимум" показывали ускорение уверенно. Дальше в тексте: почему построчная сверка выхода ломается ровно на тех правках, ради которых её заводят; из чего собирается повторяемый слепок результата и почему главную работу в нём делает нормализация, а хеш только сигнализация; где слепок не берётся вовсе и его заменяет по-колоночная сверка; чем проверять пересчёт итогов, чистку данных и операции с кластером. Отдельно - гипотеза, которую замер отклонил, и честный счёт, во что вся эта дисциплина обходится.

21.08.2026    1418    nedomolkov.ivan    0    

0

Тестирование QA Программист Бесплатно (free)

Пентест – это не только поиск уязвимостей, но и сложный проект, в котором ошибка может привести к простою, инциденту и потере доверия заказчика. Рассказываем, как правильно определить цели и границы работ, распределить ответственность, выстроить коммуникации и сделать неизбежные риски и изменения контролируемыми. На реальных кейсах разбираем, почему задержка с сообщением о критической уязвимости способна перечеркнуть технический успех, как управленческая рамка помогла разобраться в остановке турбины и когда выход за пределы скоупа приносит пользу бизнесу, а когда становится нарушением договоренностей.

17.08.2026    1165    user2181343    0    

1

Тестирование QA Программист 1С 8.3 Россия Бесплатно (free)

Написать тест на 1С несложно. Дорого стоит привести базу в состояние, где прогон вообще стартует: семь шагов, каждый ломает запуск молча — без ошибки, без записи в журнале. И эту цену платит заново каждый новый человек на проекте. Разбираю молчаливый отказ окружения как класс проблем, показываю, почему его не закрывают ни документация, ни скрипт развёртывания, и предлагаю решение — фиксацию состояния в артефакте с машинно-проверяемым критерием приёмки. Подход проверен на сквозной задаче (первая задача экзамена «1С:Специалист по платформе» с юнит- и функциональными тестами), а затем перенесён на пул тестовых баз с типовыми конфигурациями. Отдельно — каталог симптомов и их настоящих причин, который пригодится независимо от инструментария.

13.08.2026    1527    chagbig    1    

0

Тестирование QA Программист Бесплатно (free)

Разбираем, как в крупных компаниях регуляторные требования, постмортемы и внутренние ограничения постепенно превращаются в многоуровневую систему инструкций, в которой разработчику все сложнее понять, что и когда нужно проверить. Показываем opensource-сервис внешних проверок для GitLab, который автоматизирует часть этой бюрократии и сводит результат к понятному сигналу: зеленое – все в порядке, красное – нужно обратить внимание на конкретное требование. Объясняем, как такие проверки помогают «сдвинуть влево» контроль задач и снизить риск отказа во внедрении задачи в последний момент перед релизом. А заодно смотрим, может ли связка Autumn + «Вино» + немного разработческого энтузиазма превратить обязательные инструкции в инструмент, который команда сама захочет развивать.

12.08.2026    1372    Golovanoff    2    

4