Неблагодарное это дело – выдавать сообщения об ошибках

28.09.13

Разработка - Тестирование QA

Методика формирования и выдачи сообщений об ошибках. Описывается способ работы над ошибками в данных, прилагается программный код. Приводятся примеры.

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

Это хороший тест, проверьте себя. Прагматы выбирают первый вариант, зануды (не в обиду) -  второй, а гении … - вообще игнорируют Smile.

Это сообщение адресовано второй категории, к которой отношу и себя.  Итак, выбор сделан, решено  дать развернутое сообщение об ошибке. Но вот незадача – в той процедуре, в которой возникла ошибка, нет сведений для развернутого сообщения. Не беда. Добавляем параметры в процедуру и передаем в них недостающие сведения. Но и тут проблемы. В вызывающей процедуре имеется только часть этих сведений. Не очень радует, а что делать?

Ниже приводится простая процедура для преодоления этих трудностей. В комментариях к ней приводится пример использования.

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

 

// Процедура обрабатывает текст ошибки
//
// Назначение:
//
//     1. Иерархическая обработка ошибок.
//        На каждом уровне иерархии ошибку можно дополнить уточняющими
//        сведениями о месте ее возникновения.
//        Примерамии иерархии являются: вложенный вызовов процедур,
//        вложенные циклы, вложенные условия "Если Тогда Иначе" и т. д.
//
//     2. Гибкость выбора места вывода ошибок.
//        Вопрос: где выводить ошибку, в процедуре, где она возникла,
//        или в вызывающей процедуре решается гибко.
//        Если внешнюю процедуру ошибка интересует, то ошибка будет передана ей,
//        иначе вывод ошибки будет сделан во внутренней процедуре.
//
//     3. Накопление списка ошибок и выдачи их единым результатом,
//
//
//
// Параметры
//
//     ТекстНакопительОшибок - либо Неопределено, либо строка. Входной и выходной параметр.
//                             Текст, содержащий список ошибок
//     ТекстОшибки           - строка, входной параметр.
//                             Текст ошибки или собранный ранее накопитель ошибок
//     КоординатыОшибки      - любой тип, входной параметр.
//                             Приводится к строковому типу. Текст информирующий пользователя
//                             о месте возникновения ошибки. Следует указать место в
//                             именительном падеже, например "Строка 1" или ЭтотОбъект.Ссылка
//
//
// Описание
//
// 1. Если ТекстНакопительОшибок - имеет тип "Строка", то ТекстОшибки и КоординатыОшибки
//    будут добавлены в ТекстНакопительОшибок, при этом, вывода на экран не будет
//
// 2. В противном случае ТекстОшибки и КоординатыОшибки будут выведены на экран
//
// Замечание 1. Повторные одинаковые ошибки накопитель отбрасывает
// Замечание 2. Если ТекстОшибки - не простая ошибка, а уже ранее собранный накопитель
//              ошибок, то КоординатыОшибки будут добавлены слева к уже существующим
//              координатам каждой из ошибок
//
//
//
// Пример.
//
//
//      Процедура ОбработатьСтроку(НомерСтроки, Ошибки = Неопределено)
//          ОшибкуОтдать(Ошибки, "Лимит превышен", "Строка " + НомерСтроки);
//      КонецПроцедуры
//
//
//      Процедура ВариантСУточнением(Ошибки = Неопределено)
//          Ош = "";
//          ОбработатьСтроку(1, Ош);
//          ОбработатьСтроку(2, Ош);
//          Если ЗначениеЗаполнено(Ош) Тогда
//              ОшибкуОтдать(Ошибки, Ош, "ТЧ Данные");  // отдаем ошибку нижнего уровня наверх,
//                                                      // уточняя своими координатами
//          КонецЕсли;
//      КонецПроцедуры
//
//
//      Процедура ВариантБезУточнения(Ошибки = Неопределено)
//          ОбработатьСтроку(1, Ошибки);             // Проносим ошибку без контроля
//          ОбработатьСтроку(2, Ошибки);             //
//      КонецПроцедуры
//
//
//      Процедура Испытание()
//          ВариантСУточнением();                    // выдаст:
//                                                   //     Лимит превышен. См. ТЧ Данные, Строка 1
//                                                   //     Лимит превышен. См. ТЧ Данные, Строка 2
//
//          Ошибки = "";
//          ВариантСУточнением(Ошибки);
//          Если Ошибки <> "" Тогда
//              ОшибкуОтдать(, Ошибки, "Испытание"); // выдаст:
//                                                   //     Лимит превышен. См. Испытание, ТЧ Данные, Строка 1
//                                                   //     Лимит превышен. См. Испытание, ТЧ Данные, Строка 2
//          КонецЕсли;
//
//
//
//          ВариантБезУточнения();                   // выдаст:
//                                                   //     Лимит превышен. См. Строка 1
//                                                   //     Лимит превышен. См. Строка 2
//
//          Ошибки = "";
//          ВариантБезУточнения(Ошибки);
//          Если Ошибки <> "" Тогда
//              ОшибкуОтдать(, Ошибки, "Испытание"); // выдаст:
//                                                   //     Лимит превышен. См. Испытание, Строка 1
//                                                   //     Лимит превышен. См. Испытание, Строка 2
//          КонецЕсли;
//      КонецПроцедуры
//
//

Процедура ОшибкуОтдать(ТекстНакопительОшибок = Неопределено, ТекстОшибки = "", КоординатыОшибки = Неопределено) Экспорт

    Если не
ЗначениеЗаполнено(ТекстОшибки) Тогда
        Если не
ЗначениеЗаполнено(ТекстНакопительОшибок) или не ЗначениеЗаполнено(КоординатыОшибки) Тогда
            Возврат;
        КонецЕсли;
    КонецЕсли;

   
РазделительСписка = "..|..";    // между ошибками
   
Сцепка = ":,:";                 // между текстом ошибки и координатами


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

   
ВместоПС = "{;}";                 // временно заменяет Символы.ПС



   
ТекстНак = СтрЗаменить(СокрЛП(ТекстНакопительОшибок), Символы.ПС, ВместоПС);
   
ТекстНак = СтрЗаменить(ТекстНак, РазделительСписка, Символы.ПС);

   
ТекстТек = СтрЗаменить(СокрЛП(ТекстОшибки), Символы.ПС, ВместоПС);
   
ТекстТек = СтрЗаменить(ТекстТек, РазделительСписка, Символы.ПС);

   
Коорд    = СокрЛП(КоординатыОшибки);


   
// Разложение параметра ТекстНакопительОшибок в массив строк
   
мвОшибки = Новый Массив;
    Для
к = 1 По СтрЧислоСтрок(ТекстНак) Цикл
       
мвОшибки.Добавить(СтрПолучитьСтроку(ТекстНак, к));
    КонецЦикла;


   
// Разложение параметра ТекстОшибки на строки и их добавление в массив строк
   
Для НомерСтроки = 1 По СтрЧислоСтрок(ТекстТек) Цикл

       
ТекстСтроки = СокрЛП(СтрПолучитьСтроку(ТекстТек, НомерСтроки));
       
КоордСтроки = "";


       
к = Найти(ТекстСтроки, Сцепка);
        Если
к > 0 Тогда
           
КоордСтроки = СокрЛП(Сред(ТекстСтроки, к + СтрДлина(Сцепка)));
           
ТекстСтроки = СокрЛП(Лев(ТекстСтроки, к-1));
        КонецЕсли;


        Если
Коорд <> "" Тогда
            Если
КоордСтроки = "" Тогда
               
КоордСтроки = Коорд;
            Иначе
               
КоордСтроки = Коорд + ", " + КоордСтроки;
            КонецЕсли;
        КонецЕсли;


        Если
КоордСтроки <> "" Тогда
           
ТекстСтроки = ТекстСтроки + Сцепка + КоордСтроки;
        КонецЕсли;


        Если
мвОшибки.Найти(ТекстСтроки) = Неопределено Тогда
           
мвОшибки.Добавить(ТекстСтроки);
           
ТекстНак = ТекстНак + ?(ТекстНак = "", "", Символы.ПС) + ТекстСтроки;
        КонецЕсли;

    КонецЦикла;




    Если
ТипЗнч(ТекстНакопительОшибок) = Тип("Строка") Тогда

       
ТекстНак = СтрЗаменить(ТекстНак, Символы.ПС, РазделительСписка);
       
ТекстНак = СтрЗаменить(ТекстНак, ВместоПС, Символы.ПС);

       
ТекстНакопительОшибок = ТекстНак;

    Иначе

       
ТекстНак = "";
        Для каждого
ТекстСтроки Из мвОшибки Цикл
           
ТекстСтр = ТекстСтроки;
            Если
СтрДлина(ТекстСтр) > 100 Тогда
               
ТекстСтр = СтрЗаменить(ТекстСтр, Сцепка, ВместоПС + "См. ");
            Иначе
               
ТекстСтр = СтрЗаменить(ТекстСтр, Сцепка, ". См. ");
            КонецЕсли;
           
ТекстНак = ТекстНак + ?(ТекстНак = "", "", РазделительСписка) + ТекстСтр;
        КонецЦикла;

       
ТекстНак = СтрЗаменить(ТекстНак, РазделительСписка, Символы.ПС); // каждую ошибку с новой строки
       
ТекстНак = СтрЗаменить(ТекстНак, ВместоПС, Символы.ПС);          // обратная замена

       
Сообщение = Новый СообщениеПользователю;
       
Сообщение.Текст = ТекстНак;
       
Сообщение.Сообщить();

    КонецЕсли;


КонецПроцедуры

См. также

Тестирование QA DevOps и автоматизация разработки Программист Пользователь Платформа 1С v8.3 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Налоговый учет Платные (руб)

Автотесты 1С - готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарий – feature-файл, разработанный с помощью vanessa-automation. Запуск сценария выполняется интерактивно с помощью vanessa-automation или с помощью vanessa-runner в CI-системах. Доступно тестирование тонкого клиента. Поддерживаемые версии конфигураций 1С:Бухгалтерия предприятие 3.0 и версии КОРП: 3.0.166.17.

2160 руб.

20.01.2022    8319    29    0    

14

DevOps и автоматизация разработки Тестирование QA Программист Пользователь Платформа 1С v8.3 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет Платные (руб)

Автотесты 1С - готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарий – feature-файл, разработанный с помощью vanessa-automation. Запуск сценария выполняется интерактивно с помощью vanessa-automation или с помощью vanessa-runner в CI-системах. Доступно тестирование тонкого клиента. Поддерживаемые версии конфигураций 1С:Зарплата и Управление Персоналом 3 и версии КОРП: 3.1.30.108.

3000 руб.

05.08.2024    1817    17    1    

11

Тестирование QA DevOps и автоматизация разработки Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х Россия Бухгалтерский учет Налоговый учет Платные (руб)

Готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарии возможно использовать как для vanessa-automation, так и для СППР. Поддерживаемые версии конфигураций ERP2 и КА2: 2.5.17.168.

2400 руб.

04.07.2022    8849    39    1    

30

Тестирование QA Программист Платформа 1С v8.3 Бесплатно (free)

Чтобы обеспечить высокое качество тиражной конфигурации 1С, ручного тестирования недостаточно – нужно учесть множество комбинаций функциональных опций, группы доступа и влияние подсистем друг на друга. Расскажем о промышленном тестировании флагманского продукта 1С:ERP и его дочерних конфигураций.

31.01.2025    3539    Pr-Mex    26    

22

Тестирование QA Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

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

21.01.2025    964    Sergey1CSpb    6    

4

Тестирование QA Системный администратор Программист Бесплатно (free)

Нагрузочное тестирование — трудоемкий, но обязательный этап крупного IT-проекта, который позволяет выявить дефекты, проверить производительность, стабильность и отказоустойчивость решения. Стоимость тестирования связана с количеством пользователей и сценариев: чем их больше, тем дороже. При этом часто нужны многократные проверки, а вычислительных ресурсов на это может не хватить. Как тогда провести испытания высоконагруженной системы и уложиться в бюджет? Рассказываем, как с помощью нового подхода смогли сэкономить и минимизировать ручные операции при испытании производительности систем на платформе 1С.

16.01.2025    747    1C_Community    9    

4

Тестирование QA Программист Бесплатно (free)

Один раз создав сценарии автоматического тестирования, можно решить несколько задач – получить видеоинструкции для пользователей, организовать нагрузочное тестирование, настроить ролевую модель и реализовать автоматическую проверку доработок конфигурации. Расскажем об опыте применения Vanessa Automation для сокращения затрат на обучение персонала и контроля стабильности критических бизнес-процессов на проекте.

28.11.2024    2927    user1999010    3    

18

Облачные сервисы, хостинг Linux Тестирование QA Сервера Системный администратор Программист Платформа 1С v8.3 Бесплатно (free)

Завершающая публикация цикла "В облако на работу:.. Рецепты от Капитана", в ходе которых был собран полнофункциональный рабочий контур 1С в сети на отечественной Ред ОС. С веб-серверами, доменной авторизацией, архивированием, отказоустойчивостью и прочая, прочая... В этой статье мы определяемся с быстродействием системы, проводим нагрузочное тестирование и отпускаем ее в свободное плавание (зачеркнуто) выпускаем ее в продуктовый контур, где, конечно же, придется отлавливать ошибки, мониторить состояние и т.п.

31.10.2024    1744    capitan    0    

0
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. maxx 996 29.09.13 19:55 Сейчас в теме
Идея хорошая, я бы еще добавил в объект СообщениюПользователя путь к данным объектов или мест где возникла ошибка, чтобы навигация работала по списку ошибок, т.е нажал по ошибке и перешел сразу к месту где ошибка
2. Abadonna 3969 30.09.13 04:34 Сейчас в теме
(0)
// Возможно пользователь использовал Символы.ПС в своих нуждах, поэтому
// временно заменим все Символы.ПС на другую комбинацию символов.
// Потом вернем назад

ВместоПС = "{;}";

Рекомендую: (ALT+0134) (ALT+0135) - никогда простой юзверь такое на клавиатуре не наберет ;)
CratosX; rkravtsov; +2 Ответить
3. Yashazz 4804 30.09.13 12:45 Сейчас в теме
Да, уже витает в воздухе.
Я себе смастерил накопитель в виде дерева, которое отслеживает "погружение" в вызовы различных процедур да функций; а потом вывожу его в макет с расшифровкой, и показываю, где были какие сообщения. Красиво и удобно, но кода требует, конечно.
4. ufo58 161 30.09.13 17:12 Сейчас в теме
все бы ничего
и идея хороша, и посыл нормальный
но ... выводить "Сообщением", тем более в управляемых формах ... бррр
да и Дерево ... тяжеловато
подумай, может дать вариант формирования тип Текст ?
с последующим просмотром
или сохранением ...
5. TitanLuchs 416 02.10.13 14:42 Сейчас в теме
Присоединюсь к предыдущему оратору. При возможности тоже стараюсь избегать использование "Сообщить" и "СообщениеПользователю" в УФ, потому что перекореживание формы в этот момент - это иногда зрелище не для слабонервных. Одно время в своей конфе открывал отдельное окно с сообщениями, на быстродействии это не сказывалось (потому что форма все равно перерисовывается при изменении размера), но юзеров не так бесило.
6. pakill 43 03.10.13 09:38 Сейчас в теме
Вообще-то я старался сделать легкую процедуру, не зависящую ни от конфигурации, ни от контекста.
Писать что-то тяжеловесное на тот случай, который может никогда и не произойти как-то не хотелось. Я лишь ставил цель, предоставить пользователю шанс самостоятельно разобраться и исправить ошибку в данных, если таковая возникнет.

Насчет вывода ошибки с помощью Сообщить():
А как ее еще выводить на стороне сервера?

Это можно сгладить лишь частично:

#Если Сервер Тогда
Сообщить(...);
#Иначе
Предупреждение(...);
#КонецЕсли

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

7. Yashazz 4804 03.10.13 12:57 Сейчас в теме
(6) Вот я именно и заменил "Сообщить" своей процедурой. И УФ не корёжит, и на сервере работает, в протокол пишет.
8. devel0per 1 08.10.13 02:08 Сейчас в теме
Хоть комментарий к процедуре и прекрасен, но из него не ясно чем плох отладчик, ведь
нам никто не запрещает им пользоваться на сервере.
Не лучше ли будет вместо:
Коорд    = СокрЛП(КоординатыОшибки);

и
Если Коорд <> "" Тогда

писать:
Если ПустаяСтрока(Коорд) Тогда

Вот не помню в клюшках функц. ПустаяСтрока была?
14. pakill 43 09.10.13 02:44 Сейчас в теме
(8). Чем же плох отладчик? Чтож. Дайте пользователю отладчик. Пусть ищет и исправляет ошибки в данных (подчеркиваю в данных, а не в коде). Ну а я, как-то не готов давать пользователю отладчик.

Коорд = СокрЛП(..) // это чтобы вместо: "текст , текст" всегда было так: "текст, текст"
Если Коорд <> "" Тогда

Здесь первая строка нужна сама по себе, а не для того, чтобы выполнить проверку во второй строке.
Но поскольку она все же есть, то не вижу ничего плохого чтобы сравнить <> ""


(12). Насчет Попытка-Исключение.
А Вы попробуйте воспроизвести в точности тот пример из комментария с помощью попытки-исключения.
И сразу же выяснится, что вы будете заниматься разбором строк в каждой процедуре, где используете эту конструкцию. Кроме того, у Вас возникнут трудности при передаче списка ошибок. И чтобы облегчить жизнь придется написать свою процедуру, занимающуюся разбором строк и накоплением ошибок.
Но скорее всего, Вы просто используете ту самую процедуру ОшибкуОтдать(), приведенную выше.
Так что, попытка-исключение - это всего лишь, один из способов ее применения.


>>
Ну а исключение клиентского (самого высокого) уровня уже можно как угодно отработать. Сообщением, предупреждением, или записью в лог.


Заметьте, принципиальную разницу: сообщение может быть выдано не только на верхнем уровне, а на любом из уровней. В примерах как раз показан вывод из разных процедур. И это зависит от того, как вызвана процедура.
В Вашем случае - это наличие или отсутствие конструкции попытка-исключение в процедурах верхнего уровня.
Это значит, что "ВызватьИсключение" - это и есть Ваш способ вывода ошибки, т.е. Вы с этим уже заранее определились.
9. WalterMort 247 08.10.13 13:49 Сейчас в теме
Автор изобрел велосипед, вместо грамотной работы с исключениями.
10. Evil Beaver 8263 08.10.13 13:56 Сейчас в теме
(9) WalterMort, ну тогда уж приводите пример "грамотной" работы с исключениями в рамках поставленной задачи. Что вы понимаете под "грамотной" работой?
12. WalterMort 247 08.10.13 14:55 Сейчас в теме
(10) Обычная передача ошибок снизу наверх. Классов исключений в 1С нет, но описания ошибки для замысла автора достаточно:

Процедура Внешняя()
Попытка
Внутренняя();
Исключение
ВызватьИсключение "Невозможно выполнить внешняя: " + ОписаниеОшибки(); // наверх
КонецПопытки;
КонецПроцедуры

Процедура Внутренняя()
Попытка
а = б/0;
Исключение
ВызватьИсключение "Невозможно выполнить внутренняя"; // передаем наверх
КонецПопытки;
КонецПроцедуры


Результат: "Невозможно выполнить внешняя: Невозможно выполнить внутренняя"



Ну а исключение клиентского (самого высокого) уровня уже можно как угодно отработать. Сообщением, предупреждением, или записью в лог.
13. Evil Beaver 8263 08.10.13 16:05 Сейчас в теме
(12) WalterMort, вот поскольку классов исключений нет, то все, что могут передать исключения - это строки. Отсюда, шибко "грамотной" работы с исключениями все равно не будет.
11. Bukaska 140 08.10.13 13:56 Сейчас в теме
(9) WalterMort, Ой да ладно.. ну что же вы все как эти... даже не знаешь как назвать... Я конечно понимаю что нужно реализовываться, знаю что и инициатива бывает наказуема. Но кто не работает, тот не ест)))
15. monkbest 114 27.05.16 09:10 Сейчас в теме
Оставьте свое сообщение