refactor(tests): 重构测试代码并优化ruff检查规则
1. 在pyproject.toml中为测试文件添加ARG001和ARG002规则忽略 2. 重构多个CLI测试文件,移除冗余的mock断言、导入顺序调整 3. 统一测试用例的帮助信息输出逻辑,移除SystemExit捕获,简化测试流程 4. 拆分合并冗余的测试类,按功能细化测试用例 5. 移除测试代码中多余的注释和pytest导入
This commit is contained in:
+86
-166
@@ -5,8 +5,6 @@ from __future__ import annotations
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
import pyflowx as px
|
||||
from pyflowx.cli import packtool
|
||||
|
||||
@@ -17,26 +15,26 @@ from pyflowx.cli import packtool
|
||||
class TestPackSource:
|
||||
"""Test pack_source function."""
|
||||
|
||||
def test_pack_source_with_project_dir(self, tmp_path: Path) -> None:
|
||||
"""Should pack source from project directory."""
|
||||
def test_pack_source_basic(self, tmp_path: Path) -> None:
|
||||
"""Should pack source code."""
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
(project_dir / "main.py").write_text("print('hello')")
|
||||
output_dir = tmp_path / "output"
|
||||
output_dir.mkdir()
|
||||
|
||||
with patch("shutil.make_archive") as mock_archive:
|
||||
packtool.pack_source(project_dir, output_dir)
|
||||
assert mock_archive.called
|
||||
packtool.pack_source(project_dir, output_dir)
|
||||
assert output_dir.exists()
|
||||
|
||||
def test_pack_source_creates_output_dir(self, tmp_path: Path) -> None:
|
||||
"""Should create output directory if it doesn't exist."""
|
||||
def test_pack_source_with_pyproject(self, tmp_path: Path) -> None:
|
||||
"""Should pack source with pyproject.toml."""
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
(project_dir / "pyproject.toml").write_text("[project]\nname = 'test'")
|
||||
(project_dir / "main.py").write_text("print('hello')")
|
||||
output_dir = tmp_path / "output"
|
||||
|
||||
with patch("shutil.make_archive"):
|
||||
packtool.pack_source(project_dir, output_dir)
|
||||
assert output_dir.exists()
|
||||
packtool.pack_source(project_dir, output_dir)
|
||||
assert output_dir.exists()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------- #
|
||||
@@ -45,27 +43,22 @@ class TestPackSource:
|
||||
class TestPackDependencies:
|
||||
"""Test pack_dependencies function."""
|
||||
|
||||
def test_pack_dependencies_with_lib_dir(self, tmp_path: Path) -> None:
|
||||
"""Should pack dependencies from lib directory."""
|
||||
lib_dir = tmp_path / "lib"
|
||||
lib_dir.mkdir()
|
||||
dependencies = ["numpy", "pandas"]
|
||||
def test_pack_dependencies_empty(self, tmp_path: Path) -> None:
|
||||
"""Should handle empty dependencies."""
|
||||
lib_dir = tmp_path / "libs"
|
||||
|
||||
packtool.pack_dependencies(lib_dir, [])
|
||||
# Should print message and return
|
||||
|
||||
def test_pack_dependencies_with_deps(self, tmp_path: Path) -> None:
|
||||
"""Should pack dependencies."""
|
||||
lib_dir = tmp_path / "libs"
|
||||
|
||||
with patch("subprocess.run") as mock_run:
|
||||
mock_run.return_value = MagicMock(returncode=0)
|
||||
packtool.pack_dependencies(lib_dir, dependencies)
|
||||
packtool.pack_dependencies(lib_dir, ["numpy", "pandas"])
|
||||
assert mock_run.called
|
||||
|
||||
def test_pack_dependencies_empty_list(self, tmp_path: Path) -> None:
|
||||
"""Should handle empty dependency list."""
|
||||
lib_dir = tmp_path / "lib"
|
||||
lib_dir.mkdir()
|
||||
|
||||
with patch("subprocess.run") as mock_run:
|
||||
mock_run.return_value = MagicMock(returncode=0)
|
||||
packtool.pack_dependencies(lib_dir, [])
|
||||
# Should still work with empty list
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------- #
|
||||
# pack_wheel
|
||||
@@ -73,29 +66,18 @@ class TestPackDependencies:
|
||||
class TestPackWheel:
|
||||
"""Test pack_wheel function."""
|
||||
|
||||
def test_pack_wheel_with_project_dir(self, tmp_path: Path) -> None:
|
||||
"""Should pack wheel from project directory."""
|
||||
def test_pack_wheel(self, tmp_path: Path) -> None:
|
||||
"""Should pack wheel."""
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
output_dir = tmp_path / "output"
|
||||
output_dir.mkdir()
|
||||
(project_dir / "pyproject.toml").write_text("[project]\nname = 'test'")
|
||||
output_dir = tmp_path / "dist"
|
||||
|
||||
with patch("subprocess.run") as mock_run:
|
||||
mock_run.return_value = MagicMock(returncode=0)
|
||||
packtool.pack_wheel(project_dir, output_dir)
|
||||
assert mock_run.called
|
||||
|
||||
def test_pack_wheel_creates_output_dir(self, tmp_path: Path) -> None:
|
||||
"""Should create output directory if it doesn't exist."""
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
output_dir = tmp_path / "output"
|
||||
|
||||
with patch("subprocess.run") as mock_run:
|
||||
mock_run.return_value = MagicMock(returncode=0)
|
||||
packtool.pack_wheel(project_dir, output_dir)
|
||||
assert output_dir.exists()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------- #
|
||||
# install_embed_python
|
||||
@@ -103,23 +85,29 @@ class TestPackWheel:
|
||||
class TestInstallEmbedPython:
|
||||
"""Test install_embed_python function."""
|
||||
|
||||
def test_install_embed_python_with_version(self, tmp_path: Path) -> None:
|
||||
"""Should install embedded Python with version."""
|
||||
def test_install_embed_python(self, tmp_path: Path) -> None:
|
||||
"""Should install embedded Python."""
|
||||
output_dir = tmp_path / "python"
|
||||
|
||||
with patch("subprocess.run") as mock_run, patch.object(Path, "exists", return_value=False):
|
||||
mock_run.return_value = MagicMock(returncode=0)
|
||||
with patch("urllib.request.urlretrieve"), patch("zipfile.ZipFile") as mock_zipfile:
|
||||
mock_zip_instance = MagicMock()
|
||||
mock_zipfile.return_value.__enter__.return_value = mock_zip_instance
|
||||
packtool.install_embed_python("3.10", output_dir)
|
||||
assert mock_run.called
|
||||
assert mock_zip_instance.extractall.called
|
||||
|
||||
def test_install_embed_python_creates_output_dir(self, tmp_path: Path) -> None:
|
||||
"""Should create output directory if it doesn't exist."""
|
||||
def test_install_embed_python_with_cache(self, tmp_path: Path) -> None:
|
||||
"""Should use cached Python."""
|
||||
output_dir = tmp_path / "python"
|
||||
cache_dir = tmp_path / ".cache" / "pypack"
|
||||
cache_dir.mkdir(parents=True)
|
||||
cache_file = cache_dir / "python-3.10.11-embed-amd64.zip"
|
||||
cache_file.write_bytes(b"ZIP content")
|
||||
|
||||
with patch("subprocess.run") as mock_run, patch.object(Path, "exists", return_value=False):
|
||||
mock_run.return_value = MagicMock(returncode=0)
|
||||
with patch("zipfile.ZipFile") as mock_zipfile:
|
||||
mock_zip_instance = MagicMock()
|
||||
mock_zipfile.return_value.__enter__.return_value = mock_zip_instance
|
||||
packtool.install_embed_python("3.10", output_dir)
|
||||
assert output_dir.exists()
|
||||
assert mock_zip_instance.extractall.called
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------- #
|
||||
@@ -128,27 +116,15 @@ class TestInstallEmbedPython:
|
||||
class TestCreateZipPackage:
|
||||
"""Test create_zip_package function."""
|
||||
|
||||
def test_create_zip_package_with_source_dir(self, tmp_path: Path) -> None:
|
||||
"""Should create zip package from source directory."""
|
||||
def test_create_zip_package(self, tmp_path: Path) -> None:
|
||||
"""Should create ZIP package."""
|
||||
source_dir = tmp_path / "source"
|
||||
source_dir.mkdir()
|
||||
(source_dir / "test.txt").write_text("test content")
|
||||
output_file = tmp_path / "package.zip"
|
||||
|
||||
with patch("zipfile.ZipFile") as mock_zip:
|
||||
packtool.create_zip_package(source_dir, output_file)
|
||||
assert mock_zip.called
|
||||
|
||||
def test_create_zip_package_with_files(self, tmp_path: Path) -> None:
|
||||
"""Should create zip package with files."""
|
||||
source_dir = tmp_path / "source"
|
||||
source_dir.mkdir()
|
||||
test_file = source_dir / "test.txt"
|
||||
test_file.write_text("test content")
|
||||
output_file = tmp_path / "package.zip"
|
||||
|
||||
with patch("zipfile.ZipFile") as mock_zip:
|
||||
packtool.create_zip_package(source_dir, output_file)
|
||||
assert mock_zip.called
|
||||
packtool.create_zip_package(source_dir, output_file)
|
||||
assert output_file.exists()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------- #
|
||||
@@ -157,22 +133,21 @@ class TestCreateZipPackage:
|
||||
class TestCleanBuildDir:
|
||||
"""Test clean_build_dir function."""
|
||||
|
||||
def test_clean_build_dir_removes_directory(self, tmp_path: Path) -> None:
|
||||
"""Should remove build directory."""
|
||||
def test_clean_build_dir_exists(self, tmp_path: Path) -> None:
|
||||
"""Should clean existing build directory."""
|
||||
build_dir = tmp_path / "build"
|
||||
build_dir.mkdir()
|
||||
(build_dir / "test.txt").write_text("test")
|
||||
|
||||
with patch("shutil.rmtree") as mock_rmtree:
|
||||
packtool.clean_build_dir(build_dir)
|
||||
assert mock_rmtree.called
|
||||
packtool.clean_build_dir(build_dir)
|
||||
assert not build_dir.exists()
|
||||
|
||||
def test_clean_build_dir_nonexistent(self, tmp_path: Path) -> None:
|
||||
def test_clean_build_dir_not_exists(self, tmp_path: Path) -> None:
|
||||
"""Should handle nonexistent build directory."""
|
||||
build_dir = tmp_path / "build"
|
||||
build_dir = tmp_path / "nonexistent"
|
||||
|
||||
with patch.object(Path, "exists", return_value=False):
|
||||
packtool.clean_build_dir(build_dir)
|
||||
# Should not raise error
|
||||
packtool.clean_build_dir(build_dir)
|
||||
# Should print message
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------- #
|
||||
@@ -181,114 +156,59 @@ class TestCleanBuildDir:
|
||||
class TestMain:
|
||||
"""Test main function."""
|
||||
|
||||
def test_main_src_default_dirs(self) -> None:
|
||||
"""main() should handle src command with default dirs."""
|
||||
with patch("sys.argv", ["packtool", "src"]), patch.object(px, "run") as mock_run, patch.object(
|
||||
packtool, "pack_source"
|
||||
):
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
def test_main_src_command(self, tmp_path: Path) -> None:
|
||||
"""main() should handle src command."""
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
|
||||
def test_main_src_custom_dirs(self) -> None:
|
||||
"""main() should handle src command with custom dirs."""
|
||||
with patch("sys.argv", ["packtool", "src", "--project-dir", "project", "--output-dir", "output"]), patch.object(
|
||||
with patch("sys.argv", ["packtool", "src", "--project-dir", str(project_dir)]), patch.object(
|
||||
px, "run"
|
||||
) as mock_run, patch.object(packtool, "pack_source"):
|
||||
) as mock_run:
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_deps_default_dir(self) -> None:
|
||||
"""main() should handle deps command with default dir."""
|
||||
with patch("sys.argv", ["packtool", "deps"]), patch.object(px, "run") as mock_run, patch.object(
|
||||
packtool, "pack_dependencies"
|
||||
):
|
||||
def test_main_deps_command(self, tmp_path: Path) -> None:
|
||||
"""main() should handle deps command."""
|
||||
with patch("sys.argv", ["packtool", "deps", "numpy", "pandas"]), patch.object(px, "run") as mock_run:
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_deps_with_dependencies(self) -> None:
|
||||
"""main() should handle deps command with dependencies."""
|
||||
with patch("sys.argv", ["packtool", "deps", "--lib-dir", "lib", "numpy", "pandas"]), patch.object(
|
||||
def test_main_wheel_command(self, tmp_path: Path) -> None:
|
||||
"""main() should handle wheel command."""
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
|
||||
with patch("sys.argv", ["packtool", "wheel", "--project-dir", str(project_dir)]), patch.object(
|
||||
px, "run"
|
||||
) as mock_run, patch.object(packtool, "pack_dependencies"):
|
||||
) as mock_run:
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_wheel_default_dirs(self) -> None:
|
||||
"""main() should handle wheel command with default dirs."""
|
||||
with patch("sys.argv", ["packtool", "wheel"]), patch.object(px, "run") as mock_run, patch.object(
|
||||
packtool, "pack_wheel"
|
||||
):
|
||||
def test_main_embed_command(self, tmp_path: Path) -> None:
|
||||
"""main() should handle embed command."""
|
||||
with patch("sys.argv", ["packtool", "embed", "--version", "3.10"]), patch.object(px, "run") as mock_run:
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_wheel_custom_dirs(self) -> None:
|
||||
"""main() should handle wheel command with custom dirs."""
|
||||
with patch(
|
||||
"sys.argv", ["packtool", "wheel", "--project-dir", "project", "--output-dir", "output"]
|
||||
), patch.object(px, "run") as mock_run, patch.object(packtool, "pack_wheel"):
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
def test_main_zip_command(self, tmp_path: Path) -> None:
|
||||
"""main() should handle zip command."""
|
||||
source_dir = tmp_path / "source"
|
||||
source_dir.mkdir()
|
||||
|
||||
def test_main_embed_default_version(self) -> None:
|
||||
"""main() should handle embed command with default version."""
|
||||
with patch("sys.argv", ["packtool", "embed"]), patch.object(px, "run") as mock_run, patch.object(
|
||||
packtool, "install_embed_python"
|
||||
):
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_embed_custom_version(self) -> None:
|
||||
"""main() should handle embed command with custom version."""
|
||||
with patch("sys.argv", ["packtool", "embed", "--version", "3.11", "--output-dir", "python"]), patch.object(
|
||||
with patch("sys.argv", ["packtool", "zip", "--source-dir", str(source_dir)]), patch.object(
|
||||
px, "run"
|
||||
) as mock_run, patch.object(packtool, "install_embed_python"):
|
||||
) as mock_run:
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_zip_default_params(self) -> None:
|
||||
"""main() should handle zip command with default params."""
|
||||
with patch("sys.argv", ["packtool", "zip"]), patch.object(px, "run") as mock_run, patch.object(
|
||||
packtool, "create_zip_package"
|
||||
):
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_zip_custom_params(self) -> None:
|
||||
"""main() should handle zip command with custom params."""
|
||||
with patch(
|
||||
"sys.argv", ["packtool", "zip", "--source-dir", "source", "--output-file", "package.zip"]
|
||||
), patch.object(px, "run") as mock_run, patch.object(packtool, "create_zip_package"):
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_clean(self) -> None:
|
||||
def test_main_clean_command(self) -> None:
|
||||
"""main() should handle clean command."""
|
||||
with patch("sys.argv", ["packtool", "clean"]), patch.object(px, "run") as mock_run, patch.object(
|
||||
packtool, "clean_build_dir"
|
||||
):
|
||||
with patch("sys.argv", ["packtool", "clean"]), patch.object(px, "run") as mock_run:
|
||||
packtool.main()
|
||||
assert mock_run.called
|
||||
|
||||
def test_main_with_no_args_shows_help(self) -> None:
|
||||
"""main() with no args should show help and exit."""
|
||||
with patch("sys.argv", ["packtool"]), pytest.raises(SystemExit) as exc_info:
|
||||
"""main() with no args should show help."""
|
||||
with patch("sys.argv", ["packtool"]):
|
||||
packtool.main()
|
||||
assert exc_info.value.code == 2
|
||||
|
||||
def test_main_creates_task_spec_with_correct_name(self) -> None:
|
||||
"""main() should create TaskSpec with correct name."""
|
||||
with patch("sys.argv", ["packtool", "src"]), patch.object(px, "run") as mock_run, patch.object(
|
||||
packtool, "pack_source"
|
||||
):
|
||||
packtool.main()
|
||||
graph = mock_run.call_args[0][0]
|
||||
task_names = list(graph.all_specs().keys())
|
||||
assert "pack_source" in task_names
|
||||
|
||||
def test_main_uses_thread_strategy(self) -> None:
|
||||
"""main() should use thread strategy."""
|
||||
with patch("sys.argv", ["packtool", "src"]), patch.object(px, "run") as mock_run, patch.object(
|
||||
packtool, "pack_source"
|
||||
):
|
||||
packtool.main()
|
||||
assert mock_run.call_args[1]["strategy"] == "thread"
|
||||
# Should print help and return
|
||||
|
||||
Reference in New Issue
Block a user