Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new: fix algorithm for array compare #98

Merged
merged 1 commit into from
Sep 22, 2021

Conversation

lansfy
Copy link
Contributor

@lansfy lansfy commented Sep 10, 2021

Основная идея новой реализации: мы идем по массиву, который указан в тесте (expected) и ищем первый элемент из вывода сервиса (actual), который ему соответствует. Если такая пара найдена, то помещаем оба элемента в массив успешно связанных элементов (expectedFound и actualFound соответственно). Эту операцию проделываем для всех элементов из expected.

В конце операции все несвязанный элементы добавляем в конец expectedFound и actualFound. И эти два массива возвращаем из функции.

}

// scalars
return fmt.Sprintf("%v", value)
expectedFound = append(expectedFound, expectedError...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Надо бы их совместить, как мне кажется.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

да, теперь из массива возвращаю только отличающиеся части

for i := 0; i < ref.Len(); i++ {
stringChunks = append(stringChunks, representAnythingAsString(ref.Index(i).Interface()))
// For every elem in "expected" try to find elem in "actual"
func matchArrays(expected, actual interface{}, params *CompareParams) (interface{}, interface{}) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

сделал

expectedFound = append(expectedFound, expectedElem)
actualFound = append(actualFound, actualElem)
// remove actualElem from actualArray
if len(actualArray) != 1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вместо этой арифметики со слайсами в качестве результата можно просто собрать маппинг индексов:
индекс expected => соответствующий ему индекс actual

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

из функции возвращаю теперь только не совпадающие части. Заодно уменьшил число массивов до одного.

return errors
}

if params.IgnoreArraysOrdering {
expectedArray, actualArray = getUnmatchedArrays(expectedArray, actualArray, params)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Мое предложение по объединению было - изменить вот этот цикл сравнения, чтобы он для одного из режимов сравнения действовал как сейчас, а для включенного IgnoreArraysOrdering действовал по твоему алгоритму, перебирая все элементы actual-массива, запоминая "использованные". Кстати - помечать использованные можно присваиванием nil-а такому элементу.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не, ну присвоить "nil" то мы точно не можем. Ничего не противоречит тому, чтобы у пользователя допускались значения "null" в массиве, поэтому и я не могу вводить такое ограничение. Не знаю зачем, но сервисов много, возможно какому-то такое понадобится.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Но ведь это не то, что я имел в виду 😁

Кто будет выставлять этот параметр FailFast? Нужен ли он, если в тестах важна информативность (то есть, сообщение обо всех ошибках в данных, а не только о первой) больше скорости исполнения?

В общем, тут нужна помощь других контрибьютеров - возможно, я виноват, что завел тебя не туда.
@JustSkiv @What-If-I

Copy link
Contributor Author

@lansfy lansfy Sep 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Теперь все понятно.

@lansfy lansfy requested a review from luza September 13, 2021 17:35
return errors
}

if params.IgnoreArraysOrdering {
expectedArray, actualArray = getUnmatchedArrays(expectedArray, actualArray, params)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Теперь все понятно.

@fetinin fetinin added bug Something isn't working internal internal change minor release as minor labels Sep 22, 2021
@fetinin fetinin merged commit bf630f2 into lamoda:master Sep 22, 2021
@github-actions
Copy link

🚀 PR was released in v1.5.0 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working internal internal change minor release as minor released
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants