test: format test suite (#2252)

This commit is contained in:
huanghuoguoguo
2026-06-16 03:22:29 +00:00
committed by GitHub
parent 1ae5aacc00
commit f390980d0a
92 changed files with 1658 additions and 1713 deletions
+5 -12
View File
@@ -68,11 +68,7 @@ class TestNormalizeFilter:
def test_normalize_filter_multiple_conditions(self):
"""Multiple top-level keys are AND-ed (returned as multiple triples)."""
result = normalize_filter({
'file_id': 'abc',
'status': {'$ne': 'deleted'},
'created_at': {'$gte': 1700000000}
})
result = normalize_filter({'file_id': 'abc', 'status': {'$ne': 'deleted'}, 'created_at': {'$gte': 1700000000}})
assert len(result) == 3
# Order should match dict iteration order
@@ -149,11 +145,7 @@ class TestStripUnsupportedFields:
('file_id', '$eq', 'def'),
]
result = strip_unsupported_fields(
triples,
{'file_id', 'chunk_uuid'},
field_aliases={'uuid': 'chunk_uuid'}
)
result = strip_unsupported_fields(triples, {'file_id', 'chunk_uuid'}, field_aliases={'uuid': 'chunk_uuid'})
assert len(result) == 2
# 'uuid' should be resolved to 'chunk_uuid'
@@ -169,7 +161,7 @@ class TestStripUnsupportedFields:
result = strip_unsupported_fields(
triples,
{'file_id'}, # chunk_uuid not supported
field_aliases={'uuid': 'chunk_uuid'}
field_aliases={'uuid': 'chunk_uuid'},
)
assert result == []
@@ -207,4 +199,5 @@ class TestSupportedOpsConstant:
def test_supported_ops_is_frozenset(self):
"""SUPPORTED_OPS is a frozenset for immutability."""
from collections.abc import Set
assert isinstance(SUPPORTED_OPS, Set)
assert isinstance(SUPPORTED_OPS, Set)
+20 -38
View File
@@ -55,6 +55,7 @@ class TestVectorDBManagerInitialization:
# Run initialize synchronously for test
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
# Chroma should be instantiated
@@ -76,6 +77,7 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
mock_chroma_class.assert_called_once_with(mock_app)
@@ -96,6 +98,7 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
mock_qdrant_class.assert_called_once_with(mock_app)
@@ -115,6 +118,7 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
mock_seekdb_class.assert_called_once_with(mock_app)
@@ -123,11 +127,7 @@ class TestVectorDBManagerInitialization:
"""Milvus config with custom URI."""
vdb_config = {
'use': 'milvus',
'milvus': {
'uri': 'http://localhost:19530',
'token': 'root:Milvus',
'db_name': 'langbot_db'
}
'milvus': {'uri': 'http://localhost:19530', 'token': 'root:Milvus', 'db_name': 'langbot_db'},
}
mock_app = self._create_mock_app(vdb_config)
@@ -141,13 +141,11 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
mock_milvus_class.assert_called_once_with(
mock_app,
uri='http://localhost:19530',
token='root:Milvus',
db_name='langbot_db'
mock_app, uri='http://localhost:19530', token='root:Milvus', db_name='langbot_db'
)
def test_initialize_milvus_backend_defaults(self):
@@ -165,24 +163,15 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
# Should use default values
mock_milvus_class.assert_called_once_with(
mock_app,
uri='./data/milvus.db',
token=None,
db_name='default'
)
mock_milvus_class.assert_called_once_with(mock_app, uri='./data/milvus.db', token=None, db_name='default')
def test_initialize_pgvector_with_connection_string(self):
"""pgvector with connection string."""
vdb_config = {
'use': 'pgvector',
'pgvector': {
'connection_string': 'postgresql://user:pass@host:5432/langbot'
}
}
vdb_config = {'use': 'pgvector', 'pgvector': {'connection_string': 'postgresql://user:pass@host:5432/langbot'}}
mock_app = self._create_mock_app(vdb_config)
mocks = self._make_vector_import_mocks()
@@ -195,11 +184,11 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
mock_pgvector_class.assert_called_once_with(
mock_app,
connection_string='postgresql://user:pass@host:5432/langbot'
mock_app, connection_string='postgresql://user:pass@host:5432/langbot'
)
def test_initialize_pgvector_with_individual_params(self):
@@ -211,8 +200,8 @@ class TestVectorDBManagerInitialization:
'port': 5433,
'database': 'vectordb',
'user': 'admin',
'password': 'secret'
}
'password': 'secret',
},
}
mock_app = self._create_mock_app(vdb_config)
@@ -226,15 +215,11 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
mock_pgvector_class.assert_called_once_with(
mock_app,
host='db.example.com',
port=5433,
database='vectordb',
user='admin',
password='secret'
mock_app, host='db.example.com', port=5433, database='vectordb', user='admin', password='secret'
)
def test_initialize_pgvector_defaults(self):
@@ -252,15 +237,11 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
mock_pgvector_class.assert_called_once_with(
mock_app,
host='localhost',
port=5432,
database='langbot',
user='postgres',
password='postgres'
mock_app, host='localhost', port=5432, database='langbot', user='postgres', password='postgres'
)
def test_initialize_unknown_backend_defaults_to_chroma(self):
@@ -278,6 +259,7 @@ class TestVectorDBManagerInitialization:
mgr = VectorDBManager(mock_app)
import asyncio
asyncio.get_event_loop().run_until_complete(mgr.initialize())
mock_chroma_class.assert_called_once_with(mock_app)
@@ -335,4 +317,4 @@ class TestVectorDBManagerProxies:
mgr.vector_db = mock_vector_db
result = mgr.get_supported_search_types()
assert result == ['vector', 'full_text']
assert result == ['vector', 'full_text']
+46 -14
View File
@@ -39,6 +39,7 @@ class TestVectorDatabaseAbstractMethods:
def test_abstract_methods_required(self):
"""Subclass must implement all abstract methods."""
class IncompleteVectorDB(VectorDatabase):
pass
@@ -47,11 +48,21 @@ class TestVectorDatabaseAbstractMethods:
def test_supported_search_types_default(self):
"""Default supported_search_types returns [VECTOR]."""
class MinimalVectorDB(VectorDatabase):
async def add_embeddings(self, collection, ids, embeddings_list, metadatas, documents=None):
pass
async def search(self, collection, query_embedding, k=5, search_type='vector', query_text='', filter=None, vector_weight=None):
async def search(
self,
collection,
query_embedding,
k=5,
search_type='vector',
query_text='',
filter=None,
vector_weight=None,
):
pass
async def delete_by_file_id(self, collection, file_id):
@@ -71,11 +82,21 @@ class TestVectorDatabaseAbstractMethods:
def test_list_by_filter_default_implementation(self):
"""list_by_filter has default implementation returning empty."""
class MinimalVectorDB(VectorDatabase):
async def add_embeddings(self, collection, ids, embeddings_list, metadatas, documents=None):
pass
async def search(self, collection, query_embedding, k=5, search_type='vector', query_text='', filter=None, vector_weight=None):
async def search(
self,
collection,
query_embedding,
k=5,
search_type='vector',
query_text='',
filter=None,
vector_weight=None,
):
pass
async def delete_by_file_id(self, collection, file_id):
@@ -93,9 +114,8 @@ class TestVectorDatabaseAbstractMethods:
db = MinimalVectorDB()
# list_by_filter should return empty list and -1 for total
import asyncio
result = asyncio.get_event_loop().run_until_complete(
db.list_by_filter('test_collection')
)
result = asyncio.get_event_loop().run_until_complete(db.list_by_filter('test_collection'))
assert result == ([], -1)
@@ -105,14 +125,17 @@ class TestVectorDatabaseInterface:
@pytest.fixture
def mock_vector_db(self):
"""Create a minimal mock VectorDatabase for testing."""
class MockVectorDB(VectorDatabase):
def __init__(self):
self.add_embeddings = AsyncMock()
self.search = AsyncMock(return_value={
'ids': [['id1', 'id2']],
'distances': [[0.1, 0.2]],
'metadatas': [[{'key': 'val1'}, {'key': 'val2'}]]
})
self.search = AsyncMock(
return_value={
'ids': [['id1', 'id2']],
'distances': [[0.1, 0.2]],
'metadatas': [[{'key': 'val1'}, {'key': 'val2'}]],
}
)
self.delete_by_file_id = AsyncMock()
self.delete_by_filter = AsyncMock(return_value=5)
self.get_or_create_collection = AsyncMock()
@@ -121,7 +144,16 @@ class TestVectorDatabaseInterface:
async def add_embeddings(self, collection, ids, embeddings_list, metadatas, documents=None):
pass
async def search(self, collection, query_embedding, k=5, search_type='vector', query_text='', filter=None, vector_weight=None):
async def search(
self,
collection,
query_embedding,
k=5,
search_type='vector',
query_text='',
filter=None,
vector_weight=None,
):
pass
async def delete_by_file_id(self, collection, file_id):
@@ -146,7 +178,7 @@ class TestVectorDatabaseInterface:
ids=['id1', 'id2'],
embeddings_list=[[0.1, 0.2], [0.3, 0.4]],
metadatas=[{'a': 1}, {'b': 2}],
documents=['doc1', 'doc2']
documents=['doc1', 'doc2'],
)
mock_vector_db.add_embeddings.assert_called_once()
@@ -162,7 +194,7 @@ class TestVectorDatabaseInterface:
search_type='hybrid',
query_text='search text',
filter={'file_id': 'abc'},
vector_weight=0.7
vector_weight=0.7,
)
mock_vector_db.search.assert_called_once()
@@ -170,4 +202,4 @@ class TestVectorDatabaseInterface:
async def test_delete_by_filter_returns_int(self, mock_vector_db):
"""delete_by_filter returns int count."""
result = await mock_vector_db.delete_by_filter('test', {'file_id': 'abc'})
assert isinstance(result, int)
assert isinstance(result, int)
@@ -5,6 +5,7 @@ Tests cover:
- _build_milvus_expr: Milvus boolean expression string conversion
- _build_pg_conditions: PostgreSQL SQLAlchemy conditions conversion
"""
from __future__ import annotations
from importlib import import_module
@@ -122,11 +123,13 @@ class TestQdrantFilterConversion:
"""Multiple conditions are combined in must/must_not."""
qdrant_module = get_qdrant_module()
result = qdrant_module._build_qdrant_filter({
'file_id': 'abc',
'status': {'$ne': 'deleted'},
'created_at': {'$gte': 100},
})
result = qdrant_module._build_qdrant_filter(
{
'file_id': 'abc',
'status': {'$ne': 'deleted'},
'created_at': {'$gte': 100},
}
)
assert len(result.must) == 2 # file_id eq + created_at gte
assert len(result.must_not) == 1 # status ne
@@ -198,10 +201,12 @@ class TestMilvusFilterConversion:
"""Multiple conditions are joined with 'and'."""
milvus_module = get_milvus_module()
result = milvus_module._build_milvus_expr({
'file_id': 'abc',
'chunk_uuid': {'$ne': 'def'},
})
result = milvus_module._build_milvus_expr(
{
'file_id': 'abc',
'chunk_uuid': {'$ne': 'def'},
}
)
assert 'and' in result
assert 'file_id == "abc"' in result
assert 'chunk_uuid != "def"' in result
@@ -272,6 +277,7 @@ class TestPgVectorFilterConversion:
assert len(result) == 1
# Verify it's a SQLAlchemy BinaryExpression
from sqlalchemy.sql.expression import BinaryExpression
assert isinstance(result[0], BinaryExpression)
def test_ne_operator_creates_inequality_condition(self):
@@ -321,10 +327,12 @@ class TestPgVectorFilterConversion:
"""Multiple conditions return list of conditions."""
pgvector_module = get_pgvector_module()
result = pgvector_module._build_pg_conditions({
'file_id': 'abc',
'chunk_uuid': {'$ne': 'def'},
})
result = pgvector_module._build_pg_conditions(
{
'file_id': 'abc',
'chunk_uuid': {'$ne': 'def'},
}
)
assert len(result) == 2
@@ -349,11 +357,13 @@ class TestPgVectorFilterConversion:
"""Only supported fields (text, file_id, chunk_uuid) are kept."""
pgvector_module = get_pgvector_module()
result = pgvector_module._build_pg_conditions({
'text': {'$ne': ''},
'file_id': 'abc',
'chunk_uuid': {'$in': ['x', 'y']},
'unsupported': 'value',
})
result = pgvector_module._build_pg_conditions(
{
'text': {'$ne': ''},
'file_id': 'abc',
'chunk_uuid': {'$in': ['x', 'y']},
'unsupported': 'value',
}
)
assert len(result) == 3 # Only supported fields
assert len(result) == 3 # Only supported fields