Как я могу сгенерировать логическое выражение рекурсивно в гипотезе Python? - PullRequest
0 голосов
/ 06 сентября 2018

Я новичок в библиотеке гипотез Python и тестировании на основе свойств в целом. Я хочу сгенерировать произвольно вложенные выражения политики со следующей грамматикой:

((А и В) или С)

Я чувствую, что рекурсивная стратегия - это то, чего я хочу, но мне трудно понять, как ее использовать. Код, который у меня есть, кажется, генерирует только один «уровень» выражения. Вот что у меня есть:

import unittest

from hypothesis import given
from hypothesis.strategies import text, composite, sampled_from, characters, recursive, one_of


def policy_expressions():
    return recursive(attributes(), lambda base_strategy: one_of(base_strategy, policy_expression()))

@composite
def policy_expression(draw):
    left = draw(attributes())
    right = draw(attributes())
    gate = draw(gates())
    return u' '.join((left, gate, right))


def attributes():
    return text(min_size=1, alphabet=characters(whitelist_categories='L', max_codepoint=0x7e))


def gates():
    return sampled_from((u'or', u'and'))


class TestPolicyExpressionSpec(unittest.TestCase):

    @given(policy_expression=policy_expressions())
    def test_policy_expression_spec(self, policy_expression):
        print policy_expression
        assert policy_expression # not empty

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

Ответы [ 2 ]

0 голосов
/ 05 апреля 2019

Я считаю, что правильный путь - принять base_strategy в качестве аргумента policy_expression:

def policy_expressions():
    return recursive(attributes(), policy_expression)

@composite
def policy_expression(draw, base_strategy):
    left = draw(base_strategy)
    right = draw(base_strategy)
    gate = draw(gates())
    return u' '.join((left, gate, right))

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

0 голосов
/ 07 сентября 2018

Я думаю, что это может сделать то, что вы хотите.

import unittest

from hypothesis import given
from hypothesis.strategies import text, composite, sampled_from, characters, recursive, one_of


def policy_expressions():
    return one_of(attributes(), policy_expression())

@composite
def policy_expression(draw):
    left = draw(policy_expressions())
    right = draw(policy_expressions())
    gate = draw(gates())
    return u' '.join((left, gate, right))


def attributes():
    return text(min_size=1, alphabet=characters(whitelist_categories='L', max_codepoint=0x7e))


def gates():
    return sampled_from((u'or', u'and'))


class TestPolicyExpressionSpec(unittest.TestCase):

    @given(policy_expression=policy_expressions())
    def test_policy_expression_spec(self, policy_expression):
        print policy_expression
        assert policy_expression # not empty

if __name__ == '__main__':
    unittest.main()
...