Быстрый старт в тестировании на платформе 1С (Vanessa-ADD)

02.02.23

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

Если вы давно хотите освоить тестирование в мире 1С. Но не знали, с чего начать. Теперь знаете.
Отправная точка в применении автоматического тестирования на платформе 1С

Многие слышали про то, что в 1С есть разный набор инструментов для тестирования. И в мире 1С разработчики расходятся по разным монастырям. Одни считают, что тестирование не нужно и оно только увеличивает себестоимость разработки, и, мол, заказчик не готов за это платить, нужно сразу писать код хорошо. Другие считают, что без тестов всё сразу превратится в тыквы, и покрывают тестами все строчки кода, пытаются довести счетчик покрытия до 100%. Также есть и те разработчики, которые все могут, но им просто лень.

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

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

 
Философия

Бытует мнение, что писать тесты долго, лениво, бессмысленно и т.д. У каждого своя правда. И я расскажу свою. Для примера пофантазируем, что перед нами задача, взять документ, например "Реализация товаров" и доработать, добавив какое-нибудь поведение в проведение документа. Движения в новый регистр, пересчет суммы или неважно что еще. Как бы многие поступили в такой ситуации? Алгоритм действий, например, такой:

  1. Добавили метаданных / написали код
  2. Запустили предприятие
  3. Открыли список реализаций
  4. Нашли документ, который удовлетворяет условиям доработки/ создали новый
  5. Открыли документ
  6. Провели документ
  7. Вспомнили, что нужно в обработке проведения поставить точку останова. Поставили.
  8. Опять открыли документ, провели.
  9. Остановились на нужной точке.
  10. Проверили поведение системы
  11. Проверили в отчете о проводках, что поведение корректное.
  12. Убедились, что часть кода ведет себя так, как мы хотели. Идем в п 1.

Кто-нибудь узнал тут себя? Хорошо, кто сможет ответить, сколько будет итераций по п 2 - 12 ? А сколько времени в итоге займет вот этот поиск, открытие, проведение документа, отладка, просмотр отчета? Если задача была, скажем, на 3 часа (да, мы многие любим измерять в часах задачи). Сколько из них ушло на вот эту рутину проверки?

  1. Получит объект документ (найдет шаблон, сгенерит новый)
  2. Выполнит запись с проведением
  3. Запросом выдернет поводки документа и сравнит с ожидаемым результатом?

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

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

 
Суть без инструментария

Прежде чем мы пойдем разбираться, с какого инструмента начать тестировать, давайте попробуем понять, а что это вообще такое, написание тестов. Я не буду привязываться к какой-то конфигурации или бизнес логике. Представим, что вот есть у нас ПолезныйОбщийМодуль, в котором есть не менее полезная функция:

Функция ПолезноеСложение(Параметр1, Параметр2) Экспорт 
	Результат = Параметр1 + Параметр2;
	Возврат Результат;	
КонецФункции 

Как бы мы могли эту функцию проверить, если бы у нас не было никаких инструментов для тестирования?

Правильно, можно написать внешнюю обработку, которая бы вызывала эту функцию. И выглядел бы модуль формы примерно вот так:

&НаСервереБезКонтекста
Процедура КомандаПроверитьФункциюНаСервере()

	Параметр1 = 3;
	Параметр2 = 2;

	Результат = ПолезныйОбщийМодуль.ПолезноеСложение(Параметр1, Параметр2);

	Если НЕ Результат = 5 Тогда
		ВызватьИсключение "Результат полезного сложения не корректный";		
	КонецЕсли;

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

&НаКлиенте
Процедура КомандаПроверитьФункцию(Команда)
	КомандаПроверитьФункциюНаСервере();
КонецПроцедуры

И это чудесно, теперь с нами навсегда есть код на родном 1С. Который проверяет поведение кода. Мы всегда можем открыть обработку, нажать кнопку и узнать, как у нас работает функция. Даже спустя годы, обновления, доработки. Мы всегда можем просто открыть и проверить.

А если в ходе тестов у вас будут создаваться справочники, документы, записи регистров, то при частом запуске база начнет заполняться мусором от тестов. Тогда вы решите, что можно перед запуском теста открывать транзакцию, а после теста ее отменять. Тогда все данные, которые были изменены во время теста, будут отменены. Еще одно чудо.

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

 
Инструмент

В данной статье разговор будет идти про Vanessa-ADD. А если быть точным, про его механизм юнит-тестирования.

По сути, это набор внешних обработок, который поможет вам быстрее и меньшим кодом писать тесты. Также в нем есть механизмы по автоматическому запуску (например, батник, который сам запустит 1С, загрузит все ваши тесты из каталога, запустит и сложит результат куда вы захотите).

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

opm install add

Быстро скажу opm - это одна из утилит, которая будет установлена вместе с OneScript. Эта утилита помогает управлять библиотеками OneScript. А ключи install add запускают процесс установки библиотеки add. После выполнения команды в каталоге, где установлен OneScript, будет каталог lib/add. В этом каталоге почти аналогичный набор инструментов, который вы скачали бы со страницы релизов.

 
Первый тест

Давайте повторим предыдущий тест, но уже используя Vanessa-ADD. Создадим новую внешнюю обработку, отложим ее в отдельный каталог. И в модуль объекта вставим следующее:

Перем КонтекстЯдра;
Перем Ожидаем;

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
	
	НаборТестов.НачатьГруппу("Демо тесты");
 	НаборТестов.Добавить("ТестДолжен_ПроверитьРаботуПолезногоСложения", , "Проверка работы полезного сложения"); 
	
КонецПроцедуры

Процедура ТестДолжен_ПроверитьРаботуПолезногоСложения() Экспорт
	
	Параметр1 = 3;
	Параметр2 = 2;
	
	Результат = ПолезныйОбщийМодуль.ПолезноеСложение(Параметр1, Параметр2);
	
	Ожидаем.Что(Результат, "Результат полезного сложения корректен").Равно(5);
	
КонецПроцедуры

В данном коде много непонятного, но мы постепенно разберемся, что это все значит.

А теперь запустим предприятие, и откроем обработку Каталог_Vanessa_add/xddTestRunner.epf. Данная обработка позволяет много чего полезного, в том числе запускать тесты и просматривать результат выполнения.

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

 

 

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

 
Про кишки

В коде обработки сейчас много неизвестной магии. Я попробую объяснить, что это все значит, и доказать, что это всего лишь комбинация внешних обработок. Ничего нового и непонятного простому 1С разработчику тут нет.

Сразу оговорюсь, что тесты можно запускать как в контексте &НаСервере так и &НаКлиенте. Этот пример про тестирование серверного метода. Далее мы рассмотрим вариант тестирования клиентского метода.

Теперь по порядку.

  • В самом начале у нас объявляются две переменные, они очень важные, в них позже будут помещены очень полезные объекты.

  • Процедура Инициализация(КонтекстЯдраПараметр). В этой процедуре происходит инициализация всех необходимых значений. Тут также можно дополнить своей логикой, которая отрабатывает при загрузке ваших тестов. В параметр КонтекстЯдраПараметр передается Объект обработки Каталог_Vanessa_add/xddTestRunner.epfкоторый мы с вами открыли. Тут же происходит загрузка плагинов. Про плагины мы с вами поговорим чуть ниже, даже сделаем свой.

  • Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр). Эта процедура отвечает за добавление тестов в дерево. Тут также доступен КонтекстЯдраПараметр. Тут в набор тестов можно добавлять как имена процедур тестов, так и группы (папки) для удобства.

  • Ну и дальше можно писать процедуры, которые будут выполнять тесты. Имена этих процедур нужно добавить в НаборТестов.

Также в модуль можно добавить две процедуры, например вот с таким содержанием.

Процедура ПередЗапускомТеста() Экспорт
	НачатьТранзакцию();
КонецПроцедуры

Процедура ПослеЗапускаТеста() Экспорт
	Если ТранзакцияАктивна() Тогда
	    ОтменитьТранзакцию();
	КонецЕсли;
КонецПроцедуры

Эти процедуры будут выполнять перед и после каждого теста. В данном примере мы начинаем транзакцию перед тестом, и отменяем после. Таким трюком, мы откатываем все изменения, которые внесены в базу при работе теста.

Теперь про клиент. Давайте у нашей обработки с тестом добавим форму, и в ней напишем следующий код:

&НаКлиенте
Перем КонтекстЯдра;
&НаКлиенте
Перем Ожидаем;

&НаКлиенте
Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");         
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	
	НаборТестов.НачатьГруппу("Демо тесты. Клиент");
	
	НаборТестов.Добавить("ТестДолжен_ПроверитьРаботуПолезногоВычитания", , "Проверка работы полезного вычитания");
	
КонецПроцедуры

&НаКлиенте
Процедура ТестДолжен_ПроверитьРаботуПолезногоВычитания() Экспорт
	
	Параметр1 = 7;
	Параметр2 = 2;
	
	Результат = ПолезныйОбщийМодульКлиент.ПолезноеВычитание(Параметр1, Параметр2);
	
	Ожидаем.Что(Результат, "Результат полезного сложения корректен").Равно(5);
КонецПроцедуры

 
&НаКлиенте
Процедура ПередЗапускомТеста() Экспорт
	// код до теста		
КонецПроцедуры  

&НаКлиенте
Процедура ПослеЗапускаТеста() Экспорт
	// код после теста	
КонецПроцедуры

И тут логика аналогичная. Только &НаКлиенте. И вместо объектов обработок в параметры передаются формы этих обработок.

 

 
Проверка значений

Вы скорее всего заметили вот такую строку

Ожидаем.Что(Результат, "Результат полезного сложения корректен").Равно(5)

А сама переменная Ожидаем инициализируется каким-то плагином. На самом деле любой плагин - это такая же внешняя обработка, которая подключается самой Vanessa-ADD. И ее код можно посмотреть и изучить. Все плагины лежат в каталоге Каталог_Vanessa_add/plugins. Их там достаточно, и они предоставляют набор удобных инструментов. Очень полезно их посмотреть. Помимо обработки УтвержденияBDD, еще есть БазовыеУтверждения. Можно использовать вот так

Перем КонтекстЯдра;
Перем Утверждения;

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Утверждения = КонтекстЯдра.Плагин("БазовыеУтверждения"); // <-- Другой плагин
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
	
	НаборТестов.НачатьГруппу("Демо тесты");
 	НаборТестов.Добавить("ТестДолжен_ПроверитьРаботуПолезногоСложения", , "Проверка работы полезного сложения"); 
	
КонецПроцедуры

Процедура ТестДолжен_ПроверитьРаботуПолезногоСложения() Экспорт
	
	Параметр1 = 3;
	Параметр2 = 2;
	
	Результат = ПолезныйОбщийМодуль.ПолезноеСложение(Параметр1, Параметр2);
	
	Утверждения.ПроверитьРавенство(Результат, 5, "Результат полезного сложения корректен");
	
КонецПроцедуры

Но лично мне больше нравятся текучие утверждения УтвержденияBDD.

 
Шаблон теста

Для удобства у меня есть пустая обработка-шаблон, которую я копирую и делаю новый тест.

Модуль объекта такой обработки выглядит вот так

Перем КонтекстЯдра;
Перем Ожидаем;

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
  КонтекстЯдра = КонтекстЯдраПараметр;
  //НаборТестов.НачатьГруппу("Тесты. Сервер");
  //НаборТестов.Добавить("ТестДолжен_ПроверитьРаботуКодаНаСервере", , "Проверка работы на сервере");
КонецПроцедуры

Процедура ТестДолжен_ПроверитьРаботуКодаНаСервере() Экспорт
	
	ТестовыеДанные = 1;
	
	Ожидаем.Что(ТестовыеДанные, "Тестовые данные = 1").Равно(1);
	
КонецПроцедуры

Процедура ПередЗапускомТеста() Экспорт
	НачатьТранзакцию();
КонецПроцедуры

Процедура ПослеЗапускаТеста() Экспорт
	Если ТранзакцияАктивна() Тогда
	    ОтменитьТранзакцию();
	КонецЕсли;
КонецПроцедуры

и модуль формы:

&НаКлиенте
Перем КонтекстЯдра;
&НаКлиенте
Перем Ожидаем;

&НаКлиенте
Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
	СтроковыеУтилиты = КонтекстЯдра.Плагин("СтроковыеУтилиты");
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	
	//НаборТестов.НачатьГруппу("Тесты. Клиент", Ложь);
	//
	//НаборТестов.Добавить("ТестДолжен_ПроверитьРаботуКодаНаКлиенте", , "Проверка работы на клиенте");
	
КонецПроцедуры

&НаКлиенте
Процедура ТестДолжен_ПроверитьРаботуКодаНаКлиенте() Экспорт
	
	ТестовыеДанные = 1;
	
	Ожидаем.Что(ТестовыеДанные, "Тестовые данные = 1").Равно(1);
	
КонецПроцедуры
 
&НаКлиенте
Процедура ПередЗапускомТеста() Экспорт
			
КонецПроцедуры  

&НаКлиенте
Процедура ПослеЗапускаТеста() Экспорт
	
КонецПроцедуры
 
Сделаем свой плагин

Для закрепления понимания сделаем свой плагин. Бессмысленный и беспощадный. Предположим, у нас есть много тестов, которые очень часто должны для тестов сгенерировать справочник товаров. Сделаем плагин, который будем использовать как общий модуль для всех тестов, который будет генерировать элемент справочника.

Создадим в каталоге плагинов новую обработку Каталог_Vanessa_add/plugins/ГенераторТоваров.epf. Вся хитрость добавления плагина в правильной реализации интерфейса подключения.

Вот модуль формы плагина:

&НаКлиенте
Перем ПутьКФайлуПолный Экспорт;

&НаКлиенте
Перем КонтекстЯдра;


// { Plugin interface
&НаКлиенте
Функция ОписаниеПлагина(КонтекстЯдра, ВозможныеТипыПлагинов) Экспорт
	Возврат ОписаниеПлагинаНаСервере(ВозможныеТипыПлагинов);
КонецФункции

&НаКлиенте
Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
КонецПроцедуры

&НаСервере
Функция ОписаниеПлагинаНаСервере(ВозможныеТипыПлагинов)
	КонтекстЯдраНаСервере = ВнешниеОбработки.Создать("xddTestRunner");
	Возврат ЭтотОбъектНаСервере().ОписаниеПлагина(КонтекстЯдраНаСервере, ВозможныеТипыПлагинов);
КонецФункции
// } Plugin interface

// { Helpers
&НаСервере
Функция ЭтотОбъектНаСервере()
	Возврат РеквизитФормыВЗначение("Объект");
КонецФункции

// } Helpers

И модуль объекта:

Перем ПутьКФайлуПолный Экспорт;

Перем КонтекстЯдра;

// { Plugin interface
Функция ОписаниеПлагина(КонтекстЯдра, ВозможныеТипыПлагинов) Экспорт
	Результат = Новый Структура;
	Результат.Вставить("Тип", ВозможныеТипыПлагинов.Утилита);
	Результат.Вставить("Идентификатор", Метаданные().Имя);
	Результат.Вставить("Представление", "Генератор товаров");
	
	Возврат Новый ФиксированнаяСтруктура(Результат);
КонецФункции

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
КонецПроцедуры
// } Plugin interface

Функция СоздатьЭлементТоваров(Наименование) Экспорт 

	НовыйТовар = Справочники.Товары.СоздатьЭлемент();               
	
	НовыйТовар.Наименование = Наименование;
	НовыйТовар.Вид = Перечисления.ВидыТоваров.Товар;
	
	НовыйТовар.Записать();
	
	Возврат НовыйТовар.Ссылка;

КонецФункции // СоздатьЭлементТоваров()

Плагин готов, теперь давайте его проверим. Создадим новую обработку из шаблона, и вот такой у нее будет модуль объекта.

Перем КонтекстЯдра;
Перем Ожидаем; 
Перем ГенераторТоваров; // Объявим генератор товаров

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD"); 
	ГенераторТоваров = КонтекстЯдра.Плагин("ГенераторТоваров"); // подключим плагин с генератором товаров
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	НаборТестов.НачатьГруппу("Мой плагин");
	НаборТестов.Добавить("ТестДолжен_ПроверитьРаботуПлагинаПоСозданиюТоваров", , "Проверка работы плагина создания товаров");
КонецПроцедуры

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

Процедура ПередЗапускомТеста() Экспорт
	НачатьТранзакцию();
КонецПроцедуры

Процедура ПослеЗапускаТеста() Экспорт
	Если ТранзакцияАктивна() Тогда
	    ОтменитьТранзакцию();
	КонецЕсли;
КонецПроцедуры

Запустим тесты и убедимся, что наш плагин работает, и мы поняли, как устроены плагины в общем.

Аналогично, для контекста клиента. Если у формы плагина сделать экспортные методы, и подключив плагин на клиенте, можно вызывать эти методы.

 

Про оформление

Как вы заметили в последнем тесте, я разделил его на три условные блока Дано, Когда и Тогда. Это не обязательно, но это из подходов, где в тесте мы сначала определяем какие либо значения, потом выполняем действия и проверяем результат. Такое можете часто встретить в чужих тестах. Хорошим тоном придерживаться такой структуры.

 
Всякие лайфхаки и хитрости

Ниже я поделюсь некоторыми хитростями, которые помогут в тестировании.

 
Дополнительные данные для выполнения тестов

Некоторые тестируемые методы требуют дополнительных данных/файлов для выполнения. Например, загрузка из таблиц эксель, где метод на вход получает таблицу эксель как двоичные данные или путь до файла. Вариантов решения этой проблемы много, я перечислю несколько.

  1. Положить в общую папку тестовые данные и читать их оттуда. Очень простой вариант, но вылезают всякие минусы. Тесты привязаны к определенным путям, и если наша база в клиент-серверной архитектуре, файлы должны быть доступны и с сервера. Это порождает сложности, например запустить тесты на другом сервере, или ноутбуке разработчика.

  2. Положить файлы в макет самой обработки тестирования, из доставать из макета в самой процедуре теста.

  3. Более экзотичный метод, который иногда наиболее удобный, держать необходимые файлы рядом со обработкой и скачивать их на сервер при загрузке тестов.

Третий вариант может показаться самым непонятным, его мы и разберем. Пофантазируем, что у нас есть метод, который на основании json сообщения формирует новый товар.

Создадим новый тест, и модуль формы будет вот такой

&НаКлиенте
Перем КонтекстЯдра;

&НаКлиенте
Перем ПутьКФайлуПолный Экспорт;

&НаКлиенте
Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;                    
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
    // Эта процедура всегда выполняется при загрузке теста и на клиенте
    // Тогда мы в этой процедуре скачать нужный нам файл, который лежит рядом с тестом, и положим его во временный каталог на сервере.
	ФайлДжсон = СтрЗаменить(ПутьКФайлуПолный, "ЗагрузкаТовараИзДжсон.epf", "data.json");
	ОтправитьФайлНаСервер("data.json", ФайлДжсон);
КонецПроцедуры  

&НаКлиенте
Асинх Процедура ОтправитьФайлНаСервер(ИмяНаСервере, Путь) Экспорт 

	Обещание = НайтиФайлыАсинх(Путь, , Ложь);
	Файлы = Ждать Обещание;

	ДобавляемыеФайлы = Новый Массив;

    ОписаниеДобавляемогоФайла = Новый ОписаниеПередаваемогоФайла;
    ОписаниеДобавляемогоФайла.Имя = Файлы[0].ПолноеИмя;
    ДобавляемыеФайлы.Добавить(ОписаниеДобавляемогоФайла);

	Обещание = ПоместитьФайлыНаСерверАсинх(,,ДобавляемыеФайлы, ЭтаФорма.УникальныйИдентификатор);    
	Результат = Ждать Обещание;
	
	ЗаписатьФайлНаСервере(ИмяНаСервере, Результат[0].Адрес);
	
КонецПроцедуры

&НаСервере
Процедура ЗаписатьФайлНаСервере(ИмяНаСервере, АдресВХ)

	Файл = КаталогВременныхФайлов() + ПолучитьРазделительПути() + ИмяНаСервере;
	ПолучитьИзВременногоХранилища(АдресВХ).Записать(Файл);

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

А модуль объекта теста сделаем вот таким

Перем КонтекстЯдра;
Перем Ожидаем;

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
  КонтекстЯдра = КонтекстЯдраПараметр;
  НаборТестов.НачатьГруппу("Тесты. Сервер");
  НаборТестов.Добавить("ТестДолжен_ПроверитьЗагрузкуТовараИзДжсон", , "Проверка загрузки товара из json");
КонецПроцедуры

Процедура ТестДолжен_ПроверитьЗагрузкуТовараИзДжсон() Экспорт
	
	// Дано
    // Получим путь к файлу, который мы загрузили с клиента и запустим тест
	Файл  = КаталогВременныхФайлов() + ПолучитьРазделительПути() + "data.json";
	
	// Когда
	ПолезныйОбщийМодуль.ЗагрузитьТоварИзJSON(Файл); 
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Артикул", "000123");
	Запрос.УстановитьПараметр("Наименование", "Тестовая номенклатура");
	Запрос.Текст = "ВЫБРАТЬ
	               |	Товары.Ссылка КАК Ссылка
	               |ИЗ
	               |	Справочник.Товары КАК Товары
	               |ГДЕ
	               |	Товары.Наименование = &Наименование И Товары.Артикул = &Артикул";  
	РезультатЗапроса = Запрос.Выполнить();
	
	// Тогда	
	Ожидаем.Что(РезультатЗапроса.Пустой(), "Результат запроса не пустой").Равно(Ложь);
	
КонецПроцедуры

Процедура ПередЗапускомТеста() Экспорт
	НачатьТранзакцию();
КонецПроцедуры

Процедура ПослеЗапускаТеста() Экспорт
	Если ТранзакцияАктивна() Тогда
	    ОтменитьТранзакцию();
	КонецЕсли;
КонецПроцедуры

Вот таким нехитрым методом можно пробросить любые файлы с клиента на сервер перед запуском тестов. Можно возвести в абсолют и написать для этого универсальный плагин например.

 
Тестирование форм на сервере

Как-то у меня была старая легаси обработка, которая оперировала двумя файлами. Текстовой настройкой и таблицей эксель. Суть была такая, что пользователь выбирал настройку и файл эксель, и согласно с настройками - парсился эксель, создавались документы и справочники. И вот с завидной периодичностью на обновлениях это все часто ломалось. И боль заключалась в том, что вся логика была прописана в модуле формы. А мне очень хотелось покрыть тестами, да так красиво, с откатом созданных справочников и документов. Но как известно на сервере нельзя получить форму объекта, чтобы подергать её экспортные методы. А на клиенте транзакцию не начать. Можно было бы, конечно, переписать всю обработку, но она монструозная, чужая, и весь код сильно завязан на реквизитах самой формы, так что серверные методы копипастой не перенести куда-то. Я допускаю вмешательство в код формы, но минимальное. Чисто накидать где-то "Экспорт" при необходимости. И вот как я решил эту проблему. Конечно, весь код обработки я не буду сюда выкатывать, а смоделирую простой, но понятный пример.

Вот она, наша обработка. Два реквизита формы: наименование и артикул. И кнопка "Создать номенклатуру". Вот модуль формы.

&НаСервере
Процедура СоздатьНоменклатуруНаСервере()
	НовыйТовар(Перечисления.ВидыТоваров.Товар);
КонецПроцедуры

&НаКлиенте
Процедура СоздатьНоменклатуру(Команда)
	СоздатьНоменклатуруНаСервере();
КонецПроцедуры

&НаСервере
Процедура НовыйТовар(ВидТовара)

	НовыйТовар = Справочники.Товары.СоздатьЭлемент();
	
	НовыйТовар.Наименование = Наименование;
	НовыйТовар.Артикул = Артикул;
	НовыйТовар.Вид = ВидТовара;
	
	НовыйТовар.Записать();

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

Так вот, нужный метод далеко в недрах формы, на сервере. Да еще и зависит от реквизитов формы. Так просто к нему не добраться. Но выход есть. Первое, что нужно сделать, - обозначить метод как экспортный. Теперь осталось каким-то образом протащить эту форму в модуль объекта теста. Это, конечно, сложно, но возможно. Добавим еще один метод, и после всех издевательств модуль будет выглядеть так.

&НаСервере
Процедура СоздатьНоменклатуруНаСервере()
	НовыйТовар(Перечисления.ВидыТоваров.Товар);
КонецПроцедуры

&НаКлиенте
Процедура СоздатьНоменклатуру(Команда)
	СоздатьНоменклатуруНаСервере();
КонецПроцедуры

&НаСервере
Процедура НовыйТовар(ВидТовара) Экспорт // <-- добавили "экспорт"

	НовыйТовар = Справочники.Товары.СоздатьЭлемент();
	
	НовыйТовар.Наименование = Наименование;
	НовыйТовар.Артикул = Артикул;
	НовыйТовар.Вид = ВидТовара;
	
	НовыйТовар.Записать();

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

&НаСервере 
Процедура ЮнитТест(ИмяТеста, ИмяОбработки) Экспорт // <-- добавили грязный хак.

	ОписаниеЗащиты = Новый ОписаниеЗащитыОтОпасныхДействий;
	ОписаниеЗащиты.ПредупреждатьОбОпасныхДействиях = Ложь;
	КонтекстЯдра = ВнешниеОбработки.Создать("xddTestRunner", Ложь, ОписаниеЗащиты);
	ОбработкаТестирования = ВнешниеОбработки.Создать(ИмяОбработки, Ложь, ОписаниеЗащиты);
	ОбработкаТестирования.Инициализация(КонтекстЯдра);
	ОбработкаТестирования.ВыполнитьСерверныйТестФормы(ИмяТеста, ЭтотОбъект);

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

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

&НаКлиенте
Перем КонтекстЯдра;

&НаКлиенте
Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	
	НаборТестов.НачатьГруппу("Тесты формы на сервере");	
	НаборТестов.Добавить("ТестДолжен_ПроверитьСозданиеТовараИзФормы", , "Проверка создания товара из формы обработки");
	
КонецПроцедуры

&НаКлиенте
Процедура ТестДолжен_ПроверитьСозданиеТовараИзФормы() Экспорт
	
	ФормаЗагрузки = ПолучитьФорму("Обработка.ОченьНеудобнаяОбработка.Форма.Форма");
	ФормаЗагрузки.ЮнитТест("ТестДолжен_ПроверитьСозданиеТовараИзФормы", ИспользуемоеИмяФайла());
	
	// Тест и ассерты в модуле объекта в тесте "ТестДолжен_ПроверитьСозданиеТовараИзФормы"	
	
КонецПроцедуры

&НаСервере
Функция ИспользуемоеИмяФайла()
	Возврат РеквизитФормыВЗначение("Объект").Метаданные().Имя;
КонецФункции

Тут мы на клиенте получаем нужную форму и вызываем в ней специальный метод, в котором она в контексте сервера сама создаст экземпляр теста и передаст туда себя. Тем самым мы можем выполнить любой код с формой на сервере в тесте. А вот модуль объекта теста.

Перем КонтекстЯдра;
Перем Ожидаем;

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
 
КонецПроцедуры

Процедура ВыполнитьСерверныйТестФормы(ИмяТеста, ТестируемаяФорма) Экспорт 
	ПередЗапускомТеста();
	
	Выполнить(СтрШаблон("%1(ТестируемаяФорма)", ИмяТеста));
	
	ПослеЗапускаТеста();
КонецПроцедуры

Процедура ТестДолжен_ПроверитьСозданиеТовараИзФормы(ТестируемаяФорма) Экспорт
	
	// Дано
	Наименование = "Номенклатура теста формы";
	Артикул = "0031232";
	ТестируемаяФорма.Наименование = Наименование;
	ТестируемаяФорма.Артикул = Артикул;
	
	// Когда
	ТестируемаяФорма.НовыйТовар(Перечисления.ВидыТоваров.Товар);
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Артикул", Артикул);
	Запрос.УстановитьПараметр("Наименование", Наименование);
	Запрос.Текст = "ВЫБРАТЬ
	               |	Товары.Ссылка КАК Ссылка
	               |ИЗ
	               |	Справочник.Товары КАК Товары
	               |ГДЕ
	               |	Товары.Наименование = &Наименование И Товары.Артикул = &Артикул";  
	РезультатЗапроса = Запрос.Выполнить();
	
	// Тогда	
	Ожидаем.Что(РезультатЗапроса.Пустой(), "Результат запроса не пустой").Равно(Ложь)
	
КонецПроцедуры

Процедура ПередЗапускомТеста() Экспорт
	НачатьТранзакцию();
КонецПроцедуры

Процедура ПослеЗапускаТеста() Экспорт
	Если ТранзакцияАктивна() Тогда
	    ОтменитьТранзакцию();
	КонецЕсли;
КонецПроцедуры

На первый взгляд выглядит действительно сложно, но если подебажить, то ясность придет.

 
Подмена объектов (или мокирование)

Бывает ситуация, когда внутри метода есть какие-то объекты, поведение которых усложняет или делает невозможным тестирование. Вот, например, такой метод.

Процедура ЗагрузитьТоварыИзСервиса() Экспорт
	
	// Много
	// полезной
	// нагрузки

	Соединение = Новый HTTPСоединение("some.host.ru", 80);

	ТекстЗапроса = "api/v1/getmedata";
	Запрос = Новый HTTPЗапрос(ТекстЗапроса);
	РезультатЗапроса = Соединение.Получить(Запрос);
	
	ТекстОтвета = РезультатЗапроса.ПолучитьТелоКакСтроку();
	
	Чтение = новый ЧтениеJSON;
	Чтение.УстановитьСтроку(ТекстОтвета);
	Результат = ПрочитатьJSON(Чтение);
	
	НовыйТовар = Справочники.Товары.СоздатьЭлемент();
	
	НовыйТовар.Наименование = Результат.Наименование;
	НовыйТовар.Артикул = Результат.Артикул;
	НовыйТовар.Вид = Перечисления.ВидыТоваров.Товар;
	
	НовыйТовар.Записать();

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

Тут совсем беда, соединение с хостом захардкожено, и если сервис недоступен или там нет нужных данных, тест запустить не получится. Но выход есть, конечно, придется немного подхакать процедуру. Вот так.

Процедура ЗагрузитьТоварыИзСервиса(Соединение = Неопределено) Экспорт // <-- добавил необязательный параметр
	
	// Много
	// полезной
	// нагрузки
	
	Если Соединение = Неопределено Тогда // <-- Добавил условие
		Соединение = Новый HTTPСоединение("some.host.ru", 80);
	КонецЕсли;
	
	ТекстЗапроса = "api/v1/getmedata";
	Запрос = Новый HTTPЗапрос(ТекстЗапроса);
	РезультатЗапроса = Соединение.Получить(Запрос);
	
	ТекстОтвета = РезультатЗапроса.ПолучитьТелоКакСтроку();
	
	Чтение = новый ЧтениеJSON;
	Чтение.УстановитьСтроку(ТекстОтвета);
	Результат = ПрочитатьJSON(Чтение);
	
	НовыйТовар = Справочники.Товары.СоздатьЭлемент();
	
	НовыйТовар.Наименование = Результат.Наименование;
	НовыйТовар.Артикул = Результат.Артикул;
	НовыйТовар.Вид = Перечисления.ВидыТоваров.Товар;
	
	НовыйТовар.Записать();

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

Как бы родную логику не сломали, а добавили гибкости. Теперь в метод можно подсунуть любой объект, который будет эмулировать поведение HTTPСоединение. Перейдем к тесту.

Перем КонтекстЯдра;
Перем Ожидаем; 
Перем ТексОтвета;

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
  КонтекстЯдра = КонтекстЯдраПараметр;
  НаборТестов.НачатьГруппу("Мокирование объектов");
  НаборТестов.Добавить("ТестДолжен_ПроверитьПолучениеДанныхСервиса", , "Проверка получения данных сервиса");
КонецПроцедуры

Процедура ТестДолжен_ПроверитьПолучениеДанныхСервиса() Экспорт
	
	// Дано
	ТексОтвета = "{
                 | ""Артикул"": ""000123"",
                 | ""Наименование"": ""Тестовая номенклатура""
                 |}";
	
	//Когда
	ПолезныйОбщийМодуль.ЗагрузитьТоварыИзСервиса(ЭтотОбъект);
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Артикул", "000123");
	Запрос.УстановитьПараметр("Наименование", "Тестовая номенклатура");
	Запрос.Текст = "ВЫБРАТЬ
	               |	Товары.Ссылка КАК Ссылка
	               |ИЗ
	               |	Справочник.Товары КАК Товары
	               |ГДЕ
	               |	Товары.Наименование = &Наименование И Товары.Артикул = &Артикул";  
	РезультатЗапроса = Запрос.Выполнить();
	
	// Тогда	
	Ожидаем.Что(РезультатЗапроса.Пустой(), "Результат запроса не пустой").Равно(Ложь);

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

#Область МокСоединения

Функция Получить(Параметр) Экспорт 

	Возврат ЭтотОбъект;	

КонецФункции // Получить() 

Функция ПолучитьТелоКакСтроку(Параметр = Неопределено) Экспорт 

	Возврат ТексОтвета;		

КонецФункции // ПолучитьТелоКакСтроку()

#КонецОбласти

Процедура ПередЗапускомТеста() Экспорт
	НачатьТранзакцию();
КонецПроцедуры

Процедура ПослеЗапускаТеста() Экспорт
	Если ТранзакцияАктивна() Тогда
	    ОтменитьТранзакцию();
	КонецЕсли;
КонецПроцедуры

Вот мы и научили наш тест вести себя как HTTPСоединение. И можем протестировать процедуру в отрыве от самого сервиса.

 
Тестирование внешних обработок

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

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

&НаКлиенте
Процедура ВозвестиВКвадрат(Команда) Экспорт 
	Результат = ЧислоКСтепени * ЧислоКСтепени;
КонецПроцедуры

Конечно, там есть реквизиты и кнопка. Ну а теперь сам тест

&НаКлиенте
Перем КонтекстЯдра;
&НаКлиенте
Перем Ожидаем;

&НаКлиенте
Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	
	НаборТестов.НачатьГруппу("Тесты. Клиент");
	
	НаборТестов.Добавить("ТестДолжен_ПроверитьПоведениеФормыНаКлиенте", , "Проверка внешней обработки на клиенте");
	
КонецПроцедуры

&НаКлиенте
Процедура ТестДолжен_ПроверитьПоведениеФормыНаКлиенте() Экспорт
	
	// Дано 
	ТестируемаяФорма = ПолучитьФорму("ВнешняяОбработка.ПолезнаяВнешняяОбработка.Форма.Форма");
	ТестируемаяФорма.ЧислоКСтепени = 4;
	
	// Когда
	ТестируемаяФорма.ВозвестиВКвадрат(1);
	
	// Тогда
	Ожидаем.Что(ТестируемаяФорма.Результат, "Возведение в квадрат успешно").Равно(16);
	
КонецПроцедуры

Тут уже ничего нового, и все понятно. Давайте еще вот этот модуль внешней обработки протестируем.

Функция ВозведениеВКуб(Параметр) Экспорт 

	Возврат Параметр * Параметр * Параметр;

КонецФункции

И тест

Перем КонтекстЯдра;
Перем Ожидаем;

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
  КонтекстЯдра = КонтекстЯдраПараметр;
  НаборТестов.НачатьГруппу("Тесты. Сервер");
  НаборТестов.Добавить("ТестДолжен_ПроверитьВозведениеВКуб", , "Проверка возведения в куб");
КонецПроцедуры

Процедура ТестДолжен_ПроверитьВозведениеВКуб() Экспорт
	
	// Дано
	Обработка = ВнешниеОбработки.Создать("ПолезнаяВнешняяОбработка");
	
	// Когда
	Результат = Обработка.ВозведениеВКуб(2);
	
	// Тогда
	Ожидаем.Что(Результат, "Возведение в куб корректно").Равно(8);
	
КонецПроцедуры
 
Ожидаемые исключения

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

Процедура БесполезноеСложение(Параметр) Экспорт 

	Если Параметр > 5 Тогда
		ВызватьИсключение "Параметр должен быть меньше 5";
	КонецЕсли;

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

И тест к этому методу.

Перем КонтекстЯдра;
Перем Ожидаем;

Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
	КонтекстЯдра = КонтекстЯдраПараметр;
	Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD");
КонецПроцедуры

Процедура ЗаполнитьНаборТестов(НаборТестов, КонтекстЯдраПараметр) Экспорт
  КонтекстЯдра = КонтекстЯдраПараметр;
  НаборТестов.НачатьГруппу("Тесты. Проверка исключений");
  НаборТестов.Добавить("ТестДолжен_ПроверитьРаботуИсключений", , "Проверка выбрасываемых исключений");
КонецПроцедуры

Процедура ТестДолжен_ПроверитьРаботуИсключений() Экспорт
	
	// Дано
	ПараметрыМетода = Новый Массив;
	ПараметрыМетода.Добавить(10);
	
	// Тогда
	Ожидаем.Что(ПолезныйОбщийМодуль, "Обработка выбрасываемого исключения")
			.Метод("БесполезноеСложение", ПараметрыМетода)
			.ВыбрасываетИсключение("должен быть меньше");
	
КонецПроцедуры
 
Генерация данных

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

 
Запуск из консоли

Теперь представим, что мы сделали кучу тестов и хотим их запускать одной командой/батником. Не заморачиваясь с запуском самой 1С. Да еще и просмотреть результат в консоли. А кто-то даже отправить результат в allure. И это тоже можно. Но стоит вернуться в начало и удостовериться, что мы установили Vanessa-ADD как библиотеку OneScript.

Для автозапуска тестов 1С нам еще понадобится одна библиотека. Установить ее

opm install vanessa-runner

Теперь нам доступна команда vrunner. Она очень богатая и полезная. А сейчас нужно написать скрипт запуска тестов, и несколько файлов с настройками.

run_tests.cmd - Скрипт, который все сделает хорошо.

@chcp 65001
vrunner xunit "./tests" --reportsxunit "ГенераторОтчетаAllureXML{./build/allure-testsuite.xml}" --xddExitCodePath "./build/xddExitCodePath.txt" --clear-reports --xdddebug --testclient-additional "/iTaxi" --nocacheuse --xddConfig "xUnitParams.json"

env.json - Файл с настройками, в какой базе и под каким пользователем запускать

{
    "$schema": "https://raw.githubusercontent.com/vanessa-opensource/vanessa-runner/develop/vanessa-runner-schema.json",
    "default": {
        "--ibconnection": "/FC:\\Users\\n.ivanchenko\\Documents\\testing\\infobase",
        "--db-user": "Администратор",
        "--db-pwd": "",
        "--root": ".",
        "--workspace": ".",
        "--v8version": "8.3.20"

    },
    "xunit": {
        "--testclient": "Администратор::48223"
    }
}

xUnitParams.json - Файл с настройками, чтобы в консоли был виден ход выполнения результата тестирования.

{
	"$schema":"https://raw.githubusercontent.com/vanessa-opensource/vanessa-runner/develop/xunit-schema.json",
    "Отладка":false,
    "ВыводитьПодробноеПредставлениеОшибки": true,
    "ДобавлятьИмяПользователяВПредставлениеТеста":false,
    "ДелатьЛогВыполненияСценариевВТекстовыйФайл":true,
    "ИмяФайлаЛогВыполненияСценариев": "logs/xunit.log"
}
 
P.S.

Теперь у Вас есть все знания для того, чтобы начать тестировать. Никаких больше отговорок. Пишите тесты, думайте о тестах, когда не пишете тесты.

Кстати, в мире есть такой подход TDD, поднабив руку в написании тестов, можно его попробовать. Это интересный опыт.

Возможно, со временем будут придуманы еще разные хитрости. Их можно будет подсмотреть в моем репозитории. Также как и все обработки, которые описаны в этой статье.

тесты vanessa add xunit юнит

См. также

DevOps и автоматизация разработки Тестирование QA Программист Пользователь Платформа 1С v8.3 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет Платные (руб)

Автотесты 1С - готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарий – feature-файл, разработанный с помощью vanessa-automation. Запуск сценария выполняется интерактивно с помощью vanessa-automation или с помощью vanessa-runner в CI-системах. Доступно тестирование тонкого клиента. Поддерживаемые версии конфигураций 1С:Зарплата и Управление Персоналом 3 и версии КОРП: 3.1.30.57.

2160 руб.

05.08.2024    1289    15    1    

8

Тестирование QA DevOps и автоматизация разработки Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х Россия Бухгалтерский учет Налоговый учет Платные (руб)

Готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарии возможно использовать как для vanessa-automation, так и для СППР. Поддерживаемые версии конфигураций ERP2 и КА2: 2.5.17.113.

2400 руб.

04.07.2022    8377    38    1    

29

Тестирование QA DevOps и автоматизация разработки Программист Пользователь Платформа 1С v8.3 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Налоговый учет Платные (руб)

Автотесты 1С - готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарий – feature-файл, разработанный с помощью vanessa-automation. Запуск сценария выполняется интерактивно с помощью vanessa-automation или с помощью vanessa-runner в CI-системах. Доступно тестирование тонкого клиента. Поддерживаемые версии конфигураций 1С:Бухгалтерия предприятие 3.0 и версии КОРП: 3.0.156.30.

1800 руб.

20.01.2022    7788    19    0    

13

Облачные сервисы, хостинг Linux Тестирование QA Сервера Системный администратор Программист Платформа 1С v8.3 Бесплатно (free)

Завершающая публикация цикла "В облако на работу:.. Рецепты от Капитана", в ходе которых был собран полнофункциональный рабочий контур 1С в сети на отечественной Ред ОС. С веб-серверами, доменной авторизацией, архивированием, отказоустойчивостью и прочая, прочая... В этой статье мы определяемся с быстродействием системы, проводим нагрузочное тестирование и отпускаем ее в свободное плавание (зачеркнуто) выпускаем ее в продуктовый контур, где, конечно же, придется отлавливать ошибки, мониторить состояние и т.п.

31.10.2024    1319    capitan    0    

0

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

Поговорим про логирование в приложениях на базе 1С, рассмотрим проблемы, которые возникают при сборе информации из этих систем, и обсудим практический опыт применения внутренних и внешних инструментов для анализа логов.

21.10.2024    2804    leemuar    8    

22

Тестирование QA Системный администратор Программист Платформа 1С v8.3 Бесплатно (free)

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

30.08.2024    1297    Scorpion4eg    6    

7

Тестирование QA Программист Платформа 1С v8.3 Бесплатно (free)

Иногда возникают ситуации, когда надо развернуть тестовую базу клиента / свою на серверах Windows или Linux. Тестовые базы могут понадобиться в разных ситуациях: у клиента ошибка, на нашей базе она не воспроизводится, реализуем новый функционал и хотелось бы протестировать на Linux и т.д. А теперь представим, что это все на потоке. Что тестовых баз 1С не одна, а 20-30. И получаем проблему, что непонятно, занята она сейчас кем-то или нет. Предлагаю вариант решения этой проблемы.

28.06.2024    1519    Diversus    12    

5
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. kuntashov 463 02.02.23 14:02 Сейчас в теме
Отличная статья, фактически мини-курс, спасибо!
fatman78; NikitaIvanchenko; Torin; +3 Ответить
2. artbear 1563 02.02.23 14:30 Сейчас в теме
(0) Отличная статья, большое спасибо!

А еще Ванесса-АДД недавно научился прогонять тесты из расширений.
И давно умеет прогонять тесты из конфигураций
И даже есть смерженный ПР по запуску тестов откуда угодно - модуль объекта, менеджер объекта метаданных и т.п.
fatman78; Светлый ум; yukon; NikitaIvanchenko; +4 Ответить
3. NikitaIvanchenko 275 02.02.23 14:48 Сейчас в теме
Спасибо за отзывы. Надеюсь многим будет полезно, как первая ступенька из состояния "ничего не понятно в этих ваших тестах" в "я умею писать тесты"
4. MrWonder 650 02.02.23 14:51 Сейчас в теме
Спасибо за отличную работу 👍
NikitaIvanchenko; +1 Ответить
5. arcius_7012 212 02.02.23 15:18 Сейчас в теме
Хорошая статья, спасибо! Я бы еще добавил блок про отладку новых дымовых и про аллюру, имхо в аллюре удобнее смотреть результаты тестов.
NikitaIvanchenko; +1 Ответить
6. NikitaIvanchenko 275 02.02.23 15:24 Сейчас в теме
(5)
Спасибо за отзыв. Если поднимать тему про аллюр, то нужно рассказать и про него. Что это, как поднять. Получается очень обширно для одной статьи. И дымовые тесты это все же не совсем про юниты. Я статью позиционирую как точка входа для тех, кто совсем не знаком с тестированием. А вот когда человек войдет в тему, уже дальше сможет пойти и открыть для себя аллюр, ci\cd и прочие радости.
arcius_7012; +1 Ответить
7. arcius_7012 212 02.02.23 15:50 Сейчас в теме
(6) Справедливо) У меня дымовые и юнит смешались в одно. У нас оба вида тестов похоже пишутся через один и то же инструмент
NikitaIvanchenko; +1 Ответить
8. it-expertise 345 03.02.23 09:27 Сейчас в теме
Хорошая статья!
Спасибо вам за неё.
NikitaIvanchenko; +1 Ответить
9. maksa2005 550 03.02.23 13:09 Сейчас в теме
...
Прикрепленные файлы:
NikitaIvanchenko; +1 Ответить
10. CK3 03.02.23 13:17 Сейчас в теме
Очень круто! Статья, которую я ждал)
Никита, спасибо большое!
NikitaIvanchenko; +1 Ответить
12. NikitaIvanchenko 275 03.02.23 15:12 Сейчас в теме
(10)
👍 Если хотя бы один человек перейдет эту грань, и начнет жить с тестами. Значит я старался не зря. Спасибо за отзыв.
29. Alex_1066 23.06.23 09:11 Сейчас в теме
(12) Наверное только я не понял вот здесь: "А теперь запустим предприятие, и откроем обработку Каталог_Vanessa_add/xddTestRunner.epf". Эта обработка откуда взялась и где этот каталог? Скачал и раскрыл архив "add-develop", ладно.. раскрыл его - там папки в которых нет данной обработки.
NikitaIvanchenko; +1 Ответить
30. NikitaIvanchenko 275 23.06.23 09:21 Сейчас в теме
(29)
А вы точно качали из релизов?
Ссылка на релизы
Прикрепленные файлы:
31. Alex_1066 23.06.23 09:57 Сейчас в теме
(30) (30) Да, теперь вижу.. есть. Спасибо большое.
NikitaIvanchenko; +1 Ответить
32. NikitaIvanchenko 275 23.06.23 09:59 Сейчас в теме
(31) Успехов в тестировании 👍
33. Alex_1066 23.06.23 11:57 Сейчас в теме
(30) Теперь другая беда - платформа 8.3.9 - не пошло, не хватает языковых средств. Далее берём платформу 8.3.17, т.к. написано,что 8.3.13 - гарантированно рабочий. Тоже ошибка... Как понять на какой платформе всё это работает?
34. NikitaIvanchenko 275 23.06.23 12:12 Сейчас в теме
(33) у меня точно работало 18-23.
Можете описать контекст происходящего, ошибки, обычные или управляемый формы и тд. А лучше всего использовать коллективный разум и поспрашивать в чате https://t.me/vanessa_opensource_chat
35. Alex_1066 23.06.23 13:38 Сейчас в теме
(34) попробовал войти, но потом написало, что группа недоступна. Поэтому опять сюда... Платформа 8.3.18 Ошибка возникает при попытке "Загрузить тесты". Открываемвя папка - папка, содержащая саму обработку. Сообщение:"{ВнешняяОбработка.тесты_КомандныйИнтерфейс.Форма.Форма.Форма(349,47)}: Переменная не определена (НаправлениеПереходаКСтроке)".
36. NikitaIvanchenko 275 23.06.23 14:09 Сейчас в теме
(35) Кажется, что Вы ваши тесты положили рядом с xddTestRunner.epf, или в соседний каталог tests. И когда загружаете из каталога, там подтягиваются обработки для дымовых тестов.
Попробуйте ваши тесты, положить в отдельный каталог, который не пересекается с vanessa-add.
37. Alex_1066 23.06.23 14:41 Сейчас в теме
(36) Теперь просто при попытке открытия обработки ошибка.. по кнопке "Подробно"..
"Ошибка инициализации модуля: ВнешняяОбработка.тесты_КомандныйИнтерфейс.Форма.Форма.Форма
по причине:
{ВнешняяОбработка.тесты_КомандныйИнтерфейс.Форма.Форма.Форма(349,47)}: Переменная не определена (НаправлениеПереходаКСтроке)
ТаблицаФормы.ПерейтиКСтроке(ТекущаяСтрока, <<?>>НаправлениеПереходаКСтроке.Вверх);
{ВнешняяОбработка.тесты_КомандныйИнтерфейс.Форма.Форма.Форма(353,51)}: Переменная не определена (НаправлениеПереходаКСтроке)
Если ТаблицаФормы.ПерейтиКСтроке(ТекущаяСтрока, <<?>>НаправлениеПереходаКСтроке.Вверх) Тогда"
38. Alex_1066 23.06.23 15:11 Сейчас в теме
(36) Попробовал даже установить Oscript, и загрузить Ванессу в его каталог в C:\Program Files\OneScript\lib\add, как было описано в статье и вызвать обработку оттуда.. Результат точно такой же.. Куда ещё можно копнуть, или ткнуться?
39. NikitaIvanchenko 275 23.06.23 15:31 Сейчас в теме
(38)
Попробуйте удалить каталог smoke из Каталог_Vanessa_add/tests
40. Alex_1066 23.06.23 17:14 Сейчас в теме
(39) Удалил. Загрузилась обработка. Буду дальше двигаться.. Насколько этот удаленный каталог важен в дальнейшем?
41. NikitaIvanchenko 275 23.06.23 17:26 Сейчас в теме
(40) там обработки для запуска дымовых тестов. Если вы сейчас не планируете их запускать, то он вам не нужен. А в дальнейшем подразберетесь в каталогах, и вернёте
42. Alex_1066 23.06.23 17:46 Сейчас в теме
(41) Наконец смог запустить первый тест. Правда пришлось/нужно установить для конфигурации совместимость с версией, не ниже 8.3.12. Не понял зачем это нужно, но без этого не запускался тест - вываливался с ошибкой. Если же свойство конфигурации "Режим совместимости" стоит в значении "Не использовать", то обработка не работает. Спасибо. Сейчас уже легче.
NikitaIvanchenko; +1 Ответить
11. siamagic 03.02.23 15:10 Сейчас в теме
Чем это убожество лучше типового тестирования?
13. NikitaIvanchenko 275 03.02.23 15:15 Сейчас в теме
(11)
Например тем, что оно нравится мне ;)
14. siamagic 03.02.23 21:58 Сейчас в теме
(13) вы только минусов добавили
15. Asmody 05.02.23 14:37 Сейчас в теме
(11) всё что угодно лучше, чем ничего.
NikitaIvanchenko; +1 Ответить
18. Светлый ум 416 06.02.23 11:35 Сейчас в теме
(11) Что вы понимаете под "типовым" тестированием?
19. siamagic 06.02.23 12:50 Сейчас в теме
(18)https://its.1c.ru/db/metod8dev/content/5011/hdoc

туда же можно докидать сразу нагрузочное тестирование.
Светлый ум; +1 Ответить
20. NikitaIvanchenko 275 06.02.23 14:25 Сейчас в теме
(19)
Все же это в большей степени сценарное тестирование. И это немного другой этап разработки.
Наличие любых тестов хорошо, и сценарного, и модульного. А отсутствие тестов - плохо. Но мое мнение таково, что именно модульное максимально ближе к сознанию разработчика. Ну и по сценарному тестированию статей и видосиков много.
16. Leon29 05.02.23 19:53 Сейчас в теме
Добрый день!
Спасибо за статью. После прочтения я уже пробую на практике.
NikitaIvanchenko; +1 Ответить
17. NikitaIvanchenko 275 05.02.23 20:30 Сейчас в теме
(16)
Отлично. Приятно это прочитать!
21. susumanin 1 07.02.23 00:34 Сейчас в теме
Добрый день, расскажите вкратце как вы смотрите покрытие кода тестами?
Спасибо за статью! Пишите, пожалуйста, еще.
NikitaIvanchenko; +1 Ответить
22. NikitaIvanchenko 275 07.02.23 09:43 Сейчас в теме
(21)
Добрый день.
Наверно скажу ужасную вещь, на текущий момент мы отказались от замеров покрытия, и дымовых тестов. Но это не значит, что это не нужно и не полезно. Просто сейчас перестраиваем процессы. Хотим что бы дымовые работали не по всем формам, а только там где хотим и где это нужно. По замерам, пытаемся пойти не за абсолютными цифрами. А за конкретной помощью разработчику. Условно - какая часть в новом коде(в пул реквесте) не покрыта тестом. Возможно какие либо ветвления по условиям пропущены и т.д. Повторюсь, я преследую цель, что бы это ощущалось как естественный процесс, в котором инструменты помогают, а не тормозят бюрократией =)
А пока этот процесс в разработке, у нас одно простое правило. Новый код покрывается тестами, методы проверяются на ожидаемое поведение. Если трогаем "старый" код, тоже пишем тест. Но только на те места, которые "потрогали". Без фанатизма.
fatman78; susumanin; +2 Ответить
23. user1067792 09.02.23 12:05 Сейчас в теме
Как на практике выполняется тестирование, когда нужно протестировать большое количество методов одного объекта? Для каждого тестируемого метода добавляется ключевое слово Экспорт или есть еще какой-то хак?
Хочется вносить минимум изменений в тестируемый код и не делать все методы объекта / формы экспортными... Или это неизбежная плата за наличие тестов?
Напрашивается какой-то один экспортный метод с командой Выполнить(ИмяМетода_Параметры). Как в приведенном примере в статье: Процедура ВыполнитьСерверныйТестФормы(ИмяТеста, ТестируемаяФорма) Экспорт. Только не в модуле обработки, а в самом тестируемом объекте...
NikitaIvanchenko; +1 Ответить
24. NikitaIvanchenko 275 09.02.23 15:36 Сейчас в теме
(23)
Да, платить придется в любом случае. Серебряной пули нет, или я не знаю. Либо делать экспорт, либо как вы предложили просверлить универсальную процедуру. Или сделать расширение, в котором будет экспортная обертка над не экспортными методами. Как мне кажется, если тестируются методы основной конфигурации, то самый удобный вариант - через расширение. Но тут каждый сам выбирает, что ему удобней.
user1067792; +1 Ответить
25. charushkin 109 16.02.23 14:57 Сейчас в теме
Привет!

Храню плагины в отдельном каталоге репозитория. Хочу иметь удобный способ подключать их как при локальных прогонах, так и в CI (без копирования в папку `Каталог_Vanessa_add/plugins`).
У раннера появилась возможность подключать плагины из произвольного каталога? Если нет, то как вы прокидываете свои плагины в CI?
NikitaIvanchenko; +1 Ответить
26. NikitaIvanchenko 275 16.02.23 16:34 Сейчас в теме
(25) Плагины в отдельной репе, со своим CI, который собирает и копирует в нужный каталог.
27. VSvintsov1 17.02.23 14:14 Сейчас в теме
Vanessa Automation и Vanessa Add - чем отличаются?
NikitaIvanchenko; +1 Ответить
28. NikitaIvanchenko 275 21.02.23 16:50 Сейчас в теме
(27)
Vanessa Automation - Мощный набор инструментов для сценарного тестирования. В котором помимо тестов можно генерить всевозможные видео-инструкции с голосовой озвучкой.
Vanessa Add помимо модульных тестов, о которых эта статья, тоже позволяет разрабатывать сценарные тесты. Для обоих инструментов по сценарным тестам много статей, и видосиков на ютубе. Говорить какой из них лучше, я на себя такой ответственности брать не буду. Лучше попробовать оба, и самому определиться, что удобнее.
43. el-gamberro 57 16.04.24 17:33 Сейчас в теме
Спасибо за статью. Помогли разобраться с передачей файлов с клиента на сервер.
Если можно, то есть вопрос. Почему использованы асинхронные методы для помещения файла во временное хранилище? Я так понимаю это может быть удобно если будем перегружать несколько файлов и такой метод с ожиданием будет удобен? В любом случае, еще раз спасибо.
NikitaIvanchenko; +1 Ответить
44. NikitaIvanchenko 275 13.05.24 10:12 Сейчас в теме
(43) Так исторически сложилось =) взял пример из проекта под рукой.
45. el-gamberro 57 16.05.24 18:40 Сейчас в теме
(44) Ясно. Спасибо. Но я итоге решил не перекладывать файл с клиента на сервер, а с клиента разместить во временном хранилище, на сервере получить двоичные данные, размещать их в хранилище системных настроек и далее читать из хранилища другими тестовыми обработками. Двоичные данные удобные тем, что для них можно быстро получить СтрокаJSON для чтения методом ПолучитьСтрокуИзДвоичныхДанных().
Но как бы то ни было, еще раз спасибо за статью. Помогли настроиться и реализовать то что нужно было. :)
NikitaIvanchenko; +1 Ответить
Оставьте свое сообщение