예제 #1
0
파일: test_spec.py 프로젝트: mcous/decoy
def test_warn_if_called_incorrectly() -> None:
    """It should trigger a warning if bound_args is called incorrectly."""
    subject = Spec(source=some_func, name=None)

    with pytest.warns(IncorrectCallWarning,
                      match="missing a required argument"):
        subject.bind_args(wrong_arg_name="1")
예제 #2
0
파일: test_spec.py 프로젝트: mcous/decoy
def test_init() -> None:
    """It should have default spec properties."""
    subject = Spec(source=None, name=None)

    assert subject.get_signature() is None
    assert subject.get_class_type() is None
    assert subject.get_is_async() is False
예제 #3
0
def test_spy_calls(
    decoy: Decoy,
    call_handler: CallHandler,
    spy_creator: SpyCreator,
    spec: Spec,
) -> None:
    """It should send any calls to the call handler."""
    subject = Spy(spec=spec,
                  call_handler=call_handler,
                  spy_creator=spy_creator)

    decoy.when(spec.get_name()).then_return("spy_name")
    decoy.when(spec.bind_args(1, 2, three=3)).then_return(
        BoundArgs(args=(1, 2, 3), kwargs={}))
    decoy.when(
        call_handler.handle(
            SpyEvent(
                spy_id=id(subject),
                spy_name="spy_name",
                payload=SpyCall(args=(1, 2, 3), kwargs={}),
            ))).then_return(CallHandlerResult(42))

    result = subject(1, 2, three=3)

    assert result == 42
예제 #4
0
def test_spy_prop_delete(
    decoy: Decoy,
    call_handler: CallHandler,
    spy_creator: SpyCreator,
    spec: Spec,
) -> None:
    """It should record a property set call."""
    decoy.when(spec.get_name()).then_return("spy_name")

    subject = Spy(spec=spec,
                  call_handler=call_handler,
                  spy_creator=spy_creator)
    subject.some_property = 42
    del subject.some_property

    assert subject.some_property != 42

    decoy.verify(
        call_handler.handle(
            SpyEvent(
                spy_id=id(subject),
                spy_name="spy_name",
                payload=SpyPropAccess(
                    prop_name="some_property",
                    access_type=PropAccessType.DELETE,
                ),
            ), ))
예제 #5
0
def test_spy_prop_get(
    decoy: Decoy,
    call_handler: CallHandler,
    spy_creator: SpyCreator,
    spec: Spec,
) -> None:
    """It should record a property get call."""
    subject = Spy(spec=spec,
                  call_handler=call_handler,
                  spy_creator=spy_creator)

    decoy.when(spec.get_name()).then_return("spy_name")
    decoy.when(
        call_handler.handle(
            SpyEvent(
                spy_id=id(subject),
                spy_name="spy_name",
                payload=SpyPropAccess(
                    prop_name="some_property",
                    access_type=PropAccessType.GET,
                ),
            ), )).then_return(CallHandlerResult(42))

    result = subject.some_property

    assert result == 42
예제 #6
0
파일: test_spec.py 프로젝트: mcous/decoy
def test_bind_args(
    subject: Spec,
    input_args: Tuple[Any, ...],
    input_kwargs: Dict[str, Any],
    expected_args: Tuple[Any, ...],
    expected_kwargs: Dict[str, Any],
) -> None:
    """It should bind arguments to the spec's callable signature."""
    result = subject.bind_args(*input_args, **input_kwargs)

    assert result == BoundArgs(args=expected_args, kwargs=expected_kwargs)
예제 #7
0
파일: test_spec.py 프로젝트: mcous/decoy
def test_get_signature_no_type_hints() -> None:
    """It should gracefully degrade if a class's type hints cannot be resolved."""
    class _BadTypeHints:
        _not_ok: "None[Any]"

        def _ok(self, hello: str) -> None:
            ...

    subject = Spec(source=_BadTypeHints, name=None).get_child_spec("_ok")

    assert subject.get_signature() == inspect.Signature(
        parameters=[
            inspect.Parameter(
                name="hello",
                kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
                annotation=str,
            )
        ],
        return_annotation=None,
    )
예제 #8
0
async def test_spy_async_context_manager(
    decoy: Decoy,
    call_handler: CallHandler,
    spy_creator: SpyCreator,
    spec: Spec,
) -> None:
    """It should be usable in an `async with` statement."""
    enter_spec = decoy.mock(cls=Spec)
    exit_spec = decoy.mock(cls=Spec)
    enter_spy = decoy.mock(cls=AsyncSpy)
    exit_spy = decoy.mock(cls=AsyncSpy)
    error = RuntimeError("oh no")

    decoy.when(spec.get_name()).then_return("spy_name")
    decoy.when(spec.get_child_spec("__aenter__")).then_return(enter_spec)
    decoy.when(spec.get_child_spec("__aexit__")).then_return(exit_spec)
    decoy.when(spy_creator.create(spec=enter_spec,
                                  is_async=True)).then_return(enter_spy)
    decoy.when(spy_creator.create(spec=exit_spec,
                                  is_async=True)).then_return(exit_spy)
    decoy.when(await enter_spy()).then_return(42)

    subject = Spy(spec=spec,
                  call_handler=call_handler,
                  spy_creator=spy_creator)
    tb = None

    try:
        async with subject as result:
            assert result == 42
            raise error
    except RuntimeError:
        tb = sys.exc_info()[2]
        pass

    decoy.verify(await exit_spy(RuntimeError, error, tb))
예제 #9
0
파일: test_spec.py 프로젝트: mcous/decoy
def test_get_name(subject: Spec, expected_name: str,
                  expected_full_name: str) -> None:
    """It should assign names from args or spec."""
    assert subject.get_name() == expected_name
    assert subject.get_full_name() == expected_full_name
예제 #10
0
파일: test_spec.py 프로젝트: mcous/decoy
def test_get_is_async(subject: Spec, expected_is_async: bool) -> None:
    """It should get whether the Spec represents an async callable."""
    assert subject.get_is_async() is expected_is_async
예제 #11
0
파일: test_spec.py 프로젝트: mcous/decoy
def test_get_class_type(subject: Spec, expected_class_type: Type[Any]) -> None:
    """It should get the class type, if source is a class."""
    assert subject.get_class_type() == expected_class_type
예제 #12
0
파일: test_spec.py 프로젝트: mcous/decoy
def test_get_signature(
    subject: Spec,
    expected_signature: Optional[inspect.Signature],
) -> None:
    """It should inspect the spec source's signature."""
    assert subject.get_signature() == expected_signature
예제 #13
0
파일: test_spec.py 프로젝트: mcous/decoy
    assert subject.get_is_async() is False


class GetNameSpec(NamedTuple):
    """Spec data to test get_name and get_full_name."""

    subject: Spec
    expected_name: str
    expected_full_name: str


@pytest.mark.parametrize(
    GetNameSpec._fields,
    [
        GetNameSpec(
            subject=Spec(source=None, name=None),
            expected_name="unnamed",
            expected_full_name="unnamed",
        ),
        GetNameSpec(
            subject=Spec(source=some_func, name=None),
            expected_name="some_func",
            expected_full_name="tests.common.some_func",
        ),
        GetNameSpec(
            subject=Spec(
                source=some_func, name="spy_name", module_name="module_name"),
            expected_name="spy_name",
            expected_full_name="module_name.spy_name",
        ),
        GetNameSpec(