diff --git a/README.md b/README.md index a370c12..3938c9b 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,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. -### Example +### 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 #### 1. Inline type expectations @@ -148,6 +153,22 @@ Implementation notes: 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 b9f9bad..798f851 100644 --- a/pytest_mypy_plugins/collect.py +++ b/pytest_mypy_plugins/collect.py @@ -2,6 +2,7 @@ import platform import sys import tempfile +from collections import ChainMap from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Mapping, Optional import pytest @@ -83,7 +84,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.") @@ -98,7 +102,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