Как стать автором
Обновить

Комментарии 28

постойте, return 3 всё ещё успешно проходит equal(sum(1, 2), sum(2, 1))

Ну как так-то, 2 строчками ниже:


const rand = Math.random
const [n1, n2] = [ rand(), rand() ]

const actual = sum( n1, n2 )
const expected = sum( n2, n1 )

equal(actual, expected)
Вы не поверите, но и такой тест return 3 тоже проходит :D

Wait a second...


Признаю, был неправ :(

Поэтому имеет смысл комбинировать example и property-based тесты.
Могу ошибаться, но я бы добавил также свойство add x 0 = x. В таком случае просто return 3 (или любой другой константы) не сработает.

Какова вероятность, что три рандома подряд выдадут вам 3 нуля? Для 64-битного числа это будет 1/2**63**3 = 1/7e56. Если взять суперкомпьютер ближайшего будущего на 7 эксафлопс, то матожидание выпадения джекпота из [ 0 , 0 , 0 ] будет 1e38 секунд или 1e30 лет.


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

Я могу ошибаться, но думаю что либы по property-test-ы к случайным значениям ещё и явно примешивают всякие базовые пограничные значения. Скажем эмоджи, какие-нибудь особо хитрые utf8 штуки (вроде буквы Ё в mac os), нули, предельные числа, дроби и пр.

Да, хорошие реализации QuickCheck используют тот факт, что некоторые числа и строки гораздо чаще вызывают проблемы.

То есть некоторого предустановленного набора граничных условий хватит всем?


function( a , b ) {
    return 1 / ( a * b - 42 )
}

Через сколько итераций QuickCheck найдёт проблемные значения?

Вероятно не найдёт вообще. Но вроде как никто и не позиционирует это как серебрянную пулю. Все особые случаи, которые автор теста сам смог увидеть/заметить/вспомнить/понять, надо записать явным традиционным образом, а не надеяться на то, что random всё выведет.

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

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

Есть подобное, правда не совсем для property based testing, но близко — guided fuzzing, довольно популярный инструмент из этой категории — AFL. Изначально делался под C/C++, но его можно прикрутить и к другим языкам, например к питону (вот тут в третьей части это довольно неплохо описывается — а первые две посвящены как раз property based testing и генераторам тестовых данных для них, так что тоже может быть интересно)

Это уже статический анализ получается. Но в мире js с ним будет сложно, потому что всё может зависеть от контекста исполнения множеством самых разных способов

А какая альтернатива? Ждать 1e30 лет пока пользователи найдут этот баг?

Открыть ящик, выписать классы эквивалентности, и на все граничные условия написать тесты, а не пытаться брутфорсить континуум.

А не нужно выполнять все тесты с одним и тем же рандомом. На первом тесте надо запустить рандом с маленькой областью (скажем, [0, 1]), на одиннадцатом выйти в область побольше ([0,1, -1, INT_MAX, INT_MIN] ), на сотом взять уже большой разброс. Тестировать массивы, начиная с пустых, продолжая маленькими и заканчивая большими.
Не скажу за JSVerify, но в Erlang сделано именно так.
хорошо пишешь
Да, имеет смысл обратиться к другим экосистемам, в которых такое тестирование уже давно практикуется. Haskell, F#, Scala и т.д.
Ничего нового тут не придумать, учитывая то, что они начали практиковать property-тесты намного раньше.

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

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

Я думаю, проблема детерминированности решается если рандомные значения логгируются, и вообще, используются для задания начальных параметров, а не внутри теста.
Спасибо! Хотелось бы что бы тема развивалась в индустрии.

P.S. Ссылки на видео с докладов лучше приложить в самое начало.
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий