Files
TinyTorch/tests/cli/test_cli_help_consistency.py
T
Vijay Janapa ReddiandClaude 8d3025afc5 Refactor CLI commands into hierarchical folder structure
Reorganize TinyTorch CLI from flat structure to hierarchical organization
with subfolders for complex commands with subcommands.

Changes:
- Create subfolders: module/, system/, package/
- Move module commands: module_workflow.py → module/workflow.py
- Move module_reset.py → module/reset.py
- Move system commands: system.py → system/system.py
- Move system subcommands: info.py, health.py, jupyter.py → system/
- Move package commands: package.py → package/package.py
- Move package helpers: reset.py, nbdev.py → package/
- Archive deprecated files: clean.py, help.py, notebooks.py, status.py
- Update all imports in moved files and main.py
- Add __init__.py exports for each subfolder
- Create comprehensive CLI test suite (52 tests)
  - test_cli_registry.py: Validate command registration
  - test_cli_execution.py: Smoke tests for all commands
  - test_cli_help_consistency.py: Help text validation
- Update tests to match new structure

Benefits:
- Clear ownership: Easy to see which helpers belong to which commands
- Better organization: Related files grouped together
- Scales cleanly: Adding subcommands is straightforward
- Zero user impact: All commands work exactly the same

All 52 tests passing 

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 23:42:03 +01:00

247 lines
8.2 KiB
Python

"""
CLI Help Consistency Tests - Validate help text is consistent and complete
This test suite ensures:
1. Help text uses consistent formatting and terminology
2. All commands document their purpose clearly
3. Examples are provided where helpful
4. No broken references or outdated commands in help text
"""
import pytest
import subprocess
import sys
from pathlib import Path
# Add tito to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
from tito.main import TinyTorchCLI
class TestHelpConsistency:
"""Test that help text is consistent across commands."""
def setup_method(self):
"""Set up test fixtures."""
self.project_root = Path(__file__).parent.parent.parent
def get_command_help(self, *args):
"""Get help output for a command."""
result = subprocess.run(
[sys.executable, '-m', 'tito.main'] + list(args) + ['-h'],
cwd=self.project_root,
capture_output=True,
text=True
)
return result.stdout + result.stderr
def test_all_command_helps_mention_tito(self):
"""Verify all help texts mention 'tito' command."""
commands = ['setup', 'system', 'module', 'checkpoint', 'milestones']
for cmd in commands:
help_text = self.get_command_help(cmd)
assert 'tito' in help_text.lower(), (
f"Command '{cmd}' help doesn't mention 'tito'"
)
def test_bare_tito_and_help_are_different(self):
"""Verify bare 'tito' and 'tito -h' show different but related content."""
# Get bare tito output
bare_result = subprocess.run(
[sys.executable, '-m', 'tito.main'],
cwd=self.project_root,
capture_output=True,
text=True
)
# Get help output
help_result = subprocess.run(
[sys.executable, '-m', 'tito.main', '-h'],
cwd=self.project_root,
capture_output=True,
text=True
)
bare_output = bare_result.stdout
help_output = help_result.stdout
# Should both mention key commands
for cmd in ['module', 'checkpoint', 'setup']:
assert cmd in bare_output, f"'{cmd}' missing from bare tito"
assert cmd in help_output, f"'{cmd}' missing from tito -h"
# Bare should have welcome/logo
assert any(word in bare_output for word in ['Welcome', 'TORCH', 'Quick Start']), \
"Bare tito should show welcome screen"
# Help should have usage
assert 'usage:' in help_output.lower(), "tito -h should show usage"
def test_no_references_to_removed_commands(self):
"""Verify help doesn't reference commands that don't exist."""
cli = TinyTorchCLI()
registered_commands = set(cli.commands.keys())
# Get main help
help_text = self.get_command_help()
# Common command-like words that might be false positives
ignore_words = {
'command', 'commands', 'option', 'options', 'argument',
'arguments', 'help', 'version', 'verbose', 'color',
'git', 'python', 'pip', 'jupyter', 'pytest', 'run',
'build', 'install', 'create', 'delete', 'update',
'show', 'list', 'view', 'open', 'close', 'start',
'stop', 'export', 'import', 'output', 'input'
}
# Extract words that look like commands (lowercase alphanumeric)
import re
potential_commands = set(re.findall(r'\b[a-z][a-z_-]*[a-z]\b', help_text.lower()))
# Filter to reasonable command-like words
suspicious = potential_commands - registered_commands - ignore_words
# These are expected in help text but not commands
expected_non_commands = {
'system', 'module', 'first', 'time', 'complete', 'resume',
'status', 'progress', 'journey', 'profile', 'timeline',
'tinytorch', 'tiny', 'torch', 'cli', 'developer', 'student',
'workflow', 'tracking', 'capabilities', 'achievements'
}
truly_suspicious = suspicious - expected_non_commands
# Just warn if we find something, don't fail
# (This test is informational)
if truly_suspicious:
print(f"\nInfo: Found potential command references: {sorted(truly_suspicious)[:10]}")
class TestWelcomeScreen:
"""Test the welcome screen shown by bare 'tito' command."""
def setup_method(self):
"""Set up test fixtures."""
self.project_root = Path(__file__).parent.parent.parent
def test_welcome_screen_shows_quick_start(self):
"""Verify welcome screen has quick start section."""
result = subprocess.run(
[sys.executable, '-m', 'tito.main'],
cwd=self.project_root,
capture_output=True,
text=True
)
output = result.stdout
assert 'Quick Start' in output or 'Getting Started' in output, \
"Welcome screen should have Quick Start section"
def test_welcome_screen_shows_command_groups(self):
"""Verify welcome screen organizes commands into groups."""
result = subprocess.run(
[sys.executable, '-m', 'tito.main'],
cwd=self.project_root,
capture_output=True,
text=True
)
output = result.stdout
assert 'Command Groups' in output or 'Commands:' in output, \
"Welcome screen should show command groups"
def test_welcome_screen_has_examples(self):
"""Verify welcome screen shows example commands."""
result = subprocess.run(
[sys.executable, '-m', 'tito.main'],
cwd=self.project_root,
capture_output=True,
text=True
)
output = result.stdout
# Should have at least one example command
assert 'tito setup' in output or 'tito module' in output, \
"Welcome screen should show example commands"
class TestCommandDocumentation:
"""Test that commands are properly documented."""
def setup_method(self):
"""Set up test fixtures."""
self.project_root = Path(__file__).parent.parent.parent
self.cli = TinyTorchCLI()
def test_all_registered_commands_in_welcome_or_help(self):
"""Verify all registered commands appear in welcome screen or help."""
# Get welcome screen
welcome_result = subprocess.run(
[sys.executable, '-m', 'tito.main'],
cwd=self.project_root,
capture_output=True,
text=True
)
# Get help
help_result = subprocess.run(
[sys.executable, '-m', 'tito.main', '-h'],
cwd=self.project_root,
capture_output=True,
text=True
)
combined = welcome_result.stdout + help_result.stdout
missing = []
for cmd in self.cli.commands.keys():
if cmd not in combined:
missing.append(cmd)
assert not missing, (
f"Commands registered but not documented: {missing}\n"
f"Add them to welcome screen or help text"
)
def test_checkpoint_properly_documented(self):
"""Specifically test that checkpoint command is documented."""
# This addresses the user's concern about checkpoint
welcome_result = subprocess.run(
[sys.executable, '-m', 'tito.main'],
cwd=self.project_root,
capture_output=True,
text=True
)
help_result = subprocess.run(
[sys.executable, '-m', 'tito.main', '-h'],
cwd=self.project_root,
capture_output=True,
text=True
)
combined = welcome_result.stdout + help_result.stdout
assert 'checkpoint' in combined.lower(), \
"checkpoint command should be documented"
# Check it has a description
checkpoint_help = subprocess.run(
[sys.executable, '-m', 'tito.main', 'checkpoint', '-h'],
cwd=self.project_root,
capture_output=True,
text=True
)
assert 'progress' in checkpoint_help.stdout.lower() or \
'track' in checkpoint_help.stdout.lower(), \
"checkpoint help should explain its purpose"
if __name__ == '__main__':
pytest.main([__file__, '-v'])