Как писать тесто пригодный код на языке платформы 1С:Предприятие - leoniv/ass_tests GitHub Wiki
Как писать тесто-пригодный код на языке платформы 1С:Предприятие
В этом материале речь пойдет о том как писать код на языке платформы 1С:Предприятие который будет пригоден для его Unit-тестирования. Здесь не будет примеров кода, а лишь только общие рекомендации которые автор может дать на основании своего личного опыта модульного тестирования при разработке приложений для платформы 1С:Предприятие.
Описанное ниже, должно сделать ваш код не только более пригодным с точки зрения его автоматического тестирования, но и более чистым с точки зрения общего понятия о запахах кода.
Функции
и никогда Процедуры
Всегда - Забудьте слово
Процедура
пишите только функции - Ни когда не возвращайте значения через параметры
- Возвращайте из функции осмысленное значение
- Если надо вернуть множество значений верните структуру
Забыв слово Процедура
вы упростите жизнь себе когда начнете писать тесты или динамически создавать вызовы подпрограмм. Даже процедуры-обработчики которые генерирует среда разработки 1С:Предприятие (которая названа идиотским словом Конфигуратор
), такие как ПередЗаписью
, ПриИзмененииСтроки
и т.п., переделывайте в функции.
Даже если ваша функция, с точки зрения бизнес логики, не должна возвращать значения, все равно верните какое-нибудь значение для теста. Какое это будет значение зависит от ситуации, главное что бы по нему тест мог проверить поведение вашей функции.
Более того, отказ от возврата значений через параметры, в совокупности с использованием подпрограмм-функций дает еще ряд преимуществ и упрощает ваш код. На пример становится проще создавать динамические вызовы (мета-программировать). Теперь для динамического вызова вам нужен простой и боле безопасный, в сравнении с методом Выполнить
, метод Вычислить
и вы не будете извращаться по поводу того как вернуть значения, которые передал в параметрах, вызванный в eval
-е метод.
Вызов исключения против возврата булева значения
Функция это то, что делает полезную работу и возвращает результат своей работы. Забудьте про стиль языка Си в котором не было исключений и приходилось из функции возвращать 0 или 1, а результат работы функции передавать в параметрах.
Если ваша функция не булева то она обязана вернуть не булево значение. Тогда как проверить, что функция отработала правильно и можно двигаться дальше?- спросите вы. Ответ прост. Если что-то пошло не так вызовите исключение.
Для того, чтобы это работало типизируйте исключения, напишите в документации к вашей функции какое исключение от неё ожидать и если функция которая вызывает исключение это часть приватной реализации другой, публичной (экспортной) функции, тогда напишите это еще и в документации к экспортной функции.
Это дает возможность, более точно, тестировать поведение кода через ожидание исключительной ситуации, против мало значимого true|false
.
Типизируйте ваши исключения
Унылая платформа 1С:Предприятие, не позаботилась о том чтобы у программиста была возможность типизировать объекты порождаемые словом ВызватьИсключение
с целью более строгого описания исключительной ситуации. Но можно это обойти строя по определенным правилам текст сообщения и помечая его некими ключевыми словами.
Для того, чтобы это надежно работало, вам скорее всего понадобится написать некий API для типизации исключений, но это уже другая история.
Функция должна быть Атомарна
Атомарна - это значит простая, с точки зрения ветвления, короткая, делающая небольшую часть работы. Только одна обязанность должна быть у функции. Это очень важно!
Лично мне, становится дурно когда я вижу двойные, тройные и более, вложения условных операторов.
Типичный пример - обработка коллекции. Это действие состоит из двух действий: обход коллекции и обработка элемента. В том случае, когда обработка элемента это сложное действие, вынесите это действие в отдельную функцию.
Другой типичный пример, это запрос в базу данных с последующей его обработкой. В этом случае имеем, как минимум, три действия: запрос, обход коллекции, обработка элемента. Я бы еще выделил четвертое действие, это - формирование текста запроса. Если текст вашего запроса примитивен, тогда это действие можно выполнить в функции выполняющей запрос. Если ваш запрос сложный то надо уже задуматься о выносе его в отдельную функцию. Ну, а если, это динамически-формируемый текст запроса тогда вы просто обязаны вынести это действие в отдельную функцию.
Что делать с длинными условиями типа case
или для 1С если-иначеесли ... конецесли
. Тут подход должен быть творческий. Нo сперва надо проанализировать почему получается такой длинный кейс, может в нем перемешано теплое с мягким ;)?
Пишите проще и понятнее условия в условных оператрорах
Если условие вашего ветвления(цикла) сложное, вынесите его в отдельную функцию и дайте этой функции осмысленное имя. Так же стоит это сделать если не очевиден его смысл, то-есть вместо комментария возле условия, вынесите условие в функцию и напишите документацию к этой функции.
Ни когда не создавайте глобальные модули
Я не знаю пользы от глобальных модулей, а только один вред, но с точки зрения тесто-пригодности, глобальный модуль невозможно заменить тест-дублером, даже если вы научились замокивать модули с помощью механизма расширений платформы 1С:Предприятие.
Архитектура приложения
Стройте ваше приложение так, чтобы можно было вызвать функции в тестах изолированно. На сколько это можно реализовать на платформе 1С, вопрос другой. Если вы перемешаете логику, например транспорта сообщений с логикой формирования сообщений, то вам сложно будет вызвать логику формирования сообщений изолированно от транспорта, логика которого может требовать сложного окружения. "Слоистая" архитектура приложения делает его, кроме прочего, более тесто-пригодным.