Персональная страница Федора Езеева
Главная
Download
Ссылки
MS SQL
Обмен данными
Новости
Статьи
О себе
Крупные разделы...
Коллективная разработка
1С++, OOP, XP
FuncTest
FAQ
Структура 1cv7.md

This page is under construction now. Visit it later.
Страничка находится в стадии разработки. Зайдите попозже.

В написании этого текста мне особенно помог этот пример TDD для Perl.
Так же хочу поблагодарить Кабанова Алексея AKA БТР за сообщение на itland.ru, которое значительно прояснило мое сознание.
Ну и окончательное просветление меня настигло после прочтения книги Кента Бека "Экстремальное программирование. Разработка через тестирование". Особенно помогла вторая часть, где показано, как создать набор классов для тестирования.

Пример написания юниттестов на 1С.

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

Для начала - задача. Задачу я тоже утащу у Бека, надеюсь, он на меня не обидится :) У него была задача - уметь совершать арифметические операции над суммами денег, выраженными в разных валютах. Предупреждаю сразу, что я не буду решать эту задачу до конца: моя действительная цель - просто показать, как можно писать автоматизированные тесты на 1С с помощью моих классов.

Итак. Упрощаем задачу до невозможности. Выбираем одну валюту, и одно арифметическое действие. Пусть мне надо умножить пять долларов на два, и в результате я хочу получить 10 долларов. Предыдущее предложение - практически готовый тест, осталось только записать его в нотации 1С. Создаем файлик "тестБаксы.txt" и пишем туда:

Функция Сам(Конт)
	Возврат Конт;
КонецФункции

Процедура тестУмножение() Экспорт
	Баксы = СоздатьОбъект("Баксы");
	Баксы.Количество = 5;
	Баксы.Умножить(2);
	Сам(Контекст).AssertEquals(10, Баксы.Количество);
КонецПроцедуры

Этот код мне нужно а) где-то разместить, б) откуда-то запустить. Поскольку этот код тестирует работу нашего будущего класса "Баксы" - поместим его в класс "тестБаксы". Для того, чтобы мы легко смогли его запустить, а так же легко могли получить результат выполнения этого теста - унаследуем класс "тестБаксы" от класса "ТестовыйСлучай" (входит в поставку). Вот текст файла defcls.prm на этой стадии:


class тестБаксы = тестБаксы.txt : ТестовыйСлучай
{};

Создаем обработку, при нажатии на кнопку "Сформировать" и будет происходить запуск нашего теста. Вот процедура Сформировать() файла ЗапускТестов.ert:

Процедура Сформировать()
	Тест = СоздатьОбъект("тестБаксы");
	Тест.Инит("тестУмножение");
	Тест.Запустить();
	Сообщить(Тест.Результат().Печать());
КонецПроцедуры

Тут необходимо небольшое пояснение. Первой строчкой я создал тестовый случай. Второй строчкой я сказал своему случаю, что тестовый код для него находится в методе тестУмножение(). В одном классе может находится код для нескольких тестовых случаев. Третьей строчкой я запустил свой тест. И последней строчкой я вывел результат выполнения в окно сообщений.

Тест написан и готов к запуску. Давайте посмотрим, как он сломается.

Запущено тестов: 1, успешно - 0.
Неудачная попытка создания объекта
тестБаксы::тестУмножение()
Баксы = СоздатьОбъект("Баксы");
{D:\fedor config\Back_Office_ATP\Money\тестБаксы.txt(7) }
==================================

Все понятно, у нас нету класса "Баксы". Создадим его. Вот нынешнее состояние файла defcls.prm:


class тестБаксы = тестБаксы.txt : ТестовыйСлучай
{};
класс Баксы = Баксы.txt
{};
Сохраняемся, перезапускаем 1С, запускаем тесты - у класса "Баксы" нет поля "Количество". Создаем его:
Баксы.txt:
Перем Количество Экспорт;
Еще раз запускаем - нет метода Умножить(). Создаем его.
Баксы.txt:
Перем Количество Экспорт;
Процедура Умножить(Множитель) Экспорт
КонецПроцедуры
Снова запускаем. На этой стадии срабатывает метод AssertEquals(), на котором хочется остановиться подробнее. Этот метод принимает два параметра и сравнивает их. Если они равны - все хорошо, едем дальше. Если параметры различны - метод вываливает ошибку. Тестовый случай эту ошибку обрабатывает и считает такой тест непройденным.
Для прохождения теста пишем тривиальную реализацию в метод Умножить:
Баксы.txt:
Перем Количество Экспорт;
Процедура Умножить(Множитель) Экспорт
	Количество = 10;
КонецПроцедуры

Наконец-то мы добились срабатывания теста. По науке - мы теперь должны избавиться от дублирования (число 10 нам встречается дважды: в параметре AssertEquals, а так же в коде процедуры Умножить). И хотя решение этой проблемы очевидно - я все-таки сначала напишу еще один тест. Это поможет нам увидеть, как можно работать с наборами тестов.
тестБаксы.txt:

Функция Сам(Конт)
	Возврат Конт;
КонецФункции

Процедура тестУмножение() Экспорт
	Баксы = СоздатьОбъект("Баксы");
	Баксы.Количество = 5;
	Баксы.Умножить(2);
	Сам(Контекст).AssertEquals(10, Баксы.Количество);
КонецПроцедуры

Процедура тестУмножение_2() Экспорт
	Баксы = СоздатьОбъект("Баксы");
	Баксы.Количество = 4;
	Баксы.Умножить(2);
	Сам(Контекст).AssertEquals(8, Баксы.Количество);
КонецПроцедуры
ЗапускТестов.ert:

Процедура Сформировать()
	Тест = СоздатьОбъект("тестБаксы");
	Тест.Инит("тестУмножение");
	Тест.Запустить();
	Сообщить(Тест.Результат().Печать());

	Тест = СоздатьОбъект("тестБаксы");
	Тест.Инит("тестУмножение_2");
	Тест.Запустить();
	Сообщить(Тест.Результат().Печать());
КонецПроцедуры
Первый тест по прежнему проходит, второй ломается: ожидаем 8, а получаем 10. Снова меняем реализацию метода Умножить():
Баксы.txt:
Перем Количество Экспорт;
Процедура Умножить(Множитель) Экспорт
	Количество = Количество * 2;
КонецПроцедуры

Теперь проходят оба теста. Но вот беда: они выполняются по одному. И строк результата - тоже по одной на каждый тест. Для решения этой проблемы нужно тесты скомпоновать в набор. Делается это примерно так:
ЗапускТестов.ert:

Процедура Сформировать()
	Набор = СоздатьОбъект("НаборТестов");
	Набор.Добавить("тестБаксы", "тестУмножение");
	Набор.Добавить("тестБаксы", "тестУмножение_2");
	
	Набор.Запустить();
	Набор.ПечатьРезультата();
КонецПроцедуры
Не правда ли, так и тесты запускать приятнее, и результат выглядит гораздо лучше?

Rambler's Top100 1C:TOP-100

© 1998-2004 Fedor Ezeev.

Last updated: 2005-09-05