Coverage for tests / integration / test_built_package.py: 97%

35 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Integration test for built package installation. 

2 

3This module tests that lintro can be installed as a built wheel distribution 

4and imported successfully, catching circular import issues that only manifest 

5when the package is installed (not in editable mode). 

6""" 

7 

8from __future__ import annotations 

9 

10import subprocess 

11import sys 

12import tempfile 

13from pathlib import Path 

14 

15import pytest 

16from assertpy import assert_that 

17 

18 

19@pytest.mark.slow 

20def test_built_wheel_imports() -> None: 

21 """Test that lintro can be built and imported as a wheel. 

22 

23 This test: 

24 1. Builds lintro as a wheel 

25 2. Installs it in a fresh virtual environment 

26 3. Attempts to import critical modules 

27 4. Verifies no circular import errors occur 

28 

29 This catches issues that only manifest when lintro is installed as a 

30 dependency (built distribution) rather than in editable mode. 

31 """ 

32 project_root = Path(__file__).parent.parent.parent 

33 

34 with tempfile.TemporaryDirectory() as tmpdir: 

35 tmpdir_path = Path(tmpdir) 

36 venv_path = tmpdir_path / "test_venv" 

37 dist_dir = tmpdir_path / "dist" 

38 

39 # Step 1: Build the wheel 

40 build_result = subprocess.run( 

41 ["uv", "build", "--out-dir", str(dist_dir)], 

42 cwd=str(project_root), 

43 capture_output=True, 

44 text=True, 

45 timeout=60, 

46 ) 

47 assert_that(build_result.returncode).is_equal_to(0) 

48 assert_that(dist_dir.exists()).is_true() 

49 

50 # Find the built wheel 

51 wheels = list(dist_dir.glob("*.whl")) 

52 assert_that(wheels).is_not_empty() 

53 wheel_path = wheels[0] 

54 

55 # Step 2: Create a fresh virtual environment 

56 venv_result = subprocess.run( 

57 [sys.executable, "-m", "venv", str(venv_path)], 

58 capture_output=True, 

59 text=True, 

60 timeout=30, 

61 ) 

62 assert_that(venv_result.returncode).is_equal_to(0) 

63 

64 # Determine the Python executable in the venv 

65 if sys.platform == "win32": 

66 python_exe = venv_path / "Scripts" / "python.exe" 

67 else: 

68 python_exe = venv_path / "bin" / "python" 

69 

70 assert_that(python_exe.exists()).is_true() 

71 

72 # Step 3: Install the wheel in the venv 

73 install_result = subprocess.run( 

74 [str(python_exe), "-m", "pip", "install", str(wheel_path)], 

75 capture_output=True, 

76 text=True, 

77 timeout=60, 

78 ) 

79 assert_that(install_result.returncode).is_equal_to(0) 

80 

81 # Step 4: Test importing lintro modules (this is where circular imports fail) 

82 test_imports = [ 

83 "import lintro", 

84 "import lintro.parsers", 

85 "from lintro.parsers import bandit", 

86 "from lintro.parsers.actionlint.actionlint_parser import parse_actionlint_output", # noqa: E501 

87 "from lintro.plugins import ToolRegistry; ToolRegistry.get('actionlint')", 

88 "from lintro.cli import cli", 

89 ] 

90 

91 for import_statement in test_imports: 

92 import_result = subprocess.run( 

93 [str(python_exe), "-c", import_statement], 

94 capture_output=True, 

95 text=True, 

96 timeout=10, 

97 ) 

98 assert_that(import_result.returncode).described_as( 

99 f"Import failed: {import_statement}\n" 

100 f"stdout: {import_result.stdout}\n" 

101 f"stderr: {import_result.stderr}", 

102 ).is_equal_to(0) 

103 

104 # Step 5: Test that lintro CLI works 

105 cli_result = subprocess.run( 

106 [str(python_exe), "-m", "lintro", "--version"], 

107 capture_output=True, 

108 text=True, 

109 timeout=10, 

110 ) 

111 assert_that(cli_result.returncode).is_equal_to(0) 

112 assert_that(cli_result.stdout).contains("lintro")