0

我最近看了一下假设并像这样使用它:

import hypothesis.strategies as s
from hypothesis import given

@given(s.integers(min_value=-(10 ** 6), max_value=10 ** 6))
def test_factorize(an_integer):
    if an_integer == 0:
        # This is tested in `test_factorize_zero` and should throw an exception
        return
    factors = mpu.math.factorize(an_integer)
    product = 1
    for factor in factors:
        product *= factor
    assert product == an_integer

这很酷。我看到的主要限制是策略(例如s.integers),尽管有很多策略,我仍在学习有哪些策略/如何正确使用它们。

给定使用 pydantic 的类型注释类,是否有生成对象的策略?

我的尝试

from typing import Optional

from hypothesis import given
from hypothesis.strategies import from_type
from pydantic import BaseModel


class Adress(BaseModel):
    city: str
    street: str
    house_number: int
    postal_code: int


class Person(BaseModel):
    prename: str
    middlename: Optional[str]
    lastname: str
    address: Adress


@given(from_type(Person))
def test_me(person: Person):
    assert isinstance(person, Person)

当我将其另存为test_foo.py并执行pytest时,我得到:

――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― test_me ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

    @given(from_type(Person))
>   def test_me(person: Person):

test_foo.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   pydantic.error_wrappers.ValidationError: 3 validation errors for Person
E   prename
E     field required (type=value_error.missing)
E   lastname
E     field required (type=value_error.missing)
E   address
E     field required (type=value_error.missing)

pydantic/main.py:283: ValidationError
---------------------------------------------------------------- Hypothesis ----------------------------------------------------------------
You can add @seed(42732672939050403878146949573829059697) to this test or run pytest with --hypothesis-seed=42732672939050403878146949573829059697 to reproduce this failure.

如果假设产生一个没有中间名的人和一个有中间名的人,我会特别喜欢。

4

1 回答 1

1

这不会开箱即用,因为假设需要知道要使用什么类型来构建 pydantic 模型,而且我们对 pydantic 没有特别的支持(我实际上只是从这篇文章中听说过) .

为了支持它,大致可以做两件事:

  1. pydantic 可以生成正确类型的__init__方法。pydantic__init__方法的签名是__pydantic_self__, **data:Any,因此我们无法知道它期望什么参数。相反,如果类型签名与字段参数的类型签名匹配,则假设将为此开箱即用。
  2. 有人可以编写一个 PR 来为假设的实现添加 pydantic 支持,from_type以便它知道如何构建 pydantic 模型。我们已经获得了对 attrs 和 dataclasses 的自定义支持,这看起来就像那样。

如果 pydantic 开发人员对它持开放态度,我首选的解决方案将是第一个。

同时,您可以使用该builds功能为您的模型定义自定义策略。然后,您可以将其注册为该类型的策略或直接使用它。

于 2020-06-26T10:48:40.547 回答