Почему выдаются ошибки при воспроизведении ранее записанного сценария через «микрофончик»?¶
Эта проблема вызывает наибольшее удивление, при начале работы с механизмами тестирования, и нередко отбивает охоту продолжать. Да, к сожалению, платформа не позволяет в полной точности записать, и как следствие – воспроизвести все действия пользователя. Это проблема/особенность уровня платформы, имеет место в любых системах тестирования и может воспроизводиться даже на простых сценариях.
Однако, с практической точки зрения, реальные сценарии не пишутся прокликиванием (записью действий). Человек не в состоянии стабильно и безошибочно, накликать последовательность из 30+ шагов. Кроме этого, такие «накликанные» сценарии получаются очень громоздкими, потому что включают в себя много служебной информации и действий, не имеющих практического смысла с точки действий пользователя.
Совет тут такой: используйте микрофон для записи коротких временных сценариев, или для изучения модели тестируемого приложения. Реальные сценарии, разрабатывайте кодом, используя специально разработанное API Тестера.
Как открыть внешнюю обработку или обратиться к меню Файл / Открыть?¶
К сожалению, когда тестируемое приложение уже запущено, обратиться к меню Файл
возможности нет. Это ограничение платформы.
Возможны следующие варианты решения проблемы.
Вариант 1.¶
Использование промежуточной, внешней обработки.
Алгоритм действий следующий:
- В Тестере, в
Меню быстрые функции / Скачать Worker.epf
, скачиваем обработкуWorker.epf
- В тестируемом приложении, открываем эту обработку, вручную
- В Тестере, для открытия целевых внешних обработок, используем тест
Тестер.ОткрытьОбработку
(тест находится в репозитории общих тестов). Как загружать тесты, см. здесь.
Пример использования:
Подключить ();
ЗакрытьВсё ();
// Открываем внешнюю обработку
путь = "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С в режиме клиента тестирования
// Определяем параметры запуска
п = Вызвать ( "Тестер.Запустить.Параметры" );
// Название ИБ в списке информационных баз 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?:*" );
надпись = форма.НайтиОбъект ( , "Недостаточно прав *" );
если надпись = неопределено тогда
ЗаписатьОшибку ( "Какая-то ошибка при открытии объекта <" + объект + ">" );
иначе
если ( ДоступДолженБыть ) тогда
ЗаписатьОшибку ( "Недостаточно прав на объект <" + объект + ">" );
ошибки = истина;
конецесли;
конецесли;
Закрыть ( форма );
иначе
если ( не ДоступДолженБыть ) тогда
ЗаписатьОшибку ( "Прав доступа на объект <" + объект + "> быть не должно" );
ошибки = истина;
конецесли;
конецесли;
конеццикла;
возврат не ошибки;
КонецФункции
В этом примере, проверяется отсутствие прав на справочники Номенклатура
и Контрагенты
, то есть ошибочной будет ситуация, если пользователю эти справочники открыть удасться.
Данный код не является законченным решением, но демонстрирует подход к решению задач такого класса.
Если систему Тестер использовать непосредственно в процессе разработки, то поддержание теста объектов, к которым требует специальный доступ не будет накладным, и станет частью выполнения задач разделения прав доступа как таковых.
Как узнать состояние флажка (галочки) на форме, перед тем как принять решение нажимать на него или не нажимать?¶
В некоторых сценариях, требуется гарантия определенного состояния флажка, например, для сценария важно, чтобы галочка была включенной или выключенной. В этом случае, код сценария должен каким-то образом определить текущее состояние флажка, и если оно не соответствует нужному значению, выполнить нажатие на флажок для получения требуемого состояния:
флаг = Взять ( "!ЭтоУслуга" );
если ( флаг = "Нет" ) тогда
Нажать ( "!ЭтоУслуга" );
конецесли;
// Здесь мы точно уверены, что флаг Услуга включен
Как узнать, изменился ли заголовок тестируемой формы?¶
Допустим, у вас стоит задача определить, что после определенных интерактивных действий с формой, ее заголовок остался неизменным. Для решения этой задачи можно использовать свойство ТекстЗаголовка
тестируемой формы, например так:
форма = Здесь ( "Мой заголовок формы *" );
заголовок = форма.ТекстЗаголовка;
// ... какие-то действия, которые могут привести к изменению заголовка
новыйЗаголовок = форма.ТекстЗаголовка;
если ( новыйЗаголовок <> заголовок ) тогда
Стоп ( "Изменился текст заголовка формы " + заголовок );
конецесли;
Как понять, что послужило зависанию или трудноуловимой ошибке в работе приложения (менеджера или клиента тестирования)?¶
В некоторых случаях, при большом наборе тестов, может происходить зависание менеджера или тестируемого приложения. Порой, трудно понять, что именно послужило такому зависанию. Для диагностики подобных проблем, можно использовать хронограф. С его помощью, можно определить конкретный сценарий и последнюю строку выполненного Тестером кода сценария.
Внимание!
При активации хронографа, после каждой строки программного кода сценария, система будет производить серверный вызов для регистрации выполняемых действий. В связи с этим, следует учитывать следующее ограничение: если вы используете метод платформы ПоместитьФайл
(или подобные) с автоматическим формированием адреса во временном хранилище, и передаете его в серверную процедуру вашего сценария, то на момент передачи управления этой серверной процедуре, значение по адресу во временном хранилище уже будет удалено (в связи с неявным серверным вызовом кода диагностики).
Для исключения таких ситуаций, передавайте в методы ПоместитьФайл
(или подобные) проинициализированную каким-либо идентификатором переменную модуля сценария, например так:
тут.Вставить ( "Адрес" );
тут.Вставить ( "ID", новый UUID () );
файл = "c:\данные.xlsx";
ПоместитьФайл ( тут.Адрес, файл, файл, ложь, тут.ID );
обработать ();
данные = ПолучитьИзВременногоХранилища ( тут.Адрес );
данные.Записать ( "c:\mydata.txt" );
&НаСервере
Процедура обработать ()
// Получаем переданные данные
данные = ПолучитьИзВременногоХранилища ( тут.Адрес );
//
// ...обрабатываем
//
// И возвращаем обратно
тут.Адрес = ПоместитьВоВременноеХранилище ( данные, тут.ID );
КонецПроцедуры
Как эмулировать двойной клик на строке таблицы?¶
Для этого нужно получить объект тестируемой таблицы и выполнить метод Выбрать ()
:
// Перейдем к нужной строке
КСтроке ( "!Товары", "Наименование", "1С:Бухгалтерия 8" );
// Выполним двойной клик
Получить ( "!Товары").Выбрать ();
Как отключить окно прогресса выполнения сценария?¶
Если у вас реализован собственный механизм отображения прогресса сценария, стандартный прогресс может мешать его отображению.
Для отключения стандартного прогресса, в коде сценария необходимо написать следующее:
// Поместите эту строку в начало сценария
ПрогрессСкрыть ();
Как программно получить доступ к макету (табличному документу) сценария?¶
В некоторых случаях, может понадобится доступ к макету сценария, непосредственно из кода сценария. Например, в макете могут быть сохранены некие тестовые данные, которые требуется загрузить в тестируемую базу.
Для решения этой задачи, можно воспользоваться следующим кодом:
стек = Debug.Stack [ Debug.Level ];
макет = RuntimeSrv.GetSpreadsheet ( стек.Module, стек.IsVersion ).Template;
для а = 1 to макет.ВысотаТаблицы цикл
для б = 1 to макет.ШиринаТаблицы цикл
Сообщить ( макет.Область ( а, б ).Текст );
конеццикла;
конеццикла;
Примечание
Английские названия в примере непереводимы, это внутренняя реализация Тестера.
Почему получение значения ячейки табличной части документа возвращает номер строки?¶
Такая проблема может возникать в случае получения значения ячейки таблицы, форма которой неактивна.
Например, у вас открыто две вкладки, первая – отчет, вторая – документ. В коде сценария, вы находитесь в форме отчета, но используете метод Взять () по отношению к табличной части документа, который находится на второй вкладке, и соответственно - не активен. В этом случае, метод Взять () ошибок не выдаст, но получение значение может не соответствовать ожиданиям. Связано это с тем, что метод Взять (), для получения значения ячейки, предварительно выполняет активацию требуемой колонки таблицы, и в случае, если форма не активна, платформа не выполняет такой активации.
Для решения проблемы, необходимо перед выполнением метода Взять (), активировать форму документа, это можно сделать методом Здесь ():
...
документ = Здесь ( "Реализация товаров *" );
товары = Получить ( "!Товары" );
...
// Обязательно нужно указать второй параметр
Здесь ( документ, истина );
значение = Взять ( "!ТоварыЦена", товары );
Как проверять движения документов и проводки, если проведение реализовано фоновым заданием?¶
В больших конфигурациях, нередко используются фоновые задания для выполнения ряда потенциально продолжительных задач.
Например, в конфигурации ERP 2.4 используются фоновые задания для отмены проведения, проведения и формирования проводок по регламентированному учету.
Пример ниже иллюстрирует проверку проводок по регламентированному учету для документа Приобретение услуг и прочих активов
:
Здесь ( "Приобретение услуг *" );
Нажать ( "!ФормаПровести" );
// Ожидаем окончание проведения 3 секунды
Дождаться ( "Проведение", 3 );
Нажать ( "!ФормаОбработкаОтражениеДокументовВРеглУчетеПроводкиРеглУчета" );
// Запоминаем форму в переменную, чтобы потом вернуться к ней
журнал = Здесь ();
Нажать ( "!ФормаОтразитьДокументВРеглУчете" );
// Перед тем как продолжать, ожидаем старт задания 3 секунды
Дождаться ( "Старт задания", 3 );
// Ждем, пока окно прогресса не закроется и мы не вернемся в журнал.
// Максимальное ожидание 30 секунд.
ждем = 30;
пока ( ждем ) цикл
Дождаться ( "Формирование проводок", 1 );
если ( журнал = Здесь () ) тогда
прервать;
конецесли;
ждем = ждем - 1;
конеццикла;
// Здесь мы уже в журнале, где должны быть проводки.
// Выводим проводки в табличный документ и проверяем результат.
Нажать ("!ВывестиСписок");
Нажать ( "!Ok", "Вывести список" );
ПроверитьШаблон ( "", "Набор записей" );
В примере, ожидание выполнения заданий выполнено в секундах, но вы можете реализовать свою логику, включая случаи запуска тестирования на заведомо слабых компьютерах. Можно делать циклы ожидания доступности элементов, а можно просто в глобальную структуру параметров (см. Глобальная переменная) добавлять коэффициент производительности в зависимости от имени компьютера:
если ( ИмяКомпьютера () = "BusyServer" ) тогда
__.Вставить ( "Производительность", 2 );
иначе
__.Вставить ( "Производительность", 1 );
конецесли;
Соответственно, в коде ожидания можно будет написать:
Дождаться ( "Проведение", 3 * __.Производительность );
Как работать с динамически сформированными полями, например в отчетах на СКД?¶
В ряде случаев, приходится тестировать формы, элементы которых формируются динамически.
Например, отчеты на базе СКД конфигурации ERP могут содержать такие идентификаторы полей:
Что в свою очередь делает нечитабельным текст сценария при их прямом использовании:
Фокус ( "!ЗначениеПараметраНастроек_Начало_520a2e1a7dd64881a5f5cf852bdd7a7f" );
Для выхода из ситуации, можно использовать текст заголовка (даже если заголовок скрыт) с использованием символов-шаблонов поиска, например так:
Фокус ( "*Начало*" );
В этом примере, мы используем звездочки слева и справа для поиска нужного элемента формы.
Как обойти таблицу или динамический список не зная сколько там записей?¶
В некоторых сценариях, требуется обход коллекции с выполнением некоторого однотипного действия для для каждой её строки. Пример кода ниже, иллюстрирует подход к решению такой задачи: (пример на базе конфигурации БП3):
Подключить ();
ЗакрытьВсё ();
Меню ( "Банк и касса / Платежные поручения" );
Здесь ();
список = Получить ( "!Список" );
список.ПерейтиКПервойСтроке ();
пока ( истина ) цикл
Сообщить ( Взять ( "!Дата", список ) );
попытка
список.ПерейтиКСледующейСтроке ();
исключение
прервать;
конецпопытки;
конеццикла;
Отключить ();
Пример ниже для обхода табличной части Услуги
документа Реализация
:
// Считаем, что документ уже открыт..
Здесь ();
таблица = Получить ( "!Услуги" );
таблица.ПерейтиКПервойСтроке ();
пока ( истина ) цикл
Сообщить ( Взять ( "!УслугиНомерСтроки", таблица ) );
попытка
таблица.ПерейтиКСледующейСтроке ();
исключение
прервать;
конецпопытки;
конеццикла;
Как программно получить последнюю ошибку упавшего сценария?¶
Если в коде сценария выполняются запуски вложенных сценариев методами Вызвать ()
/ Позвать ()
, то самостоятельный перехват и обработка ошибок (возникших в этих вложенных сценариях), на уровне их вызова, имеет ряд особенностей.
Рассмотрим два варианта программного перехвата ошибки:
// Первый случай
Попытка
x = 1 / 0;
Исключение
ошибка = ОписаниеОшибки (); // Здесь будет текст ошибки деления на 0
КонецПопытки;
// Второй случай
Попытка
Вызвать ( "ПроверяемыйСценарий" ); // Допустим, в этом сценарии делается: x = 1 / 0;
Исключение
ошибка = ОписаниеОшибки (); // Сюрприз, здесь не будет текста ошибки
КонецПопытки;
В первом случае, ошибка возникает на уровне выполнения текущего сценария и может быть стандартно обработана самим кодом.
Во втором примере, это не работает в связи с особенностями работы платформы при возникновении исключений между клиент/серверными вызовами. Поэтому, Тестер самостоятельно производит их обработку, логирование и переброс.
Таким образом, для того, чтобы получить ошибку упавшего сценария, можно использовать такой код:
Попытка
Вызвать ( "ПроверяемыйСценарий" );
Исключение
ошибка = последняяОшибка (); // Здесь будет ссылка, с представлением ошибки
КонецПопытки;
&НаСервере
Функция последняяОшибка ()
с = "
|выбрать разрешенные первые 1 Журнал.Ссылка как Ссылка
|из Справочник.ErrorLog как Журнал
|где Журнал.User = &Пользователь
|упорядочить по Журнал.Date убыв
|";
з = новый Запрос ( с );
з.УстановитьПараметр ( "Пользователь", ПараметрыСеанса.User );
таблица = з.Выполнить ().Выгрузить ();
возврат ? ( таблица.Количество () = 0, неопределено, таблица [ 0 ].Ссылка );
КонецФункции
Как сравнить значения полей по шаблону или с использованием регулярного выражения?¶
Существует ряд задач, когда нужно провести сверку значений с использованием * (звездочки) или других символов подстановки. Для такой проверки, обычно используются регулярные выражения, однако в реальных сценариях, можно столкнуться с проблемой экранирования эталонной строки перед тем, как пропустить её через регулярное выражение.
Пример. Допустим нам нужно сравнить эталонную JSon-строку со значением, считанным из файла или поля тестируемой формы. При этом, в сравнении, нужно учесть, что значения части свойств принимать во внимание нет необходимости. Таким образом, наша эталонная JSon-строка должна содержать в себе соответствующие для таких полей, маркеры.
Для хранения эталонной строки будем использовать шаблон теста (вкладка Шаблон
), значение будем хранить в самой первой ячейке. Предварительно, отмаркируем поля этой строки, чтобы жесткое сравнение по ним не выполнялось. Вот как на картинке ниже:
Сохраненную выше строку в шаблоне, в коде сценария, мы можем получить так:
Стек = Debug.Stack [ Debug.Level ];
Макет = RuntimeSrv.GetSpreadsheet ( стек.Module, стек.IsVersion ).Template;
Эталон = Макет.Область ( 1, 1 ).Текст;
Следующий шаг – экранирование эталонной строки:
Эталон = экранировать ( Эталон );
где функция:
&НаСервере
Функция экранировать ( Значение )
exp = Regexp.Get ();
exp.Pattern = "[.*+?^${}()|[\]\\]";
возврат exp.Replace ( Значение, "\$&" );
КонецФункции
После экранирования, нужно заменить маркер на регулярное выражение:
// Вместо "*" нам нужно примерно следующее, согласно лексике регулярных выражений: ".+"
Эталон = Output.Sformat ( Эталон, новый Структура ( "Звезда", ".+" ) );
На этом этапе, эталон готов к сравнению, и полный пример кода может выглядеть так:
// Значение, которое нужно проверить
Значение = "*** Здесь должно быть тестируемое значение ***";
// Получение и обработка эталона
Стек = Debug.Stack [ Debug.Level ];
Макет = RuntimeSrv.GetSpreadsheet ( стек.Module, стек.IsVersion ).Template;
Эталон = экранировать ( Макет.Область ( 1, 1 ).Текст );
// Сравнение с использованием регулярных выражений
если ( равны ( Эталон, Значение ) ) тогда
Сообщить ( "Равны" );
иначе
Стоп ( "Не равны" );
конецесли;
&НаСервере
Функция равны ( Эталон, Значение )
exp = Regexp.Get ();
// Будем требовать, чтобы строки были одинаковы с самого начала
exp.Pattern = "^" + Эталон;
возврат exp.Test ( Значение );
КонецФункции
&НаСервере
Функция экранировать ( Значение )
exp = Regexp.Get ();
exp.Pattern = "[.*+?^${}()|[\]\\]";
стр = exp.Replace ( Значение, "\$&" );
возврат Output.Sformat ( стр, новый Структура ( "Звезда, Вопрос", ".+", "." ) );
КонецФункции
Как запускать сценарии с уникальным идентификатором окружения без предварительного захвата и модификации переменной окружения?¶
Наверняка, многие из вас сталкивались с такой ситуацией: тест готов и помещен в репозиторий, но следующий его запуск, выполняется без создания окружения, потому что тест с таким идентификатором уже зарегистрирован в вашей системе.
Как правило, вам приходится захватывать сценарий и менять его идентификатор тестового окружения. Такая же ситуация может возникать и в случаях, когда вы запускаете сценарии коллег, которые их “держат”, либо когда у вас агент тестирования пускает тесты без восстановления тестовой базы каждый раз.
Все случаи можно свести к следующему желаемому поведению системы: если я не владею тестом, значит я его не разрабатываю в данный момент, и значит, если я его запускаю, мне скорее всего нужно провернуть этот тест от начала до конца, без оптимизаций с учетом идентификатора тестового окружения.
Эта задача может быть решена созданием тест-метода получения идентификатора окружения.
Создайте в библиотеке общих тестов такой метод:
стэк = Debug.Stack [ Debug.Level - 1 ];
если ( стэк.IsVersion
или не захвачен ( стэк.Module ) ) тогда
Пауза ( 1 );
значение = Цел ( ( ТекущаяУниверсальнаяДатаВМиллисекундах () / 1000 ) % 1000000000 );
возврат Conversion.DecToHex ( значение );
иначе
возврат _;
конецесли;
&НаСервере
Функция захвачен ( Модуль )
с = "
|выбрать разрешенные первые 1 1
|из Справочник.Scenarios как Сценарии
| //
| // Редактирование
| //
| соединение РегистрСведений.Editing as Редактирование
| on Редактирование.Scenario = Сценарии.Ref
| and Редактирование.User = &Я
|где Сценарии.Code = &Модуль
|";
з = новый Запрос ( с );
з.УстановитьПараметр ( "Модуль", Модуль );
з.УстановитьПараметр ( "Я", ПараметрыСеанса.User );
возврат не з.Выполнить ().Пустой ();
КонецФункции
И теперь, в ваших функциях создания окружения, вы можете использовать этот метод вот так:
тест = окружение ( "2563E596" );
создатьОкружение ( тест );
// .....
Функция окружение ( Идентификатор )
// Теперь, если вы не владеете этим тестом, ид-окружения
// будет каждый раз разным
ид = Вызвать ( "Общее.ИД", Идентификатор );
п = новый Структура ();
п.Вставить ( "ИД", ид );
п.Вставить ( "Поставщик", "_Поставщик " + ид );
п.Вставить ( "Организация", "Деловой союз" );
п.Вставить ( "Товары", определитьТовары ( ид ) );
возврат п;
КонецФункции
Как проверить, что отчет пустой?¶
В некоторых сценариях, проверка отчета по шаблону может не требоваться, и достаточным прохождением теста может быть информация о том, есть в отчете какие-то данные или нет.
Например, чтобы проверить что такой отчет пустой:
у менеджера тестирования нет возможности напрямую получить текст подсказки Отчет не сформирован...
Однако, можно воспользоваться анализом размера области данных, применив такой подход:
отчет = Получить ( "!Результат" );
вширь = отчет.ПолучитьРазмерОбластиДанныхДокументаПоГоризонтали ();
ввысь = отчет.ПолучитьРазмерОбластиДанныхДокументаПоВертикали ();
если ( вширь + ввысь = 0 ) тогда
Стоп ( "Отчет не сформирован!" );
конецесли;
Почему скриншот формируется в виде черного квадрата?¶
Это может происходить в одном из следующих случаев:
- Тестируемое приложение минимизировано
- Вы запускаете тестирование на удаленном сервере, к которому подключаетесь по RDP, и при этом:
- Приложение RDP-клиента свернуто (минимизировано)
- Вы не подключены к удаленной сессии
Итак, если ваши скрипты не пере-запускают тестируемое приложение и оно постоянно открыто, убедитесь, что оно не свёрнуто, желательно вообще развернуть его на весь экран (см. метод МаксимизироватьОкно).
В случае, если тестирование идет в RDP-сессии, убедитесь, что сам RDP-клиент не свернут, потому что в минимизированном варианте, он перестает обновлять экран терминальной сессии. Можно заставить его так не делать, для этого нужно на вашем компьютере (где вы запускаете RDP-клиент) внести в реестр следующее значение:
[HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client]
"RemoteDesktop_SuppressWhenMinimized"=dword:00000002
С такой модификацией, свёрнутый RDP-клиент будет обновлять экран, и скриншоты уже не будут черными. Чтобы изменения вступили в силу, нужно перезапустить RDP-клиент.
Последний случай, самый сложный, хотя и очень распространенный. Например, у вас удаленный сервер, на нем активная терминальная сессия (к которой вы в текущей момент времени не подключены), вы запускаете тесты по требованию или по регламенту, и вам совсем не обязательно к этому серверу подключаться. В такой ситуации, единственным способом заставить обновляться экран сессии, является “переброс” этой сессии в консоль сервера. Для переброса сессии, в Тестере есть специальный метод ПерейтиВКонсоль. При вызове этого метода, сервер переключит сессию в консоль, и формирование скриншотов станет доступно.
Таким образом, в своих скриптах CI, или тест-методах инициализации запуска, вы можете использовать примерно такой код:
если ( ИмяКомпьютера () = "TestServer" ) тогда
ПерейтиВКонсоль ();
конецесли;
Следует учитывать, что консоль на сервере одна, поэтому если на вашем сервере запущено несколько сессий для тестирования, только одна в один момент времени может быть перенаправлена в серверную консоль
Как проверить наличие навигационных ссылок у объекта?¶
Допустим, перед вами стоит задача проверить состав ссылок в навигационной панели для какого-то объекта:
И если какой-то ссылки в панели нет, выдать сообщение об ошибке.
Код ниже демонстрирует, как это можно реализовать:
Здесь ( "О выдаче денеж*" );
проверить = "Процессы и задачи, Переписка, Форум, Журнал передачи, Протокол работы";
ссылкиНаФорме = взятьСсылки ();
для каждого ссылка из Conversion.StringToArray ( проверить ) цикл
если ( ссылкиНаФорме.Найти ( ссылка ) = неопределено ) тогда
Стоп ( "Ссылка " + ссылка + " не найдена в навигационной панели" );
конецесли;
конеццикла;
&НаКлиенте
Функция взятьСсылки ()
список = новый Массив ();
для каждого ссылка из ПолучитьСсылки ().НайтиОбъекты () цикл
список.Добавить ( ссылка.ТекстЗаголовка );
конеццикла;
возврат список;
КонецФункции
Как параметризировать шаблон сценария?¶
В некоторых случаях, для проверки по шаблону может быть недостаточно служебных символов автоподстановки (* или ?), и проверка должна выполняться по точному соответствию полей шаблона. Однако, в случае использования идентификатора окружения, такая проверка будет затруднительна в силу постоянно меняющихся тестовых данных.
Для решения этой задачи, можно использовать следующий подход:
- Сделать из шаблона макет
- Параметризировать нужные поля
- Написать небольшую функцию по заполнению параметризированного шаблона.
На картинке ниже показано, как вызвать свойства шаблона, сделать из него Макет, затем, вызвать свойства требуемой ячейки, и сделать из неё параметр:
Следующим шагом, нам нужно написать код, с функцией преобразования параметров шаблона, и собственно самой проверки:
// Готовим структуру для заполнения параметризированного шаблона
п = новый Структура ( "Товар", "Комбайн MOULINEX A77 4C" );
// Так как я готовил и прогонял пример на основе демо-базы ERP,
// то в качестве параметра я передаю конкретное название номенклатуры.
// Однако, в случае проверки реальных тестовых данных, параметр можно
// сформировать динамически, с учетом значения идентификатора, например:
// п = новый Структура ( "Товар", "Номенклатура с упаковкой " + ид );
// Вызываем функцию подготовки шаблона
шаблон = подготовитьШаблон ( п );
// Выполняем проверку, передавая ранее подготовленный шаблон
// (подробнее о параметрах процедуры ПроверитьШаблон см. в справке)
ПроверитьШаблон ( "", , , шаблон );
&НаСервере
Функция подготовитьШаблон ( Параметры )
стек = Debug.Stack [ Debug.Level ];
шаблон = RuntimeSrv.GetSpreadsheet ( стек.Module, стек.IsVersion );
макет = шаблон.Template;
область = макет.ПолучитьОбласть ();
область.Параметры.Заполнить ( Параметры );
макет.Очистить ();
макет.Вывести ( область );
возврат шаблон;
КонецФункции
В результате, система проведет сравнение динамически подготовленного шаблона с табличным документом на стороне тестируемого приложения. В качестве примера, была взята табличная часть Товары
документа Заказ клиента
из конфигурации ERP:
Стоит отметить, что в случае обнаружения ошибки, Тестер выдаст сообщение на основании динамических данных, а не сохраненного в сценарии макета табличного документа. Этот нюанс следует иметь ввиду при анализе падений.
Вот еще один пример динамической подготовки макета для проверки. Его отличие состоит в том, что мы используем области макета для построения нашего собственного табличного документа для проверки:
шаблон = подготовитьШаблон ();
ПроверитьШаблон ( "", , , шаблон );
// Ниже вариант если нужно показать шаблон
// при возникновении ошибки
//попытка
// ПроверитьШаблон ( "", , , шаблон );
//исключение
// шаблон.Template.Показать ();
// вызватьисключение ( ОписаниеОшибки () );
//конецпопытки;
&НаСервере
Функция подготовитьШаблон ()
стек = Debug.Stack [ Debug.Level ];
шаблон = RuntimeSrv.GetSpreadsheet ( стек.Module, стек.IsVersion );
макет = шаблон.Template;
лист = новый ТабличныйДокумент ();
лист.Вывести ( макет.ПолучитьОбласть ( "Шапка" ) );
запись = макет.ПолучитьОбласть ( "Строка" );
для к = 1 по 5 цикл
поля = запись.Параметры;
поля.Номер = "Номер";
поля.Дата = "Дата";
поля.Статус = "Статус";
поля.Организация = "Организация";
поля.Контрагент = "Контрагент";
лист.Вывести ( запись );
конеццикла;
макет.Макет = ложь;
макет.Очистить ();
макет.Вывести ( лист );
возврат шаблон;
КонецФункции
В свою очередь, сам макет может в Тестере у нас определен вот так:
А можно в коде сценария объявить переменную области видимости весь сценарий?¶
Объявить переменную в начале модуля, как это обычно делается в коде 1С, для сценария нельзя.
Однако, у сценариев есть локальная структура, которая работает по очень схожему принципу. Подробности см. здесь.
Как подсчитать итог по колонке таблицы?¶
Допустим, у вас есть такая таблица:
И вам по колонке Сумма
требуется подсчитать итог. Для этого, можно воспользоваться следующим кодом:
таблица = Получить ( "!Товары" );
таблица.ПерейтиКПервойСтроке ();
сумма = 0;
пока ( истина ) цикл
сумма = сумма + Взять ( "!ТоварыСумма", таблица );
попытка
таблица.ПерейтиКСледующейСтроке ();
исключение
прервать;
конецпопытки;
конеццикла;
ВСтудию ( сумма );
Как проверить, что отчет после каких-либо действий не изменился?¶
Некоторые задачи ставят целью проверить неизменность данных, после внесения в систему каких-то изменений. Например, требуется проверить, что после обновления конфигурации, отчет ABC/XYZ - анализ номенклатуры
выдает те же данные, что и до обновления.
Код ниже демонстрирует подход к решению этой задачи на примере типовой конфигурации ERP2:
Подключить ();
ЗакрытьВсё ();
// Откроем отчет и подождем пока он сформируется
Коммандос ( "e1cib/app/Отчет.ABCXYZАнализНоменклатуры" );
Нажать ( "!СформироватьОтчет" );
Пауза ( 5 );
// Запишем отчет в файл
отчет = Получить ( "!ОтчетТабличныйДокумент" );
файл = ПолучитьИмяВременногоФайла ( "mxl" );
Приложение.УстановитьРезультатДиалогаВыбораФайла ( истина, файл );
отчет.ЗаписатьСодержимоеВФайл ();
// Далее, мы закрываем тестируемое приложение (см.метод Отключить),
// делаем загрузку обновления конфигурации в пакетном режиме и другие действия.
// Затем, мы заново запускам тестируемое приложение.
//
// ...здесь ваш код обновления и перезапуска тестируемого приложения...
// ....................................................................
// На этот момент приложение уже перезапущено, подключаемся,
// открываем отчет ABC/XYZ - анализ номенклатуры и ждем формирования
Подключить ();
ЗакрытьВсё ();
Коммандос ( "e1cib/app/Отчет.ABCXYZАнализНоменклатуры" );
Нажать ( "!СформироватьОтчет" );
Пауза ( 5 );
// Далее, мы передадим на сервер ранее сохраненный файл отчета
// и получим от него ТабличныйДокумент
тут.Вставить ( "Адрес" );
тут.Вставить ( "ID", новый UUID () );
ПоместитьФайл ( тут.Адрес, файл, файл, ложь, тут.ID );
УдалитьФайлы ( файл );
// Получаем отчет-эталон в виде специальной структуры
эталон = взятьШаблон ();
// И теперь мы просто сверяем два отчета: текущий и ранее сохраненный
ПроверитьШаблон ( "!ОтчетТабличныйДокумент", , , эталон );
&НаСервере
Функция взятьШаблон ()
// Получаем переданные данные
данные = ПолучитьИзВременногоХранилища ( тут.Адрес );
файл = ПолучитьИмяВременногоФайла ( "mxl" );
данные.Записать ( файл );
макет = Новый ТабличныйДокумент ();
макет.Прочитать ( файл );
УдалитьФайлы ( файл );
// Формируем проверяемые области, в нашем случае - это весь отчет
области = новый ТаблицаЗначений ();
колонки = области.Колонки;
колонки.Добавить ( "Up" );
колонки.Добавить ( "Bottom" );
колонки.Добавить ( "Left" );
колонки.Добавить ( "Right" );
область = области.Добавить ();
область.Up = 1;
область.Bottom = макет.ВысотаТаблицы;
область.Left = 1;
область.Right = макет.ШиринаТаблицы;
// Возвращаем структуру данных, которую ожидает метод проверки шаблонов
возврат новый Структура ( "Template, Areas", макет, Collections.Serialize ( области ) );
КонецФункции
Как проверить видимость элемента формы?¶
Видимость элемента формы можно проверить двумя способами:
- Использовать процедуру ПроверитьСтатус. Однако, данная процедура, выбросит исключение и остановит сценарий, если заданное условие проверки не совпадет с фактической видимостью поля тестируемого приложения.
- Если вам нужно просто получить значение видимости для реализации своего алгоритма, можно воспользоваться таким кодом:
видно = Получить ( "!Контрагент" ).ТекущаяВидимость (); если ( видно ) тогда // Ваш код... конецесли;
Как проверить колонтитулы печатной формы/отчета?¶
Для решения этой задачи можно использовать следующий сценарий:
Подключить ();
ЗакрытьВсё ();
// Откроем отчет и подождем пока он сформируется
Коммандос ( "e1cib/app/Отчет.ABCXYZАнализНоменклатуры" );
Нажать ( "!СформироватьОтчет" );
Пауза ( 5 );
// Запишем отчет в файл
отчет = Получить ( "!ОтчетТабличныйДокумент" );
файл = ПолучитьИмяВременногоФайла ( "mxl" );
Приложение.УстановитьРезультатДиалогаВыбораФайла ( истина, файл );
отчет.ЗаписатьСодержимоеВФайл ();
// Поместим файл во временное хранилище
тут.Вставить ( "Адрес" );
тут.Вставить ( "ID", новый UUID () );
ПоместитьФайл ( тут.Адрес, файл, файл, ложь, тут.ID );
УдалитьФайлы ( файл );
// Получим значение колонтитула и проверим его.
// Для краткости, используем текучие выражения.
// Следующая строка кода должна вызвать ошибку,
// потому что ERP не формирует указанный колонтитул
Заявить ( нижнийСправа () ).Равно ( "Какой-то колонтитул" );
&НаСервере
Функция нижнийСправа ()
// Получаем табличный документ
данные = ПолучитьИзВременногоХранилища ( тут.Адрес );
память = данные.ОткрытьПотокДляЧтения ();
макет = Новый ТабличныйДокумент ();
макет.Прочитать ( память );
память.Закрыть ();
// Вернем правый нижний колонтитул
возврат макет.НижнийКолонтитул.ТекстСправа;
КонецФункции
Как обойти проблему записи данных, требующих монопольного доступа?¶
Допустим, вашему тесту требуется изменить какие-то глобальные настройки программы. При этом, логика сохранения таких настроек в тестируемом приложении, устанавливает монопольный режим доступа к базе. В этой ситуации, ваш тест может иногда падать из-за диалога с ошибкой блокировки. Часто, это происходит из-за выполняющихся в тестируемом приложении фоновых заданий (даже если вы их отключили на уровне настроек кластера).
Для того, чтобы с высокой вероятностью произвести запись нужных данных, попытку их сохранения нужно пробовать повторить через какое-то время с течении определенного интервала времени. Пример ниже, показывает как это можно реализовать (подразумевается обязательная его адаптация под ваши условия тестирования)
// Пытаемся сохранить данные в течении 15 секунд
перестатьПытаться = ТекущаяДата () + 15;
// Выключаем контроль ошибок
ИгнорироватьОшибки = истина;
пока ( ТекущаяДата () < перестатьПытаться ) цикл
Нажать ( "!ФормаЗаписатьИЗакрыть" );
попытка
ПроверитьОшибки ();
прервать;
исключение
Закрыть ( "1?:*" );
Пауза ( 1 );
конецпопытки;
конеццикла;
ИгнорироватьОшибки = ложь;