"""Tests for testing_engine.file_scanner module."""
import pytest
from pathlib import Path
import tempfile
import os
from testing_engine.file_scanner import discover_python_sources, relative_to_root, EXCLUDED_DIRS
class TestDiscoverPythonSources:
"""Test suite for discover_python_sources function."""
def test_discover_python_sources_finds_py_files(self, tmp_path):
"""Test that discover_python_sources finds .py files in the directory."""
# Create test Python files
(tmp_path / "module1.py").write_text("# module1")
(tmp_path / "module2.py").write_text("# module2")
subdir = tmp_path / "subdir"
subdir.mkdir()
(subdir / "module3.py").write_text("# module3")
# Discover sources
sources = discover_python_sources(tmp_path)
# Verify all files are found
assert len(sources) == 3
file_names = {p.name for p in sources}
assert file_names == {"module1.py", "module2.py", "module3.py"}
def test_discover_python_sources_excludes_venv(self, tmp_path):
"""Test that virtual environment directories are excluded."""
# Create files in excluded directories
(tmp_path / "module1.py").write_text("# module1")
for excluded in [".venv", "venv"]:
excluded_dir = tmp_path / excluded
excluded_dir.mkdir()
(excluded_dir / "excluded.py").write_text("# excluded")
# Discover sources
sources = discover_python_sources(tmp_path)
# Verify only the non-excluded file is found
assert len(sources) == 1
assert sources[0].name == "module1.py"
def test_discover_python_sources_excludes_cache_dirs(self, tmp_path):
"""Test that cache directories are excluded."""
# Create files in cache directories
(tmp_path / "module1.py").write_text("# module1")
for excluded in ["__pycache__", ".pytest_cache", "node_modules"]:
excluded_dir = tmp_path / excluded
excluded_dir.mkdir()
(excluded_dir / "excluded.py").write_text("# excluded")
# Discover sources
sources = discover_python_sources(tmp_path)
# Verify only the non-excluded file is found
assert len(sources) == 1
assert sources[0].name == "module1.py"
def test_discover_python_sources_excludes_build_dirs(self, tmp_path):
"""Test that build directories are excluded."""
(tmp_path / "module1.py").write_text("# module1")
for excluded in ["dist", "build"]:
excluded_dir = tmp_path / excluded
excluded_dir.mkdir()
(excluded_dir / "excluded.py").write_text("# excluded")
sources = discover_python_sources(tmp_path)
assert len(sources) == 1
assert sources[0].name == "module1.py"
def test_discover_python_sources_empty_directory(self, tmp_path):
"""Test that an empty directory returns an empty list."""
sources = discover_python_sources(tmp_path)
assert sources == []
def test_discover_python_sources_nested_structure(self, tmp_path):
"""Test discovery in a nested directory structure."""
# Create nested structure
(tmp_path / "root.py").write_text("# root")
level1 = tmp_path / "level1"
level1.mkdir()
(level1 / "file1.py").write_text("# file1")
level2 = level1 / "level2"
level2.mkdir()
(level2 / "file2.py").write_text("# file2")
sources = discover_python_sources(tmp_path)
assert len(sources) == 3
file_names = {p.name for p in sources}
assert file_names == {"root.py", "file1.py", "file2.py"}
class TestRelativeToRoot:
"""Test suite for relative_to_root function."""
def test_relative_to_root_single_file(self, tmp_path):
"""Test converting a single absolute path to relative."""
file_path = tmp_path / "module.py"
file_path.write_text("# module")
relative = relative_to_root([file_path], tmp_path)
assert len(relative) == 1
assert relative[0] == "module.py"
def test_relative_to_root_nested_files(self, tmp_path):
"""Test converting nested paths to relative."""
subdir = tmp_path / "subdir"
subdir.mkdir()
file1 = tmp_path / "root.py"
file2 = subdir / "nested.py"
file1.write_text("# root")
file2.write_text("# nested")
relative = relative_to_root([file1, file2], tmp_path)
assert len(relative) == 2
assert "root.py" in relative
assert "subdir/nested.py" in relative or "subdir\\nested.py" in relative
def test_relative_to_root_empty_list(self, tmp_path):
"""Test with an empty list of paths."""
relative = relative_to_root([], tmp_path)
assert relative == []
def test_relative_to_root_resolves_paths(self, tmp_path):
"""Test that paths are resolved before making relative."""
# Create a file and reference it with '..'
subdir = tmp_path / "subdir"
subdir.mkdir()
file_path = tmp_path / "module.py"
file_path.write_text("# module")
# Reference from subdir using ..
relative_ref = subdir / ".." / "module.py"
relative = relative_to_root([relative_ref], tmp_path)
assert len(relative) == 1
assert relative[0] == "module.py"
class TestExcludedDirs:
"""Test suite for EXCLUDED_DIRS constant."""
def test_excluded_dirs_contains_common_paths(self):
"""Test that EXCLUDED_DIRS includes common exclusion patterns."""
expected = {
".venv", "venv", ".mcp", ".git", "__pycache__",
"node_modules", "site-packages", "dist", "build", ".pytest_cache"
}
assert expected.issubset(EXCLUDED_DIRS)
def test_excluded_dirs_is_set(self):
"""Test that EXCLUDED_DIRS is a set for efficient lookup."""
assert isinstance(EXCLUDED_DIRS, set)