Files
ALwrity/backend/test/test_linkedin_keyword_fix.py

272 lines
11 KiB
Python

#!/usr/bin/env python3
"""
Test Script for LinkedIn Content Generation Keyword Fix
This script tests the fixed keyword processing by calling the LinkedIn content generation
endpoint directly and capturing detailed logs to analyze API usage patterns.
"""
import asyncio
import json
import time
import logging
from datetime import datetime
from typing import Dict, Any
import sys
import os
# Add the backend directory to the Python path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# Configure detailed logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(f'test_linkedin_keyword_fix_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log'),
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger(__name__)
# Import the LinkedIn service
from services.linkedin_service import LinkedInService
from models.linkedin_models import LinkedInPostRequest, LinkedInPostType, LinkedInTone, GroundingLevel, SearchEngine
class LinkedInKeywordTest:
"""Test class for LinkedIn keyword processing fix."""
def __init__(self):
self.linkedin_service = LinkedInService()
self.test_results = []
self.api_call_count = 0
self.start_time = None
def log_api_call(self, endpoint: str, duration: float, success: bool):
"""Log API call details."""
self.api_call_count += 1
logger.info(f"API Call #{self.api_call_count}: {endpoint} - Duration: {duration:.2f}s - Success: {success}")
async def test_keyword_phrase(self, phrase: str, test_name: str) -> Dict[str, Any]:
"""Test a specific keyword phrase."""
logger.info(f"\n{'='*60}")
logger.info(f"TESTING: {test_name}")
logger.info(f"KEYWORD PHRASE: '{phrase}'")
logger.info(f"{'='*60}")
test_start = time.time()
try:
# Create the request
request = LinkedInPostRequest(
topic=phrase,
industry="Technology",
post_type=LinkedInPostType.PROFESSIONAL,
tone=LinkedInTone.PROFESSIONAL,
grounding_level=GroundingLevel.ENHANCED,
search_engine=SearchEngine.GOOGLE,
research_enabled=True,
include_citations=True,
max_length=1000
)
logger.info(f"Request created: {request.topic}")
logger.info(f"Research enabled: {request.research_enabled}")
logger.info(f"Search engine: {request.search_engine}")
logger.info(f"Grounding level: {request.grounding_level}")
# Call the LinkedIn service
logger.info("Calling LinkedIn service...")
response = await self.linkedin_service.generate_linkedin_post(request)
test_duration = time.time() - test_start
self.log_api_call("LinkedIn Post Generation", test_duration, response.success)
# Analyze the response
result = {
"test_name": test_name,
"keyword_phrase": phrase,
"success": response.success,
"duration": test_duration,
"api_calls": self.api_call_count,
"error": response.error if not response.success else None,
"content_length": len(response.data.content) if response.success and response.data else 0,
"sources_count": len(response.research_sources) if response.success and response.research_sources else 0,
"citations_count": len(response.data.citations) if response.success and response.data and response.data.citations else 0,
"grounding_status": response.grounding_status if response.success else None,
"generation_metadata": response.generation_metadata if response.success else None
}
if response.success:
logger.info(f"✅ SUCCESS: Generated {result['content_length']} characters")
logger.info(f"📊 Sources: {result['sources_count']}, Citations: {result['citations_count']}")
logger.info(f"⏱️ Total duration: {test_duration:.2f}s")
logger.info(f"🔢 API calls made: {self.api_call_count}")
# Log content preview
if response.data and response.data.content:
content_preview = response.data.content[:200] + "..." if len(response.data.content) > 200 else response.data.content
logger.info(f"📝 Content preview: {content_preview}")
# Log grounding status
if response.grounding_status:
logger.info(f"🔍 Grounding status: {response.grounding_status}")
else:
logger.error(f"❌ FAILED: {response.error}")
return result
except Exception as e:
test_duration = time.time() - test_start
logger.error(f"❌ EXCEPTION in {test_name}: {str(e)}")
self.log_api_call("LinkedIn Post Generation", test_duration, False)
return {
"test_name": test_name,
"keyword_phrase": phrase,
"success": False,
"duration": test_duration,
"api_calls": self.api_call_count,
"error": str(e),
"content_length": 0,
"sources_count": 0,
"citations_count": 0,
"grounding_status": None,
"generation_metadata": None
}
async def run_comprehensive_test(self):
"""Run comprehensive tests for keyword processing."""
logger.info("🚀 Starting LinkedIn Keyword Processing Test Suite")
logger.info(f"Test started at: {datetime.now()}")
self.start_time = time.time()
# Test cases
test_cases = [
{
"phrase": "ALwrity content generation",
"name": "Single Phrase Test (Should be preserved as-is)"
},
{
"phrase": "AI tools, content creation, marketing automation",
"name": "Comma-Separated Test (Should be split by commas)"
},
{
"phrase": "LinkedIn content strategy",
"name": "Another Single Phrase Test"
},
{
"phrase": "social media, digital marketing, brand awareness",
"name": "Another Comma-Separated Test"
}
]
# Run all tests
for test_case in test_cases:
result = await self.test_keyword_phrase(
test_case["phrase"],
test_case["name"]
)
self.test_results.append(result)
# Reset API call counter for next test
self.api_call_count = 0
# Small delay between tests
await asyncio.sleep(2)
# Generate summary report
self.generate_summary_report()
def generate_summary_report(self):
"""Generate a comprehensive summary report."""
total_time = time.time() - self.start_time
logger.info(f"\n{'='*80}")
logger.info("📊 COMPREHENSIVE TEST SUMMARY REPORT")
logger.info(f"{'='*80}")
logger.info(f"🕐 Total test duration: {total_time:.2f} seconds")
logger.info(f"🧪 Total tests run: {len(self.test_results)}")
successful_tests = [r for r in self.test_results if r["success"]]
failed_tests = [r for r in self.test_results if not r["success"]]
logger.info(f"✅ Successful tests: {len(successful_tests)}")
logger.info(f"❌ Failed tests: {len(failed_tests)}")
if successful_tests:
avg_duration = sum(r["duration"] for r in successful_tests) / len(successful_tests)
avg_content_length = sum(r["content_length"] for r in successful_tests) / len(successful_tests)
avg_sources = sum(r["sources_count"] for r in successful_tests) / len(successful_tests)
avg_citations = sum(r["citations_count"] for r in successful_tests) / len(successful_tests)
logger.info(f"📈 Average generation time: {avg_duration:.2f}s")
logger.info(f"📝 Average content length: {avg_content_length:.0f} characters")
logger.info(f"🔍 Average sources found: {avg_sources:.1f}")
logger.info(f"📚 Average citations: {avg_citations:.1f}")
# Detailed results
logger.info(f"\n📋 DETAILED TEST RESULTS:")
for i, result in enumerate(self.test_results, 1):
status = "✅ PASS" if result["success"] else "❌ FAIL"
logger.info(f"{i}. {status} - {result['test_name']}")
logger.info(f" Phrase: '{result['keyword_phrase']}'")
logger.info(f" Duration: {result['duration']:.2f}s")
if result["success"]:
logger.info(f" Content: {result['content_length']} chars, Sources: {result['sources_count']}, Citations: {result['citations_count']}")
else:
logger.info(f" Error: {result['error']}")
# API Usage Analysis
logger.info(f"\n🔍 API USAGE ANALYSIS:")
total_api_calls = sum(r["api_calls"] for r in self.test_results)
logger.info(f"Total API calls across all tests: {total_api_calls}")
if successful_tests:
avg_api_calls = sum(r["api_calls"] for r in successful_tests) / len(successful_tests)
logger.info(f"Average API calls per successful test: {avg_api_calls:.1f}")
# Save detailed results to JSON file
report_data = {
"test_summary": {
"total_duration": total_time,
"total_tests": len(self.test_results),
"successful_tests": len(successful_tests),
"failed_tests": len(failed_tests),
"total_api_calls": total_api_calls
},
"test_results": self.test_results,
"timestamp": datetime.now().isoformat()
}
report_filename = f"linkedin_keyword_test_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
with open(report_filename, 'w') as f:
json.dump(report_data, f, indent=2, default=str)
logger.info(f"📄 Detailed report saved to: {report_filename}")
logger.info(f"{'='*80}")
async def main():
"""Main test execution function."""
try:
test_suite = LinkedInKeywordTest()
await test_suite.run_comprehensive_test()
except Exception as e:
logger.error(f"❌ Test suite failed: {str(e)}")
raise
if __name__ == "__main__":
print("🚀 Starting LinkedIn Keyword Processing Test Suite")
print("This will test the keyword fix and analyze API usage patterns...")
print("=" * 60)
asyncio.run(main())