Оптимизация использования стратегий (генерация данных)

Я хотел бы оптимизировать скорость генерации данных для своих модульных тестов. Кажется, что такие стратегии, как from_regex и dictionaries, требуют много времени для создания примеров.

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

from hypothesis import given
from hypothesis.strategies import (
    booleans,
    composite,
    dictionaries,
    from_regex,
    integers,
    lists,
    one_of,
    text,
)

param_names = from_regex(r"[a-z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*", fullmatch=True)
param_values = one_of(booleans(), integers(), text(), lists(text()))


@composite
def composite_params_dicts(draw, min_size=0):
    """Provides a dictionary of parameters."""
    params = draw(
        dictionaries(keys=param_names, values=param_values, min_size=min_size)
    )

    return params


params_dicts = dictionaries(keys=param_names, values=param_values)


@given(params=params_dicts)
def test_standard(params):
    assert params is not None


@given(params=composite_params_dicts(min_size=1))
def test_composite(params):
    assert len(params) > 0


@given(integer=integers(min_value=1))
def test_integer(integer):
    assert integer > 0

Тест test_integer() используется как справочник, поскольку он использует простую стратегию.

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

test_composite() использовать составную стратегию, которая принимает необязательный аргумент. test_standard() используйте аналогичную стратегию, за исключением того, что она не является составной.

Ниже результаты теста:

> pytest hypothesis-sandbox/test_dicts.py --hypothesis-show-statistics
============================ test session starts =============================
platform linux -- Python 3.7.3, pytest-5.0.1, py-1.8.0, pluggy-0.12.0
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('/home/damien/Sandbox/hypothesis/.hypothesis/examples')
rootdir: /home/damien/Sandbox/hypothesis
plugins: hypothesis-4.28.2
collected 3 items                                                                                                                                                       

hypothesis-sandbox/test_dicts.py ...                                    [100%]
=========================== Hypothesis Statistics ============================

hypothesis-sandbox/test_dicts.py::test_standard:

  - 100 passing examples, 0 failing examples, 1 invalid examples
  - Typical runtimes: 0-35 ms
  - Fraction of time spent in data generation: ~ 98%
  - Stopped because settings.max_examples=100
  - Events:
    * 2.97%, Retried draw from TupleStrategy((<hypothesis._strategies.CompositeStrategy object at 0x7f72108b9630>,
    one_of(booleans(), integers(), text(), lists(elements=text()))))
    .filter(lambda val: all(key(val) not in seen 
    for (key, seen) in zip(self.keys, seen_sets))) to satisfy filter

hypothesis-sandbox/test_dicts.py::test_composite:

  - 100 passing examples, 0 failing examples, 1 invalid examples
  - Typical runtimes: 0-47 ms
  - Fraction of time spent in data generation: ~ 98%
  - Stopped because settings.max_examples=100

hypothesis-sandbox/test_dicts.py::test_integer:

  - 100 passing examples, 0 failing examples, 0 invalid examples
  - Typical runtimes: < 1ms
  - Fraction of time spent in data generation: ~ 57%
  - Stopped because settings.max_examples=100

========================== 3 passed in 3.17 seconds ==========================

Составные стратегии медленнее?

Как оптимизировать индивидуальную стратегию?


person Damien Flament    schedule 24.07.2019    source источник


Ответы (1)


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

Советы по оптимизации стратегии сводятся к «не делай медленных вещей», так как нет способа пойти быстрее.

  • Сведите к минимуму использование .filter(...), поскольку повторные попытки выполняются медленнее, чем их отсутствие.
  • Размеры шапки, особенно вложенных вещей.

Итак, для вашего примера это могло бы быть быстрее, если бы вы ограничили размер списков, но в противном случае это просто медленно (иш!), Потому что вы генерируете много данных, но мало с ними делаете.

person Zac Hatfield-Dodds    schedule 28.07.2019