-
Notifications
You must be signed in to change notification settings - Fork 43
implemented pytest for makepyfile #286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fda3c88
6a98ec4
0f6d0b3
cb6ded1
ef57b66
c8f55a2
70d6782
8eccc6e
a6ceec7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,260 @@ | ||
| import os | ||
| from encodings.aliases import aliases | ||
| from pathlib import Path | ||
| from textwrap import dedent | ||
| from typing import Tuple | ||
|
|
||
| import pytest | ||
|
|
||
| pytest_plugins = ["pytester"] | ||
|
|
||
|
|
||
| def not_debug(): | ||
| """run tests only when not in CI and debug is enabled.""" | ||
| return os.getenv("CI", False) or not os.getenv("PYTEST_DEBUG_MAKEPYFILE", False) | ||
|
|
||
|
|
||
| def enc(enc): | ||
| try: | ||
| _ = "abc".encode(enc) | ||
| except LookupError: | ||
| return False | ||
|
|
||
| return True | ||
|
|
||
|
|
||
| all_encodings = set(filter(enc, aliases.values())) | ||
|
|
||
|
|
||
| @pytest.fixture(params=all_encodings) | ||
| def encoding(request): | ||
| return request.param | ||
|
|
||
|
|
||
| @pytest.fixture( | ||
| params=[ | ||
| ("3", "4"), | ||
| ("A", "B"), | ||
| ("!", "?"), | ||
| ("☆", "☁"), | ||
| ("✅", "💥"), | ||
| ("é", "ü"), | ||
| ("Я", "ж"), # Cyrillic characters | ||
| ("Ф", "Щ"), # More Cyrillic | ||
| ("電腦", "电脑"), # Chinese: traditional vs simplified for "computer" | ||
| ("学校", "がっこう"), # Japanese: Kanji vs Hiragana for "school" | ||
| ], | ||
| ids=[ | ||
| "numbers", | ||
| "letters", | ||
| "punctuation", | ||
| "stars", | ||
| "check-explosion", | ||
| "accented_letters", | ||
| "cyrillic_basic", | ||
| "cyrillic_complex", | ||
| "chinese_computer", | ||
| "japanese_school", | ||
| ], | ||
| ) | ||
| def any_charset(request): | ||
| return request.param | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def makepyfile_encoded(testdir, encoding, any_charset): | ||
| a, b = any_charset | ||
|
|
||
| original_file = testdir.makepyfile( | ||
| f""" | ||
| def f(): | ||
| ''' | ||
| >>> print('{a}') | ||
| {b} | ||
| ''' | ||
| pass | ||
| """, | ||
| encoding=encoding, | ||
| ) | ||
|
|
||
| expected_diff = dedent( | ||
| f""" | ||
| >>> print('{a}') | ||
| - {b} | ||
| + {a} | ||
| """ | ||
| ).strip("\n") | ||
|
|
||
| yield original_file, expected_diff, encoding | ||
|
|
||
|
|
||
| def makebasicfile(tmp_path: Path, a, b, encoding: str) -> Tuple[Path, str]: | ||
| """alternative implementation without the use of `testdir.makepyfile`.""" | ||
|
|
||
| original_file = Path(tmp_path).joinpath("test_basic.py") | ||
| code = dedent( | ||
| f""" | ||
| def f(): | ||
| ''' | ||
| >>> print('{a}') | ||
| {b} | ||
| ''' | ||
| pass | ||
| """ | ||
| ) | ||
|
|
||
| original_file.write_text(code, encoding=encoding) | ||
|
|
||
| expected_diff = dedent( | ||
| f""" | ||
| >>> print('{a}') | ||
| - {b} | ||
| + {a} | ||
| """ | ||
| ).strip("\n") | ||
|
|
||
| return original_file, expected_diff | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def basic_encoded(tmp_path, encoding, any_charset): | ||
|
|
||
| a, b = any_charset | ||
|
|
||
| file, diff = makebasicfile(tmp_path, a, b, encoding) | ||
|
|
||
| yield file, diff, encoding | ||
|
|
||
|
|
||
| @pytest.mark.skipif(not_debug(), reason="skipped in CI or debugging is not enabled.") | ||
| def test_makepyfile(makepyfile_encoded): | ||
| """ | ||
| Test is expected to fail because of UnicodeDecodeError. | ||
|
|
||
| Just to compare visually with `test_basicfile` to see the difference | ||
| """ | ||
|
|
||
| file, diff, enc = makepyfile_encoded | ||
|
|
||
| text = Path(file).read_text(enc) | ||
|
|
||
| print(text, diff) | ||
|
|
||
|
|
||
| @pytest.mark.skipif(not_debug(), reason="skipped in CI or debugging is not enabled.") | ||
| def test_basicfile(basic_encoded): | ||
| """ | ||
| Test is expected to fail because of UnicodeDecodeError. | ||
|
|
||
| Just to compare visually with `test_makepyfile` to see the difference | ||
| """ | ||
| file, diff, enc = basic_encoded | ||
|
|
||
| text = Path(file).read_text(enc) | ||
|
|
||
| print(text, diff) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note for other reviewers: See https://github.com/scientific-python/pytest-doctestplus/pull/286/files#r2004356445
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. set env variable |
||
|
|
||
| @pytest.mark.skip(reason="makepyfile uses encoding only on bytes objects.") | ||
| def test_compare_make_basic_file(testdir, encoding, any_charset): | ||
| """ | ||
| Compare testdir.makepyfile with pathlib.Path.writetext to create python files. | ||
|
|
||
| Expected behavior is when `testdir.makepyfile` created a file with given encoding, | ||
| `makebasicfile` also should be able to encode the charset. | ||
|
|
||
| If a UnicodeEncodeError is raised, it means `testdir.makepyfile` screwed up the | ||
| encoding. | ||
| """ | ||
|
|
||
| a, b = any_charset | ||
|
|
||
| # create a python file with testdir.makepyfile in the old fashioned way | ||
|
|
||
| make_file = testdir.makepyfile( | ||
| f""" | ||
| def f(): | ||
| ''' | ||
| >>> print('{a}') | ||
| {b} | ||
| ''' | ||
| pass | ||
| """, | ||
| encoding=encoding, | ||
| ) | ||
|
|
||
| assert Path( | ||
| make_file | ||
| ).is_file(), f"`testdir.makepyfile` failed encode {repr((a,b))} with {encoding=}" | ||
|
|
||
| make_diff = dedent( | ||
| f""" | ||
| >>> print('{a}') | ||
| - {b} | ||
| + {a} | ||
| """ | ||
| ).strip("\n") | ||
|
|
||
| # try to check if makepyfile screwed up and create python file in a different way | ||
|
|
||
| try: | ||
| basic_file, basic_diff = makebasicfile(str(testdir), a, b, encoding) | ||
| except UnicodeEncodeError: | ||
| pytest.fail( | ||
| f"testdir.makepyfile encoding {repr((a,b))} with {encoding=}, but it sould have failed." | ||
| ) | ||
|
|
||
| assert Path( | ||
| basic_file | ||
| ).is_file(), f"`makebasicfile` failed encode {repr((a,b))} with {encoding=}" | ||
| assert ( | ||
| make_diff == basic_diff | ||
| ), "sanity check - diffs always should be the same, if not my test implementation is wrong." | ||
|
|
||
|
|
||
| def test_compare_write_bytes(testdir, encoding, any_charset): | ||
| """ | ||
| `makeypfile` ignores keyword arguments `encoding` if content is not bytes. | ||
|
|
||
| 1. create test data and convert to bytes, if encoding failes the test is skipped. | ||
| 2. use both functions to create python file | ||
|
|
||
| - if both functions raise the same error, everything is as expected | ||
| - if Path.write_bytes succeeds so should `testdir.makepyfile` and error should be None | ||
| - both files sould exist after the test | ||
| """ | ||
|
|
||
| a, b = any_charset | ||
|
|
||
| try: | ||
| bytes_content = dedent(f""" | ||
| def f(): | ||
| ''' | ||
| >>> print('{a}') | ||
| {b} | ||
| ''' | ||
| pass | ||
| """ | ||
| ).encode(encoding) | ||
| except UnicodeEncodeError: | ||
| # skip test do testdata could not prepared | ||
| pytest.xfail(f"{repr(any_charset)} cannot be encoded with {encoding=}") | ||
|
|
||
| try: | ||
| make_file = testdir.makepyfile( | ||
| bytes_content, | ||
| encoding=encoding, | ||
| ) | ||
| except Exception as e: | ||
| error = e # if both function fail the same, everything is as expected | ||
| else: | ||
| error = None | ||
|
|
||
| basic_file = Path(str(testdir)).joinpath("test_basic.py") | ||
| try: | ||
| basic_file.write_bytes(bytes_content) | ||
| except Exception as e: | ||
| assert type(error) is type(e), f"basically never should happen, but {e=} was raised." | ||
| else: | ||
| assert error is None, f"makepyfile screwed up {encoding=} and raised {error=}" | ||
|
|
||
| assert Path(make_file).is_file() and Path(basic_file).is_file(), "files are missing." | ||
Uh oh!
There was an error while loading. Please reload this page.