目标:成功通过测试用例,对于
NotImplementedError
中
test_score_not_implemented_error()
@singledispatch
def score()
的目的是提高
NotImplementedError
,如果当
count_neg
和
count_pos
提供的参数不匹配||时|也
Tuple[int, int]
.
Tuple[List[int], List[int]]
我想通过以下方式测试此异常处理。
.
test_score_not_implemented_error()
但是,出乎意料的是,我因在其他多态函数上实现
而收到错误。
@typechecked
I我对需要多态函数的方法充满信心,并且我的测试函数具有适当的测试用例。我怀疑问题在于我如何实现
的多态函数。
def score()
调整:
从多态函数中删除
会抛出:
@typechecked
:
FAILED tests/test_tps.py::test_score_not_implemented_error[0-01] - TypeError: can only concatenate str (not "int") to str
FAILED tests/test_tps.py::test_score_not_implemented_error[count_neg3-count_pos3] - TypeError: unsupported operand type(s) for +: 'int' and 'str'
FAILED tests/test_tps.py::test_score_not_implemented_error[count_neg4-count_pos4] - TypeError: unsupported operand type(s) for +: 'int' and 'str'
FAILED tests/test_tps.py::test_score_not_implemented_error[count_neg5-count_pos5] - TypeError: unsupported operand type(s) for +: 'int' and 'str'
tests/test_score.py
回溯:
from typeguard import typechecked
from functools import singledispatch
import pytest
from pytest_cases import parametrize
from typing import Any, List, Tuple, Type, Union
@singledispatch
def score(count_neg: Any, count_pos: Any) -> None:
raise NotImplementedError(f'{type(count_neg)} and or {type(count_pos)} are not supported.')
@score.register(int)
@typechecked
def score_int(count_neg: int, count_pos: int) -> float:
return round(100 * count_pos / (count_pos + count_neg), 1)
@score.register(list)
@typechecked
def score_list(count_neg: List[int], count_pos: List[int]) -> float:
return round(100 * sum(count_pos) / (sum(count_pos) + sum(count_neg)), 1)
@parametrize('count_neg, count_pos',
[('0', 0),
(0, '0'),
('0', '0'),
(['0'], [0]),
([0], ['0']),
(['0'], ['0']),
(None, None)])
def test_score_not_implemented_error(count_neg: Union[str, int, List[str], List[int], None],
count_pos: Union[str, int, List[str], List[int], None],
error: Type[BaseException] = NotImplementedError):
with pytest.raises(error) as exc_info:
score(count_neg, count_pos)
assert exc_info.type is error
Traceback:
(venv) me@laptop:~/BitBucket/project $ python -m pytest tests/test_score.py
===================================================================================================================== test session starts =====================================================================================================================
platform linux -- Python 3.9.16, pytest-7.4.0, pluggy-1.0.0
rootdir: /home/danielbell/BitBucket/pdl1-lung
plugins: hydra-core-1.3.2, typeguard-3.0.2, mock-3.11.1, cases-3.6.13, dvc-3.2.3, anyio-3.5.0
collected 7 items
tests/test_tps.py .F.FFF. [100%]
========================================================================================================================== FAILURES ===========================================================================================================================
___________________________________________________________________________________________________________ test_score_not_implemented_error[0-01] ____________________________________________________________________________________________________________
count_neg = 0, count_pos = '0', error = <class 'NotImplementedError'>
@parametrize('count_neg, count_pos',
[('0', 0),
(0, '0'),
('0', '0'),
(['0'], [0]),
([0], ['0']),
(['0'], ['0']),
(None, None)])
def test_score_not_implemented_error(count_neg: Union[str, int, List[str], List[int], None],
count_pos: Union[str, int, List[str], List[int], None],
error: Type[BaseException] = NotImplementedError):
with pytest.raises(error) as exc_info:
> score(count_neg, count_pos)
tests/test_tps.py:38:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../miniconda3/envs/pdl1lung/lib/python3.9/functools.py:888: in wrapper
return dispatch(args[0].__class__)(*args, **kw)
tests/test_tps.py:16: in score_int
def score_int(count_neg: int, count_pos: int) -> float:
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_functions.py:113: in check_argument_types
check_type_internal(value, expected_type, memo=memo)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
value = '0', annotation = <class 'int'>, memo = <typeguard.CallMemo object at 0x7f591213ccc0>
def check_type_internal(value: Any, annotation: Any, memo: TypeCheckMemo) -> None:
"""
Check that the given object is compatible with the given type annotation.
This function should only be used by type checker callables. Applications should use
:func:`~.check_type` instead.
:param value: the value to check
:param annotation: the type annotation to check against
:param memo: a memo object containing configuration and information necessary for
looking up forward references
"""
if isinstance(annotation, ForwardRef):
try:
annotation = evaluate_forwardref(annotation, memo)
except NameError:
if global_config.forward_ref_policy is ForwardRefPolicy.ERROR:
raise
elif global_config.forward_ref_policy is ForwardRefPolicy.WARN:
warnings.warn(
f"Cannot resolve forward reference {annotation.__forward_arg__!r}",
TypeHintWarning,
stacklevel=get_stacklevel(),
)
return
if annotation is Any or annotation is SubclassableAny or isinstance(value, Mock):
return
# Skip type checks if value is an instance of a class that inherits from Any
if not isclass(value) and SubclassableAny in type(value).__bases__:
return
extras: tuple[Any, ...]
origin_type = get_origin(annotation)
if origin_type is Annotated:
annotation, *extras_ = get_args(annotation)
extras = tuple(extras_)
origin_type = get_origin(annotation)
else:
extras = ()
if origin_type is not None:
args = get_args(annotation)
# Compatibility hack to distinguish between unparametrized and empty tuple
# (tuple[()]), necessary due to https://github.com/python/cpython/issues/91137
if origin_type in (tuple, Tuple) and annotation is not Tuple and not args:
args = ((),)
else:
origin_type = annotation
args = ()
for lookup_func in checker_lookup_functions:
checker = lookup_func(origin_type, args, extras)
if checker:
checker(value, origin_type, args, memo)
return
if not isinstance(value, origin_type):
> raise TypeCheckError(f"is not an instance of {qualified_name(origin_type)}")
E typeguard.TypeCheckError: argument "count_pos" (str) is not an instance of int
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:680: TypeCheckError
___________________________________________________________________________________________________ test_score_not_implemented_error[count_neg3-count_pos3] ___________________________________________________________________________________________________
count_neg = ['0'], count_pos = [0], error = <class 'NotImplementedError'>
@parametrize('count_neg, count_pos',
[('0', 0),
(0, '0'),
('0', '0'),
(['0'], [0]),
([0], ['0']),
(['0'], ['0']),
(None, None)])
def test_score_not_implemented_error(count_neg: Union[str, int, List[str], List[int], None],
count_pos: Union[str, int, List[str], List[int], None],
error: Type[BaseException] = NotImplementedError):
with pytest.raises(error) as exc_info:
> score(count_neg, count_pos)
tests/test_tps.py:38:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../miniconda3/envs/pdl1lung/lib/python3.9/functools.py:888: in wrapper
return dispatch(args[0].__class__)(*args, **kw)
tests/test_tps.py:22: in score_list
def score_list(count_neg: List[int], count_pos: List[int]) -> float:
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_functions.py:113: in check_argument_types
check_type_internal(value, expected_type, memo=memo)
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:676: in check_type_internal
checker(value, origin_type, args, memo)
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:273: in check_list
check_type_internal(v, args[0], memo)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
value = '0', annotation = <class 'int'>, memo = <typeguard.CallMemo object at 0x7f5854383770>
def check_type_internal(value: Any, annotation: Any, memo: TypeCheckMemo) -> None:
"""
Check that the given object is compatible with the given type annotation.
This function should only be used by type checker callables. Applications should use
:func:`~.check_type` instead.
:param value: the value to check
:param annotation: the type annotation to check against
:param memo: a memo object containing configuration and information necessary for
looking up forward references
"""
if isinstance(annotation, ForwardRef):
try:
annotation = evaluate_forwardref(annotation, memo)
except NameError:
if global_config.forward_ref_policy is ForwardRefPolicy.ERROR:
raise
elif global_config.forward_ref_policy is ForwardRefPolicy.WARN:
warnings.warn(
f"Cannot resolve forward reference {annotation.__forward_arg__!r}",
TypeHintWarning,
stacklevel=get_stacklevel(),
)
return
if annotation is Any or annotation is SubclassableAny or isinstance(value, Mock):
return
# Skip type checks if value is an instance of a class that inherits from Any
if not isclass(value) and SubclassableAny in type(value).__bases__:
return
extras: tuple[Any, ...]
origin_type = get_origin(annotation)
if origin_type is Annotated:
annotation, *extras_ = get_args(annotation)
extras = tuple(extras_)
origin_type = get_origin(annotation)
else:
extras = ()
if origin_type is not None:
args = get_args(annotation)
# Compatibility hack to distinguish between unparametrized and empty tuple
# (tuple[()]), necessary due to https://github.com/python/cpython/issues/91137
if origin_type in (tuple, Tuple) and annotation is not Tuple and not args:
args = ((),)
else:
origin_type = annotation
args = ()
for lookup_func in checker_lookup_functions:
checker = lookup_func(origin_type, args, extras)
if checker:
checker(value, origin_type, args, memo)
return
if not isinstance(value, origin_type):
> raise TypeCheckError(f"is not an instance of {qualified_name(origin_type)}")
E typeguard.TypeCheckError: item 0 of argument "count_neg" (list) is not an instance of int
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:680: TypeCheckError
___________________________________________________________________________________________________ test_score_not_implemented_error[count_neg4-count_pos4] ___________________________________________________________________________________________________
count_neg = [0], count_pos = ['0'], error = <class 'NotImplementedError'>
@parametrize('count_neg, count_pos',
[('0', 0),
(0, '0'),
('0', '0'),
(['0'], [0]),
([0], ['0']),
(['0'], ['0']),
(None, None)])
def test_score_not_implemented_error(count_neg: Union[str, int, List[str], List[int], None],
count_pos: Union[str, int, List[str], List[int], None],
error: Type[BaseException] = NotImplementedError):
with pytest.raises(error) as exc_info:
> score(count_neg, count_pos)
tests/test_tps.py:38:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../miniconda3/envs/pdl1lung/lib/python3.9/functools.py:888: in wrapper
return dispatch(args[0].__class__)(*args, **kw)
tests/test_tps.py:22: in score_list
def score_list(count_neg: List[int], count_pos: List[int]) -> float:
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_functions.py:113: in check_argument_types
check_type_internal(value, expected_type, memo=memo)
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:676: in check_type_internal
checker(value, origin_type, args, memo)
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:273: in check_list
check_type_internal(v, args[0], memo)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
value = '0', annotation = <class 'int'>, memo = <typeguard.CallMemo object at 0x7f58540d45e0>
def check_type_internal(value: Any, annotation: Any, memo: TypeCheckMemo) -> None:
"""
Check that the given object is compatible with the given type annotation.
This function should only be used by type checker callables. Applications should use
:func:`~.check_type` instead.
:param value: the value to check
:param annotation: the type annotation to check against
:param memo: a memo object containing configuration and information necessary for
looking up forward references
"""
if isinstance(annotation, ForwardRef):
try:
annotation = evaluate_forwardref(annotation, memo)
except NameError:
if global_config.forward_ref_policy is ForwardRefPolicy.ERROR:
raise
elif global_config.forward_ref_policy is ForwardRefPolicy.WARN:
warnings.warn(
f"Cannot resolve forward reference {annotation.__forward_arg__!r}",
TypeHintWarning,
stacklevel=get_stacklevel(),
)
return
if annotation is Any or annotation is SubclassableAny or isinstance(value, Mock):
return
# Skip type checks if value is an instance of a class that inherits from Any
if not isclass(value) and SubclassableAny in type(value).__bases__:
return
extras: tuple[Any, ...]
origin_type = get_origin(annotation)
if origin_type is Annotated:
annotation, *extras_ = get_args(annotation)
extras = tuple(extras_)
origin_type = get_origin(annotation)
else:
extras = ()
if origin_type is not None:
args = get_args(annotation)
# Compatibility hack to distinguish between unparametrized and empty tuple
# (tuple[()]), necessary due to https://github.com/python/cpython/issues/91137
if origin_type in (tuple, Tuple) and annotation is not Tuple and not args:
args = ((),)
else:
origin_type = annotation
args = ()
for lookup_func in checker_lookup_functions:
checker = lookup_func(origin_type, args, extras)
if checker:
checker(value, origin_type, args, memo)
return
if not isinstance(value, origin_type):
> raise TypeCheckError(f"is not an instance of {qualified_name(origin_type)}")
E typeguard.TypeCheckError: item 0 of argument "count_pos" (list) is not an instance of int
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:680: TypeCheckError
___________________________________________________________________________________________________ test_score_not_implemented_error[count_neg5-count_pos5] ___________________________________________________________________________________________________
count_neg = ['0'], count_pos = ['0'], error = <class 'NotImplementedError'>
@parametrize('count_neg, count_pos',
[('0', 0),
(0, '0'),
('0', '0'),
(['0'], [0]),
([0], ['0']),
(['0'], ['0']),
(None, None)])
def test_score_not_implemented_error(count_neg: Union[str, int, List[str], List[int], None],
count_pos: Union[str, int, List[str], List[int], None],
error: Type[BaseException] = NotImplementedError):
with pytest.raises(error) as exc_info:
> score(count_neg, count_pos)
tests/test_tps.py:38:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../miniconda3/envs/pdl1lung/lib/python3.9/functools.py:888: in wrapper
return dispatch(args[0].__class__)(*args, **kw)
tests/test_tps.py:22: in score_list
def score_list(count_neg: List[int], count_pos: List[int]) -> float:
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_functions.py:113: in check_argument_types
check_type_internal(value, expected_type, memo=memo)
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:676: in check_type_internal
checker(value, origin_type, args, memo)
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:273: in check_list
check_type_internal(v, args[0], memo)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
value = '0', annotation = <class 'int'>, memo = <typeguard.CallMemo object at 0x7f58541444f0>
def check_type_internal(value: Any, annotation: Any, memo: TypeCheckMemo) -> None:
"""
Check that the given object is compatible with the given type annotation.
This function should only be used by type checker callables. Applications should use
:func:`~.check_type` instead.
:param value: the value to check
:param annotation: the type annotation to check against
:param memo: a memo object containing configuration and information necessary for
looking up forward references
"""
if isinstance(annotation, ForwardRef):
try:
annotation = evaluate_forwardref(annotation, memo)
except NameError:
if global_config.forward_ref_policy is ForwardRefPolicy.ERROR:
raise
elif global_config.forward_ref_policy is ForwardRefPolicy.WARN:
warnings.warn(
f"Cannot resolve forward reference {annotation.__forward_arg__!r}",
TypeHintWarning,
stacklevel=get_stacklevel(),
)
return
if annotation is Any or annotation is SubclassableAny or isinstance(value, Mock):
return
# Skip type checks if value is an instance of a class that inherits from Any
if not isclass(value) and SubclassableAny in type(value).__bases__:
return
extras: tuple[Any, ...]
origin_type = get_origin(annotation)
if origin_type is Annotated:
annotation, *extras_ = get_args(annotation)
extras = tuple(extras_)
origin_type = get_origin(annotation)
else:
extras = ()
if origin_type is not None:
args = get_args(annotation)
# Compatibility hack to distinguish between unparametrized and empty tuple
# (tuple[()]), necessary due to https://github.com/python/cpython/issues/91137
if origin_type in (tuple, Tuple) and annotation is not Tuple and not args:
args = ((),)
else:
origin_type = annotation
args = ()
for lookup_func in checker_lookup_functions:
checker = lookup_func(origin_type, args, extras)
if checker:
checker(value, origin_type, args, memo)
return
if not isinstance(value, origin_type):
> raise TypeCheckError(f"is not an instance of {qualified_name(origin_type)}")
E typeguard.TypeCheckError: item 0 of argument "count_neg" (list) is not an instance of int
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/typeguard/_checkers.py:680: TypeCheckError
====================================================================================================================== warnings summary =======================================================================================================================
../../miniconda3/envs/pdl1lung/lib/python3.9/site-packages/cytomine/models/collection.py:26
/home/danielbell/miniconda3/envs/pdl1lung/lib/python3.9/site-packages/cytomine/models/collection.py:26: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.10 it will stop working
from collections import MutableSequence
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=================================================================================================================== short test summary info ===================================================================================================================
FAILED tests/test_tps.py::test_score_not_implemented_error[0-01] - typeguard.TypeCheckError: argument "count_pos" (str) is not an instance of int
FAILED tests/test_tps.py::test_score_not_implemented_error[count_neg3-count_pos3] - typeguard.TypeCheckError: item 0 of argument "count_neg" (list) is not an instance of int
FAILED tests/test_tps.py::test_score_not_implemented_error[count_neg4-count_pos4] - typeguard.TypeCheckError: item 0 of argument "count_pos" (list) is not an instance of int
FAILED tests/test_tps.py::test_score_not_implemented_error[count_neg5-count_pos5] - typeguard.TypeCheckError: item 0 of argument "count_neg" (list) is not an instance of int
=========================================================================================================== 4 failed, 3 passed, 1 warning in 0.94s ============================================================================================================
你的测试函数中存在类型提示问题。告诉它期望
Union[str, int, List[str], List[int], None]
类型的
count_neg
和
count_pos
。
这告诉
typeguard
这些类型是可以接受的,因此它不会引发期望的
TypeError
。然后,它会根据传递的第一个参数的类型将输入调度到
score_int
或
score_list
,这会导致在尝试对字符串执行数学运算时出现错误。
需要做两件事来解决此问题:
-
从测试函数的参数化中删除错误类型。
只希望测试的函数是否在收到无效类型时引发
NotImplementedError
,因此不需要在类型提示中包含有效类型。 -
使用
@singledispatch
注册通用类型。 这将确保在没有为特定类型注册处理程序时,始终调用泛型函数。
以下是如何更新代码以实现此目的的方法:
from typeguard import typechecked
from functools import singledispatch
import pytest
from pytest_cases import parametrize
from typing import Any, List, Tuple, Type, Union
@singledispatch
def score(count_neg: Any, count_pos: Any) -> None:
raise NotImplementedError(f'{type(count_neg)} and or {type(count_pos)} are not supported.')
@score.register
@typechecked
def score_int(count_neg: int, count_pos: int) -> float:
return round(100 * count_pos / (count_pos + count_neg), 1)
@score.register
@typechecked
def score_list(count_neg: List[int], count_pos: List[int]) -> float:
return round(100 * sum(count_pos) / (sum(count_pos) + sum(count_neg)), 1)
@parametrize('count_neg, count_pos',
[('0', 0),
(0, '0'),
('0', '0'),
(['0'], [0]),
([0], ['0']),
(['0'], ['0']),
(None, None)])
def test_score_not_implemented_error(count_neg: Any, count_pos: Any):
with pytest.raises(NotImplementedError) as exc_info:
score(count_neg, count_pos)
assert exc_info.type is NotImplementedError
这些更改将确保在向
score
函数传递无效类型时,始终引发
NotImplementedError
。