scripts-test-strategy-brief-system
#!/usr/bin/env python3 """ā
title: "Test configuration" component_type: script version: "1.0.0" audience: contributor status: stable summary: "Test Suite: Strategy Brief System ==================================" keywords: ['brief', 'generation', 'strategy', 'system', 'test'] tokens: ~500 created: 2025-12-22 updated: 2025-12-22 script_name: "test-strategy-brief-system.py" language: python executable: true usage: "python3 scripts/test-strategy-brief-system.py [options]" python_version: "3.10+" dependencies: [] modifies_files: false network_access: false requires_auth: falseā
Test Suite: Strategy Brief System
Comprehensive tests for the strategy brief generation system including:
- Agent file validation (CODITECT standard compliance)
- A2A agent card validation (JSON schema)
- Script syntax validation
- Workflow structure validation
- Hook functionality tests
Usage: python3 scripts/test-strategy-brief-system.py python3 scripts/test-strategy-brief-system.py -v # verbose python3 scripts/test-strategy-brief-system.py --component agents # specific component """
import argparse import json import os import subprocess import sys import re from pathlib import Path from typing import Dict, List, Tuple, Any, Optional from datetime import datetime
Test configuration
STRATEGY_AGENTS = [ "market-researcher", "competitive-analyst", "trend-analyst", "framework-specialist", "synthesis-writer" ]
STRATEGY_SCRIPTS = [ "strategy-brief-generator.py", "strategy-brief-templates.py", "strategy-brief-cli.py", "strategy-financial-models.py", "strategy-mermaid-diagrams.py", "strategy-visual-frameworks.py", "strategy-powerpoint-exporter.py", "strategy-examples.py" ]
STRATEGY_HOOKS = [ "strategy-brief-pre-generation.py", "strategy-brief-post-generation.py" ]
WORKFLOW_FILE = "workflows/strategy-brief-generation.workflow.md"
Required YAML frontmatter fields for agents
REQUIRED_AGENT_FIELDS = ["name", "description", "tools", "model"]
Required A2A card fields
REQUIRED_A2A_FIELDS = ["agent", "capabilities", "interaction", "constraints", "composability", "quality", "metadata"]
class TestResult: """Represents a single test result.""" def init(self, name: str, passed: bool, message: str = "", details: str = ""): self.name = name self.passed = passed self.message = message self.details = details
def __str__(self):
status = "ā
PASS" if self.passed else "ā FAIL"
result = f"{status} | {self.name}"
if self.message:
result += f" | {self.message}"
return result
class TestSuite: """Test suite for strategy brief system."""
def __init__(self, base_path: Path, verbose: bool = False):
self.base_path = base_path
self.verbose = verbose
self.results: List[TestResult] = []
self.start_time = datetime.now()
def log(self, message: str):
"""Log message if verbose mode."""
if self.verbose:
print(f" [DEBUG] {message}")
def add_result(self, result: TestResult):
"""Add test result."""
self.results.append(result)
print(result)
if self.verbose and result.details:
for line in result.details.split('\n'):
print(f" {line}")
# ==================== AGENT TESTS ====================
def test_agent_file_exists(self, agent_name: str) -> TestResult:
"""Test that agent .md file exists."""
agent_path = self.base_path / "agents" / f"{agent_name}.md"
exists = agent_path.exists()
return TestResult(
f"Agent file exists: {agent_name}",
exists,
"" if exists else f"Missing: {agent_path}"
)
def test_agent_yaml_frontmatter(self, agent_name: str) -> TestResult:
"""Test agent has valid YAML frontmatter."""
agent_path = self.base_path / "agents" / f"{agent_name}.md"
if not agent_path.exists():
return TestResult(f"Agent YAML: {agent_name}", False, "File not found")
content = agent_path.read_text()
# Check for YAML frontmatter
if not content.startswith("---"):
return TestResult(f"Agent YAML: {agent_name}", False, "No YAML frontmatter found")
# Extract frontmatter
parts = content.split("---", 2)
if len(parts) < 3:
return TestResult(f"Agent YAML: {agent_name}", False, "Invalid frontmatter structure")
frontmatter = parts[1]
# Check required fields
missing = []
for field in REQUIRED_AGENT_FIELDS:
if f"{field}:" not in frontmatter:
missing.append(field)
if missing:
return TestResult(
f"Agent YAML: {agent_name}",
False,
f"Missing fields: {', '.join(missing)}"
)
return TestResult(f"Agent YAML: {agent_name}", True, "All required fields present")
def test_agent_sections(self, agent_name: str) -> TestResult:
"""Test agent has required sections."""
agent_path = self.base_path / "agents" / f"{agent_name}.md"
if not agent_path.exists():
return TestResult(f"Agent sections: {agent_name}", False, "File not found")
content = agent_path.read_text()
required_sections = [
"## Core Responsibilities",
"## Capabilities",
"## Invocation",
"## Limitations",
"## Integration"
]
missing = []
for section in required_sections:
if section not in content:
missing.append(section)
if missing:
return TestResult(
f"Agent sections: {agent_name}",
False,
f"Missing: {', '.join(missing)}"
)
return TestResult(f"Agent sections: {agent_name}", True, "All required sections present")
# ==================== A2A CARD TESTS ====================
def test_a2a_card_exists(self, agent_name: str) -> TestResult:
"""Test that A2A agent card exists."""
card_path = self.base_path / "config" / "agents" / f"{agent_name}.json"
exists = card_path.exists()
return TestResult(
f"A2A card exists: {agent_name}",
exists,
"" if exists else f"Missing: {card_path}"
)
def test_a2a_card_valid_json(self, agent_name: str) -> TestResult:
"""Test that A2A card is valid JSON."""
card_path = self.base_path / "config" / "agents" / f"{agent_name}.json"
if not card_path.exists():
return TestResult(f"A2A JSON valid: {agent_name}", False, "File not found")
try:
with open(card_path) as f:
json.load(f)
return TestResult(f"A2A JSON valid: {agent_name}", True)
except json.JSONDecodeError as e:
return TestResult(f"A2A JSON valid: {agent_name}", False, str(e))
def test_a2a_card_schema(self, agent_name: str) -> TestResult:
"""Test that A2A card has required schema fields."""
card_path = self.base_path / "config" / "agents" / f"{agent_name}.json"
if not card_path.exists():
return TestResult(f"A2A schema: {agent_name}", False, "File not found")
try:
with open(card_path) as f:
card = json.load(f)
except json.JSONDecodeError:
return TestResult(f"A2A schema: {agent_name}", False, "Invalid JSON")
missing = []
for field in REQUIRED_A2A_FIELDS:
if field not in card:
missing.append(field)
if missing:
return TestResult(
f"A2A schema: {agent_name}",
False,
f"Missing fields: {', '.join(missing)}"
)
# Check nested required fields
if "agent" in card:
agent_fields = ["id", "name", "version", "description"]
for field in agent_fields:
if field not in card["agent"]:
missing.append(f"agent.{field}")
if missing:
return TestResult(f"A2A schema: {agent_name}", False, f"Missing: {', '.join(missing)}")
return TestResult(f"A2A schema: {agent_name}", True, "Schema valid")
def test_a2a_card_agent_id_format(self, agent_name: str) -> TestResult:
"""Test that A2A card agent ID follows format."""
card_path = self.base_path / "config" / "agents" / f"{agent_name}.json"
if not card_path.exists():
return TestResult(f"A2A ID format: {agent_name}", False, "File not found")
try:
with open(card_path) as f:
card = json.load(f)
except json.JSONDecodeError:
return TestResult(f"A2A ID format: {agent_name}", False, "Invalid JSON")
agent_id = card.get("agent", {}).get("id", "")
expected_pattern = rf"coditect:{agent_name}:v\d+\.\d+"
if re.match(expected_pattern, agent_id):
return TestResult(f"A2A ID format: {agent_name}", True, f"ID: {agent_id}")
else:
return TestResult(
f"A2A ID format: {agent_name}",
False,
f"Expected pattern coditect:{agent_name}:vX.X, got: {agent_id}"
)
# ==================== SCRIPT TESTS ====================
def test_script_exists(self, script_name: str) -> TestResult:
"""Test that script file exists."""
script_path = self.base_path / "scripts" / script_name
exists = script_path.exists()
return TestResult(
f"Script exists: {script_name}",
exists,
"" if exists else f"Missing: {script_path}"
)
def test_script_syntax(self, script_name: str) -> TestResult:
"""Test that script has valid Python syntax."""
script_path = self.base_path / "scripts" / script_name
if not script_path.exists():
return TestResult(f"Script syntax: {script_name}", False, "File not found")
try:
result = subprocess.run(
[sys.executable, "-m", "py_compile", str(script_path)],
capture_output=True,
text=True,
timeout=30
)
if result.returncode == 0:
return TestResult(f"Script syntax: {script_name}", True)
else:
return TestResult(
f"Script syntax: {script_name}",
False,
result.stderr.strip()[:200]
)
except subprocess.TimeoutExpired:
return TestResult(f"Script syntax: {script_name}", False, "Timeout")
except Exception as e:
return TestResult(f"Script syntax: {script_name}", False, str(e))
def test_script_has_docstring(self, script_name: str) -> TestResult:
"""Test that script has a module docstring."""
script_path = self.base_path / "scripts" / script_name
if not script_path.exists():
return TestResult(f"Script docstring: {script_name}", False, "File not found")
content = script_path.read_text()
# Check for docstring after shebang
lines = content.split('\n')
docstring_found = False
for i, line in enumerate(lines[:10]): # Check first 10 lines
if '"""' in line or "'''" in line:
docstring_found = True
break
return TestResult(
f"Script docstring: {script_name}",
docstring_found,
"" if docstring_found else "No module docstring found"
)
def test_script_has_main(self, script_name: str) -> TestResult:
"""Test that script has main entry point."""
script_path = self.base_path / "scripts" / script_name
if not script_path.exists():
return TestResult(f"Script main: {script_name}", False, "File not found")
content = script_path.read_text()
has_main = 'if __name__ == "__main__"' in content or "if __name__ == '__main__'" in content
return TestResult(
f"Script main: {script_name}",
has_main,
"" if has_main else "No __main__ guard found"
)
# ==================== WORKFLOW TESTS ====================
def test_workflow_exists(self) -> TestResult:
"""Test that workflow file exists."""
workflow_path = self.base_path / WORKFLOW_FILE
exists = workflow_path.exists()
return TestResult(
f"Workflow exists",
exists,
"" if exists else f"Missing: {workflow_path}"
)
def test_workflow_yaml_frontmatter(self) -> TestResult:
"""Test workflow has valid YAML frontmatter."""
workflow_path = self.base_path / WORKFLOW_FILE
if not workflow_path.exists():
return TestResult("Workflow YAML", False, "File not found")
content = workflow_path.read_text()
if not content.startswith("---"):
return TestResult("Workflow YAML", False, "No YAML frontmatter")
required_fields = ["name", "description", "version", "trigger", "inputs", "outputs"]
missing = []
# Extract frontmatter
parts = content.split("---", 2)
if len(parts) >= 2:
frontmatter = parts[1]
for field in required_fields:
if f"{field}:" not in frontmatter:
missing.append(field)
if missing:
return TestResult("Workflow YAML", False, f"Missing: {', '.join(missing)}")
return TestResult("Workflow YAML", True, "All required fields present")
def test_workflow_steps(self) -> TestResult:
"""Test workflow has step definitions."""
workflow_path = self.base_path / WORKFLOW_FILE
if not workflow_path.exists():
return TestResult("Workflow steps", False, "File not found")
content = workflow_path.read_text()
# Count step headers
step_pattern = r"### Step \d+:"
steps = re.findall(step_pattern, content)
if len(steps) < 3:
return TestResult("Workflow steps", False, f"Only {len(steps)} steps found, expected 3+")
return TestResult("Workflow steps", True, f"{len(steps)} steps defined")
# ==================== HOOK TESTS ====================
def test_hook_exists(self, hook_name: str) -> TestResult:
"""Test that hook file exists."""
hook_path = self.base_path / "hooks" / hook_name
exists = hook_path.exists()
return TestResult(
f"Hook exists: {hook_name}",
exists,
"" if exists else f"Missing: {hook_path}"
)
def test_hook_executable(self, hook_name: str) -> TestResult:
"""Test that hook is executable."""
hook_path = self.base_path / "hooks" / hook_name
if not hook_path.exists():
return TestResult(f"Hook executable: {hook_name}", False, "File not found")
is_executable = os.access(hook_path, os.X_OK)
return TestResult(
f"Hook executable: {hook_name}",
is_executable,
"" if is_executable else "Not executable (chmod +x needed)"
)
def test_hook_syntax(self, hook_name: str) -> TestResult:
"""Test that hook has valid Python syntax."""
hook_path = self.base_path / "hooks" / hook_name
if not hook_path.exists():
return TestResult(f"Hook syntax: {hook_name}", False, "File not found")
try:
result = subprocess.run(
[sys.executable, "-m", "py_compile", str(hook_path)],
capture_output=True,
text=True,
timeout=30
)
if result.returncode == 0:
return TestResult(f"Hook syntax: {hook_name}", True)
else:
return TestResult(f"Hook syntax: {hook_name}", False, result.stderr.strip()[:200])
except Exception as e:
return TestResult(f"Hook syntax: {hook_name}", False, str(e))
def test_hook_json_io(self, hook_name: str) -> TestResult:
"""Test that hook uses JSON I/O pattern."""
hook_path = self.base_path / "hooks" / hook_name
if not hook_path.exists():
return TestResult(f"Hook JSON I/O: {hook_name}", False, "File not found")
content = hook_path.read_text()
has_json_load = "json.load" in content
has_json_dumps = "json.dumps" in content or "json.dump" in content
if has_json_load and has_json_dumps:
return TestResult(f"Hook JSON I/O: {hook_name}", True)
missing = []
if not has_json_load:
missing.append("json.load (stdin)")
if not has_json_dumps:
missing.append("json.dumps (stdout)")
return TestResult(f"Hook JSON I/O: {hook_name}", False, f"Missing: {', '.join(missing)}")
# ==================== INTEGRATION TESTS ====================
def test_agent_a2a_consistency(self, agent_name: str) -> TestResult:
"""Test that agent .md and A2A card are consistent."""
agent_path = self.base_path / "agents" / f"{agent_name}.md"
card_path = self.base_path / "config" / "agents" / f"{agent_name}.json"
if not agent_path.exists() or not card_path.exists():
return TestResult(f"Agent-A2A consistency: {agent_name}", False, "Files missing")
# Extract description from agent
agent_content = agent_path.read_text()
parts = agent_content.split("---", 2)
if len(parts) < 3:
return TestResult(f"Agent-A2A consistency: {agent_name}", False, "Invalid agent format")
frontmatter = parts[1]
# Extract name from frontmatter
name_match = re.search(r"^name:\s*(.+)$", frontmatter, re.MULTILINE)
agent_name_yaml = name_match.group(1).strip() if name_match else ""
# Load A2A card
try:
with open(card_path) as f:
card = json.load(f)
except:
return TestResult(f"Agent-A2A consistency: {agent_name}", False, "Invalid A2A JSON")
card_id = card.get("agent", {}).get("id", "")
# Check name matches
if agent_name not in card_id:
return TestResult(
f"Agent-A2A consistency: {agent_name}",
False,
f"Name mismatch: YAML={agent_name_yaml}, A2A ID={card_id}"
)
return TestResult(f"Agent-A2A consistency: {agent_name}", True, "Names consistent")
def test_activation_status(self, component_type: str, component_name: str) -> TestResult:
"""Test that component is in activation status file."""
status_path = self.base_path / ".coditect" / "component-activation-status.json"
if not status_path.exists():
return TestResult(f"Activation: {component_name}", False, "Status file not found")
try:
with open(status_path) as f:
status = json.load(f)
except:
return TestResult(f"Activation: {component_name}", False, "Invalid status JSON")
components = status.get("components", [])
for comp in components:
if comp.get("type") == component_type and comp.get("name") == component_name:
if comp.get("activated"):
return TestResult(f"Activation: {component_name}", True, "Activated")
else:
return TestResult(f"Activation: {component_name}", False, "Not activated")
return TestResult(f"Activation: {component_name}", False, "Not in status file")
# ==================== RUN ALL TESTS ====================
def run_all_tests(self, component: Optional[str] = None):
"""Run all tests or specific component tests."""
print("=" * 70)
print("STRATEGY BRIEF SYSTEM - TEST SUITE")
print("=" * 70)
print(f"Started: {self.start_time.strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Base path: {self.base_path}")
print("=" * 70)
if component is None or component == "agents":
print("\nš¦ AGENT TESTS")
print("-" * 50)
for agent in STRATEGY_AGENTS:
self.add_result(self.test_agent_file_exists(agent))
self.add_result(self.test_agent_yaml_frontmatter(agent))
self.add_result(self.test_agent_sections(agent))
if component is None or component == "a2a":
print("\nš A2A AGENT CARD TESTS")
print("-" * 50)
for agent in STRATEGY_AGENTS:
self.add_result(self.test_a2a_card_exists(agent))
self.add_result(self.test_a2a_card_valid_json(agent))
self.add_result(self.test_a2a_card_schema(agent))
self.add_result(self.test_a2a_card_agent_id_format(agent))
if component is None or component == "scripts":
print("\nš SCRIPT TESTS")
print("-" * 50)
for script in STRATEGY_SCRIPTS:
self.add_result(self.test_script_exists(script))
self.add_result(self.test_script_syntax(script))
self.add_result(self.test_script_has_docstring(script))
self.add_result(self.test_script_has_main(script))
if component is None or component == "workflow":
print("\nš WORKFLOW TESTS")
print("-" * 50)
self.add_result(self.test_workflow_exists())
self.add_result(self.test_workflow_yaml_frontmatter())
self.add_result(self.test_workflow_steps())
if component is None or component == "hooks":
print("\nšŖ HOOK TESTS")
print("-" * 50)
for hook in STRATEGY_HOOKS:
self.add_result(self.test_hook_exists(hook))
self.add_result(self.test_hook_executable(hook))
self.add_result(self.test_hook_syntax(hook))
self.add_result(self.test_hook_json_io(hook))
if component is None or component == "integration":
print("\nš INTEGRATION TESTS")
print("-" * 50)
for agent in STRATEGY_AGENTS:
self.add_result(self.test_agent_a2a_consistency(agent))
self.add_result(self.test_activation_status("agent", agent))
# Summary
self.print_summary()
def print_summary(self):
"""Print test summary."""
total = len(self.results)
passed = sum(1 for r in self.results if r.passed)
failed = total - passed
duration = (datetime.now() - self.start_time).total_seconds()
print("\n" + "=" * 70)
print("TEST SUMMARY")
print("=" * 70)
print(f"Total: {total}")
print(f"Passed: {passed} ā
")
print(f"Failed: {failed} ā")
print(f"Duration: {duration:.2f}s")
print(f"Success: {passed/total*100:.1f}%")
print("=" * 70)
if failed > 0:
print("\nFAILED TESTS:")
for r in self.results:
if not r.passed:
print(f" ā {r.name}: {r.message}")
print()
sys.exit(1)
else:
print("\nā
ALL TESTS PASSED")
sys.exit(0)
def main(): parser = argparse.ArgumentParser(description="Test Strategy Brief System") parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output") parser.add_argument("--component", choices=["agents", "a2a", "scripts", "workflow", "hooks", "integration"], help="Test specific component only")
args = parser.parse_args()
# Determine base path
base_path = Path(__file__).parent.parent
# Run tests
suite = TestSuite(base_path, verbose=args.verbose)
suite.run_all_tests(component=args.component)
if name == "main": main()