diff --git a/README.md b/README.md index 1d42aac..8a96c7c 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,12 @@ Implementation notes: [`eval`](https://docs.python.org/3/library/functions.html#eval). It is advised to take a peek and learn about how `eval` works. +### Placeholders + +In addition to test cases, re-usable placeholders can be defined in a top level element names `placeholders`, pieces of +text which can be reused in any test cases within the YAML test file - see example below. + +### Examples Repository also offers a [JSONSchema](pytest_mypy_plugins/schema.json), with which it validates the input. It can also offer your editor auto-completions, descriptions, and validation. @@ -190,6 +196,22 @@ Properties that you can parametrize: reveal_type(a) # NR: .*str.* ``` +#### 6. Placeholders + +```yaml +- case: test_placeholder + main: | + a = 1 + b = 'hello' + + reveal_type(a) # N: {{ reveal }} "builtins.int" + reveal_type(b) # NR: {{ reveal }} {{ str }} + +- placeholders: + reveal: "Revealed type is" + str: ".*str.*" +``` + ## Options ``` diff --git a/pytest_mypy_plugins/collect.py b/pytest_mypy_plugins/collect.py index 0670d99..6df9628 100644 --- a/pytest_mypy_plugins/collect.py +++ b/pytest_mypy_plugins/collect.py @@ -4,6 +4,7 @@ import platform import sys import tempfile +from collections import ChainMap from dataclasses import dataclass from typing import ( TYPE_CHECKING, @@ -116,7 +117,10 @@ def collect(self) -> Iterator["YamlTestItem"]: if not isinstance(parsed_file, list): raise ValueError(f"Test file has to be YAML list, got {type(parsed_file)!r}.") - for raw_test in parsed_file: + templates = ChainMap(*[t["placeholders"] for t in parsed_file if "placeholders" in t]) + + raw_tests = [c for c in parsed_file if "case" in c] + for raw_test in raw_tests: test_name_prefix = raw_test["case"] if " " in test_name_prefix: raise ValueError(f"Invalid test name {test_name_prefix!r}, only '[a-zA-Z0-9_]' is allowed.") @@ -131,7 +135,7 @@ def collect(self) -> Iterator["YamlTestItem"]: test_name_suffix = "" test_name = f"{test_name_prefix}{test_name_suffix}" - main_content = utils.render_template(template=raw_test["main"], data=params) + main_content = utils.render_template(template=raw_test["main"], data=ChainMap(params, templates)) main_file = File(path="main.py", content=main_content) test_files = [main_file] + parse_test_files(raw_test.get("files", [])) expect_fail = raw_test.get("expect_fail", False) diff --git a/pytest_mypy_plugins/tests/test-placeholders.yml b/pytest_mypy_plugins/tests/test-placeholders.yml new file mode 100644 index 0000000..4dce7a2 --- /dev/null +++ b/pytest_mypy_plugins/tests/test-placeholders.yml @@ -0,0 +1,19 @@ +- case: test_placeholder + main: | + a = 1 + b = 'hello' + + reveal_type(a) # N: {{ reveal }} "builtins.int" + reveal_type(b) # NR: {{ reveal }} {{ str }} + +- case: test_using_parametrized_for_templates + parametrized: + - rtype: "Revealed type is" + main: | + a = 1 + + reveal_type(a) # N: {{ rtype }} "builtins.int" + +- placeholders: + reveal: "Revealed type is" + str: ".*str.*" \ No newline at end of file