Skip to content
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

Speed up parameterized tests which use Git #761

Merged
merged 25 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ca5327e
test: speed up `test_black_options`
akaihola Oct 20, 2024
79126ce
chore: update to Darkgraylib 2.1.0
akaihola Oct 21, 2024
653126e
test: speed up `test_black_config_file_and_options`
akaihola Oct 29, 2024
55b8e7f
test: speed up `test_black_config_file_and_options`
akaihola Nov 4, 2024
84b0420
test: speed up `test_options`
akaihola Nov 4, 2024
26be628
test: speed up `test_git_get_modified_python_files`
akaihola Nov 4, 2024
f93b968
test: speed up `test_main_retval`
akaihola Nov 4, 2024
aa8372e
test: speed up `test_revision`
akaihola Nov 4, 2024
930199e
test: add `unix_and_windows_newline_repos` helper
akaihola Nov 9, 2024
a843d62
test: speed up `test_format_edited_parts`
akaihola Nov 4, 2024
f92c50c
test: speed up `test_main`
akaihola Nov 5, 2024
c1280bf
test: speed up `test_git_exists_in_revision` and `test_get_missing_at…
akaihola Nov 5, 2024
792581f
test: speed up `test_main_stdin_filename_repo`
akaihola Nov 8, 2024
21fab21
test: speed up `test_apply_isort`
akaihola Nov 8, 2024
87c6443
test: speed up `test_apply_isort_exclude`
akaihola Nov 8, 2024
45abdd6
test: speed up `test_build_isort_args`
akaihola Nov 8, 2024
7b47002
test: speed up `test_main_historical_ok`
akaihola Nov 9, 2024
95f0bcd
test: speed up `test_git_get_modified_python_files`
akaihola Nov 9, 2024
f4588f8
test: speed up `test_reformat_and_flynt_single_file`
akaihola Nov 9, 2024
d294092
test: speed up `test_format_edited_parts_stdin`
akaihola Nov 9, 2024
0d546db
test: speed up `test_flynt_single_file`
akaihola Nov 9, 2024
f461f86
test: speed up `test_format_edited_parts_historical`
akaihola Nov 9, 2024
64953cf
test: speed up `test_edited_linenums_differ_compare_revisions` and `t…
akaihola Nov 9, 2024
8ef6e64
test: speed up `test_edited_linenums_differ_revision_vs_lines_multili…
akaihola Nov 9, 2024
91742fb
test: speed up `test_main_isort.py`
akaihola Nov 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion constraints-oldest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# interpreter and Python ependencies. Keep this up-to-date with minimum
# versions in `setup.cfg`.
black==22.3.0
darkgraylib==2.0.1
darkgraylib==2.1.0
defusedxml==0.7.1
flake8-2020==1.6.1
flake8-bugbear==22.1.11
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ ignore = [
"ANN001", # Missing type annotation for function argument
"ANN201", # Missing return type annotation for public function
"ANN204", # Missing return type annotation for special method `__init__`
"ARG001", # Unused function argument
"C408", # Unnecessary `dict` call (rewrite as a literal)
"PLR0913", # Too many arguments in function definition (n > 5)
"S101", # Use of `assert` detected
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ packages = find:
install_requires =
# NOTE: remember to keep `constraints-oldest.txt` in sync with these
black>=22.3.0
darkgraylib~=2.0.1
darkgraylib~=2.1.0
toml>=0.10.0
typing_extensions>=4.0.1
# NOTE: remember to keep `.github/workflows/python-package.yml` in sync
Expand Down
23 changes: 23 additions & 0 deletions src/darker/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Configuration and fixtures for the Pytest based test suite."""

import pytest

try:
from black.files import _load_toml
except ImportError:
# Black 24.1.1 and earlier don't have `_load_toml`.
_load_toml = None # type: ignore[assignment]


@pytest.fixture
def load_toml_cache_clear() -> None:
"""Clear LRU caching in `black.files._load_toml` before each test.

To use this on all test cases in a test module, add this to the top::

pytestmark = pytest.mark.usefixtures("load_toml_cache_clear")

"""
if _load_toml:
# Black 24.1.1 and earlier don't have `_load_toml`, so no LRU cache to clear.
_load_toml.cache_clear()
11 changes: 11 additions & 0 deletions src/darker/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from typing import Generator, Optional
from unittest.mock import patch

from darkgraylib.testtools.git_repo_plugin import GitRepoFixture


@contextmanager
def _package_present(
Expand Down Expand Up @@ -43,3 +45,12 @@ def flynt_present(present: bool) -> Generator[None, None, None]:
fake_flynt_module.code_editor = ModuleType("process") # type: ignore
fake_flynt_module.code_editor.fstringify_code_by_line = None # type: ignore
yield


@contextmanager
def unix_and_windows_newline_repos(request, tmp_path_factory):
"""Create temporary repositories for Unix and windows newlines separately."""
with GitRepoFixture.context(
request, tmp_path_factory
) as repo_unix, GitRepoFixture.context(request, tmp_path_factory) as repo_windows:
yield {"\n": repo_unix, "\r\n": repo_windows}
114 changes: 77 additions & 37 deletions src/darker/tests/test_command_line.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# pylint: disable=too-many-arguments,too-many-locals,use-dict-literal
"""Unit tests for `darker.command_line` and `darker.__main__`."""

"""Unit tests for :mod:`darker.command_line` and :mod:`darker.__main__`"""
# pylint: disable=too-many-arguments,too-many-locals
# pylint: disable=no-member,redefined-outer-name,unused-argument,use-dict-literal

from __future__ import annotations

import os
import re
Expand All @@ -22,10 +25,14 @@
from darker.tests.helpers import flynt_present, isort_present
from darkgraylib.config import ConfigurationError
from darkgraylib.git import RevisionRange
from darkgraylib.testtools.git_repo_plugin import GitRepoFixture
from darkgraylib.testtools.helpers import raises_if_exception
from darkgraylib.utils import TextDocument, joinlines

pytestmark = pytest.mark.usefixtures("find_project_root_cache_clear")
# Clear LRU caches for `find_project_root()` and `_load_toml()` before each test
pytestmark = pytest.mark.usefixtures(
"find_project_root_cache_clear", "load_toml_cache_clear"
)


@pytest.mark.kwparametrize(
Expand Down Expand Up @@ -463,6 +470,24 @@ def test_help_with_flynt_package(capsys):
)


@pytest.fixture(scope="module")
def black_options_files(request, tmp_path_factory):
"""Fixture for the `test_black_options` test."""
with GitRepoFixture.context(request, tmp_path_factory) as repo:
(repo.root / "pyproject.toml").write_bytes(b"[tool.black]\n")
(repo.root / "black.cfg").write_text(
dedent(
"""
[tool.black]
line-length = 81
skip-string-normalization = false
target-version = 'py38'
"""
)
)
yield repo.add({"main.py": 'print("Hello World!")\n'}, commit="Initial commit")


@pytest.mark.kwparametrize(
dict(options=[], expect=call()),
dict(
Expand Down Expand Up @@ -547,34 +572,35 @@ def test_help_with_flynt_package(capsys):
),
),
)
def test_black_options(monkeypatch, tmpdir, git_repo, options, expect):
"""Black options from the command line are passed correctly to Black"""
monkeypatch.chdir(tmpdir)
(tmpdir / "pyproject.toml").write("[tool.black]\n")
(tmpdir / "black.cfg").write(
dedent(
"""
[tool.black]
line-length = 81
skip-string-normalization = false
target-version = 'py38'
"""
)
)
added_files = git_repo.add(
{"main.py": 'print("Hello World!")\n'}, commit="Initial commit"
)
added_files["main.py"].write_bytes(b'print ("Hello World!")\n')
def test_black_options(black_options_files, options, expect):
"""Black options from the command line are passed correctly to Black."""
# The Git repository set up by the module-scope `black_options_repo` fixture is
# shared by all test cases. The "main.py" file modified by the test run needs to be
# reset to its original content before the next test case.
black_options_files["main.py"].write_bytes(b'print ("Hello World!")\n')
with patch.object(
black_formatter, "Mode", wraps=black_formatter.Mode
) as file_mode_class:

main(options + [str(path) for path in added_files.values()])
main(options + [str(path) for path in black_options_files.values()])

assert black_options_files["main.py"].read_bytes() == b'print("Hello World!")\n'
_, expect_args, expect_kwargs = expect
file_mode_class.assert_called_once_with(*expect_args, **expect_kwargs)


@pytest.fixture(scope="module")
def black_config_file_and_options_files(request, tmp_path_factory):
"""Git repository fixture for the `test_black_config_file_and_options` test."""
with GitRepoFixture.context(request, tmp_path_factory) as repo:
repo_files = repo.add(
{"main.py": "foo", "pyproject.toml": "* placeholder, will be overwritten"},
commit="Initial commit",
)
repo_files["main.py"].write_bytes(b"a = [1, 2,]")
yield repo_files


@pytest.mark.kwparametrize(
dict(config=[], options=[], expect=call()),
dict(
Expand Down Expand Up @@ -673,23 +699,33 @@ def test_black_options(monkeypatch, tmpdir, git_repo, options, expect):
expect=call(preview=True),
),
)
def test_black_config_file_and_options(git_repo, config, options, expect):
def test_black_config_file_and_options(
black_config_file_and_options_files, config, options, expect
):
"""Black configuration file and command line options are combined correctly"""
added_files = git_repo.add(
{"main.py": "foo", "pyproject.toml": joinlines(["[tool.black]"] + config)},
commit="Initial commit",
)
added_files["main.py"].write_bytes(b"a = [1, 2,]")
repo_files = black_config_file_and_options_files
repo_files["pyproject.toml"].write_text(joinlines(["[tool.black]", *config]))
mode_class_mock = Mock(wraps=black_formatter.Mode)
# Speed up tests by mocking `format_str` to skip running Black
format_str = Mock(return_value="a = [1, 2,]")
with patch.multiple(black_formatter, Mode=mode_class_mock, format_str=format_str):

main(options + [str(path) for path in added_files.values()])
main(options + [str(path) for path in repo_files.values()])

assert mode_class_mock.call_args_list == [expect]


@pytest.fixture(scope="module")
def options_repo(request, tmp_path_factory):
"""Git repository fixture for the `test_options` test."""
with GitRepoFixture.context(request, tmp_path_factory) as repo:
paths = repo.add(
{"a.py": "1\n", "b.py": "2\n", "my.cfg": ""}, commit="Initial commit"
)
paths["a.py"].write_bytes(b"one\n")
yield repo


@pytest.mark.kwparametrize(
dict(
options=["a.py"],
Expand Down Expand Up @@ -784,41 +820,45 @@ def test_black_config_file_and_options(git_repo, config, options, expect):
),
),
)
def test_options(git_repo, options, expect):
def test_options(options_repo, monkeypatch, options, expect):
"""The main engine is called with correct parameters based on the command line

Executed in a clean directory so Darker's own ``pyproject.toml`` doesn't interfere.

"""
paths = git_repo.add(
{"a.py": "1\n", "b.py": "2\n", "my.cfg": ""}, commit="Initial commit"
)
paths["a.py"].write_bytes(b"one\n")
with patch('darker.__main__.format_edited_parts') as format_edited_parts:
monkeypatch.chdir(options_repo.root)

retval = main(options)

expect_formatter = BlackFormatter()
expect_formatter.config = expect[4]
actual_formatter = format_edited_parts.call_args.args[4]
assert actual_formatter.config == expect_formatter.config
expect = (Path(git_repo.root), expect[1]) + expect[2:4] + (expect_formatter,)
expect = (Path(options_repo.root), expect[1]) + expect[2:4] + (expect_formatter,)
format_edited_parts.assert_called_once_with(
*expect, report_unmodified=False, workers=1
)
assert retval == 0


@pytest.fixture(scope="module")
def main_retval_repo(request, tmp_path_factory):
"""Git repository fixture for the `test_main_retval` test."""
with GitRepoFixture.context(request, tmp_path_factory) as repo:
repo.add({"a.py": ""}, commit="Initial commit")
yield


@pytest.mark.kwparametrize(
dict(arguments=["a.py"], changes=False),
dict(arguments=["a.py"], changes=True),
dict(arguments=["--check", "a.py"], changes=False),
dict(arguments=["--check", "a.py"], changes=True, expect_retval=1),
expect_retval=0,
)
def test_main_retval(git_repo, arguments, changes, expect_retval):
def test_main_retval(main_retval_repo, arguments, changes, expect_retval):
"""``main()`` return value is correct based on ``--check`` and reformatting."""
git_repo.add({"a.py": ""}, commit="Initial commit")
format_edited_parts = Mock()
format_edited_parts.return_value = (
[
Expand Down
Loading
Loading