# ============================================================================ # OUTPUT FORMATTERS # ============================================================================ import os import json from datetime import datetime from openpyxl import Workbook from openpyxl.styles import Font, PatternFill, Alignment from app.config import Config from app.models.schemas import TestCase from app.utils.logger import logger class OutputFormatter: """Format test cases for different output types""" @staticmethod def to_excel(test_cases: list, filename: str) -> str: """Generate Excel file""" filepath = os.path.join(Config.OUTPUT_DIR, filename) wb = Workbook() ws = wb.active ws.title = "Test Cases" # Headers headers = [ "Test Case ID", "Task Code", "Project", "Feature", "Title", "Objective", "Priority", "Type", "Category", "Preconditions", "Test Steps", "Expected Outcome" ] # Styling header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") header_font = Font(color="FFFFFF", bold=True) for col, header in enumerate(headers, start=1): cell = ws.cell(row=1, column=col, value=header) cell.fill = header_fill cell.font = header_font cell.alignment = Alignment(horizontal="center", vertical="center") # Data row = 2 for tc in test_cases: ws.cell(row, 1, tc.test_case_id) ws.cell(row, 2, tc.task_code) ws.cell(row, 3, tc.project_name) ws.cell(row, 4, tc.feature_name) ws.cell(row, 5, tc.title) ws.cell(row, 6, tc.objective) ws.cell(row, 7, tc.priority.value) ws.cell(row, 8, tc.test_type.value) ws.cell(row, 9, tc.category.value) ws.cell(row, 10, "\n".join(tc.preconditions)) # Format test steps steps_text = "" for step in tc.test_steps: steps_text += f"{step.step_number}. {step.action}\n" steps_text += f" Expected: {step.expected_result}\n" if step.test_data: steps_text += f" Data: {step.test_data}\n" steps_text += "\n" ws.cell(row, 11, steps_text) ws.cell(row, 12, tc.expected_outcome) row += 1 # Auto-adjust column widths for col in ws.columns: max_length = 0 column = col[0].column_letter for cell in col: try: if len(str(cell.value)) > max_length: max_length = len(cell.value) except: pass adjusted_width = min(max_length + 2, 50) ws.column_dimensions[column].width = adjusted_width wb.save(filepath) logger.info(f"📊 Excel file saved: {filepath}") return filepath @staticmethod def to_json(test_cases: list, filename: str, metadata: dict = None) -> str: """Generate JSON file with proper structure for CRUD operations""" filepath = os.path.join(Config.OUTPUT_DIR, filename) # Structure for CRUD compatibility data = { "test_cases": [tc.dict() for tc in test_cases], "metadata": metadata or { "created_at": datetime.now().isoformat(), "test_cases_count": len(test_cases) } } with open(filepath, 'w') as f: json.dump(data, f, indent=2, default=str) logger.info(f"📄 JSON file saved: {filepath}") return filepath