From: Sagi Shadur Date: Fri, 30 Oct 2020 15:12:04 +0000 (+0200) Subject: Extract formatting tests (#1785) X-Git-Url: https://git.madduck.net/etc/vim.git/commitdiff_plain/e6cd10e7615f4df537e2eaefcf3904a4feecad1f?ds=sidebyside Extract formatting tests (#1785) * Update test versions * Use parametrize to remove tests duplications * Extract sources format tests * Fix mypy errors * Fix .travis.yml --- diff --git a/.travis.yml b/.travis.yml index 86cf24d..f035343 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,9 @@ cache: directories: - $HOME/.cache/pre-commit env: - - TEST_CMD="coverage run -m unittest" + - TEST_CMD="tox -e py" install: - - pip install coverage coveralls pre-commit + - pip install coverage coveralls pre-commit tox - pip install -e '.[d]' script: - $TEST_CMD diff --git a/test_requirements.txt b/test_requirements.txt index 999d05c..3e65cdb 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,4 +1,5 @@ -pytest >= 6.0.1 -pytest-mock >= 3.2.0 -pytest-cases >= 2.1.2 -coverage >= 5.2.1 \ No newline at end of file +pytest >= 6.1.1 +pytest-mock >= 3.3.1 +pytest-cases >= 2.3.0 +coverage >= 5.3 +parameterized >= 0.7.4 \ No newline at end of file diff --git a/tests/test_black.py b/tests/test_black.py index 7927b36..b0cf6ed 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -5,7 +5,6 @@ import logging from concurrent.futures import ThreadPoolExecutor from contextlib import contextmanager from dataclasses import replace -from functools import partial import inspect from io import BytesIO, TextIOWrapper import os @@ -38,13 +37,19 @@ from black import Feature, TargetVersion from pathspec import PathSpec # Import other test classes -from tests.util import THIS_DIR, read_data, DETERMINISTIC_HEADER +from tests.util import ( + THIS_DIR, + read_data, + DETERMINISTIC_HEADER, + BlackBaseTestCase, + DEFAULT_MODE, + fs, + ff, + dump_to_stderr, +) from .test_primer import PrimerCLITests # noqa: F401 -DEFAULT_MODE = black.FileMode(experimental_string_processing=True) -ff = partial(black.format_file_in_place, mode=DEFAULT_MODE, fast=True) -fs = partial(black.format_str, mode=DEFAULT_MODE) THIS_FILE = Path(__file__) PY36_VERSIONS = { TargetVersion.PY36, @@ -57,10 +62,6 @@ T = TypeVar("T") R = TypeVar("R") -def dump_to_stderr(*output: str) -> str: - return "\n" + "\n".join(output) + "\n" - - @contextmanager def cache_dir(exists: bool = True) -> Iterator[Path]: with TemporaryDirectory() as workspace: @@ -122,29 +123,7 @@ class BlackRunner(CliRunner): sys.stderr = hold_stderr -class BlackTestCase(unittest.TestCase): - maxDiff = None - _diffThreshold = 2 ** 20 - - def assertFormatEqual(self, expected: str, actual: str) -> None: - if actual != expected and not os.environ.get("SKIP_AST_PRINT"): - bdv: black.DebugVisitor[Any] - black.out("Expected tree:", fg="green") - try: - exp_node = black.lib2to3_parse(expected) - bdv = black.DebugVisitor() - list(bdv.visit(exp_node)) - except Exception as ve: - black.err(str(ve)) - black.out("Actual tree:", fg="red") - try: - exp_node = black.lib2to3_parse(actual) - bdv = black.DebugVisitor() - list(bdv.visit(exp_node)) - except Exception as ve: - black.err(str(ve)) - self.assertMultiLineEqual(expected, actual) - +class BlackTestCase(BlackBaseTestCase): def invokeBlack( self, args: List[str], exit_code: int = 0, ignore_config: bool = True ) -> None: @@ -163,16 +142,6 @@ class BlackTestCase(unittest.TestCase): ), ) - @patch("black.dump_to_file", dump_to_stderr) - def checkSourceFile(self, name: str, mode: black.FileMode = DEFAULT_MODE) -> None: - path = THIS_DIR.parent / name - source, expected = read_data(str(path), data=False) - actual = fs(source, mode=mode) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, mode) - self.assertFalse(ff(path)) - @patch("black.dump_to_file", dump_to_stderr) def test_empty(self) -> None: source = expected = "" @@ -192,48 +161,6 @@ class BlackTestCase(unittest.TestCase): os.unlink(tmp_file) self.assertFormatEqual(expected, actual) - def test_run_on_test_black(self) -> None: - self.checkSourceFile("tests/test_black.py") - - def test_run_on_test_blackd(self) -> None: - self.checkSourceFile("tests/test_blackd.py") - - def test_black(self) -> None: - self.checkSourceFile("src/black/__init__.py") - - def test_pygram(self) -> None: - self.checkSourceFile("src/blib2to3/pygram.py") - - def test_pytree(self) -> None: - self.checkSourceFile("src/blib2to3/pytree.py") - - def test_conv(self) -> None: - self.checkSourceFile("src/blib2to3/pgen2/conv.py") - - def test_driver(self) -> None: - self.checkSourceFile("src/blib2to3/pgen2/driver.py") - - def test_grammar(self) -> None: - self.checkSourceFile("src/blib2to3/pgen2/grammar.py") - - def test_literals(self) -> None: - self.checkSourceFile("src/blib2to3/pgen2/literals.py") - - def test_parse(self) -> None: - self.checkSourceFile("src/blib2to3/pgen2/parse.py") - - def test_pgen(self) -> None: - self.checkSourceFile("src/blib2to3/pgen2/pgen.py") - - def test_tokenize(self) -> None: - self.checkSourceFile("src/blib2to3/pgen2/tokenize.py") - - def test_token(self) -> None: - self.checkSourceFile("src/blib2to3/pgen2/token.py") - - def test_setup(self) -> None: - self.checkSourceFile("setup.py") - def test_piping(self) -> None: source, expected = read_data("src/black/__init__", data=False) result = BlackRunner().invoke( @@ -291,22 +218,6 @@ class BlackTestCase(unittest.TestCase): self.assertIn("\033[31m", actual) self.assertIn("\033[0m", actual) - @patch("black.dump_to_file", dump_to_stderr) - def test_function(self) -> None: - source, expected = read_data("function") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_function2(self) -> None: - source, expected = read_data("function2") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) def _test_wip(self) -> None: source, expected = read_data("wip") @@ -322,14 +233,6 @@ class BlackTestCase(unittest.TestCase): black.assert_equivalent(source, actual) black.assert_stable(source, actual, black.FileMode()) - @patch("black.dump_to_file", dump_to_stderr) - def test_function_trailing_comma(self) -> None: - source, expected = read_data("function_trailing_comma") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - @unittest.expectedFailure @patch("black.dump_to_file", dump_to_stderr) def test_trailing_comma_optional_parens_stability1(self) -> None: @@ -351,14 +254,6 @@ class BlackTestCase(unittest.TestCase): actual = fs(source) black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) - def test_expression(self) -> None: - source, expected = read_data("expression") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) def test_pep_572(self) -> None: source, expected = read_data("pep_572") @@ -434,14 +329,6 @@ class BlackTestCase(unittest.TestCase): self.assertIn("\033[31m", actual) self.assertIn("\033[0m", actual) - @patch("black.dump_to_file", dump_to_stderr) - def test_fstring(self) -> None: - source, expected = read_data("fstring") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) def test_pep_570(self) -> None: source, expected = read_data("pep_570") @@ -472,14 +359,6 @@ class BlackTestCase(unittest.TestCase): black.assert_equivalent(source, not_normalized) black.assert_stable(source, not_normalized, mode=mode) - @patch("black.dump_to_file", dump_to_stderr) - def test_docstring(self) -> None: - source, expected = read_data("docstring") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) def test_docstring_no_string_normalization(self) -> None: """Like test_docstring but with string normalization off.""" @@ -490,14 +369,6 @@ class BlackTestCase(unittest.TestCase): black.assert_equivalent(source, actual) black.assert_stable(source, actual, mode) - def test_long_strings(self) -> None: - """Tests for splitting long strings.""" - source, expected = read_data("long_strings") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - def test_long_strings_flag_disabled(self) -> None: """Tests for turning off the string processing logic.""" source, expected = read_data("long_strings_flag_disabled") @@ -506,162 +377,6 @@ class BlackTestCase(unittest.TestCase): self.assertFormatEqual(expected, actual) black.assert_stable(expected, actual, mode) - @patch("black.dump_to_file", dump_to_stderr) - def test_long_strings__edge_case(self) -> None: - """Edge-case tests for splitting long strings.""" - source, expected = read_data("long_strings__edge_case") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_long_strings__regression(self) -> None: - """Regression tests for splitting long strings.""" - source, expected = read_data("long_strings__regression") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_slices(self) -> None: - source, expected = read_data("slices") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_percent_precedence(self) -> None: - source, expected = read_data("percent_precedence") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_comments(self) -> None: - source, expected = read_data("comments") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_comments2(self) -> None: - source, expected = read_data("comments2") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_comments3(self) -> None: - source, expected = read_data("comments3") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_comments4(self) -> None: - source, expected = read_data("comments4") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_comments5(self) -> None: - source, expected = read_data("comments5") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_comments6(self) -> None: - source, expected = read_data("comments6") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_comments7(self) -> None: - source, expected = read_data("comments7") - mode = replace(DEFAULT_MODE, target_versions={black.TargetVersion.PY38}) - actual = fs(source, mode=mode) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_comment_after_escaped_newline(self) -> None: - source, expected = read_data("comment_after_escaped_newline") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_cantfit(self) -> None: - source, expected = read_data("cantfit") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_import_spacing(self) -> None: - source, expected = read_data("import_spacing") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_composition(self) -> None: - source, expected = read_data("composition") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_composition_no_trailing_comma(self) -> None: - source, expected = read_data("composition_no_trailing_comma") - mode = replace(DEFAULT_MODE, target_versions={black.TargetVersion.PY38}) - actual = fs(source, mode=mode) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_empty_lines(self) -> None: - source, expected = read_data("empty_lines") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_remove_parens(self) -> None: - source, expected = read_data("remove_parens") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_string_prefixes(self) -> None: - source, expected = read_data("string_prefixes") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) def test_numeric_literals(self) -> None: source, expected = read_data("numeric_literals") @@ -680,21 +395,6 @@ class BlackTestCase(unittest.TestCase): black.assert_equivalent(source, actual) black.assert_stable(source, actual, mode) - @patch("black.dump_to_file", dump_to_stderr) - def test_numeric_literals_py2(self) -> None: - source, expected = read_data("numeric_literals_py2") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_python2(self) -> None: - source, expected = read_data("python2") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) def test_python2_print_function(self) -> None: source, expected = read_data("python2_print_function") @@ -704,14 +404,6 @@ class BlackTestCase(unittest.TestCase): black.assert_equivalent(source, actual) black.assert_stable(source, actual, mode) - @patch("black.dump_to_file", dump_to_stderr) - def test_python2_unicode_literals(self) -> None: - source, expected = read_data("python2_unicode_literals") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) def test_stub(self) -> None: mode = replace(DEFAULT_MODE, is_pyi=True) @@ -770,78 +462,6 @@ class BlackTestCase(unittest.TestCase): black.assert_equivalent(source, actual) black.assert_stable(source, actual, DEFAULT_MODE) - @patch("black.dump_to_file", dump_to_stderr) - def test_fmtonoff(self) -> None: - source, expected = read_data("fmtonoff") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_fmtonoff2(self) -> None: - source, expected = read_data("fmtonoff2") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_fmtonoff3(self) -> None: - source, expected = read_data("fmtonoff3") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_fmtonoff4(self) -> None: - source, expected = read_data("fmtonoff4") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_remove_empty_parentheses_after_class(self) -> None: - source, expected = read_data("class_blank_parentheses") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_new_line_between_class_and_code(self) -> None: - source, expected = read_data("class_methods_new_line") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_bracket_match(self) -> None: - source, expected = read_data("bracketmatch") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_tuple_assign(self) -> None: - source, expected = read_data("tupleassign") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - - @patch("black.dump_to_file", dump_to_stderr) - def test_beginning_backslash(self) -> None: - source, expected = read_data("beginning_backslash") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - def test_tab_comment_indentation(self) -> None: contents_tab = "if 1:\n\tif 2:\n\t\tpass\n\t# comment\n\tpass\n" contents_spc = "if 1:\n if 2:\n pass\n # comment\n pass\n" @@ -1569,13 +1189,6 @@ class BlackTestCase(unittest.TestCase): two = black.read_cache(short_mode) self.assertNotIn(path, two) - def test_tricky_unicode_symbols(self) -> None: - source, expected = read_data("tricky_unicode_symbols") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - def test_single_file_force_pyi(self) -> None: pyi_mode = replace(DEFAULT_MODE, is_pyi=True) contents, expected = read_data("force_pyi") @@ -1672,13 +1285,6 @@ class BlackTestCase(unittest.TestCase): self.assertIn(path, pyi_cache) self.assertNotIn(path, normal_cache) - def test_collections(self) -> None: - source, expected = read_data("collections") - actual = fs(source) - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, DEFAULT_MODE) - def test_pipe_force_py36(self) -> None: source, expected = read_data("force_py36") result = CliRunner().invoke( diff --git a/tests/test_format.py b/tests/test_format.py new file mode 100644 index 0000000..e467770 --- /dev/null +++ b/tests/test_format.py @@ -0,0 +1,98 @@ +from unittest.mock import patch + +import black +from parameterized import parameterized + +from tests.util import ( + BlackBaseTestCase, + fs, + ff, + DEFAULT_MODE, + dump_to_stderr, + read_data, + THIS_DIR, +) + +SIMPLE_CASES = [ + "beginning_backslash", + "bracketmatch", + "cantfit", + "class_blank_parentheses", + "class_methods_new_line", + "collections", + "comments", + "comments2", + "comments3", + "comments4", + "comments5", + "comments6", + "comments7", + "comment_after_escaped_newline", + "composition", + "composition_no_trailing_comma", + "docstring", + "empty_lines", + "expression", + "fmtonoff", + "fmtonoff2", + "fmtonoff3", + "fmtonoff4", + "fstring", + "function", + "function2", + "function_trailing_comma", + "import_spacing", + "long_strings", + "long_strings__edge_case", + "long_strings__regression", + "numeric_literals_py2", + "percent_precedence", + "python2", + "python2_unicode_literals", + "remove_parens", + "slices", + "string_prefixes", + "tricky_unicode_symbols", + "tupleassign", +] + + +SOURCES = [ + "tests/test_black.py", + "tests/test_format.py", + "tests/test_blackd.py", + "src/black/__init__.py", + "src/blib2to3/pygram.py", + "src/blib2to3/pytree.py", + "src/blib2to3/pgen2/conv.py", + "src/blib2to3/pgen2/driver.py", + "src/blib2to3/pgen2/grammar.py", + "src/blib2to3/pgen2/literals.py", + "src/blib2to3/pgen2/parse.py", + "src/blib2to3/pgen2/pgen.py", + "src/blib2to3/pgen2/tokenize.py", + "src/blib2to3/pgen2/token.py", + "setup.py", +] + + +class TestSimpleFormat(BlackBaseTestCase): + @parameterized.expand(SIMPLE_CASES) + @patch("black.dump_to_file", dump_to_stderr) + def test_simple_format(self, filename: str) -> None: + source, expected = read_data(filename) + actual = fs(source) + self.assertFormatEqual(expected, actual) + black.assert_equivalent(source, actual) + black.assert_stable(source, actual, DEFAULT_MODE) + + @parameterized.expand(SOURCES) + @patch("black.dump_to_file", dump_to_stderr) + def test_source_is_formatted(self, filename: str) -> None: + path = THIS_DIR.parent / filename + source, expected = read_data(str(path), data=False) + actual = fs(source, mode=DEFAULT_MODE) + self.assertFormatEqual(expected, actual) + black.assert_equivalent(source, actual) + black.assert_stable(source, actual, DEFAULT_MODE) + self.assertFalse(ff(path)) diff --git a/tests/util.py b/tests/util.py index 9c3d3cb..da65ed0 100644 --- a/tests/util.py +++ b/tests/util.py @@ -1,7 +1,10 @@ +import os import unittest from contextlib import contextmanager from pathlib import Path -from typing import List, Tuple, Iterator +from typing import List, Tuple, Iterator, Any +import black +from functools import partial THIS_DIR = Path(__file__).parent PROJECT_ROOT = THIS_DIR.parent @@ -9,6 +12,39 @@ EMPTY_LINE = "# EMPTY LINE WITH WHITESPACE" + " (this comment will be removed)" DETERMINISTIC_HEADER = "[Deterministic header]" +DEFAULT_MODE = black.FileMode(experimental_string_processing=True) +ff = partial(black.format_file_in_place, mode=DEFAULT_MODE, fast=True) +fs = partial(black.format_str, mode=DEFAULT_MODE) + + +def dump_to_stderr(*output: str) -> str: + return "\n" + "\n".join(output) + "\n" + + +class BlackBaseTestCase(unittest.TestCase): + maxDiff = None + _diffThreshold = 2 ** 20 + + def assertFormatEqual(self, expected: str, actual: str) -> None: + if actual != expected and not os.environ.get("SKIP_AST_PRINT"): + bdv: black.DebugVisitor[Any] + black.out("Expected tree:", fg="green") + try: + exp_node = black.lib2to3_parse(expected) + bdv = black.DebugVisitor() + list(bdv.visit(exp_node)) + except Exception as ve: + black.err(str(ve)) + black.out("Actual tree:", fg="red") + try: + exp_node = black.lib2to3_parse(actual) + bdv = black.DebugVisitor() + list(bdv.visit(exp_node)) + except Exception as ve: + black.err(str(ve)) + self.assertMultiLineEqual(expected, actual) + + @contextmanager def skip_if_exception(e: str) -> Iterator[None]: try: @@ -24,11 +60,15 @@ def read_data(name: str, data: bool = True) -> Tuple[str, str]: """read_data('test_name') -> 'input', 'output'""" if not name.endswith((".py", ".pyi", ".out", ".diff")): name += ".py" - _input: List[str] = [] - _output: List[str] = [] base_dir = THIS_DIR / "data" if data else PROJECT_ROOT - with open(base_dir / name, "r", encoding="utf8") as test: + return read_data_from_file(base_dir / name) + + +def read_data_from_file(file_name: Path) -> Tuple[str, str]: + with open(file_name, "r", encoding="utf8") as test: lines = test.readlines() + _input: List[str] = [] + _output: List[str] = [] result = _input for line in lines: line = line.replace(EMPTY_LINE, "")