from slowlogs.result import summarize_results_v2 import os import sys import unittest import tempfile import shutil from unittest.mock import patch, MagicMock # Add the project root to the Python path sys.path.insert(0, os.path.abspath( os.path.join(os.path.dirname(__file__), '..'))) class TestSummarizeResultsV2(unittest.TestCase): def setUp(self): # Create a temporary directory for test database self.test_dir = tempfile.mkdtemp() self.db_path = os.path.join(self.test_dir, '.slowlog_issues.db') self.csv_path = os.path.join(self.test_dir, 'slowlog_issues.csv') # Patch the database and CSV paths in the module self.patcher = patch('slowlogs.result.os.path.expanduser') self.mock_expanduser = self.patcher.start() # Make expanduser return different values based on the path def expanduser_side_effect(path): if path.startswith('~/'): return os.path.join(self.test_dir, path[2:]) return path self.mock_expanduser.side_effect = expanduser_side_effect # Sample data for testing self.sample_issue = MagicMock() self.sample_issue.digest = "test_digest_123" self.sample_issue.query = "SELECT * FROM test_table WHERE id = 1" self.sample_issue.message = "Test message" self.sample_issue.type = "slow_query" self.sample_issue.query_time = 1.23 self.sample_issue.severity = "high" self.sample_issue.variability_pct = 25.5 # Add missing attribute self.sample_issue.plan_count = 3 # Add missing attribute self.sample_result = MagicMock() self.sample_result.issues_count = 1 self.sample_result.issues = [self.sample_issue] self.sample_result.rule = "test_rule" self.sample_result.message = "Test rule message" self.detect_results = { "cluster1": [self.sample_result] } def tearDown(self): # Clean up the temporary directory self.patcher.stop() if os.path.exists(self.test_dir): shutil.rmtree(self.test_dir) def test_summarize_results_v2_with_new_issue(self): # Test with a new issue (not in database) report, new_issues_report = summarize_results_v2( self.detect_results, feishu_message_type="text" ) # Verify the report contains expected content self.assertIn("### Slow Query Detection Report", report) self.assertIn("Cluster ID: cluster1 - Total Issues: 1", report) self.assertIn("Test rule message", report) # Verify new issues report self.assertIn("test_digest_123", new_issues_report) self.assertIn("slow_query", new_issues_report) # Verify CSV file was created and has content self.assertTrue(os.path.exists(self.csv_path), f"CSV file not found at {self.csv_path}") with open(self.csv_path, 'r') as f: csv_content = f.read() self.assertIn("test_digest_123", csv_content) self.assertIn("slow_query", csv_content) # Verify database was updated import sqlite3 conn = sqlite3.connect(self.db_path) cursor = conn.cursor() cursor.execute( 'SELECT digest FROM issues WHERE digest = ?', ("test_digest_123",)) result = cursor.fetchone() self.assertIsNotNone(result, "Digest not found in database") self.assertEqual(result[0], "test_digest_123") conn.close() def test_summarize_results_v2_with_existing_issue(self): # First run - issue gets added to database summarize_results_v2(self.detect_results) # Second run - same issue should not be reported as new report, new_issues_report = summarize_results_v2(self.detect_results) # New issues report should be empty self.assertEqual(new_issues_report, "") @patch('slowlogs.result.requests.post') def test_summarize_results_v2_with_feishu(self, mock_post): # Mock the Feishu API response mock_response = MagicMock() mock_response.raise_for_status.return_value = None mock_post.return_value = mock_response # Test with Feishu integration report, _ = summarize_results_v2( self.detect_results, feishu_message_type="card", feishu_page="https://test.feishu.cn/test" ) # Verify Feishu API was called mock_post.assert_called_once() # Verify the payload contains expected content args, kwargs = mock_post.call_args self.assertIn("content", kwargs["json"]) self.assertIn("New Slow Query Issues", str(kwargs["json"]["content"])) if __name__ == "__main__": unittest.main()