Хочу выразить благодарность за статью so-quest . Именно она оказалась необходимым толчком для изучения xUnitFor1C, о работе с которым и пойдет речь ниже.
А так-же разработчикам xUnitFor1C за замечательный набор инструментов.
Статья не претендует на истину в последней инстанции или на руководство. Скорее наоброт - я надеюсь, что она будет раскритикована и в комментариях гуру покажут мастер-класс написания тестов.
xUnitFor1C это набор внешних обработок 1с, облегчающих, а главное, упорядочивающих тестирование. В этой статье будет использоваться только xddTestRunner.epf (тестов выполнятель).
Разрабатывается обработка для ведения логов работы робота и вывода кликабельного отчета. Дополнительной сложностью является вывод в отчет служебных сообщений, возникших в процессе работы робота (например, при проведении документов). Применим "разработку через тестирование".
Готовим окружение.
Набор тестов - это обработка, содержащаа экспортную функцию ПолучитьсписокТестов(ЮнитТестирование). В документации предложен шаблон такой обработки. Создаем её и сохраняем. Модуль обработки выглядит так:
Перем ЮТест; // ссылка на экземпляр фреймворка xUnitFor1C - объект обработки UnitTestRunner
Перем ОбработкаОбъект;
Перем ИмяФайлаВнешнейОбработки;
Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт
ЮТест = ЮнитТестирование;
ВсеТесты = Новый Массив;
ВсеТесты.Добавить("ТестДолжен_СложитьДваИДва");
Возврат ВсеТесты;
КонецФункции
Процедура ПередЗапускомТеста() Экспорт
ОбработкаОбъект = ВнешниеОбработки.Создать(ИмяФайлаВнешнейОбработки);
НачатьТранзакцию();
КонецПроцедуры
Процедура ПослеЗапускаТеста() Экспорт
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
ОбработкаОбъект = Неопределено;
КонецПроцедуры
Процедура ТестДолжен_СложитьДваИДва() Экспорт
ЮТест.ПроверитьРавенство(2 + 2, 5, "2 + 2, 4");
КонецПроцедуры
/////////////////////////////////////////////////////////
//Здесь будем писать наши тесты
ИмяФайлаВнешнейОбработки = "E:\todo1c\develop\epf\todo1c.epf";
Запускаем xddTestRunner.epf. Для меня интерфейс оказался неожиданно дружелюбным. Загружаем тесты из каталога. Проверяем. Должен появиться один тест. Тест должен провалиться. Исправляем тест.
ЮТест.ПроверитьРавенство(2 + 2, 4, "2 + 2, 4"); // ошибка исправлена
Теперь тест должен пройти успешно.
Цикл разработки.
1) Создаем неработающий тест
Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт
...
ВсеТесты.Добавить("ТестДолжен_ДобавитьЗадачу");
...
КонецФункции
Процедура ТестДолжен_ДобавитьЗадачу() Экспорт
ОбработкаОбъект.ДобавитьЗадачу("Пройти первый тест");
ЮТест.ПроверитьРавенство(ОбработкаОбъект.СписокЗадач.Количество(), 1, "Задача не добавлена");
КонецПроцедуры
Перезагружаем список тестов, проверяем тестов теперь 2 и второй провалился.
2) Делаем ровно столько, чтобы тест прошел успешно.
Содаем табличную часть в обработке с полями "выполнена" и "текст".
Добавляем в модуль
Процедура ДобавитьЗадачу(ТекстЗадачи) Экспорт
НоваяЗадача = СписокЗадач.Добавить();
НоваяЗадача.Выполнена = Ложь;
НоваяЗадача.Текст = ТекстЗадачи;
КонецПроцедуры
Проверяем, что тест прошел.
3) Рефакторинг.
При таком подходе код сразу покрыт тестами, и его можно менять, не боясь, что у изменений будут "неучтенные последствия".
Согласно TDD шаги 1,2,3 постоянно повторяются, причем длительность итерации должна быть как можно меньше.
Независимость тестов.
Для обеспечения независимости предусмотрены следующие процедуры:
Процедура ПередЗапускомТеста() Экспорт
ОбработкаОбъект = ВнешниеОбработки.Создать(ИмяФайлаВнешнейОбработки);
НачатьТранзакцию();
КонецПроцедуры
Процедура ПослеЗапускаТеста() Экспорт
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
ОбработкаОбъект = Неопределено;
КонецПроцедуры
При необходимости повторить...
1) Тест
Процедура ТестДолжен_ВыполнитьЗадачу() Экспорт
ОбработкаОбъект.ДобавитьЗадачу("Пройти второй тест");
ЮТест.ПроверитьРавенство(ОбработкаОбъект.СписокЗадач[0].Выполнена, Ложь, "Задача создана выполненной");
ОбработкаОбъект.ВыполнитьЗадачу(0);
ЮТест.ПроверитьРавенство(ОбработкаОбъект.СписокЗадач[0].Выполнена, Истина, "Задача не выполнена");
КонецПроцедуры
2) Реализация
Процедура ВыполнитьЗадачу(ИндексЗадачи) Экспорт
СписокЗадач[ИндексЗадачи].Выполнена = Истина;
КонецПроцедуры
При необходимости повторить снова..
Полностью процесс написания можно посмотреть по коммитам в репозитории на github
https://github.com/Alienjob/todo1c/commits/master
Не нашел как сделать скачивание бесплатным, так что в том репозитории есть и приложенный к статье архив.
Спасибо за внимание, надеюсь найдутся люди которые после этой статьи примут на вооружение описанные принципы и мир станет чуточку лучше.
P.S.: Кто здесь?
Когда появляется вопрос "как составить запрос", "как сделать печатную форму", ответ тут же находится. В конце концов, можно посмотреть, как это сделано в типовой конфигурации. Но когда появились вопросы "А что же мне писать в тесты? А как тестировать отчеты? А управляемые формы? А запись в базу?" в типовых конфигурациях ответов я не нашел. Ну и пришлось изобретать свои костыли..
Но ведь кто-то уже применяет эти подходы (раз кто-то написал xddTestRunner). Наверное этот кто-то сталкивался со многими трудностями и решил их. Поэтому на случай, если кому-то захочется выговориться, приложил еще одну обработку, в которой не всё так гладко и красиво получилось. Надеюсь на конструктивную критику и ссылки на почитать. =)