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

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

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

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

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

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

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

Вариант 1.

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

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

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

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

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

// Открываем внешнюю обработку
путь = "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. Запустить сразу нужное количество приложений, и затем, переключаясь между ними, выполнять нужные сценарии

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

// Запуск 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 ) тогда
    Стоп ( "Отчет не сформирован!" );
конецесли;

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

Это может происходить в одном из следующих случаев:

  1. Тестируемое приложение минимизировано
  2. Вы запускаете тестирование на удаленном сервере, к которому подключаетесь по RDP, и при этом:
    1. Приложение RDP-клиента свернуто (минимизировано)
    2. Вы не подключены к удаленной сессии

Итак, если ваши скрипты не пере-запускают тестируемое приложение и оно постоянно открыто, убедитесь, что оно не свёрнуто, желательно вообще развернуть его на весь экран (см. метод МаксимизироватьОкно).

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

[HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client]
"RemoteDesktop_SuppressWhenMinimized"=dword:00000002

С такой модификацией, свёрнутый RDP-клиент будет обновлять экран, и скриншоты уже не будут черными. Чтобы изменения вступили в силу, нужно перезапустить RDP-клиент.

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

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

если ( ИмяКомпьютера () = "TestServer" ) тогда
    ПерейтиВКонсоль ();
конецесли;

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

Как проверить наличие навигационных ссылок у объекта?

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

И если какой-то ссылки в панели нет, выдать сообщение об ошибке.

Код ниже демонстрирует, как это можно реализовать:

Здесь ( "О выдаче денеж*" );
проверить = "Процессы и задачи, Переписка, Форум, Журнал передачи, Протокол работы";
ссылкиНаФорме = взятьСсылки ();
для каждого ссылка из Conversion.StringToArray ( проверить ) цикл
    если ( ссылкиНаФорме.Найти ( ссылка ) = неопределено ) тогда
        Стоп ( "Ссылка " + ссылка + " не найдена в навигационной панели" );
    конецесли;
конеццикла;

&НаКлиенте
Функция взятьСсылки ()

    список = новый Массив ();
    для каждого ссылка из ПолучитьСсылки ().НайтиОбъекты () цикл
        список.Добавить ( ссылка.ТекстЗаголовка );
    конеццикла;
    возврат список;

КонецФункции

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

В некоторых случаях, для проверки по шаблону может быть недостаточно служебных символов автоподстановки (* или ?), и проверка должна выполняться по точному соответствию полей шаблона. Однако, в случае использования идентификатора окружения, такая проверка будет затруднительна в силу постоянно меняющихся тестовых данных.

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

  1. Сделать из шаблона макет
  2. Параметризировать нужные поля
  3. Написать небольшую функцию по заполнению параметризированного шаблона.

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

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

// Готовим структуру для заполнения параметризированного шаблона
п = новый Структура ( "Товар", "Комбайн 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 ( области ) );

КонецФункции

Как проверить видимость элемента формы?

Видимость элемента формы можно проверить двумя способами:

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

Как проверить колонтитулы печатной формы/отчета?

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

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

// Откроем отчет и подождем пока он сформируется
Коммандос ( "e1cib/app/Отчет.ABCXYZАнализНоменклатуры" );
Нажать ( "!СформироватьОтчет" );
Пауза ( 5 );

// Запишем отчет в файл
отчет = Получить ( "!ОтчетТабличныйДокумент" );
файл = ПолучитьИмяВременногоФайла ( "mxl" );
Приложение.УстановитьРезультатДиалогаВыбораФайла ( истина, файл );
отчет.ЗаписатьСодержимоеВФайл ();

// Поместим файл во временное хранилище
тут.Вставить ( "Адрес" );
тут.Вставить ( "ID", новый UUID () );
ПоместитьФайл ( тут.Адрес, файл, файл, ложь, тут.ID );
УдалитьФайлы ( файл );

// Получим значение колонтитула и проверим его.
// Для краткости, используем текучие выражения.
// Следующая строка кода должна вызвать ошибку,
// потому что ERP не формирует указанный колонтитул
Заявить ( нижнийСправа () ).Равно ( "Какой-то колонтитул" );

&НаСервере
Функция нижнийСправа ()

    // Получаем табличный документ
    данные = ПолучитьИзВременногоХранилища ( тут.Адрес );
    память = данные.ОткрытьПотокДляЧтения ();
    макет = Новый ТабличныйДокумент ();
    макет.Прочитать ( память );
    память.Закрыть ();

    // Вернем правый нижний колонтитул
    возврат макет.НижнийКолонтитул.ТекстСправа;

КонецФункции

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

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

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

// Пытаемся сохранить данные в течении 15 секунд
перестатьПытаться = ТекущаяДата () + 15;

// Выключаем контроль ошибок
ИгнорироватьОшибки = истина;
пока ( ТекущаяДата () < перестатьПытаться ) цикл
    Нажать ( "!ФормаЗаписатьИЗакрыть" );
    попытка
        ПроверитьОшибки ();
        прервать;
    исключение
        Закрыть ( "1?:*" );
        Пауза ( 1 );
    конецпопытки;
конеццикла;
ИгнорироватьОшибки = ложь;