Сравнение коллекций
Речь пока идет только об обработке УтвержденияBDD
Что имеем - умеет сравнивать только примитивные типы. Это хорошо. Не умеет сравнивать коллекции. Это плохо, потому как чаще всего надо именно коллекции сравнивать (по крайней мере мне). Как я вижу сравнение? Есть тест - Процедура ТестПроверкиРавенстваСтруктур() Экспорт
СтруктураПроверки = новый Структура;
СтруктураПроверки.Вставить("Поле",1);
СтруктураПроверки.Вставить("Поле2",новый Структура("Поле3",4));
СтруктураПроверки2 = новый Структура;
СтруктураПроверки2.Вставить("Поле",1);
СтруктураПроверки2.Вставить("Поле2",новый Структура("Поле3",4));
Ожидаем.Что(СтруктураПроверки).Равно(СтруктураПроверки2);
КонецПроцедуры
Как видно - пытаемся сравнить 2 структуры (взяты для простоты, остальные коллекции аналогично работают)
Предлагая сделать так - результат сравнения не булево, а структура, примерно так
Функция Ок(значение) возврат Новый Структура("Тип,Результат",1,Значение) КонецФункции
Функция Ошибка(значение) возврат Новый Структура("Тип,Результат",0,Значение) КонецФункции
функция Проверить2Значения(Проверяемое,Ожидание) экспорт типЧто = ТипЗнч(Проверяемое); типСЧем = ТипЗнч(Ожидание); если типЧто <> типСЧем тогда Возврат Ошибка("Типы различаются. Первый - "+типЧто+", Второй - "+типСЧем); конецЕсли;
// типы равны!
если ПримитивныеТипы.СодержитТип(типЧто) тогда
Если ЛогическоеВыражениеВерно(x = y) тогда
Возврат Ок(Истина);
Иначе
Возврат Ошибка(СформироватьСообщениеОбОшибке(х, "РАВНО (" + у + ")."));
Возврат ложь;
КонецЕсли;
конецЕсли;
КонецФункции
Вызывающая функция анализирует что вернули по полю Тип, если 0 - то сравнение прошло с ошибкой, в поле значение - описание ошибки (может быть строка, может еще что), Если 1 - то сравнение прошло успешно.
Остается вопрос сообщений. Предположим даны 2 структуры - х = Новый Структура("Поле1",1); у = Новый Структура("Поле1","Поле2"); Сравнение вернет ложь (поля не равны), Текст сообщения может быть таким - "Не равны значения поля 'Поле1' - Ожидалось '"Поле2"', есть '1'", но что выводить для более сложных случаев? Например если так - х = Новый Структура("Поле1",1); х0 = Новый Структура("Поле1",1); у = Новый Структура("Поле1",х0);
Фактически вопрос сводиться к простому - как выводить позицию в коллекции в которой возникла ошибка? что выводить в ожиданиях и результате?
АПИ утверждений БДД не нарушается, это хорошо. @wizi4d Что скажешь?
что выводить для более сложных случаев? Например если так -
х = Новый Структура("Поле1",1);
х0 = Новый Структура("Поле1",1);
у = Новый Структура("Поле1",х0);
Фактически вопрос сводиться к простому - как выводить позицию в коллекции, в которой возникла ошибка? что выводить в ожиданиях и результате?
В примере непонятно, что с чем сравниваем! если х и у, тогда будет выдано сообщение о разных типах, если х и х0, тогда простое сообщение, указанное у тебя в тексте
Главный вопрос сравнения коллекций - что делать, если в одной коллекции есть элементы, которой нет во второй коллекции. Эти коллекции равны или не равны? Тут возможны несколько поведений
@kuntashov Твое мнение также интересно (в свете тест-раннера для 1скрипт)
сравниваем х и у. А какое сообщение будет? "Не равны значения поля 'Поле1' - Ожидалось '1', есть ???? а вот что вместо есть ставить? Я пока вижу так "Не равны значения поля 'Поле1' - Ожидалось '1', есть 'Структура' Или "Не равны значения поля 'Поле1' - Ожидалось '1', есть ХХХ Вместо ХХХ - сериализованное в json значение структуры у.
Главный вопрос сравнения коллекций - что делать, если в одной коллекции есть элементы, >которой нет во второй коллекции. Эти коллекции равны или не равны?
Для начала считаем что не равны, потому что иначе придется менять инициализацию тестов, и переменные контекста в тестирование добавлять
"Не равны значения поля 'Поле1' - Ожидалось '1', есть ????
а вот что вместо есть ставить?
Я пока вижу так
"Не равны значения поля 'Поле1' - Ожидалось '1', есть 'Структура'
Или
"Не равны значения поля 'Поле1' - Ожидалось '1', есть ХХХ
Вместо ХХХ - сериализованное в json значение структуры у.
ИМХО сериализовать и показывать лучше только первый уровень коллекции для исключения слишком большого вывода.
Для начала считаем что не равны, потому что иначе придется менять инициализацию тестов, и переменные контекста в тестирование добавлять
не понял. Поясни на примере
Процедура Инициализация(КонтекстЯдраПараметр) Экспорт
КонтекстЯдра = КонтекстЯдраПараметр;
Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD",ЭтотОбъект); // **Добавили ссылку на наш объект который тестируем**
КонецПроцедуры
Функция ХитраяПроверка(х,у) экспорт /// **Эту функцию используем для тестирования**
Если х.Поле1 = у.Поле0 тогда
Возрат Ожидание.СоздатьОк(Истина);
иначе
Возрат Ожидание.СоздатьОшибка("Не равно никак");
конецесли;
конецфункии
Процедура ТестПроверкиРавенстваСтруктур() Экспорт
СтруктураПроверки = новый Структура;
СтруктураПроверки.Вставить("Поле",1);
СтруктураПроверки.Вставить("Поле2",новый Структура("Поле3",4));
СтруктураПроверки2 = новый Структура;
СтруктураПроверки2.Вставить("Поле0",0);
СтруктураПроверки2.Вставить("Поле",1);
СтруктураПроверки2.Вставить("Поле2",новый Структура("Поле3",4));
Ожидаем.Что(СтруктураПроверки).СвояПроверка("ХитраяПроверка",СтруктураПроверки2); // **Вызов нашей функции через прокладку**
КонецПроцедуры
Примерно так Вообще об этом надо будет думать, так как тестировать можно не только коллекции, но и всякие хитриые штуки - типа COMобъектов, XDTO и прочей чуши
Главный вопрос сравнения коллекций - что делать, если в одной коллекции есть элементы, которой нет во второй коллекции.
Возможно, стоит сделать два метода: КоллекцииРавны(ПроверяемаяКоллекция, ЭталоннаяКоллекция) (для Структур и Соответствий) и КоллекцияЯвляетсяПодмножеством(ПроверяемаяКоллекция, ЭталоннаяКоллекция)
Второй случай как раз, когда по составу ключей из ПроверяемаяКоллекция она совпадает с ЭталоннойКоллекцией, но в ЭталоннойКоллекции есть и другие ключи. При этом к вложенным коллекциям должна применяться та же стратегия.
Ребята, оформляйте код в блок из тройных обратных одинарных кавычек (которая буква Ё в русской раскладке).
@kuntashov
Возможно, стоит сделать два метода:
КоллекцииРавны(ПроверяемаяКоллекция, ЭталоннаяКоллекция)(для Структур и Соответствий) иКоллекцияЯвляетсяПодмножеством(ПроверяемаяКоллекция, ЭталоннаяКоллекция)
Я уже сталкивался с подобными проблемами при разработке/использовании утверждений по сравнению таблиц/печатных форм.
Подобные проблемы есть не только для Структур/соответствий, но и для таблиц значений и деревьев.
Что делать, если в одной из таблиц/деревьев есть лишние колонки? здесь использование термина подмножество вроде не звучит
тут настраиваемая проверка. Либо пользователь текстом сам пишет, а проверка через выполнить/вычислить это вычисляет, либо - пользователь пишет свой сравниватель с реализацией интерфейса Утверждений, затем регистрирует в коллекции сравнвателей и может вызывать потом себя
но и для таблиц значений и деревьев.
-
ТаблицаЗначений- это индексированная коллекция строк. -
КоллекцияКолонокТаблицыЗначений- это индексированная коллекция объектов типа КолонкаТаблицыЗначений -
ДеревоЗначений- это объект, свойствоСтрокикоторого -КоллекцияСтрокДереваЗначений- также индексированная коллекция и т.п.
Применение термина подмножество мне кажется уместным для любой коллекции.
Если уж заниматься детально этой задачей, то для индексированных коллекций, например, массивов, важно также - они равны, т.е. у них одинаков И состав И порядок или они эквивалентны (т.е. у них одинаков состав, а порядок элементов может отличаться).
Почему тебе не нравится термин подмножество?
@kuntashov Лады, по подмножеству я согласен. ИМХО пока предлагаю работать над равенством.
Эквивалентность ИМХО нужно выделить в соседнюю задачу, если у кого-то возникнет необходимость, может сделать.
@wwall ИМХО ты смешиваешь 2 задачи: 1 сравнение коллекций 2 АПИ пользовательских функций-утверждений
ИМХО удобнее их обсуждать отдельно.
@artbear согласен, будет потребность - сдела(ют|ем).
В первом приближении готово. Отправил Артуру, после того как выложит - можно критиковать. Доделаю на неделе. Мне пока только сравнение структур нужно
Мне не нравится, что метод Равно превратиться в монстра перегруженного функционалом. Можем стоит новый метод сделать, аналог equal в java и sharp?
@wizi4d Я согласен, что монстр и перегрузка это плохо.
Но если с точки зрения для пользователя API метода Равно не изменится, ИМХО это будет хорошо.
Этого монстра никто не видит. Видят только результат работы - равно или нет. И второе - если плодить методы - то что мешает тогда явно писать ТаблицаЗначенийРавно(), ДеревоЗначенийРавно(), МассивРавно() ?
Когда я писал про монстра, я в первую очередь говорил про код и возможность его поддерживать и модифицировать. То что предлагается существенно повысит цикломатическую сложность. В других языках, например java или c#, проверка равенства подразумевает исключительно проверку одинаковости ссылок на объект. Если перекроить метод Равно, то возможность такой проверки исчезнет. Для приведенного сценария используется не проверка на равенство, а проверка эквивалентности (equal). Вот это я и предлагаю сделать:
Ожидаем.Что(Коллекция1).Эквивалентна(Коллекция2);
Я не против нового метода.
Но мы уже выше обсуждали:
Если уж заниматься детально этой задачей, то для индексированных коллекций, например, массивов, важно также - они равны, т.е. у них одинаков И состав И порядок или они эквивалентны (т.е. у них одинаков состав, а порядок элементов может отличаться).
Как мы будем разделять понятия равно и эквивалентность для коллекций ?
Добавил пулл-реквест #589 c кодом от @wwall Предлагаю обсудить.