Files
wehub-resource-sync 7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

985 lines
31 KiB
Python

"""
Tests for the candidate exploration system.
Tests cover:
- BaseCandidateExplorer search execution
- Exploration time and candidate limits
- Query generation and result handling
"""
import time
from unittest.mock import Mock
class TestBaseCandidateExplorer:
"""Tests for the BaseCandidateExplorer class."""
def test_base_explorer_execute_search_list_results(self):
"""Test _execute_search with list results."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
# Create a concrete implementation for testing
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
mock_search.run.return_value = [
{"title": "Result 1", "snippet": "Snippet 1"},
{"title": "Result 2", "snippet": "Snippet 2"},
]
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
max_candidates=50,
max_search_time=60.0,
)
result = explorer._execute_search("test query")
assert "results" in result
assert len(result["results"]) == 2
assert result["query"] == "test query"
def test_base_explorer_execute_search_dict_results(self):
"""Test _execute_search with dict results."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
mock_search.run.return_value = {
"results": [
{"title": "Result 1", "snippet": "Snippet 1"},
],
"total": 1,
}
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
result = explorer._execute_search("test query")
assert "results" in result
assert len(result["results"]) == 1
def test_base_explorer_should_continue_time_limit(self):
"""Test exploration stops at time limit."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
max_candidates=100,
max_search_time=1.0, # 1 second limit
)
start_time = time.time() - 2.0 # Simulate 2 seconds elapsed
result = explorer._should_continue_exploration(start_time, 0)
assert result is False # Should stop due to time limit
def test_base_explorer_should_continue_candidate_limit(self):
"""Test exploration stops at max candidates."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
max_candidates=10,
max_search_time=60.0,
)
start_time = time.time() # Just started
result = explorer._should_continue_exploration(start_time, 15)
assert result is False # Should stop due to candidate limit
def test_base_explorer_deduplicate_candidates(self):
"""Test candidate deduplication."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
from local_deep_research.advanced_search_system.candidates.base_candidate import (
Candidate,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
candidates = [
Candidate(name="Apple Inc"),
Candidate(name="apple inc"), # Duplicate (case insensitive)
Candidate(name="Google"),
Candidate(name=" google "), # Duplicate (with whitespace)
Candidate(name="Microsoft"),
]
unique = explorer._deduplicate_candidates(candidates)
assert len(unique) == 3 # Only Apple, Google, Microsoft
def test_base_explorer_rank_candidates_by_relevance(self):
"""Test candidate ranking."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
from local_deep_research.advanced_search_system.candidates.base_candidate import (
Candidate,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
candidates = [
Candidate(
name="Random Thing", metadata={"query": "unrelated search"}
),
Candidate(
name="Python Language", metadata={"query": "python programming"}
),
]
ranked = explorer._rank_candidates_by_relevance(
candidates, "python programming"
)
# The candidate with matching query words should rank higher
assert ranked[0].name == "Python Language"
def test_base_explorer_extract_entity_names_empty(self):
"""Test entity name extraction with empty text."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
# Empty text should return empty list
names = explorer._extract_entity_names("")
assert names == []
names = explorer._extract_entity_names(" ")
assert names == []
def test_base_explorer_execute_search_unknown_format(self):
"""Test _execute_search with unknown result format."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
mock_search.run.return_value = "unexpected string result"
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
result = explorer._execute_search("test query")
assert "results" in result
assert result["results"] == []
def test_base_explorer_execute_search_exception(self):
"""Test _execute_search handles exceptions."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
mock_search.run.side_effect = Exception("Search error")
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
result = explorer._execute_search("test query")
assert "results" in result
assert result["results"] == []
def test_base_explorer_execute_search_tracks_queries(self):
"""Test _execute_search tracks explored queries."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
mock_search.run.return_value = []
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
explorer._execute_search("Test Query")
assert "test query" in explorer.explored_queries
def test_base_explorer_extract_candidates_empty_results(self):
"""Test _extract_candidates_from_results with empty results."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
candidates = explorer._extract_candidates_from_results(
{"results": []}, "test query"
)
assert candidates == []
def test_base_explorer_extract_candidates_no_query(self):
"""Test _extract_candidates_from_results without original query."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
results = {"results": [{"title": "Test", "snippet": "Content"}]}
candidates = explorer._extract_candidates_from_results(results)
assert candidates == []
def test_base_explorer_extract_candidates_with_results(self):
"""Test _extract_candidates_from_results with actual results."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(content="Answer 1\nAnswer 2")
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
results = {
"results": [
{"title": "Title 1", "snippet": "Snippet 1"},
{"title": "Title 2", "snippet": "Snippet 2"},
],
"query": "search query",
}
candidates = explorer._extract_candidates_from_results(
results, "original query"
)
assert len(candidates) == 2
assert candidates[0].name == "Answer 1"
def test_base_explorer_extract_candidates_skips_duplicates(self):
"""Test _extract_candidates_from_results skips already found candidates."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
from local_deep_research.advanced_search_system.candidates.base_candidate import (
Candidate,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(
content="Existing Answer\nNew Answer"
)
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
explorer.found_candidates["Existing Answer"] = Candidate(
name="Existing Answer"
)
results = {"results": [{"title": "Title", "snippet": "Snippet"}]}
candidates = explorer._extract_candidates_from_results(results, "query")
assert len(candidates) == 1
assert candidates[0].name == "New Answer"
def test_base_explorer_generate_answer_candidates(self):
"""Test _generate_answer_candidates method."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(
content="• Answer One\n- Answer Two\n1. Answer Three"
)
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
answers = explorer._generate_answer_candidates(
"Question?", "Search content"
)
assert len(answers) == 3
assert "Answer One" in answers
assert "Answer Two" in answers
assert "Answer Three" in answers
def test_base_explorer_generate_answer_candidates_exception(self):
"""Test _generate_answer_candidates handles exceptions."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.side_effect = Exception("Model error")
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
answers = explorer._generate_answer_candidates("Question?", "Content")
assert answers == []
def test_base_explorer_generate_answer_candidates_limits_to_five(self):
"""Test _generate_answer_candidates limits results to 5."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(
content="A1\nA2\nA3\nA4\nA5\nA6\nA7\nA8"
)
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
answers = explorer._generate_answer_candidates("Q?", "Content")
assert len(answers) <= 5
def test_base_explorer_generate_answer_candidates_skips_short(self):
"""Test _generate_answer_candidates skips very short answers."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(content="AB\nValid Answer\nXY")
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
answers = explorer._generate_answer_candidates("Q?", "Content")
assert "AB" not in answers
assert "XY" not in answers
assert "Valid Answer" in answers
def test_base_explorer_extract_entity_names_with_text(self):
"""Test _extract_entity_names with actual text."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(content="Apple Inc\nGoogle LLC")
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
names = explorer._extract_entity_names("Text about Apple and Google")
assert len(names) == 2
assert "Apple Inc" in names
def test_base_explorer_extract_entity_names_with_entity_type(self):
"""Test _extract_entity_names with entity type specified."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(content="New York\nLos Angeles")
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
explorer._extract_entity_names("Text about cities", "city")
# Should have invoked model with entity type in prompt
call_args = mock_model.invoke.call_args[0][0]
assert "city" in call_args
def test_base_explorer_extract_entity_names_exception(self):
"""Test _extract_entity_names handles exceptions."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.side_effect = Exception("Model error")
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
names = explorer._extract_entity_names("Some text")
assert names == []
def test_base_explorer_extract_entity_names_filters_articles(self):
"""Test _extract_entity_names filters names starting with articles."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(
content="The Company\na small thing\nan entity\nValid Name"
)
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
names = explorer._extract_entity_names("Text")
assert "The Company" not in names
assert "a small thing" not in names
assert "an entity" not in names
assert "Valid Name" in names
def test_base_explorer_extract_entity_names_limits_to_five(self):
"""Test _extract_entity_names limits results to 5."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_model.invoke.return_value = Mock(
content="Name1\nName2\nName3\nName4\nName5\nName6\nName7"
)
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
names = explorer._extract_entity_names("Text")
assert len(names) <= 5
def test_base_explorer_should_continue_returns_true(self):
"""Test _should_continue_exploration returns True when within limits."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
max_candidates=100,
max_search_time=60.0,
)
start_time = time.time()
result = explorer._should_continue_exploration(start_time, 5)
assert result is True
def test_base_explorer_rank_empty_candidates(self):
"""Test _rank_candidates_by_relevance with empty list."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
result = explorer._rank_candidates_by_relevance([], "query")
assert result == []
def test_base_explorer_rank_with_result_title(self):
"""Test _rank_candidates_by_relevance with result_title metadata."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
from local_deep_research.advanced_search_system.candidates.base_candidate import (
Candidate,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
candidates = [
Candidate(
name="Low Match",
metadata={
"query": "unrelated",
"result_title": "something else",
},
),
Candidate(
name="High Match",
metadata={
"query": "python programming",
"result_title": "python programming guide",
},
),
]
ranked = explorer._rank_candidates_by_relevance(
candidates, "python programming"
)
assert ranked[0].name == "High Match"
def test_base_explorer_init_defaults(self):
"""Test BaseCandidateExplorer initialization defaults."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
BaseCandidateExplorer,
)
class TestExplorer(BaseCandidateExplorer):
def explore(
self, initial_query, constraints=None, entity_type=None
):
pass
def generate_exploration_queries(
self, base_query, found_candidates, constraints=None
):
return []
mock_model = Mock()
mock_search = Mock()
explorer = TestExplorer(
model=mock_model,
search_engine=mock_search,
)
assert explorer.max_candidates == 50
assert explorer.max_search_time == 60.0
assert explorer.explored_queries == set()
assert explorer.found_candidates == {}
def test_exploration_strategy_enum(self):
"""Test ExplorationStrategy enum values."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
ExplorationStrategy,
)
assert ExplorationStrategy.BREADTH_FIRST.value == "breadth_first"
assert ExplorationStrategy.DEPTH_FIRST.value == "depth_first"
assert (
ExplorationStrategy.CONSTRAINT_GUIDED.value == "constraint_guided"
)
assert (
ExplorationStrategy.DIVERSITY_FOCUSED.value == "diversity_focused"
)
assert ExplorationStrategy.ADAPTIVE.value == "adaptive"
def test_exploration_result_dataclass(self):
"""Test ExplorationResult dataclass."""
from local_deep_research.advanced_search_system.candidate_exploration.base_explorer import (
ExplorationResult,
ExplorationStrategy,
)
from local_deep_research.advanced_search_system.candidates.base_candidate import (
Candidate,
)
candidates = [Candidate(name="Test")]
result = ExplorationResult(
candidates=candidates,
total_searched=10,
unique_candidates=5,
exploration_paths=["path1", "path2"],
metadata={"key": "value"},
elapsed_time=5.5,
strategy_used=ExplorationStrategy.BREADTH_FIRST,
)
assert len(result.candidates) == 1
assert result.total_searched == 10
assert result.unique_candidates == 5
assert len(result.exploration_paths) == 2
assert result.metadata["key"] == "value"
assert result.elapsed_time == 5.5
assert result.strategy_used == ExplorationStrategy.BREADTH_FIRST