Эта статья является переводом страницы Hypothesis — Details and advanced features взятой из официального руководства. Я не смог найти какой то полезной информации на русском языке по использованию Гипотезы, кроме выступления  23 ноября 2017 г. Александра Шорина на "Moscow Python Meetup 50". Решил разобраться. В итоге что то перевел. В этой части рассмотрим менее распространенные особенности Hypothesis, которые вам не нужны для того что бы начать его использовать, но, тем не менее, облегчат вашу жизнь. Обычно результат неудачного теста выглядит примерно так: Будет напечатано с repr каждого именованного аргумента. Иногда этого недостаточно, потому что у вас есть значения с repr, который не очень описателен или потому, вам нужно увидеть результат некоторых промежуточных шагов вашего теста. Вот в чем заключается функция note: Примечание печатается в последнем запуске теста, чтобы включить любую дополнительную информацию, которая может понадобиться в тесте. Если вы используете pytest вы можете увидеть ряд статистических данных о выполненных тестах
передавая аргумент командной строки --hypothesis-show-statistics. Что позволит включить
некоторые общие статистические данные о тесте: Например, если вы выполнили следующее с --hypothesis-show-statistics: Вы увидите: Заключительная строка "Stopped because" особенно важна для note: она сообщает вам значение настройки, которое определяет, когда тест должен прекратить пробовать новые примеры. Это может быть полезно для понимания поведения тестов. В идеале всегда хочется иметь max_examples. В некоторых случаях (например, в фильтрах и рекурсивных стратегиях) вы увидите события, которые описывают некоторые аспекты генерации данных: В итоге получите что-то вроде: Можно также отметить пользовательские события в тесте с помощью функции event: Тогда вы увидите результат: Аргументы event могут быть любого типа, но два события будут считаться одинаковыми, если они совпадают при преобразовании в строку с str. Иногда Hypothesis не дает вам точно правильный тот самый вид данных, который вы хотите — это в основном правильные формы. Это не особенно страшно, но некоторые примеры при этом будут сбоить, а вы не хотите заботиться о них. Вы можете просто игнорировать эти случаи, прервав тест раньше, но при этом возникает риск случайно упустить важное и испытать намного меньше, чем вы расчитывали. Также было бы неплохо потратить меньше времени на плохие примеры — если вы используете 100 примеров на тест (по умолчанию), и получается, что 70 из этих примеров не соответствуют вашим потребностям, получается что очень много времени потрачено впустую. Например, предположим, что у вас был следующий код: Выполнение его даст нам: Это раздражает. Мы (возможно) знаем что то о NaN, но в данном эпизоде нам не хотелось бы о нем вспоминать и как то обрабатывать эту ситуацию, но как только Hypothesis найдет пример NaN, он всё бросит и поспешит рассказать нам об этом. Тест провалится и испортит нам всю статистику, а мы хотим его пройти. Так что давайте блокировать этот конкретный пример: Этот вариант кода уже проходит без проблем. В целях исключения легкого предполагаемого перехвата вы можете предположить гораздо больше, чем намеревались и Hypothesis не удастся тест если он не сможет найти достаточно примеров, проходящих assumption (предположение). Если бы мы написали: Тогда при запуске у нас получилось бы исключение: Hypothesis имеет адаптивную стратегию разведки, чтобы попытаться избежать случаев, которые фальсифицируют assumptions и, как правило, приводит к тому, что все еще можно найти examples (примеры) в труднодоступных ситуациях. Предположим, у нас было следующее: Неудивительно, что такой тест потерпит неудачу и выдаст фальсифицирующий пример . Добавление assume(xs) к этому удалит тривиальный пустой пример и дает нам . Добавим assume(all(x > 0 for x in xs)) и, о, чудо! он проходит! Действительно, сумма положительных больше нуля! Удивительное не в том, что он не находит встречный пример, но что он находит достаточно примеров на всех. Чтобы убедиться, что происходит что-то интересное, попробуем это на длинных списках. Например, добавим assume(len(xs) > 10). В принципе, это никогда не должно быть example: примитивная стратегия найдет меньше одного из тысячи примеров, потому что, если каждый элемент списка отрицателен с вероятностью наполовину, вам придется получить десять из них, случайно. В конфигурации по умолчанию гипотеза сдается задолго до того, как она попробовала 1000 примеров (по умолчанию она пробует 200). Вот что произойдет, если мы попытаемся запустить это: Как видим, Hypothesis не находит много примеров, но некоторые — вполне достаточны, чтобы получить благополучный результат. В общем, если вы можете себе позволить точнее формировать свои стратегии для своих тестов, то вы должны это использовать — например integers(1, 1000) намного лучше, чем assume(1 <= x <= 1000). Тип объекта, который используется для изучения примеров, предоставленных вашей тестовой функции, называется hypothesis.SearchStrategy.
Они создаются с использованием функций, открытых в модуле hypothesis.strategies. Многие из этих стратегий предоставляют различные аргументы, которые можно использовать для настройки генерации. Например, для целых чисел вы можете указать min и max значения целых чисел, которые вам требуются. Если вы хотите увидеть, что именно выдаст стратегия, вы можете запросить пример: Многие стратегии построены из других стратегий. Например, если вы хотите определить кортеж, нужно сказать, что происходит в каждом элементе: Дополнительная информация :doc:available in a separate document <data>. Декоратор @given может использоваться для указания того, какие аргументы функции должны быть параметризованы. Вы можете использовать аргументы позиционного или именованного вида или их микс. Например, все приведенные ниже действительны: Следующие нет: Правила определения того, что является допустимым использованием given, следующие: Причина поведения "крайних правых именованных аргументов" заключается в том, что @given с помощью методов экземпляра: self будет передано функции как нормальное и не будет параметризоваться. Функция, возвращенная given, имеет все те же аргументы, что и исходный тест, за вычетом тех, которые заполнены @given. Hypothesis предоставляет вам средство, которое позволяет вам контролировать, как он запускает примеры. Это позволяет выполнять такие действия, как настройка и разборка каждого примера, выполнение примеров в подпроцессе, преобразование тестов сопрограмм в обычные тесты и т. д. Например, TransactionTestCase в
Django extra запускается каждый пример в отдельной транзакции базы данных. Таким образом, вводя понятие executor или по русски исполнителя. executor-это, по сути, функция, которая берет блок кода и запускает его. По умолчанию executor-ом является: Вы определяете исполнителей, определив метод execute_example в классе. Любые методы тестирования используемые в этом классе с декоратором @given будут использовать self.execute_example как исполнителя теста. Например, следующий executor выполняет весь свой код дважды: Примечание: функции, которые вы используете в map и т.п. Будут работать внутри исполнителя. т.е. они не будут вызываться до вызова функции перешедшей к execute_example. Исполнитель должен уметь обрабатывать передаваемую функцию, которая возвращает None, иначе он не сможет запускать обычные тестовые случаи. Например, следующий исполнитель недействителен: и должны быть переписаны как: Вы можете использовать функции исследования данных Hypothesis, чтобы найти значения, удовлетворяющие некоторому предикату (условию отбора). Это обычно полезно для изучения пользовательских стратегий, определенных с помощью: @composite, или экспериментировать с условиями фильтрации данных. Первый аргумент hypothesis.find описывает данные обычным способом для аргумента hypothesis.given, и поддерживает all the same data types <data>. Второй-это предикат, который он должен удовлетворить. Конечно, не все условия выполняются. Если вы запросите у Hypothesis пример с условием, которое всегда ложно, это вызовет ошибку: (lambda x: unknown связано с тем, что Hypothesis не может получить исходный код лямбда-выражения из интерактивной консоли python. ) В некоторых случаях hypothesis может решить, что делать, когда вы опускаете аргументы. Это основано на самоанализе, а не на магии, и поэтому имеет четко определенные пределы. hypothesis.strategies.builds() проверят сигнатуру target ( В python3.6 inspect.getfullargspec()). Если есть обязательные аргументы с аннотациями типа и стратегия не была передана hypothesis.strategies.builds(), то hypothesis.strategies.from_type() используется для их заполнения. Вы также можете передать специальное значение hypothesis.infer() в качестве аргумента, чтобы запихнуть в этот вывод аргументы со значением по умолчанию. @given не выполняет никакого неявного вывода для требуемых аргументов, поскольку это нарушило бы совместимость с функционалом pytest.
hypothesis.infer может использоваться в качестве аргумента ключевого слова для явного заполнения аргумента из аннотации типа. Аннотации типа PEP 3107 не поддерживаются в Python 2, и Hypothesis не проверяет комментарии типа PEP 484 во время выполнения. В то время как hypothesis.strategies.from_type будет работать как обычно, вывод в
hypothesis.strategies.builds и @given будет работать, только если вы вручную создадите атрибут __annotations__ (например, с помощью декораторов @annotations(...) и @returns(...)).  Модуль typing полностью поддерживается на Python 2, Если у вас установлен backport. Модуль typing является временным и имеет ряд внутренних изменений между Python 3.5.0 и 3.6.1, в том числе во второстепенных версиях. Все они поддерживаются, но могут возникнуть проблемы со старой версией модуля. Пожалуйста, сообщите нам о них и рассмотрите возможность обновления до более новой версии Python в качестве обходного пути.  Обратно Дальше