Props-based тестирование это такой хитрый способ не писать юнит-тесты. И обосраться, как же без этого.

Trivia

Для начала, нагм понадобятся генераторы. В основе их лежат бесконечные списки, энумераторы или бесконечные генераторы, то есть, с точки зрения утиного типа, просто фабрики, которые выдают объекты в определнном порядке. Общая логика их написания простая: сначала идут особые точки, потом случайные. Если тип подразумевает ограниченное множество, то можно использовать и конечные аналоги. Так как все это изоморфно бесконечным (и иногда конечным) спискам, будем использовать термин список значений, чтобы обозначить все эти варианты.

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

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

#!/usr/bin/env node

function* multiplication(x, y) {
  let xs = [], ys = []

  for(;;) {
    const x1 = x.next()
    if (!x1.done) {
      xs.push(x1.value)
      for(let i in ys) { yield [x1.value, ys[i]] }
    }

    const y1 = y.next()

    if (!y1.done) {
      ys.push(y1.value)
      for(let i in xs) { yield [xs[i], y1.value] }
    }

    if (x1.done && y1.done) { return }
  }
}

module.exports = multiplication

Таким образом, мы получаем значения из этих списков по очереди. Заметим, что такое умножение не ассоциативно, поэтому обобщим (за кадром) эту функцию на произведение N элементов.

Переминожать генераторы в js - тяжкий труд, но в этом языке они достаточно естественны, что ускоряет написание примера

Бесконечные тесты

Плохи тем, что никогда не знаешь, упадут ли они (проблема остановки в чистом виде). Их количество разумно ограничить сверху большим числом. Проблема больших чисел в том, что они действительно больше. Для вещественных чисел, например, мы хотим покрыть достаточно большой список особых случаев из коробки, начиная от 0 и 1, и заканчивая комбинациями констант. Плюс бесконечный хвост нам тоже зачем то нужен, так что, мы возьмем не меньше 100 первых элементов списка значений. Эта цифра умножается при декартовом произведении. Предположим, у нас есть 2 переменных. Это 10 000 итераций. Если мы возьмем 3 переменных, то получим 1 000 000 итераций. Это очень много, если мы говорим об одно единственном тесте, даже в C мы вряд успеем моргнуть, даже если функция сводится к простой арифметеке

Получается, все зря?

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

Спеки, которые ловят ошибки, о которых автор не подумал

это, конечно, хорошо, но это ложное ощущение надежности, кавередж из ниоткуда, хуяк хуяк и на продакшен. dixi

Post scriptum

Автор начал писать это статью с мыслью о том, что props-based тесты это круто ☹