Почему мой простой тест на конечные гипотезы никогда не останавливается? - PullRequest
5 голосов
/ 01 июля 2019

Я использую набор тестов с гипотезой-4.24.6 и pytest-5.0.0. Мой тест имеет конечный набор возможных входных данных, но гипотеза никогда не заканчивает тестирование.

Я сократил его до следующего минимального примера, который я запускаю как pytest test.py

from hypothesis import given
import hypothesis.strategies as st


@given(x=st.just(0)
         | st.just(1),
       y=st.just(0)
         | st.just(1)
         | st.just(2))
def test_x_y(x, y):
    assert True

Я ожидаю, что он попробует все шесть комбинаций здесь, а затем добьется успеха. Или, возможно, небольшой кратный, чтобы проверить на облупленность. Вместо этого он работает бесконечно (после 15 минут тестирования я его убиваю).

Если я прерву тест, обратные следы, кажется, показывают, что он просто непрерывно генерирует новые примеры.

Что я здесь не так сделал?

Ответы [ 2 ]

3 голосов
/ 01 июля 2019

Это, похоже, связано с количеством успешных тестов hypothesis пытается сгенерировать:

>>> from hypothesis import given, strategies as st
>>> @given(st.integers(0,1), st.integers(0,2))
... def test(x, y):
...   print(x, y)
...   assert True
... 
>>> test()
0 0
1 1
1 0
1 2
1 1
0 1
0 0
1 2
0 2
0 2
1 0
1 2
0 1
0 1
1 2
[snip…]

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

Самый простой подход может быть просто ограничить количество примеров , необходимых для прохождения этого теста:

>>> from hypothesis import settings
>>> @settings(max_examples=30)
... @given(st.integers(0,1), st.integers(0,2))
... def test(x, y):
...   print(x, y)
...   assert True
... 
>>> test()
0 0
1 1
1 0
0 2
1 2
0 1
0 1
1 1
1 0
1 1
0 1
1 2
1 1
0 0
0 2
0 2
0 0
1 2
1 0
0 1
1 0
1 0
0 1
1 2
1 1
0 2
0 0
1 2
0 0
0 2

Другой подход, учитывая небольшое количество тестовых случаев, состоит в том, чтобы явным образом описать их все, используя @example и попросить hypothesis запустить только те явные примеры :

>>> from hypothesis import given, example, settings, Phase, strategies as st
>>> @settings(phases=(Phase.explicit,))
... @given(x=st.integers(), y=st.integers())
... @example(x=0, y=0)
... @example(x=0, y=1)
... @example(x=0, y=2)
... @example(x=1, y=0)
... @example(x=1, y=1)
... @example(x=1, y=2)
... def test(x, y):
...   print(x, y)
...   assert True
... 
>>> test()
0 0
0 1
0 2
1 0
1 1
1 2

Также обратите внимание, что st.just(0) | st.just(1) эквивалентно st.one_of(st.just(0), st.just(1)), поэтому выберите подход и придерживайтесь его, но не смешивайте их.

1 голос
/ 04 июля 2019

Эта ошибка была исправлена ​​в Гипотезе 4.26.2 , или, по крайней мере, мы так думали; на самом деле исправлено в 4.26.3, хотя: https://hypothesis.readthedocs.io/en/latest/changes.html#v4-26-3

...