Тестер: частые вопросы

Программирование - Практика программирования

тесты тестирование сценарий TDD BDD

141
Ошибкам бой - тесты норма жизни!

Приветствую, друзья!
Искренне надеюсь, что разгар лета не застал вас в офисе, или хотя бы сбавил обороты трудовой рутины. Со мной случилось второе, и в высвободившееся время, мне удалось собрать заметки, частично готовый материал, всё скомпоновать и оформить статью.
Предлагаю вашему вниманию подборку вопросов по системе тестирования Тестер (https://github.com/grumagargler/tester). Прошлая публикация была длинною в небольшой роман, поэтому развитие темы в ключе вопрос-ответ, стало неизбежным. Хочу верить, что этот труд будет служить шпаргалкой для бывалых, хорошим справочником для новичков, и возбудителем интереса к теме тестирования, невольного читателя.

Содержание

Тестирование приложения

Почему выдаются ошибки при воспроизведении ранее записанного сценария через «микрофончик»?

Эта проблема вызывает наибольшее удивление, при начале работы с механизмами тестирования, и нередко отбивает охоту продолжать. Да, к сожалению, платформа не позволяет в полной точности записать, и как следствие – воспроизвести все действия пользователя. Это проблема/особенность уровня платформы, имеет место в любых системах тестирования и может воспроизводиться даже на простых сценариях.

Однако, с практической точки зрения, реальные сценарии не пишутся прокликиванием (записью действий). Человек не в состоянии стабильно и безошибочно, накликать последовательность из 30+ шагов. Кроме этого, такие «накликанные» сценарии получаются очень громоздкими, потому что включают в себя много служебной информации и действий, не имеющих практического смысла с точки действий пользователя.

Совет тут такой: используйте микрофон для записи коротких временных сценариев, или для изучения модели тестируемого приложения. Реальные сценарии, разрабатывайте кодом, используя специально разработанное API Тестера.

Как открыть внешнюю обработку или обратиться к меню Файл / Открыть?

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

Возможны следующие варианты решения проблемы.

Вариант 1.

Использование промежуточной, внешней обработки.

Алгоритм действий следующий:

  1. В Тестере, в Меню быстрые функции / Скачать Worker.epf, скачиваем обработку Worker.epf
  2. В тестируемом приложении, открываем эту обработку, вручную
  3. В Тестере, для открытия целевых внешних обработок, используем тест Тестер.ОткрытьОбработку (тест находится в репозитории общих тестов по ссылке https://github.com/grumagargler/CommonTests). Как загружать тесты, см. здесь.

Пример использования:

Подключить ();
ЗакрытьВсё ();

// Открываем внешнюю обработку
путь = "c:\ПечатьДокументаЗаказПокупателя.epf";
Вызвать ( "Тестер.ОткрытьОбработку", путь );

Обратите внимание, метод ЗакрытьВсё закроет всё, но обработку Worker.epf оставит открытой.
Таким образом, достаточно Worker.epf открыть лишь однажды, и продолжить разработку
целевой обработки без необходимости постоянной загрузки промежуточной обработки Worker.epf.

Вариант 2.

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

Вариант 3.

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

Для этой цели можно использовать общий тест Тестер.Запустить, см. пример:

п = Вызвать ( "Тестер.Запустить.Параметры" );
п.Пользователь = "Администратор (ОрловАВ)";
п.База = "ERP Управление предприятием 2 (демо)";
п.Обработка = "C:\Users\Dmitry\Desktop\МояОбработка.epf";
Вызвать ( "Тестер.Запустить", п ); // Окно безопасности будет подавлено

Как при пометке на удаление элемента из формы списка определить, что элемент уже помечен на удаление?

// По тексту в диалоге определяем, помечается элемент или снимается пометка
этоУдаление = Найти ( Получить ( "!Поле1", "1?:*" ).ТекстЗаголовка, "Пометить" ) = 1;
если ( этоУдаление ) тогда
    Нажать ( "Да", "1?:*" );
иначе
    // Элемент уже помечен на удаление
конецесли;

Как нажать на кнопку Открыть?

Здесь ( "Заказ клиента ДС*" );

// Первый способ
Получить ( "#Партнер" ).Открыть ();

// Второй способ
Получить ( "Основное / Клиент" ).Открыть ();

Как нажать на кнопку Создать?

Здесь ( "Заказ клиента ДС*" );

партнер = Фокус ( "#Партнер" );
партнер.Создать ();

Как установить значение поля-переключателя (радиобаттона)?

Для того, чтобы изменить значение такого поля:

можно воспользоваться следующим кодом:

// Вариант 1
Установить ( "Gender", "Female" );

// Вариант 2
Установить ( "!Sex", "Female" ); // Sex в данном случае является именем реквизита формы

Еще один пример, конфигурация УТ11, справочник Склады и магазины:

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

Установить ( "!ТипСкладаОптовый", "Оптовый склад" );

Пример для конфигурации Розница 2.2:

Установить ( "!ПереключательТиповПО", 1 );

Как быстро проанализировать оптимальность проделанных в программе изменений?

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

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

Как выбрать из меню, которое формируется программно, методом ПоказатьВыборИзМеню?

Для этой задачи нужно использовать метод тестируемой формы ВыполнитьВыборИзМеню ().

Пример:

Здесь ( "Документы" );
Нажать ( "!ФормаСоздатьДокумент" );
ТекущийОбъект.ВыполнитьВыборИзМеню ( "Создать документ" );

Как перейти к строке таблицы по значениям нескольких колонок?

Допустим, у вас есть такой список:

И требуется в нем перейти к строке с клиентом “Инвема”  и “% оплаты” = 100%. Для решения этой задачи нужно использовать метод ПерейтиКСтроке объекта ТестируемаяТаблицаФормы.

Пример:

Здесь ( "Заказы клиентов" );

список = Получить ( "!Список" );
список.ПерейтиКПервойСтроке (); // Хотим найти строку начиная с начала списка

поиск = новый Соответствие ();
поиск.Вставить ( "Клиент", "Инвема" ); // Клиент - название колонки, Инвема - искомое значение
поиск.Вставить ( "% оплаты", "100" );

перешли = список.ПерейтиКСтроке ( поиск );
если ( не перешли ) тогда
	вызватьисключение "Не удалось перейти к заказу";
конецесли;

// Важно:
// Искомые значения должны быть в точности такими, как в таблице.
// Например "100.00" в колонке "% оплаты" найдено не будет.
// Учитывайте эти особенности, особенно когда работаете с разными форматами дат и чисел

Подробнее о методах объекта ТестируемаяТаблицаФормы смотрите в синтаксис помощнике конфигуратора.

Как проверить результат проведения документа?

Существует как минимум две стратегии проверки результатов проведения документов.

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

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

Техника работы с шаблонами и тестированием бизнес-логики описана здесь.

Для получения определенности тестирования, нужна правильная архитектура сценария и настроенное окружение. Подробнее см. Внедрение / Структура сценария.

Как определить количество строк в таблице?

Для этого можно использовать тест-метод Таблица.Количество, пример работы с которым показан ниже:

таблица = Получить ( "!Товары" );
количество = Вызвать ( "Таблица.Количество", таблица );
если ( количество = 0 ) тогда
	Стоп ( "Таблица товаров пустая!" );
конецесли;

Данный тест-метод находится в поставляемой с Тестером демонстрационной базе.

Почему переход к строке таблицы не всегда заканчивается успешно?

Такое может происходить в случае поиска строки в связанной таблице. Например, вы переходите к строке в Таблица 2, но Таблица 2 зависит от Таблица 1. При этом зависимость определяется в процедуре ПриАктивацииСтроки, Таблица 1, через использование отложенной процедуры заполнения (ПодключитьОбработчикОжидания) второй таблицы.

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

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

Кстроке ( "!Таблица1", "Клиент", "ТОО Ромашка" );
Пауза ( 1 ); // подождем, пока сформируются записи во второй таблице
Кстроке ( "!Таблица2", "Товар", "Датчик давления" );

Как выбрать значение в поле с составным типом?

Допустим у вас есть форма и на ней реквизит Документ, тип которого составной:

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

форма = Здесь ( "Моя форма" ); // Измените на заголовок вашей формы

// Выбираем документ
Выбрать ( "!Документ" );

// Фокусируемся на окне выбора типа данных
Здесь ( "Выбор типа данных" );

// Выберем нужным нам тип
КСтроке ( "!TypeTree", "", "Заказ на перемещение" );
Нажать ( "!OK" );

// Откроется форма списка, сфокусируемся на ней
Здесь ( "Заказы на перемещение товаров" );

// Выберем нужный нам документ
КСтроке ( "!Список", "Номер", "ТД00-000008" );
Нажать ( "!ФормаВыбрать" );

// Вернемся к нашей изначальной форме
Здесь ( форма );

Как нажать на ссылку в навигационной панели формы?

Допустим, у вас стоит задача нажать на ссылку в навигационной панели формы, как показано на картинке:

Для решения этой задачи можно применить следующий код:

Здесь ( "Строка заявки *" );

Нажать ( "Схема", ПолучитьСсылки () );

Подробнее о методе ПолучитьСсылки () читайте здесь.

Как сверить отчет со справочником?

Допустим, у вас стоит задача сверить два объекта.

Предположим, первым объектом будет отчет по остаткам товаров, вторым – справочник Номенклатура.

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

Данный тест разрабатывался для конфигурации ERP2, учет по характеристикам не ведется.

Подключить ();
ЗакрытьВсё ();

// Открываем справочник
Коммандос ( "e1cib/list/Справочник.Номенклатура" );
товары = Здесь ( "Номенклатура" );
// Динамический список. Если в ваших условиях он другой
// тогда просмотрите Тестером структуру таблиц формы списка и укажите нужную
список = Получить ( "!СписокРасширенныйПоискНоменклатура" );

// Открываем отчет и формируем его
Коммандос ( "e1cib/app/Отчет.ОстаткиИДоступностьТоваров" );
отчет = Здесь ( "Остатки и дост*" );
Нажать ( "Сформировать" );
Пауза ( 5 );

// Определяем параметры и начинаем сверять отчет по справочником
отчет = Здесь ( "Остатки и дост*" );
табдок = Получить ( "!ОтчетТабличныйДокумент" );
строка = 9; // первая значимая строка отчета
колонкаТовар = 2;
колонкаИтого = 1;
колонкаАртикул = 1;
// Якорь отчета
конец = "Итого";
// Если 5 раз товар пустой - выйдем из цикла, чтобы тест не выполнялся бесконечно
естьТовар = 5;
пока ( естьТовар ) цикл
	адрес = "!ОтчетТабличныйДокумент[R" + Формат ( строка, "NG=" ) + "C";
	ячейкаТовар = адрес + колонкаТовар + "]";
	товар = Взять ( ячейкаТовар );
	если ( товар = "" ) тогда
		ячейкаИтого = адрес + колонкаИтого + "]";
		если ( конец = Взять ( ячейкаИтого ) ) тогда
			прервать;
		конецесли;
		естьТовар = естьТовар - 1;
	иначе
		перешли = КСтроке ( список, "Наименование", товар );
		если ( перешли ) тогда
			артикулВОтчете = Взять ( адрес + колонкаАртикул + "]" );
			// Артикул определяется по идентификатору колонки. В вашем случае, если используется
			// другая таблица, идентификатор может быть другой. Анализируйте Тестером.
			артикулВСправочнике = Взять ( "!СписокРасширенныйПоискНоменклатураАртикул", список );
			если ( артикулВОтчете <> артикулВСправочнике ) тогда
				Стоп ( "Артикул в отчете для товара " + товар + " не совпадает со справочником" );
			конецесли;
		иначе
			Стоп ( "В отчете товар " + товар + " есть, а в справочнике нет" );
		конецесли;
		естьТовар = 5;
	конецесли;
	Сообщить ( товар );
	строка = строка + 1;
конеццикла;
если ( не естьТовар ) тогда
	Стоп ( "Не смогли определить конец отчета!" );
конецесли;

Как тестировать одновременно несколько запущенных приложений под разными пользователями?

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

Эту задачу можно решить несколькими способами:

  1. Запускать и тестировать приложение(я) одно за другим
  2. Запустить сразу нужное количество приложений, и затем, переключаясь между ними, выполнять нужные сценарии

Оба случая основываются на запуске тестируемого приложения из Тестера, для этого можно воспользоваться общим сценарием, входящим в состав общих тестов (https://github.com/grumagargler/CommonTests), следующим образом:

// ***************************************
// Запуск 1С в режиме клиента тестирования
// ***************************************

// Определяем параметры запуска
п = Вызвать ( "Тестер.Запустить.Параметры" );
// Название ИБ в списке информационных баз 1С-стартера
п.База = "ERP Управление предприятием 2 (демо)";
// Пользователь ИБ
п.Пользователь = "Администратор (ОрловАВ)";
// Порт, на котором будет принимать команды тестируемое приложение
п.Порт = 1538;
// Другие параметры, при необходимости
п.Параметры = "/LRU"; // Язык интерфейса
// Максимальное время ожидания запуска. Если приложение запуститься быстрее
// тест сразу же будет продолжен, не дожидаясь окончания 30 секунд.
п.Ждать = 45;
// Запускаем приложение
Вызвать ( "Тестер.Запустить", п );

// ********************************************
// Подключение Тестера к запущенному приложению
// ********************************************

// Подключаемся к порту 1538, там нас ждут
Подключить ( , 1538 );
// Эта команда уже будет выполнена в контексте запущенного на 1538 порту приложения
ЗакрытьВсё ();

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

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

Для разнообразия вариантов, пример ниже показывает, как можно запустить два разных приложения, и в каждом из них, закрыть окна, и выполнить другие операции:

// Порты запуска приложений
портЕРП = 1538;
портБух = 1539;

// Мы хотим, чтобы Тестер фотографировал ошибки каждого приложения
// даже если их окна будут перекрывать друг друга. Маска поиска задается
// регулярным выражением. Поиск производится по заголовку главного окна
скриншотыЕРП = "Демонстрационная база / 1С:ERP.+";
скриншотыБух = "Демонстрационная база / Абдулов.+";

// ******************
// Запуск ERP
// ******************

п = Вызвать ( "Тестер.Запустить.Параметры" );
п.База = "ERP Управление предприятием 2 (демо)";
п.Пользователь = "Администратор (ОрловАВ)";
п.Порт = портЕРП;
п.Параметры = "/LRU"; // Язык интерфейса
п.Ждать = 45;
Вызвать ( "Тестер.Запустить", п );

// ********************
// Запуск Бухгалтерии
// ********************

п.База = "Бухгалтерия предприятия КОРП (демо)";
п.Пользователь = "Абдулов (директор)";
п.Порт = портБух; // Другой порт
Вызвать ( "Тестер.Запустить", п );

// ***********************************
// Работаем с запущенными приложениями
// ***********************************

// Системный параметр, задает маску поиска приложения по его заголовку
ScreenshotsLocator = скриншотыЕРП;

// Закроем окна в ЕРП
Подключить ( , портЕРП );
ЗакрытьВсё ();
Отключить ();

// Закроем окна в Бухгалтерии
ScreenshotsLocator = скриншотыБух;
Подключить ( , портБух );
ЗакрытьВсё ();
Отключить ();

// Откроем в ЕРП справочник номенклатура
ScreenshotsLocator = скриншотыЕрп;
Подключить ( , портЕРП );
Коммандос ( "e1cib/list/Справочник.Номенклатура" );

// Делаем что-то еще
// .....

// ***********************
// Закрываем приложения
// ***********************

Подключить ( , портЕРП );
Отключить ( истина ); // Параметр истина - приложение будет закрыто

Подключить ( , портБух );
Отключить ( истина );

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

Как открыть записи регистра с отбором по регистратору?

Для решения этой задачи можно воспользоваться общим тестом Общее.Найти.

В примере ниже, открывается список регистра накопления, и устанавливается отбор по номеру документа:

Подключить ();
ЗакрытьВсё ();

Коммандос ( "e1cib/list/РегистрНакопления.НДСЗаписиКнигиПокупок" );
Здесь ( "НДС Покупки" );

п = Вызвать ( "Общее.Найти.Параметры" );
п.Где = "Регистратор";
п.Что = "ТД00-000043"; // Номер документа. Предварительно, может быть получен методом Взять ()
п.Кнопка = "#ФормаНайти";
п.Как = 0; // По началу строки

Вызвать ( "Общее.Найти", п );

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

Как выполнить запрос к базе данных тестируемого приложения?

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

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

конектор = новый COMОбъект ( "V83.COMConnector" );
база = "File='C:\Users\Dmitry\Documents\1C\DemoEnterprise20'";
//база = "Srvr='localhost';Ref='DemoEnterprise20'"; // для базы на сервере
пользователь = "Администратор (ОрловАВ)";
соединение = конектор.Connect ( база + ";Usr='" + пользователь + "'" );
источник = соединение.NewObject ( "Запрос" );
источник.Text = "
|выбрать Записи.СуммаБезНДС как Сумма, Записи.НДС как НДС
|из РегистрНакопления.НДСЗаписиКнигиПродаж как Записи
|где Записи.Регистратор ссылка Документ.РеализацияТоваровУслуг
|и выразить ( Записи.Регистратор как Документ.РеализацияТоваровУслуг ).Номер = &Номер
|";
номер = "ДС00-000002";
источник.УстановитьПараметр ( "Номер", номер );
данные = источник.Выполнить ().Выгрузить ();
запись = ? ( данные.Количество () = 0, неопределено, данные.Получить ( 0 ) );
если ( запись = неопределено ) тогда
	Стоп ( "Отсутствуют записи в регистре НДС с продаж по РН№ " + номер );
конецесли;

сумма = 52190;
ндс = 9394.20;

если ( запись.Сумма <> сумма
	или запись.НДС <> ндс ) тогда
	Стоп ( "Неверная запись в регистре НДС с продаж по РН№ " + номер );
конецесли;

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

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

Пример:

п = новый Структура ();
соединение.АвтоматическоеЗаполнениеОтчетности.ОписаниеПоказателей_РасчетПоНалогуНаПрибыль_2015Кв1 ( п );

Как локализовать ошибку выполнения сценария при групповом запуске тестов?

Иногда возникают ситуации, когда запуск сценария в ручном режиме происходит успешно, но при этом, групповой (ночной) запуск сценариев – выдает ошибку.

Для локализации подобных проблем, можно использовать условную отладку сценария.

В примере ниже, показано, как включить условную отладку, если выполняемое сценарием действие по каким-то причинам не выполняется:

попытка
	Ввести ( "!МоеЧисловоеПоле", 10 );
исключение
	// Если что-то пошло не так,
	// с этого места Тестер начнет отладку
	// и будет ждать действий пользовтеля
	ОтладкаСтарт ();
конецпопытки;

Почему отчет Сводка дает неверное (завышенное) время выполнения сценариев?

Такая ситуация может возникать при вызове сценариев сценариями.

Например, у нас есть Сценарий1, который вызывает Сценарий2. Если Сценарий1 и Сценарий2 являются обычными сценариями (о типах сценариев см. здесь), тогда время выполнения Сценарий1, справедливо будет включать в себя время выполнения Сценарий2. В свою очередь, отчет Сводка, корректно покажет продолжительность выполнения обоих сценариев по отдельности, но в сумме, время будет неверным, потому что сценарии включены друг в друга.

Технически, Тестер не ограничивает программиста в выборе типа вызываемого сценария. Однако, имеет смысл придерживаться следующей рекомендации: если вы вызываете сценарий, значит он “зависимый” или скоро таким станет. В этом случае, все сценарии, которые вызываются, лучше делать методами или библиотечными сценариями.

Если придерживаться такого правила, отчет Сводка отфильтрует служебные (сценарии-методы) и выдаст корректный результат по сумме времени выполнения всех тестов.

Как проверять права доступа (или их отсутствие) к объектам?

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

Например, ваш тест может запустить тестируемое приложение с предопределенным пользователем, у которого не должно быть прав на некоторый перечень объектов, пример кода ниже:

// Подключение к уже запущенному приложению
// Для запуска приложения, см. общий тест Тестер.Запустить
Подключить();

объекты = "Номенклатура,Контрагенты";
если ( ошибкаДоступа ( "Справочник", объекты, ложь ) ) тогда
	Стоп ( "Возникли ошибки доступа. Детали см. в журнале ошибок" );
конецесли;

Функция ошибкаДоступа ( Тип, Список, ДоступДолженБыть )

	ошибки = ложь;
	для каждого объект из СтрРазделить ( Список, "," ) цикл
		ЗакрытьВсе();
		Коммандос ( "e1cib/list/" + Тип + "." + объект );
		окноОшибки = Дождаться ( "1?:*" );
		если ( окноОшибки ) тогда
			форма = Здесь ( "1?:*" );
			надпись = форма.НайтиОбъект ( , "Недостаточно прав *" );
			если надпись = неопределено тогда
				ЗаписатьОшибку ( "Какая-то ошибка при открытии объекта <" + объект + ">" );
			иначе
				если ( ДоступДолженБыть ) тогда
					ЗаписатьОшибку ( "Недостаточно прав на объект <" + объект + ">" );
					ошибки = истина;
				конецесли;
			конецесли;
			Закрыть ( форма );
		иначе
			если ( не ДоступДолженБыть ) тогда
				ЗаписатьОшибку ( "Прав доступа на объект <" + объект + "> быть не должно" );
				ошибки = истина;
			конецесли;
		конецесли;
	конеццикла;
	возврат не ошибки;
	
КонецФункции

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

Данный код не является законченным решением, но демонстрирует подход к решению задач такого класса.

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

Как узнать состояние флажка (галочки) на форме, перед тем как принять решение нажимать на него или не нажимать?

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

флаг = Взять ( "!ЭтоУслуга" );
если ( флаг = "Ложь" ) тогда
	Нажать ( "!ЭтоУслуга" );
конецесли;
// Здесь мы точно уверены, что флаг Услуга включен

Как узнать, изменился ли заголовок тестируемой формы?

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

форма = Здесь ( "Мой заголовок формы *" );
заголовок = форма.ТекстЗаголовка;
// ... какие-то действия, которые могут привести к изменению заголовка
новыйЗаголовок = форма.ТекстЗаголовка;
если ( новыйЗаголовок <> заголовок ) тогда
	Стоп ( "Изменился текст заголовка формы " + заголовок );
конецесли;

Как понять, что послужило зависанию или трудноуловимой ошибке в работе приложения (менеджера или клиента тестирования)?

В некоторых случаях, при большом наборе тестов, может происходить зависание менеджера или тестируемого приложения. Порой, трудно понять, что именно послужило такому зависанию. Для диагностики подобных проблем, можно использовать специальное свойство DebugInfo.LogExecution. С его помощью, можно определить конкретный сценарий и последнюю строку выполненного Тестером кода сценария.

Почему скриншот формируется в виде черного квадрата?

Такое может происходить в случае запуска тестирования в RDP-сессии, окно которого свернуто. Решение проблемы – не сворачивать окно RDP-сессии; его можно куда передвинуть или уменьшить, что бы прохождение теста не мешало текущей работе.

Как эмулировать двойной клик на строке таблицы?

Для этого нужно получить объект тестируемой таблицы и выполнить метод Выбрать ():

// Перейдем к нужной строке
КСтроке ( "!Товары", "Наименование", "1С:Бухгалтерия 8" );
// Выполним двойной клик
Получить ( "!Товары").Выбрать ();

Как отключить окно прогресса выполнения сценария?

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

Для отключения стандартного прогресса, в коде сценария необходимо написать следующее:

// Поместите эту строку в начало сценария
Debug.ShowProgress = ложь;

Работа в среде

Где синтаксическая подсветка кода?

К сожалению, встроенный в платформу текстовый редактор не имеет продвинутых средств работы с программным кодом, включая его синтаксическую подсветку в режиме управляемых форм. Решением проблемы является использование продукта Microsoft Visual Studio Code (vscode). Открытая архитектура этого редактора и разработанные сообществом плагины, позволяют синхронизироваться vscode и Тестеру в обе стороны. При наборе кода сценария, кроме привычного IntelliSense работают подсказки к методам Тестера; разработанный плагин взаимодействует с ним для получения полей тестируемого приложения.

Например, при наборе Нажать ( “ плагин покажет в выпадающем списке редактора vscode, какие кнопки можно нажать в текущем окне тестируемого приложения:

Или, при установке текущий формы, подсказка будет такой:

Подробнее см. в документации Интеграция с Visual Studio Code.

А как отлаживать сценарии?

Для запуска сценария в режиме отладки, используется комбинация Alt+F5, либо контекстное меню в редакторе сценария Запустить отладку.

Для установки точек останова, используется метод ОтладкаСтарт (). С его помощью можно остановить сценарий в нужном месте, либо сделать это по определенному условию:

попытка
	Ввести ( "!МоеЧисловоеПоле", 10 );
исключение
	// Если что-то пошло не так,
	// с этого места Тестер начнет отладку
	// и будет ждать действий пользовтеля
	ОтладкаСтарт ();
конецпопытки;

Как по-быстрому прогнать пару сценариев?

Если в ходе работ вы хотите не отвлекаясь прогнать ряд тестов – используйте механизм заданий. Это позволяет делегировать прогон сценария другой машине. Впоследствии, через журнал задач, вы cможете определить статус прохождения тестов, и при необходимости, проанализировать ситуацию отчетом Сводка, журналом ошибок или логом выполнения. Подробнее см. Механизм заданий.

Как узнать, когда последний раз запускался сценарий, кем, и был ли запуск успешным?

Находясь в сценарии:

Каждый из пунктов предназначен для соответствующего анализа. Эти же функции доступны в контекстом меню дерева сценариев.

Я редактирую тест и хочу его запустить на другой машине, я должен его предварительно помещать в хранилище?

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

Как производить рефакторинг сценариев в процессе разработки?

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

Подход 1. В сценариях, вместо строкового представления, используйте идентификаторы.

Например, вместо Ввести ( “Покупатель”, “Рога и копыта” ) используйте: Ввести ( “!Контрагент”, “Рога и копыта” ).

Таким образом, заполнение поля будет выполнено по идентификатору, и не будет зависеть от представления (которое обычно меняется чаще, чем идентификатор) и/или языка интерфейса пользователя, что критично важно при тестировании многоязычных конфигураций.

Подход 2. Поиск используемого фрагмента в дереве сценариев, например так:

Подход 3. Использование отчета Сценарии для точного поиска выражения:

Подход 4. Рекомендуемый. Так как Тестер умеет автоматически зеркалировать сценарии на файловую систему, можно использовать богатые возможности внешних текстовых редакторов, например, Microsoft Visual Studio Code:

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

Как вы работаете в vscode, там ведь кроме набора текста больше никаких удобств?

Разработка сценариев в Visual Studio Code может стать очень удобным инструментом, хотя и требует определенной практики и изучение возможностей среды.

Вот список наиболее полезных комбинации клавиш для работы с кодом сценария:

Ctrl + E. Открывает окно нечеткого поиска сценария для его открытия в новой вкладке.

Ctrl + Shift + E. Активация дерева файлов проекта.

Alt + F12. Открытие в сплывающем окне модуля процедуры, функции или сценария. Удобно использовать для беглого просмотра когда связанного сценария.

Ctrl + Shift + O. Быстрый переход к процедуре/функции кода сценария.

Ctrl + Shift + F, Ctrl + Shift + H. Глобальный поиск и глобальная замена. Важной способностью этих функций является возможность указания начальной папки (поле чувствительно к регистру) поиска/замены.

Автоматизация

На тестовом сервере много баз и хранилищ, как указать Тестеру, какую базу прогонять и какие обновления в неё загружать?

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

При ночном тестировании, некоторые мои сценарии запускают одновременно несколько приложений под разными пользователями, как их потом закрыть при очередном прогоне?

Для этого нужно обратить внимание на два ключевых момента:

  1. Закрытие приложений при работе теста.
  2. Закрытие приложений перед началом тестирования.

Закрытие приложений при работе теста

Сценарии, из которых запускаются новые сессии, должны вначале подключиться к ним и закрыть сессии:

// Отключаемся от текущей тестируемой сессии
Отключить ();

// Где-то в структуре данных у вас должен быть порт для
// запуска новой тестируемой сессии
порт = Окружение.ПортУтверждающегоЗаявки;

// Перед запуском новой сессии, попробуем вначале к ней подключиться
попытка
	Подключить ( , порт );
	завершить = истина;
исключение
	завершить = ложь;
конецпопытки;
если ( завершить ) тогда
	// Здесь мы уже подключены к старой сессии.
	// Закроем в ней все окна и отключаемся с завершением работы приложения
	ЗакрытьВсё ();
	Отключить ( истина );
конецесли;

// Здесь мы уверены, что предыдущая сессия на этом порту завершена
// и запуск новой сессии будет занимать ожидаемый порт
// и ожидаемо контролироваться сценарием
п = Вызвать ( "Тестер.Запустить.Параметры");
п.Пользователь = "Петров";
п.База = "Бухгалтерия предприятия";
п.Порт = порт;
Вызвать ( "Тестер.Запустить", п );

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

Закрытие приложений перед началом тестирования

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

Так нужно делать по нескольким причинам:

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

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

Отключение можно организовать следующим образом:

с = СвойстваПриложения.Port;
до = 5;
для порт = с по c + до цикл
	попытка
		Подключить ( , порт );
		Отключить ( истина );
	исключение
	конецпопытки;
конеццикла;

Алгоритм выше, опирается на факт возможного наличия тестовых клиентов в диапазоне от порта приложения (задается в справочнике Приложения) до 5 одновременных сессий. Отсюда, следует рекомендация: при запуске дополнительных сессий, используйте не фиксированные порты, а относительные, с инкрементацией к значению порта, заданного в свойствах приложения.

Как исключить тесты разрабатываемого функционала от ночного прогона?

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

Вариант 1. Создать отдельную группу тестов, и исключить её из выборки сценариев для тестирования (см. тест Сценарии в репозитории общих тестов).

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

Вариант 3. Использовать децентрализованное хранение сценариев. В этом варианте, мы можете создать создать свою копию тестов выгружать/загружать изменения в общее хранилище. Подробнее см. здесь.

Концептуальные

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

Зачем программисту автоматизированное тестирование?

Программисты находят значительно более эффективной практику написания кода без ошибок, нежели спуск времени на тестирование и рутину с этим связанную. Однако, внедрение автоматизированного тестирования в свою работу – это один из качественных рывков вперед в развитии своих способностей как программиста. Это не научно доказанный факт, но практика показывает, что класс программиста выше, если произведенный им код, он же кодом и проверяет (не обязательно TDD).

Почему в Тестере, все сценарии в виде программного кода?

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

А можно не кодировать вручную, а записывать сценарий?

Да. В Тестере реализовано несколько механизмов формирования сценария:

Вариант 1: Пишется код вручную.

Плюсы:

  • Возможность формировать реальные сценарии
  • Сценарии получаются краткими (страница кода сценария будет равносильна трем-четырем страницам преобразованного журнала действий пользователя)

Минусы:

  • Нужно полностью понимать как работает прикладная модель тестируемого приложения
  • Нужно знать язык 1С на базовом уровне

Вариант 2: Сценарий пишется по действиям пользователя (см. на панели микрофон).

Плюсы:

  • Быстро можно получить тест

Минусы:

  • Не всегда тест будет воспроизводим (особенности платформы)
  • Тесты очень многословные, содержат много служебной информации и невыразительны
  • Реальные тесты очень сложно

Вариант 3: Использование мастера (см. на панели подбор действия).

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

Плюсы:

  • Быстрое создание шагов
  • Интерактивность

Минусы:

  • Нужно понимать как работает прикладная модель тестируемого приложения

Общая рекомендация: если вы программист, пишите сценарии кодом.

Почему в Тестере нет средств загрузки начальных данных из макета или файла?

Одной из фундаментальных задач при разработке Тестера было желание создать систему, при которой промежуток времени, между написанием кода и его тестом, был бы минимальным. Данная цель была достигнута; следствием стало накопление большого числа тестов: сотни, а для некоторых проектов, тысячи. Такая ситуация предъявляет особые требования к содержанию, прогону и анализу результатов тестирования, с которой мы в свое время успешно не справились.

С ростом количества сценариев, у нас началась фатальная деградация процесса в виде большого числа ложных падений с общим синдромом: устаревание, сложность анализа и потеря понимания тестовых данных разработчиками. Нам понадобилось много времени в виде попыток реализации механизмов представления тестовых данных, начиная с xml, заканчивая табличным документом с хранением непустых значений, цветами областей, умными расшифровками и мини языком с вычисляемыми выражениями, чтобы наконец понять: тестовые данные требуют алгоритма их формирования, рефакторинга и отладки, что попадает под определение “программный код”.

Программный код воплотил собой отсутствие в Тестере каких-либо механизмов выгрузки/загрузки данных. Подробнее о реализации подхода читайте в документации Данные для тестирования.

Как организовать специальный порядок выполнения тестов?

Желательно этого не делать; правильным решением является несвязность и независимость сценариев от последовательности запуска.

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

Такой подход неизбежно приведет к следующим проблемам:

  1. Падение одного теста, послужит источником ложного падения от него зависимых. Это может обернуться катастрофой, потому что при растущем количестве тестов, будет очень сложно вычислять точки падения, и разбирать цепочки, отматывая назад зависимости с целью определения реальных ошибок.
  2. Сложность рефакторинга связанных тестов, по причине исполнения ими двух ролей: проверка себя и поставка окружения другим сценариям. Естественное нежелание модифицировать работающие зависимости, заканчивается слабым покрытием растущего функционала решения.
  3. Сложность распараллеливания тестов. Когда тестов будет много, либо в их логике будет производиться долгая обработка данных, ночи на прогон может не хватить. Потребуется распараллеливание. Эту задачу будет очень сложно решить для связанных тестов.

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

141

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. olegtymko 127 26.07.18 05:27 Сейчас в теме
Огонь! Надо будет попробовать вашу систему тестирования.
Max27; grumagargler; +2 Ответить
2. karpik666 2176 26.07.18 09:13 Сейчас в теме
Подскажите тестер только для управляемых форм или для обычных тоже подойдет?
4. grumagargler 499 26.07.18 15:09 Сейчас в теме
(2) только для управляемых
3. ivanov660 929 26.07.18 11:03 Сейчас в теме
Подскажите:
- Запуск через командную строку еще не реализовали?
- И выгрузку результатов выполнения в один из форматов отчетов XML JUnit, Allure или другой?
5. grumagargler 499 26.07.18 15:15 Сейчас в теме
(3) Запуск тестера с передачей ключей был изначально, но вероятно я не понял ваш вопрос.
Тесты, скрипты для CI и отчетность, всё внутри тестера, делать внешнюю задач пока не поступало.
6. acsent 1121 15.10.18 16:53 Сейчас в теме
Но почему бы не писать обработки тестирования, а не скрипты. тогда с раскрасской нет проблем.
Типо как в xUnitFor1C
7. grumagargler 499 15.10.18 18:08 Сейчас в теме
(6)
Но почему бы не писать обработки тестирования, а не скрипты. тогда с раскрасской нет проблем.

Причин много, вот некоторые из них:
- скорость написания-запуска, в одном окне на втором мониторе
- скриптами легче манипулировать, это текст. В тестере, в дереве их легко искать, открывать в отдельных вкладках, запускать, смотреть версии, синхронизировать (выгружать/загружать), делать глобальный рефакторинг
- код скрипта дорабатывается тестером перед запуском для возможности контроля исполнения каждой строки кода, замера времени, формирования полного пути в случае ошибок (в случае взаимосвязанных тестов).

С синтаксической подсветкой проблем уже нет, есть интеграция с vscode
8. Fragster 857 09.11.18 15:31 Сейчас в теме
Отличный инструмент, действительно удобно. Жду развития плагина для vscode (почти всегда неправильно работает intellisense по элементам управления :))

При использовании возник вопрос:

Как проверить данные в табличной части?

ОписаниеСтроки = Новый Соответствие();
ОписаниеСтроки.Вставить("Колонка 1", "Представление 1"); // возможно ли тут использовать не представление, а значение?
ОписаниеСтроки.Вставить("Колонка 1", "Представление 2"); // возможно ли тут использовать не представление, а значение?
Список = Получить("!ТабличнаяЧасть");
Если Не Список.ПерейтиКСтроке(ОписаниеСтроки) Тогда
	ВызватьИсключение "Строка не найдена";
КонецЕсли;

Проверить ( "!ТабличнаяЧастьПоле", ОжидаемоеЗначение); // тут ошибка 18: Неподходящий тип элемента управления для вызванного действия. 
Показать
9. Fragster 857 09.11.18 15:53 Сейчас в теме
(8) Методом тыка определил, что для полей табличных частей всегда надо указывать родителя:

Проверить("!ТабличнаяЧасть / !ТабличнаяЧастьПоле", 19500); // для текущей строки
Проверить("!ТабличнаяЧасть / !ТабличнаяЧастьПоле [3]", 19500); // для строки по номеру
10. grumagargler 499 09.11.18 18:52 Сейчас в теме
(9) День добрый! Спасибо за отзыв!
Для проверки, вы еще можете передать родителя в виде третьего параметра:
таблица = Получить ( "!Товары" );
Проверить("!ТабличнаяЧастьПоле", 19500, товары);

Развитие плагина идет, но пока интелисенс работаем в основном на подброс названия поля по типу, согласно открытого в текущий момент тестового приложения.
Приглашаю вас в чат, там я смогу более оперативно отвечать на вопросы.
11. Fragster 857 09.11.18 19:41 Сейчас в теме
Еще прошу добавить в ЧаВо - для проверки шаблона таблицы, открывающейся в новом окне табличного документа - в качестве имени поля надо передавать пустую строку (на странице элементов формы отображается <Поле>)

Нажать("!ФормаПечатьРасчета");
Здесь();
ПроверитьШаблон ( "" );
grumagargler; +1 Ответить
Оставьте свое сообщение