Files
daily_stock_analysis/tests/test_search_performance.py
LouisHong 6a070eb479 #602 [PR 8] 问股与回测接入优化及 Web 交互回归修复 (#824)
* feat(web): consolidate dashboard, chat, and backtest UI improvements

- polish dashboard follow-up pages and shared UI states across home, chat, and backtest flows
- consolidate chat and backtest page layout, styling, and interaction improvements into a single web UI update
- improve follow-up context handling in chat and add broader regression coverage for dashboard and chat components
- refine text color and opacity usage across shared components for more consistent readability
- restore home page mobile scrolling after the broader UI refactor changed page overflow behavior
- update related tests and changelog entries to reflect the finalized web interaction and styling changes

* feat(ui): optimize light theme shadows, navigation, alerts, and chat bubble styles

- Soften light mode box-shadows globally, replacing hardcoded grays with dynamic CSS variables for a cleaner, non-muddy depth effect.
- Unify SidebarNav active item style: remove inset shadow, apply primary background, and use bold font for better visibility.
- Fix ApiErrorAlert and InlineAlert contrast in light mode: use deep red text for high legibility, and robust dark/light theme CSS variables.
- Fix ThemeToggle menu z-index (z-40) in Shell to prevent overlap by main content pages (e.g., Settings, Backtest).
- Refactor ChatPage avatars and message bubbles to use dedicated dual-theme CSS classes (.chat-avatar-*, .chat-bubble-*).
- Add distinct borders to User/AI chat avatars with lowered opacity in dark mode to prevent visual glare.
- Add subtle borders to AI message bubbles in light mode to enhance separation, preserving semi-transparent borders in dark mode.

* fix(web): restore picker flows and align chat/report interactions

- restore intelligent import file picker behavior and add regression coverage
- align report markdown E2E expectations with the current UI
- improve markdown plain-text extraction used by report export flows
- fix chat session history deletion accessibility by separating row selection and delete actions into independent native buttons
- add chat history regression tests for keyboard-accessible deletion behavior
- deduplicate shared action button variant styles without changing the public Button variant API
- keep user-facing web interactions consistent after recent UI updates

* fix(web): resolve dashboard build issue and speed resolver benchmarks

- remove duplicate notify fields from useHomeDashboardState to fix the dsa-web TypeScript build
- keep the theme toggle button disabled in the current UI state
- cache local name-to-code indexes and fast-return on ambiguous local stock names
- split resolver performance coverage into fast-path and typo-fallback benchmarks with warm-up steps and smaller iteration budgets

* update README.md
2026-03-24 20:03:05 +08:00

89 lines
3.1 KiB
Python

# -*- coding: utf-8 -*-
"""
===================================
Search Algorithm Performance Tests
===================================
Benchmarks the name-to-code resolution engine under load.
"""
import time
import pytest
from unittest.mock import patch
from src.services.name_to_code_resolver import resolve_name_to_code
class TestSearchPerformance:
"""Benchmark tests for stock search resolution."""
@pytest.mark.benchmark
def test_resolve_name_to_code_fast_path_throughput(self):
"""Benchmark the common fast paths without typo/fuzzy fallbacks dominating runtime."""
inputs = [
"600519", "00700", "AAPL", "TSLA",
"贵州茅台", "腾讯控股", "阿里巴巴",
"aaaaaaa", "1234567",
]
# Warm caches/import paths before timing.
for s in inputs:
resolve_name_to_code(s)
start_time = time.time()
iterations = 30
for _ in range(iterations):
for s in inputs:
resolve_name_to_code(s)
duration = time.time() - start_time
avg_ms = (duration / (iterations * len(inputs))) * 1000
print(f"\nAverage fast-path resolution time: {avg_ms:.2f}ms")
assert avg_ms < 20, f"Fast-path resolution too slow: {avg_ms:.2f}ms"
@pytest.mark.benchmark
@patch("src.services.name_to_code_resolver._get_akshare_name_to_code", return_value={})
def test_resolve_name_to_code_typo_fallback_budget(self, mock_akshare):
"""Benchmark typo/fuzzy fallback separately with a smaller iteration budget."""
typo_inputs = [
"贵州茅苔",
"平安银形",
]
for s in typo_inputs:
resolve_name_to_code(s)
start_time = time.time()
iterations = 10
for _ in range(iterations):
for s in typo_inputs:
resolve_name_to_code(s)
duration = time.time() - start_time
avg_ms = (duration / (iterations * len(typo_inputs))) * 1000
print(f"\nAverage typo/fallback resolution time: {avg_ms:.2f}ms")
assert avg_ms < 100, f"Typo fallback too slow: {avg_ms:.2f}ms"
@pytest.mark.benchmark
@patch("src.services.name_to_code_resolver._get_akshare_name_to_code")
def test_fuzzy_match_performance_large_set(self, mock_akshare):
"""Test difflib fuzzy matching performance with a 5000+ stock set."""
# Simulate 5000 stocks from AkShare
fake_market = {f"股票_{i}": f"{i:06d}" for i in range(5000)}
mock_akshare.return_value = fake_market
query = "股票_4999" # Worst case or near worst case for fuzzy matching
start_time = time.time()
iterations = 20
for _ in range(iterations):
resolve_name_to_code(query)
duration = time.time() - start_time
avg_ms = (duration / iterations) * 1000
print(f"\nFuzzy match (5000 stocks) avg time: {avg_ms:.2f}ms")
# Fuzzy matching 5000 strings is CPU intensive.
# Aiming for < 100ms per request on a standard CI environment.
assert avg_ms < 200, f"Fuzzy matching too slow: {avg_ms:.2f}ms"