Тестирование (внешняя обработка)




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

38 Comments

  1. detec

    Поставил плюс авансом.

    Reply
  2. afedorov

    — При нажатии кнопки «Сохранить и закрыть» в форме записи нового документа ошибка:

    {Форма.Документ_Запись.Форма(183)}: Значение не является значением объектного типа (Родитель)

    Вычислять = ?(ТекущиеДанные.Родитель = Неопределено, Текущи

    Reply
  3. awk

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

    Reply
  4. awk

    (2) Исправил:

    — При нажатии кнопки «Сохранить и закрыть» в форме записи нового документа ошибка:

    {Форма.Документ_Запись.Форма(183)}: Значение не является значением объектного типа (Родитель)

    Вычислять = ?(ТекущиеДанные.Родитель = Неопределено, ТекущиеДанные.Вычислять,ТекущиеДанные.Родитель.Вычислять);

    Документ созданый по умолчанию конфигуратором.

    — В форме записи нового справочника поле описания «скукожено».

    А про:

    — В большинстве форм заголовки не совсем правильные.

    Можно поподробнее?

    Reply
  5. afedorov

    (4) Например, для формы Справочник_Запись, Документ_Запись, Документ_ПроверкаРеквизитов, заголовок «Обработка Шаблонное тестирование».

    Заголовок «Обработка Запрос к базе» подходит по смыслу к Форма_SQL, но помоему не к Форма_Запроса и Форма_VBS.

    Reply
  6. artbear

    Для тестировщиков рекомендую посмотреть систему чистого юнит-тестирования SnowTest

    http://www.1cpp.ru/forum/YaBB.pl?num=1267016427/0

    fez в Рарусе ее активно юзает

    Reply
  7. artbear

    (0) Жаль, конечно, что код для 8.2, на 8.1 еще немало народу работает 🙁

    Reply
  8. artbear

    (0) 1. Предлагаю сделать какой-нибудь файл с набором универсальных тестов, не зависящих от конфигурации.

    ИМХО это удобно для демонстрации работы обработки.

    2. Тестированием занимаюсь давно и в 77 и в 8.0/8.1/8.2, из опыта знаю, что неудобно выдавать данные прохождения тестов по всем тестам.

    Если все тесты прошли, достаточно вывести зеленую полосу или просто написать ОК.

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

    Любое другое решение просто будет показывать абсолютно ненужную подробную инфу.

    Максимум, что еще можно позволить — показать общее количество тестов и количество прошедших тестов.

    Reply
  9. artbear

    (0) Не обозначена инфа о выполнении кода в транзакции или без нее.

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

    Тест сам должен подчищать данные или это сделает обработка-браузер тестов ?

    Reply
  10. artbear

    (0) 1. По Алгоритмам непонятен тип Px,Qx и т.д.

    Поясни, что это означает?

    2. Есть ли возможность сохранять ожидания тестов и сверять их при выполнение тестов

    Reply
  11. artbear

    (0) Сравнение данных теста с заранее сохраненными тестовыми данными очень удобно.

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

    Без этой фичи придется в КАЖДОМ тесте вручную решать вопрос хранения тестовых данных, с которыми сравниваем работу теста.

    Reply
  12. awk

    (5) Исправлю, но с низким приоритетом.

    (6) Спасибо, посмотрю.

    (7) К сожалению, сейчас спонсируется (оплачивается мне лично) только разработка на 8.2 найдется спонсор — буду писать под 8.1 и т.д.

    (8)

    1. Со временем в планах (время правда дефицит).

    2. То есть нужно добавить: «Уровень детализации отчета» — думал над этим, но руки пока не дошли. Сделаю с высоким приоритетом.

    (9) Подчистка пока идет на уровне самих тестов. Хотя добавить процедуры ПередВыполнениемТестирования, ПередВыполнениемТеста, ПослеВыполненияТеста, ПослеВыполненияТестов — мысль хорошая. НачатьТранзакцию(), ЗафиксироватьТранзакцию(), ОтменитьТранзакцию() вставлять можно туда будет.

    (10) По алгоритмам я расписал в справке.

    Но кратко о том что это:

    Есть таблица с тремя колонками: «Имя», «Тип»(Px,Qx,Fx), «Текст».

    Есть функция: ВыполнитьКод(Имя, Параметры) — возвращающая массив Результаты

    У функции три модели поведения в зависимости от типа (Px,Qx,Fx) текста, проименованного в колонке «Имя».

    Функция по имени (переменная №1 переданная в функцию) отбирает строки таблицы и последовательно их выполняет.

    Если тип Qx то выполняется запрос и в Результаты добавляется результат запроса (при этом Параметры пытаются передаться как «Параметры запроса»)

    Если тип Px то Выполняется Текст и ничего не добавляется.

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

    (10) При записи отчет сохраняется вместе с тестом. Между тестами можно передавать данные через переменную ГлобальныеПараметры. И сравнивать соответственно. Что бы зафиксировать ошибку достаточно выполнить ДобавитьОшибку(«Описание», «Подробное описание», Расшифровка).

    Сохранить так же можно ЗначениеВФайл.

    Или что-то более конкретное имеется ввиду?

    Reply
  13. CheBurator

    Поясните, плиз, неграмотному в тестировании — каким образом вообще происходит генерация эталонных данных и сравнение результата с эталоном?

    Reply
  14. artbear

    (13) В сабже, похоже, этого в чистом виде нет.

    А ведь это очень важная задача. в (11) я привел примеры использования.

    (12) 1. ИМХО было бы очень удобно автоматически хранить ожидаемые данные теста в данных самого теста и при выполнении сверять ожидаемые данные и данные теста. Это можно сделать спец.параметров в данных теста.

    В этом случае твоя обработка сможет решать сразу 2 задачи — и юнит-тестирование в чистом виде, и тестирование/сравнение с образцом.

    2. По отмене транзакций ИМХО самый простой вариант — это добавить доп.параметр типа ИспользоватьТранзакцию, по умолчанию он включен.

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

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

    Reply
  15. awk

    (14)

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

    Пример(не из головы):

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

    В текущем варианте это делается:

    1. Создаем тест генерирующий входные данные.

    2. Создаем тест который вызывает обработку импорта данных.

    3. Создаем тест проверяющий почтовый ящик.

    + 0. тесты установки значений по умолчанию.

    1.1 Хранить ожидаемые данные теста в данных самого теста — не вариант, а вот именованные двоичные данные — это идея. Их в любом тесте можно преобразовать в таблицу, структуру и т.д., а алгоритм преобразования занести в алгоритмы. Как наберется пара алгоритмов, можно внести в обработку. (Это мое мнение, готов обсудить, т.к. результат теста понятие очень размытое).

    2. Я сначала хотел включить флаг: «Выполнять в транзакции», но не стал, так как посчитал, что проще добавить обработчики ПередЗаписью ПослеЗаписи, где можно если нужно поставить НачатьТранзакцию(); ОтменитьТранзакцию(); Есть мысль, флаг «Выполнять в транзакции» добавить к каждому тесту и верхний уровень перекроет нижний. Но надо подумать, пока решаю вопрос с «уровнем сообщений для вывода в отчет» + рефакторинг.

    Reply
  16. artbear

    (15) 2. По транзакции — из моего опыта я знаю, что 95% тестов удобнее делать с автотранзакцией, и только оставшие 5% можно делать с собственной обработкой транзакции и чисткой данных.

    Например, при тестирования серверного кода на 8.1 транзакции уже не помогут 🙂

    Если заставить тестировщика КАЖДЫЙ раз прописывать условие ввода транзакций, это будет очень неудобно и пользователь будет часто забывать это делать 🙂

    1. А как сделать тест, генерирующий данные? это и будет основная сложность.

    НАМНОГО проще каким-то образом добавить к тесту эталон в любом виде — хоть таблица, хоть двоичные данные, и уже этот эталон сравнивать с результатом.

    Опять же из своего опыта — мной юзается всего 2 вида тестов — юнит-тесты (чистые тесты с подготовкой данных, выполнением над ними неких действий, проверки и очистка данных) (юзаю SnowTest) и функциональные тесты(сравнение с эталоном) (юзаю свою сильно устаревшую систему FuncTest.v8 (есть в профиле) — наследника от FuncTest для 77)

    У тебя юнит-тесты вполне можно организовать, а вот сравнение с эталоном пока ОЧЕНЬ НЕУДОБНО 🙁 т.е. в реальной работе тестировщика использовать обработку будет трудновато 🙁

    Reply
  17. awk

    (16) Тогда план развития, в порядке реализации:

    1. Заголовки (3) третье замечание

    2. Транзакции ??? Надо ответить на вопрос «Быть или не быть?»: «Транзакция на тест» или «Транзакция на тесты».

    3. Сравнение с эталоном.

    3.1 Добавление двоичных данных в тест.

    3.2 Прикрутить обработку «Сравнение данных» (она может сравнивать две таблицы и результат в скд выводить, а таблицы можно ввести вручную или из источника (SQL, 1C запрос, Запрос к внешней базе 1С, 1С Код));

    4???

    Reply
  18. lustin
    artbear пишет:

    Для тестировщиков рекомендую посмотреть систему чистого юнит-тестирования SnowTest

    http://www.1cpp.ru/forum/YaBB.pl?num=1267016427/0

    fez в Рарусе ее активно юзает

    ОФФ: вроде ж не в Рарусе, а в Яндексе.

    Reply
  19. artbear

    (18) Упс, конечно, Яндекс 🙂 Откуда взялся Рарус??

    Reply
  20. artbear

    (17) 1. По заголовкам не понял. в (3) вроде ничего не говорится, только об ошибках

    несложно ИМХО

    2. Транзакции — преимущество имеют транзакции у группы тестов

    чуть сложнее

    3. Эталон обязательно нужен.

    Самое сложное

    ИМХО, решив 2 и 3, закроем большинство потребностей в тестировании !

    Reply
  21. awk

    (20)

    — В большинстве форм заголовки не совсем правильные.

    Действительно — не сложно. Подправил, но пока не выложил.

    2. Транзакции — преимущество имеют транзакции у группы тестов

    чуть сложнее

    Просто, так что в ближайшее время.

    Третье да сложно, но есть наработки в отдельном отчете.

    Reply
  22. support

    Перспективный проект! Даешь юнит тесты для конфигураций.

    Reply
  23. artbear

    (21) Как только добавишь сравнение с эталоном, я могу встроить в твою обработку готовый код/форму

    1. для тестирования внешних печатных форм.

    правда, придется менять конфу, иначе отловишь показ табличного документа 🙁

    Но ИМХО это того стоит.

    2. для тестирования подготовленных произвольных отчетов

    В модуле отчета должны быть служебные методы, с помощью которых могут быть получены данные отчета.

    Интерфейс у меня давно разработан и используется в моем Functest.v8

    Очень удобно юзать при разработке и доработке отчетов и печатных форм.

    Reply
  24. awk

    (23) как-то так.

    Reply
  25. artbear

    (24) Пока некогда смотреть, работы навалилось. В субботу посмотрю.

    Reply
  26. romansun

    8.2 — чорт, чорт, чорт… )))

    awk пишет:

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

    Мда, даунгрэйд уже как-то нелогичен, наверное, будет. Но так хотелось бы…

    А что по поводу стандартной 1С-ной тестировочной конфигурации? Её юзает народ, какие впечатления?

    Reply
  27. romansun

    По теме:

    Функция ПолучитьИмяФайла(ФайлЗначение) может пересечься с типовой глобальной функцией, в случае если на соответствующем общем модуле установлена галка «Глобальный».

    В современных конфах 1С похоже сняло почти везде эту галку с общих модулей, а вот, к примеру, моя рабочая, бывшая в девичестве БП1.5, имеет на всех общих модулях установленный признак «Глобальный».

    Не критично, но возможно имеет смысл переименовать функцию

    Reply
  28. awk

    (27) Спасибо, Надо себе на заметку кинуть — рефакторинг (префиксы).

    (26)

    1. Ответ почему не 8.1 в комменте (12).

    2. Да был опыт, но как-то не очень понравилась. Как проверка того, что изменения не внесли в старый функционал ошибки — отлично. Но создать произвольный эталон для сравнения — сложновато. Да и цена 35 000 (для простых смертных). 35 000 Стоит Test Complete 8, правда на 1С его сложно натравить, но если функционал сравнивать, то он в разы превосходит 1С Сценарное тестирование.

    Reply
  29. romansun

    (28)

    у нас есть сценарное тестирование, велосипедики на иконках там супер, ага 🙂

    Таки да — сложно, сложно и сложно. Съедает очень много времени выделенного человека.

    Чуть изменилась структура базы — тесты посыпались, изменилась форма элемента — тесты посыпались. Хорошо работает, когда ничего не меняется )). Но только зачем тогда тестировать?

    Сравнение с эталоном помогает протестить всю цепочку. К примеру, рождение, жизнь и смерть основного средства. В картинках. Но набивание и отладка такого теста — ого-го по времени :(.

    Но тестировать надо, поэтому смотрю вот какие есть еще варианты для 1С..

    Reply
  30. awk

    (29) А какая версия? У меня была 1.2.3.4, но вроде как сейчас 2.х.х.х.

    Reply
  31. afedorov

    (29) Если для 8.1, то можете попробовать мою обработку «Шаблонное тестирование», которую можно найти на этом сайте. Там есть сравнение с эталоном, и его просто создавать или изменять.

    Reply
  32. romansun

    ага, спасибо, обязательно гляну.

    Reply
  33. Nur

    Спасибо

    Reply
  34. s_ryabov

    Спасибо

    Reply
  35. KliMich

    Спасибо.

    Reply
  36. boggonzikov

    Где посмотреть пример?.

    В файлах «Пример теста», качается Тестирование.epf

    Reply
  37. awk

    (36) boggonzikov, Раньше это был пример. Сейчас не знаю где взять.

    Reply
  38. Serg O.

    в типах значений… почему то нет типа СписокЗначений

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *