Skip to content

Commit 57eee32

Browse files
authored
fix(plugins): remove cwd change before running pytest (#1943)
1 parent 9184a03 commit 57eee32

File tree

6 files changed

+49
-107
lines changed

6 files changed

+49
-107
lines changed

src/cli/pytest_commands/base.py

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
"""Base classes and utilities for pytest-based CLI commands."""
22

3-
import os
43
import sys
54
from abc import ABC, abstractmethod
6-
from contextlib import contextmanager
75
from dataclasses import dataclass, field
86
from os.path import realpath
97
from pathlib import Path
@@ -14,8 +12,8 @@
1412
from rich.console import Console
1513

1614
CURRENT_FOLDER = Path(realpath(__file__)).parent
15+
PACKAGE_INSTALL_FOLDER = CURRENT_FOLDER.parent.parent
1716
PYTEST_INI_FOLDER = CURRENT_FOLDER / "pytest_ini_files"
18-
STATIC_TESTS_WORKING_DIRECTORY = CURRENT_FOLDER.parent.parent
1917

2018

2119
@dataclass
@@ -25,7 +23,7 @@ class PytestExecution:
2523
config_file: Path
2624
"""Path to the pytest configuration file (e.g., 'pytest-fill.ini')."""
2725

28-
test_path_args: List[str] = field(default_factory=list)
26+
command_logic_test_paths: List[str] = field(default_factory=list)
2927
"""List of tests that have to be appended to the start of pytest command arguments."""
3028

3129
args: List[str] = field(default_factory=list)
@@ -44,60 +42,35 @@ def process_args(self, args: List[str]) -> List[str]:
4442
pass
4543

4644

47-
@contextmanager
48-
def chdir(path: Path | None):
49-
"""Context manager to change the current working directory and restore it unconditionally."""
50-
if path is None:
51-
yield
52-
return
53-
54-
prev_cwd = Path.cwd()
55-
os.chdir(path)
56-
try:
57-
yield
58-
finally:
59-
os.chdir(prev_cwd)
60-
61-
6245
@dataclass(kw_only=True)
6346
class PytestRunner:
6447
"""Handles execution of pytest commands."""
6548

6649
console: Console = field(default_factory=lambda: Console(highlight=False))
6750
"""Console to use for output."""
6851

69-
pytest_working_directory: Path | None = None
70-
"""
71-
Working directory that pytest should use to start and look for tests.
72-
If set, the working directory of the process will be changed to this directory
73-
before running pytest, and a plugin will be used to change the working directory
74-
back to the original directory to run the rest of the pytest plugins
75-
(so flags like `--input` in `consume` do work with relative paths).
76-
"""
77-
7852
def run_single(self, execution: PytestExecution) -> int:
7953
"""Run pytest once with the given configuration and arguments."""
8054
root_dir_arg = ["--rootdir", "."]
8155
pytest_args = (
8256
["-c", str(execution.config_file)]
8357
+ root_dir_arg
84-
+ execution.test_path_args
58+
+ [
59+
str(PACKAGE_INSTALL_FOLDER / test_path)
60+
for test_path in execution.command_logic_test_paths
61+
]
8562
+ execution.args
8663
)
87-
if self.pytest_working_directory:
64+
if execution.command_logic_test_paths:
8865
pytest_args += [
8966
"-p",
90-
"pytest_plugins.working_directory",
91-
"--working-directory",
92-
f"{Path.cwd()}",
67+
"pytest_plugins.fix_package_test_path",
9368
]
94-
9569
if self._is_verbose(execution.args):
9670
pytest_cmd = f"pytest {' '.join(pytest_args)}"
9771
self.console.print(f"Executing: [bold]{pytest_cmd}[/bold]")
9872

99-
with chdir(self.pytest_working_directory):
100-
return pytest.main(pytest_args)
73+
return pytest.main(pytest_args)
10174

10275
def _is_verbose(self, args: List[str]) -> bool:
10376
"""Check if verbose output is requested."""
@@ -145,8 +118,8 @@ class PytestCommand:
145118
plugins: List[str] = field(default_factory=list)
146119
"""Plugins to load for the pytest command."""
147120

148-
static_test_paths: List[Path] | None = None
149-
"""Static tests that contain the command logic."""
121+
command_logic_test_paths: List[Path] | None = None
122+
"""Path to test files that contain the command logic."""
150123

151124
pytest_ini_folder: Path = PYTEST_INI_FOLDER
152125
"""Folder where the pytest configuration files are located."""
@@ -159,10 +132,6 @@ def config_path(self) -> Path:
159132
def execute(self, pytest_args: List[str]) -> None:
160133
"""Execute the command with the given pytest arguments."""
161134
executions = self.create_executions(pytest_args)
162-
if self.static_test_paths:
163-
self.runner.pytest_working_directory = STATIC_TESTS_WORKING_DIRECTORY
164-
else:
165-
self.runner.pytest_working_directory = None
166135
result = self.runner.run_multiple(executions)
167136
sys.exit(result)
168137

@@ -172,8 +141,8 @@ def test_args(self) -> List[str]:
172141
Return the test-path arguments that have to be appended to all PytestExecution
173142
instances.
174143
"""
175-
if self.static_test_paths:
176-
return [str(path) for path in self.static_test_paths]
144+
if self.command_logic_test_paths:
145+
return [str(path) for path in self.command_logic_test_paths]
177146
return []
178147

179148
def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]:
@@ -187,7 +156,7 @@ def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]:
187156
return [
188157
PytestExecution(
189158
config_file=self.config_path,
190-
test_path_args=self.test_args,
159+
command_logic_test_paths=self.test_args,
191160
args=processed_args,
192161
)
193162
]

src/cli/pytest_commands/consume.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
def create_consume_command(
1414
*,
15-
static_test_paths: List[Path],
15+
command_logic_test_paths: List[Path],
1616
is_hive: bool = False,
1717
command_name: str = "",
1818
) -> PytestCommand:
@@ -32,27 +32,27 @@ def create_consume_command(
3232
return PytestCommand(
3333
config_file="pytest-consume.ini",
3434
argument_processors=processors,
35-
static_test_paths=static_test_paths,
35+
command_logic_test_paths=command_logic_test_paths,
3636
)
3737

3838

39-
def get_static_test_paths(command_name: str, is_hive: bool) -> List[Path]:
39+
def get_command_logic_test_paths(command_name: str, is_hive: bool) -> List[Path]:
4040
"""Determine the command paths based on the command name and hive flag."""
4141
base_path = Path("pytest_plugins/consume")
4242
if command_name == "hive":
4343
commands = ["rlp", "engine"]
44-
static_test_paths = [
44+
command_logic_test_paths = [
4545
base_path / "simulators" / "simulator_logic" / f"test_via_{cmd}.py" for cmd in commands
4646
]
4747
elif command_name in ["engine", "rlp"]:
48-
static_test_paths = [
48+
command_logic_test_paths = [
4949
base_path / "simulators" / "simulator_logic" / f"test_via_{command_name}.py"
5050
]
5151
elif command_name == "direct":
52-
static_test_paths = [base_path / "direct" / "test_via_direct.py"]
52+
command_logic_test_paths = [base_path / "direct" / "test_via_direct.py"]
5353
else:
5454
raise ValueError(f"Unexpected command: {command_name}.")
55-
return static_test_paths
55+
return command_logic_test_paths
5656

5757

5858
@click.group(context_settings={"help_option_names": ["-h", "--help"]})
@@ -67,7 +67,7 @@ def consume_command(is_hive: bool = False) -> Callable[[Callable[..., Any]], cli
6767
def decorator(func: Callable[..., Any]) -> click.Command:
6868
command_name = func.__name__
6969
command_help = func.__doc__
70-
static_test_paths = get_static_test_paths(command_name, is_hive)
70+
command_logic_test_paths = get_command_logic_test_paths(command_name, is_hive)
7171

7272
@consume.command(
7373
name=command_name,
@@ -78,7 +78,9 @@ def decorator(func: Callable[..., Any]) -> click.Command:
7878
@functools.wraps(func)
7979
def command(pytest_args: List[str], **kwargs) -> None:
8080
consume_cmd = create_consume_command(
81-
static_test_paths=static_test_paths, is_hive=is_hive, command_name=command_name
81+
command_logic_test_paths=command_logic_test_paths,
82+
is_hive=is_hive,
83+
command_name=command_name,
8284
)
8385
consume_cmd.execute(list(pytest_args))
8486

@@ -117,5 +119,5 @@ def hive() -> None:
117119
@common_pytest_options
118120
def cache(pytest_args: List[str], **kwargs) -> None:
119121
"""Consume command to cache test fixtures."""
120-
cache_cmd = create_consume_command(static_test_paths=[], is_hive=False)
122+
cache_cmd = create_consume_command(command_logic_test_paths=[], is_hive=False)
121123
cache_cmd.execute(list(pytest_args))

src/cli/pytest_commands/execute.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ def _create_execute_subcommand(
2424
config_file: str,
2525
help_text: str,
2626
required_args: List[str] | None = None,
27-
static_test_paths: List[Path] | None = None,
27+
command_logic_test_paths: List[Path] | None = None,
2828
) -> click.Command:
2929
"""Create an execute subcommand with standardized structure."""
3030
pytest_command = PytestCommand(
3131
config_file=config_file,
3232
argument_processors=[HelpFlagsProcessor(f"execute-{command_name}", required_args)],
33-
static_test_paths=static_test_paths,
33+
command_logic_test_paths=command_logic_test_paths,
3434
)
3535

3636
@execute.command(
@@ -69,7 +69,7 @@ def command(pytest_args: List[str], **_kwargs) -> None:
6969
"pytest-execute-eth-config.ini",
7070
"Test a client's configuration using the `eth_config` RPC endpoint.",
7171
required_args=["--network=Mainnet", "--rpc-endpoint=http://localhost:8545"],
72-
static_test_paths=[Path("pytest_plugins/execute/eth_config/execute_eth_config.py")],
72+
command_logic_test_paths=[Path("pytest_plugins/execute/eth_config/execute_eth_config.py")],
7373
)
7474

7575
recover = _create_execute_subcommand(
@@ -82,5 +82,5 @@ def command(pytest_args: List[str], **_kwargs) -> None:
8282
"--start-eoa-index=1",
8383
"--destination=0x0000000000000000000000000000000000000000",
8484
],
85-
static_test_paths=[Path("pytest_plugins/execute/execute_recover.py")],
85+
command_logic_test_paths=[Path("pytest_plugins/execute/execute_recover.py")],
8686
)

src/pytest_plugins/consume/consume.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -446,12 +446,3 @@ def pytest_generate_tests(metafunc):
446446
if "client_type" in metafunc.fixturenames:
447447
client_ids = [client.name for client in metafunc.config.hive_execution_clients]
448448
metafunc.parametrize("client_type", metafunc.config.hive_execution_clients, ids=client_ids)
449-
450-
451-
def pytest_collection_modifyitems(items):
452-
"""Modify collected item names to remove the test runner function from the name."""
453-
for item in items:
454-
original_name = item.originalname
455-
remove = f"{original_name}["
456-
if item.name.startswith(remove):
457-
item.name = item.name.removeprefix(remove)[:-1]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
Pytest plugin to fix the test IDs for all pytest command that use a command-logic test
3+
file.
4+
"""
5+
6+
from typing import List
7+
8+
import pytest
9+
10+
11+
def pytest_collection_modifyitems(items: List[pytest.Item]):
12+
"""Modify collected item names to remove the test runner function from the name."""
13+
for item in items:
14+
original_name = item.originalname # type: ignore
15+
remove = f"{original_name}["
16+
if item.name.startswith(remove):
17+
item.name = item.name.removeprefix(remove)[:-1]
18+
if remove in item.nodeid:
19+
item._nodeid = item.nodeid[item.nodeid.index(remove) + len(remove) : -1]

src/pytest_plugins/working_directory.py

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)