pytest-dev / pytest-dev/pytest
type-safe markers
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 14.5k
- Forks
- 3.4k
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 35
Description
What's the problem this feature will solve?
currently when creating a custom marker, there's no way for the type checker to ensure the arguments are correct. the builtin markers work around this by having type-checking only subtypes of MarkDecorator like so (in _pytest/mark./structures.py):
# Typing for builtin pytest marks. This is cheating; it gives builtin marks
# special privilege, and breaks modularity. But practicality beats purity...
if TYPE_CHECKING:
from _pytest.scope import _ScopeName
class _SkipMarkDecorator(MarkDecorator):
@overload # type: ignore[override,misc,no-overload-impl]
def __call__(self, arg: Markable) -> Markable:
...
@overload
def __call__(self, reason: str = ...) -> "MarkDecorator":
...
Describe the solution you'd like
a way to define markers in a type-safe way, similar to how the builtin markers are defined. maybe something like this:
# conftest.py
class Foo(MarkDecorator):
@override
def __call__(self, value: int) -> MarkDecorator: ...
# test_foo.py
from conftest import Foo
@Foo("asdf") # error: expected int, got str
def test_asdf(): ...
Alternative Solutions
remove the @final from MarkGenerator and allow plugins to subtype it with their custom markers:
# conftest.py
from pytest import MarkGenerator
class CustomMarkers(MarkGenerator):
foo: Callable[[int], MarkDecorator]
# test_foo.py
from conftest import CustomMarkers
mark = CustomMarkers()
@mark.foo("asdf") # error: expected int, got str
def test_asdf(): ...
this solution probably isn't the best though since there'd be no way to enforce that users use your subtype. whereas making each marker separate classes would at least allow you to enforce that @Foo is used over @mark.foo using --strict-markers
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading _pytest/mark./structures.py, especially MarkDecorator and the builtin marker typing definitions. Compare the proposed custom MarkDecorator and MarkGenerator approaches, then determine and document a supported type-safe API with coverage for incorrect marker argument types and marker usage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100