test_package_structure.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. """Test suite for Python package structure.
  2. Tests that the package structure is correct and imports work properly.
  3. This ensures modern Python packaging (src/ layout, pyproject.toml) is successful.
  4. """
  5. import pytest
  6. import sys
  7. from pathlib import Path
  8. class TestCliPackage:
  9. """Test skill_seekers.cli package structure and imports."""
  10. def test_cli_package_exists(self):
  11. """Test that skill_seekers.cli package can be imported."""
  12. import skill_seekers.cli
  13. assert skill_seekers.cli is not None
  14. def test_cli_has_version(self):
  15. """Test that skill_seekers.cli package has __version__."""
  16. import skill_seekers.cli
  17. assert hasattr(skill_seekers.cli, '__version__')
  18. assert skill_seekers.cli.__version__ == '2.0.0'
  19. def test_cli_has_all(self):
  20. """Test that skill_seekers.cli package has __all__ export list."""
  21. import skill_seekers.cli
  22. assert hasattr(skill_seekers.cli, '__all__')
  23. assert isinstance(skill_seekers.cli.__all__, list)
  24. assert len(skill_seekers.cli.__all__) > 0
  25. def test_llms_txt_detector_import(self):
  26. """Test that LlmsTxtDetector can be imported from skill_seekers.cli."""
  27. from skill_seekers.cli import LlmsTxtDetector
  28. assert LlmsTxtDetector is not None
  29. def test_llms_txt_downloader_import(self):
  30. """Test that LlmsTxtDownloader can be imported from skill_seekers.cli."""
  31. from skill_seekers.cli import LlmsTxtDownloader
  32. assert LlmsTxtDownloader is not None
  33. def test_llms_txt_parser_import(self):
  34. """Test that LlmsTxtParser can be imported from skill_seekers.cli."""
  35. from skill_seekers.cli import LlmsTxtParser
  36. assert LlmsTxtParser is not None
  37. def test_open_folder_import(self):
  38. """Test that open_folder can be imported from skill_seekers.cli (if utils exists)."""
  39. try:
  40. from skill_seekers.cli import open_folder
  41. # If import succeeds, function should not be None
  42. assert open_folder is not None
  43. except ImportError:
  44. # If utils.py doesn't exist, that's okay for now
  45. pytest.skip("utils.py not found, skipping open_folder test")
  46. def test_cli_exports_match_all(self):
  47. """Test that exported items in __all__ can actually be imported."""
  48. import skill_seekers.cli as cli
  49. for item_name in cli.__all__:
  50. if item_name == 'open_folder' and cli.open_folder is None:
  51. # open_folder might be None if utils doesn't exist
  52. continue
  53. assert hasattr(cli, item_name), f"{item_name} not found in cli package"
  54. class TestMcpPackage:
  55. """Test skill_seekers.mcp package structure and imports."""
  56. def test_mcp_package_exists(self):
  57. """Test that skill_seekers.mcp package can be imported."""
  58. import skill_seekers.mcp
  59. assert skill_seekers.mcp is not None
  60. def test_mcp_has_version(self):
  61. """Test that skill_seekers.mcp package has __version__."""
  62. import skill_seekers.mcp
  63. assert hasattr(skill_seekers.mcp, '__version__')
  64. assert skill_seekers.mcp.__version__ == '2.0.0'
  65. def test_mcp_has_all(self):
  66. """Test that skill_seekers.mcp package has __all__ export list."""
  67. import skill_seekers.mcp
  68. assert hasattr(skill_seekers.mcp, '__all__')
  69. assert isinstance(skill_seekers.mcp.__all__, list)
  70. def test_mcp_tools_package_exists(self):
  71. """Test that skill_seekers.mcp.tools subpackage can be imported."""
  72. import skill_seekers.mcp.tools
  73. assert skill_seekers.mcp.tools is not None
  74. def test_mcp_tools_has_version(self):
  75. """Test that skill_seekers.mcp.tools has __version__."""
  76. import skill_seekers.mcp.tools
  77. assert hasattr(skill_seekers.mcp.tools, '__version__')
  78. assert skill_seekers.mcp.tools.__version__ == '2.0.0'
  79. class TestPackageStructure:
  80. """Test overall package structure integrity (src/ layout)."""
  81. def test_cli_init_file_exists(self):
  82. """Test that src/skill_seekers/cli/__init__.py exists."""
  83. init_file = Path(__file__).parent.parent / 'src' / 'skill_seekers' / 'cli' / '__init__.py'
  84. assert init_file.exists(), "src/skill_seekers/cli/__init__.py not found"
  85. def test_mcp_init_file_exists(self):
  86. """Test that src/skill_seekers/mcp/__init__.py exists."""
  87. init_file = Path(__file__).parent.parent / 'src' / 'skill_seekers' / 'mcp' / '__init__.py'
  88. assert init_file.exists(), "src/skill_seekers/mcp/__init__.py not found"
  89. def test_mcp_tools_init_file_exists(self):
  90. """Test that src/skill_seekers/mcp/tools/__init__.py exists."""
  91. init_file = Path(__file__).parent.parent / 'src' / 'skill_seekers' / 'mcp' / 'tools' / '__init__.py'
  92. assert init_file.exists(), "src/skill_seekers/mcp/tools/__init__.py not found"
  93. def test_cli_init_has_docstring(self):
  94. """Test that skill_seekers.cli/__init__.py has a module docstring."""
  95. import skill_seekers.cli
  96. assert skill_seekers.cli.__doc__ is not None
  97. assert len(skill_seekers.cli.__doc__) > 50 # Should have substantial documentation
  98. def test_mcp_init_has_docstring(self):
  99. """Test that skill_seekers.mcp/__init__.py has a module docstring."""
  100. import skill_seekers.mcp
  101. assert skill_seekers.mcp.__doc__ is not None
  102. assert len(skill_seekers.mcp.__doc__) > 50 # Should have substantial documentation
  103. class TestImportPatterns:
  104. """Test that various import patterns work correctly."""
  105. def test_direct_module_import(self):
  106. """Test importing modules directly."""
  107. from skill_seekers.cli import llms_txt_detector
  108. from skill_seekers.cli import llms_txt_downloader
  109. from skill_seekers.cli import llms_txt_parser
  110. assert llms_txt_detector is not None
  111. assert llms_txt_downloader is not None
  112. assert llms_txt_parser is not None
  113. def test_class_import_from_package(self):
  114. """Test importing classes from package."""
  115. from skill_seekers.cli import LlmsTxtDetector, LlmsTxtDownloader, LlmsTxtParser
  116. assert LlmsTxtDetector.__name__ == 'LlmsTxtDetector'
  117. assert LlmsTxtDownloader.__name__ == 'LlmsTxtDownloader'
  118. assert LlmsTxtParser.__name__ == 'LlmsTxtParser'
  119. def test_package_level_import(self):
  120. """Test importing entire packages."""
  121. import skill_seekers
  122. import skill_seekers.cli
  123. import skill_seekers.mcp
  124. import skill_seekers.mcp.tools
  125. assert 'skill_seekers' in sys.modules
  126. assert 'skill_seekers.cli' in sys.modules
  127. assert 'skill_seekers.mcp' in sys.modules
  128. assert 'skill_seekers.mcp.tools' in sys.modules
  129. class TestBackwardsCompatibility:
  130. """Test that existing code patterns still work."""
  131. def test_direct_file_import_still_works(self):
  132. """Test that direct file imports still work (backwards compatible)."""
  133. # This ensures we didn't break existing code
  134. from skill_seekers.cli.llms_txt_detector import LlmsTxtDetector
  135. from skill_seekers.cli.llms_txt_downloader import LlmsTxtDownloader
  136. from skill_seekers.cli.llms_txt_parser import LlmsTxtParser
  137. assert LlmsTxtDetector is not None
  138. assert LlmsTxtDownloader is not None
  139. assert LlmsTxtParser is not None
  140. def test_module_path_import_still_works(self):
  141. """Test that full module path imports still work."""
  142. import skill_seekers.cli.llms_txt_detector
  143. import skill_seekers.cli.llms_txt_downloader
  144. import skill_seekers.cli.llms_txt_parser
  145. assert skill_seekers.cli.llms_txt_detector is not None
  146. assert skill_seekers.cli.llms_txt_downloader is not None
  147. assert skill_seekers.cli.llms_txt_parser is not None
  148. class TestRootPackage:
  149. """Test root skill_seekers package."""
  150. def test_root_package_exists(self):
  151. """Test that skill_seekers root package can be imported."""
  152. import skill_seekers
  153. assert skill_seekers is not None
  154. def test_root_has_version(self):
  155. """Test that skill_seekers root package has __version__."""
  156. import skill_seekers
  157. assert hasattr(skill_seekers, '__version__')
  158. assert skill_seekers.__version__ == '2.0.0'
  159. def test_root_has_metadata(self):
  160. """Test that skill_seekers root package has metadata."""
  161. import skill_seekers
  162. assert hasattr(skill_seekers, '__author__')
  163. assert hasattr(skill_seekers, '__license__')
  164. assert skill_seekers.__license__ == 'MIT'
  165. class TestCLIEntryPoints:
  166. """Test that CLI entry points are properly configured."""
  167. def test_main_cli_module_exists(self):
  168. """Test that main.py module exists and can be imported."""
  169. from skill_seekers.cli import main
  170. assert main is not None
  171. assert hasattr(main, 'main')
  172. assert callable(main.main)
  173. def test_main_cli_has_parser(self):
  174. """Test that main.py has parser creation function."""
  175. from skill_seekers.cli.main import create_parser
  176. parser = create_parser()
  177. assert parser is not None
  178. # Test that main subcommands are configured
  179. assert parser.prog == 'skill-seekers'