Skip to content

Commit ac9919b

Browse files
author
LittleCoinCoin
committed
test: add version command test suite
Add comprehensive test suite for hatch --version command implementation: - test_get_hatch_version_retrieves_from_metadata: Unit test for version retrieval - test_get_hatch_version_handles_package_not_found: Unit test for error handling - test_version_command_displays_correct_format: Integration test for CLI flow - test_import_hatch_without_version_attribute: Integration test for import safety - test_no_conflict_with_package_version_flag: Regression test for flag conflicts Tests follow CrackingShells testing standards using wobble framework. All 5 tests pass with 100% pass rate. Related to: Phase 2 test definition (test_definition_v1.md)
1 parent 28313b2 commit ac9919b

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

tests/test_cli_version.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
"""
2+
Test suite for hatch --version command implementation.
3+
4+
This module tests the version command functionality:
5+
- Version retrieval from importlib.metadata
6+
- Error handling for PackageNotFoundError
7+
- CLI version display format
8+
- Import safety after removing __version__
9+
- No conflicts with existing flags
10+
11+
Tests follow CrackingShells testing standards using wobble framework.
12+
"""
13+
14+
import unittest
15+
import sys
16+
from pathlib import Path
17+
from unittest.mock import patch, MagicMock
18+
from io import StringIO
19+
20+
# Add parent directory to path
21+
sys.path.insert(0, str(Path(__file__).parent.parent))
22+
23+
from hatch.cli_hatch import main, get_hatch_version
24+
25+
try:
26+
from wobble.decorators import regression_test, integration_test
27+
except ImportError:
28+
# Fallback decorators if wobble not available
29+
def regression_test(func):
30+
return func
31+
32+
def integration_test(scope="component"):
33+
def decorator(func):
34+
return func
35+
return decorator
36+
37+
38+
class TestVersionCommand(unittest.TestCase):
39+
"""Test suite for hatch --version command implementation."""
40+
41+
@regression_test
42+
def test_get_hatch_version_retrieves_from_metadata(self):
43+
"""Test get_hatch_version() retrieves version from importlib.metadata."""
44+
with patch('hatch.cli_hatch.version', return_value='0.7.0-dev.3') as mock_version:
45+
result = get_hatch_version()
46+
47+
self.assertEqual(result, '0.7.0-dev.3')
48+
mock_version.assert_called_once_with('hatch')
49+
50+
@regression_test
51+
def test_get_hatch_version_handles_package_not_found(self):
52+
"""Test get_hatch_version() handles PackageNotFoundError gracefully."""
53+
from importlib.metadata import PackageNotFoundError
54+
55+
with patch('hatch.cli_hatch.version', side_effect=PackageNotFoundError()):
56+
result = get_hatch_version()
57+
58+
self.assertEqual(result, 'unknown (development mode)')
59+
60+
@integration_test(scope="component")
61+
def test_version_command_displays_correct_format(self):
62+
"""Test version command displays correct format via CLI."""
63+
test_args = ['hatch', '--version']
64+
65+
with patch('sys.argv', test_args):
66+
with patch('hatch.cli_hatch.get_hatch_version', return_value='0.7.0-dev.3'):
67+
with patch('sys.stdout', new_callable=StringIO) as mock_stdout:
68+
with self.assertRaises(SystemExit) as cm:
69+
main()
70+
71+
# argparse action='version' exits with code 0
72+
self.assertEqual(cm.exception.code, 0)
73+
74+
# Verify output format: "hatch 0.7.0-dev.3"
75+
output = mock_stdout.getvalue().strip()
76+
self.assertRegex(output, r'hatch\s+0\.7\.0-dev\.3')
77+
78+
@integration_test(scope="component")
79+
def test_import_hatch_without_version_attribute(self):
80+
"""Test that importing hatch module works without __version__ attribute."""
81+
try:
82+
import hatch
83+
84+
# Import should succeed
85+
self.assertIsNotNone(hatch)
86+
87+
# __version__ should not exist (removed in implementation)
88+
self.assertFalse(hasattr(hatch, '__version__'),
89+
"hatch.__version__ should not exist after cleanup")
90+
91+
except ImportError as e:
92+
self.fail(f"Failed to import hatch module: {e}")
93+
94+
@regression_test
95+
def test_no_conflict_with_package_version_flag(self):
96+
"""Test that --version (Hatch) doesn't conflict with -v (package version)."""
97+
# Test package add command with -v flag (package version specification)
98+
test_args = ['hatch', 'package', 'add', 'test-package', '-v', '1.0.0']
99+
100+
with patch('sys.argv', test_args):
101+
with patch('hatch.cli_hatch.HatchEnvironmentManager') as mock_env:
102+
mock_env_instance = MagicMock()
103+
mock_env.return_value = mock_env_instance
104+
mock_env_instance.add_package_to_environment.return_value = True
105+
106+
try:
107+
main()
108+
except SystemExit as e:
109+
# Should execute successfully (exit code 0)
110+
self.assertEqual(e.code, 0)
111+
112+
# Verify package add was called with version argument
113+
mock_env_instance.add_package_to_environment.assert_called_once()
114+
call_args = mock_env_instance.add_package_to_environment.call_args
115+
116+
# Version argument should be '1.0.0'
117+
self.assertEqual(call_args[0][2], '1.0.0') # Third positional arg is version
118+
119+
120+
if __name__ == '__main__':
121+
unittest.main()
122+

0 commit comments

Comments
 (0)