API Testing Guide
This guide covers the comprehensive test suite available for testing hlquery API endpoints across all supported client libraries.
Overview
The hlquery project includes a complete test suite with native language tests for each API client library. Each API directory contains tests written in that API's native language:
- PHP API: Tests written in PHP (
.phpfiles) - Complete PHP Tests Guide - Perl API: Tests written in Perl (
.plfiles) - Complete Perl Tests Guide - Python API: Tests written in Python (
.pyfiles) - Complete Python Tests Guide - Node.js API: Tests written in Node.js (
.jsfiles) - Complete Node.js Tests Guide - Node.js API: Tests written in JavaScript (
.jsfiles) - C++ API: Tests written in C++ (
.cppfiles) - Rust API: Tests written in Rust (
.rsfiles)
These tests provide:
- Comprehensive Coverage: Tests for all major API endpoints
- Native Language: Each API uses its own client library
- Easy Execution: Individual test scripts and test runners
- Real-World Scenarios: Tests that create, use, and clean up test data
Test Structure
Directory Layout
Tests are organized in tests/ subdirectories within each API client directory:
api/
├── python/tests/ # Python API tests (.py files)
├── node/tests/ # Node.js API tests (.js files)
├── php/tests/ # PHP API tests (.php files)
├── perl/tests/ # Perl API tests (.pl files)
├── cpp/tests/ # C++ API tests (.cpp files)
└── rust/tests/ # Rust API tests (.rs files)
Each tests/ directory contains 31 comprehensive test scripts written in that API's native language, covering all aspects of the API, including core functionality, advanced features, error handling, and edge cases.
Note: All Perl, PHP, Python, and Node.js tests are fully implemented with detailed developer comments. See the Perl Tests Guide, PHP Tests Guide, Python Tests Guide, and Node.js Tests Guide for complete documentation.
Important: Each API's tests use that API's own client library:
- PHP tests use the PHP client (
Hlquery\Client) - Perl tests use the Perl client (
Hlquery::Client) - Node.js tests use the Node.js client (
Client) - C++ tests use the C++ client (
hlquery::Client) - Rust tests use the Rust client (
hlquery_rust_client::Client)
Available Test Scripts
1. test_auth (Authentication Test)
Purpose: Tests authentication functionality
What it tests:
- Health check without authentication
- Bearer token authentication
- API key authentication
- Token validation
Usage:
# PHP
php api/php/tests/test_auth.php
# Perl
perl api/perl/tests/test_auth.pl
# Node.js
node api/node/tests/test_auth.js
# C++ (compile first)
cd api/cpp && make test_auth && ./build/test_auth
# Rust (compile first)
cd api/rust && cargo build --bin test_auth && cargo run --bin test_auth
Example Output:
----------------------------------------------------------------==============================
TEST: Authentication with Bearer Token
----------------------------------------------------------------------
Health check without auth: 200
Set bearer token: test_tok...
Health check with bearer token: 200
Set API key: test_tok...
Health check with API key: 200
✓ Authentication test completed
2. test_search (Search Test)
Purpose: Comprehensive search functionality testing
What it tests:
- Basic text search
- Filtered searches
- Sorted searches
- Paginated searches
- Wildcard searches
Features:
- Creates test collection with sample data
- Tests multiple search scenarios
- Provides detailed pass/fail reporting
- Automatic cleanup
Usage:
# PHP
php api/php/tests/test_search.php
# Perl
perl api/perl/tests/test_search.pl
# Node.js
node api/node/tests/test_search.js
# C++ (compile first)
cd api/cpp && make test_search && ./build/test_search
# Rust (compile first)
cd api/rust && cargo build --bin test_search && cargo run --bin test_search
3. test_docs_insert (Document Insertion Test)
Purpose: Document insertion and collection creation
What it tests:
- Creating a new collection with schema
- Inserting documents into collections
- Document retrieval verification
- Collection cleanup
Test Flow:
- Creates a test collection with fields:
title,content,tags - Inserts a test document with sample data
- Verifies the document was inserted correctly
- Cleans up the test collection
Usage:
# PHP
php api/php/tests/test_docs_insert.php
# Perl
perl api/perl/tests/test_docs_insert.pl
# Node.js
node api/node/tests/test_docs_insert.js
4. test_search_cols.py
Purpose: Search across multiple collections
What it tests:
- Listing all available collections
- Searching within each collection
- Handling collections with different schemas
- Multi-collection search scenarios
Usage:
python api/python/tests/test_search_cols.py
5. test_list_all_cols.py
Purpose: Collection listing with pagination
What it tests:
- Listing all collections
- Pagination support (offset/limit)
- Collection metadata display
- Document count per collection
Features:
- Displays collection names and document counts
- Supports pagination parameters
- Formatted output for easy reading
Usage:
python api/python/tests/test_list_all_cols.py
6. test_create_collection.py
Purpose: Collection creation with various schemas
What it tests:
- Creating collections with different field types
- Schema validation
- Collection retrieval after creation
- Collection deletion (cleanup)
Schema Types Tested:
- String fields
- Float fields
- String array fields
- Float array fields (for vectors)
Usage:
python api/python/tests/test_create_collection.py
7. test_get_collection.py
Purpose: Retrieving collection details
What it tests:
- Getting collection information
- Retrieving collection fields
- Formatted field display
- Error handling for non-existent collections
Usage:
python api/python/tests/test_get_collection.py
8. test_update_document.py
Purpose: Document update operations
What it tests:
- Updating existing documents
- Partial updates (updating specific fields)
- Verifying updates were applied
- Error handling
Test Flow:
- Creates or uses existing collection
- Inserts a test document
- Updates the document with new data
- Verifies the update was successful
- Cleans up test data
Usage:
python api/python/tests/test_update_document.py
9. test_delete_document.py
Purpose: Document deletion operations
What it tests:
- Deleting documents by ID
- Verifying deletion was successful
- Error handling for non-existent documents
- Cleanup procedures
Usage:
python api/python/tests/test_delete_document.py
10. test_vector_search.py
Purpose: Vector similarity search
What it tests:
- Creating collections with vector fields
- Inserting documents with embeddings
- Performing vector similarity searches
- Vector search parameters (threshold, normalize)
Vector Operations:
- Creates test collection with
float[]embedding field - Inserts document with sample vector
- Performs similarity search with query vector
- Tests vector search parameters
Usage:
python api/python/tests/test_vector_search.py
11. test_multi_search.py
Purpose: Multi-collection search operations
What it tests:
- Searching across multiple collections simultaneously
- Handling different collection schemas
- Aggregating results from multiple searches
- Error handling for missing collections
Usage:
python api/python/tests/test_multi_search.py
12. test_health.py
Purpose: System health and monitoring endpoints
What it tests:
GET /health- Health check endpointGET /stats- Server statisticsGET /status- Detailed server statusGET /metrics- JSON metrics (currently minimal)GET /- Root status response
Usage:
python api/python/tests/test_health.py
13. test_bulk_operations.py
Purpose: Bulk document operations
What it tests:
- Bulk document import
- Verifying bulk import results
- Bulk delete by filter
- Handling large batches of documents
Test Flow:
- Creates test collection
- Imports multiple documents in a single operation
- Verifies all documents were imported
- Tests bulk delete functionality
- Cleans up test collection
Usage:
python api/perl/tests/test_bulk_operations.py
python api/php/tests/test_bulk_operations.py
python api/node/tests/test_bulk_operations.py
14. test_synonyms.py
Purpose: Synonym management operations
What it tests:
- Listing synonyms for a collection
- Creating/updating synonyms
- Retrieving specific synonyms
- Deleting synonyms
Synonym Operations:
- Creates synonym groups (e.g., car, automobile, vehicle, auto)
- Tests CRUD operations on synonyms
- Verifies synonym persistence
Usage:
python api/perl/tests/test_synonyms.py
python api/php/tests/test_synonyms.py
python api/node/tests/test_synonyms.py
15. test_stopwords.py
Purpose: Stopword management operations
What it tests:
- Listing stopwords for a collection
- Adding stopwords
- Deleting stopwords
- Stopword filtering behavior
Usage:
python api/perl/tests/test_stopwords.py
python api/php/tests/test_stopwords.py
python api/node/tests/test_stopwords.py
16. test_overrides.py
Purpose: Search override management
What it tests:
- Listing search overrides
- Creating search overrides with rules
- Retrieving override details
- Deleting overrides
Override Features:
- Tests query matching rules
- Tests result inclusion/exclusion
- Verifies override application
Usage:
python api/perl/tests/test_overrides.py
python api/php/tests/test_overrides.py
python api/node/tests/test_overrides.py
17. test_aliases.py
Purpose: Collection alias management
What it tests:
- Listing all aliases
- Creating aliases for collections
- Retrieving alias details
- Deleting aliases
Alias Operations:
- Maps aliases to collection names
- Tests alias resolution
- Verifies alias persistence
Usage:
python api/perl/tests/test_aliases.py
python api/php/tests/test_aliases.py
python api/node/tests/test_aliases.py
18. test_facets.py
Purpose: Facet counts and aggregation
What it tests:
- Getting facet counts for fields
- Facet aggregation across documents
- Facet filtering
- Multiple facet fields
Usage:
python api/perl/tests/test_facets.py
python api/php/tests/test_facets.py
python api/node/tests/test_facets.py
19. test_export.py
Purpose: Document export operations
What it tests:
- Exporting documents from collections
- Export with filters
- Export with limits
- Export data format
Usage:
python api/perl/tests/test_export.py
python api/php/tests/test_export.py
python api/node/tests/test_export.py
20. test_delete_collection.py
Purpose: Collection deletion operations
What it tests:
- Deleting collections
- Verifying deletion was successful
- Error handling for non-existent collections
- Cleanup verification
Test Flow:
- Creates test collection
- Verifies collection exists
- Deletes the collection
- Verifies collection no longer exists
Usage:
python api/perl/tests/test_delete_collection.py
python api/php/tests/test_delete_collection.py
python api/node/tests/test_delete_collection.py
21. test_update_collection.py
Purpose: Collection schema updates
What it tests:
- Updating collection schemas
- Adding new fields to collections
- Modifying existing fields
- Verifying schema changes
Schema Update Operations:
- Adds new fields to existing collections
- Tests field type changes
- Verifies schema persistence
Usage:
python api/perl/tests/test_update_collection.py
python api/php/tests/test_update_collection.py
python api/node/tests/test_update_collection.py
22. test_error_handling.py
Purpose: Error handling and validation
What it tests:
- Getting non-existent collections (404 errors)
- Getting non-existent documents (404 errors)
- Deleting non-existent resources
- Invalid schema validation
- Invalid search parameters
Error Scenarios:
- Tests proper error codes (400, 404, 422)
- Validates error message formats
- Ensures graceful error handling
Usage:
python api/perl/tests/test_error_handling.py
python api/php/tests/test_error_handling.py
python api/node/tests/test_error_handling.py
23. test_edge_cases.py
Purpose: Edge cases and boundary conditions
What it tests:
- Documents with special characters
- Empty string values
- Large limit values
- Zero limit values
- Wildcard-only searches
Edge Case Scenarios:
- Special characters:
&,<,>,",' - Empty fields
- Boundary values
- Unusual but valid inputs
Usage:
python api/perl/tests/test_edge_cases.py
python api/php/tests/test_edge_cases.py
python api/node/tests/test_edge_cases.py
24. test_data_types.py
Purpose: Data type validation
What it tests:
- String fields
- Float fields
- Integer fields
- String array fields
- Float array fields (vectors)
Data Type Coverage:
- Tests all supported field types
- Validates type constraints
- Tests array operations
- Vector field handling
Usage:
python api/perl/tests/test_data_types.py
python api/php/tests/test_data_types.py
python api/node/tests/test_data_types.py
25. test_pagination.py
Purpose: Pagination with various scenarios
What it tests:
- First page retrieval
- Subsequent pages
- Large offsets
- Limits larger than total
- Search pagination
Pagination Scenarios:
- Tests offset/limit combinations
- Validates pagination consistency
- Tests boundary conditions
- Search result pagination
Usage:
python api/perl/tests/test_pagination.py
python api/php/tests/test_pagination.py
python api/node/tests/test_pagination.py
26. test_list_documents.py
Purpose: Document listing operations
What it tests:
- Listing all documents
- Listing with limits
- Listing with offsets
- Empty result handling
- Large offset handling
Listing Operations:
- Tests various listing parameters
- Validates result consistency
- Tests edge cases for listing
Usage:
python api/perl/tests/test_list_documents.py
python api/php/tests/test_list_documents.py
python api/node/tests/test_list_documents.py
python api/cpp/tests/test_list_documents.py
python api/rust/tests/test_list_documents.py
27. test_get_document.py
Purpose: Retrieve individual documents by ID
What it tests:
- Getting documents by ID
- Verifying document retrieval
- Error handling for non-existent documents
- Document field validation
Usage:
python api/perl/tests/test_get_document.py
python api/php/tests/test_get_document.py
python api/node/tests/test_get_document.py
python api/cpp/tests/test_get_document.py
python api/rust/tests/test_get_document.py
28. test_stats.py
Purpose: Server statistics and metrics
What it tests:
GET /stats- Server statisticsGET /connections- Active connectionsGET /rocksdb- RocksDB engine statsGET /doctotal- Document counts
Usage:
python api/perl/tests/test_stats.py
python api/php/tests/test_stats.py
python api/node/tests/test_stats.py
python api/cpp/tests/test_stats.py
python api/rust/tests/test_stats.py
29. test_import_documents.py
Purpose: Document import operations
What it tests:
- Importing single documents
- Importing multiple documents
- Verifying import results
- Import validation
Usage:
python api/perl/tests/test_import_documents.py
python api/php/tests/test_import_documents.py
python api/node/tests/test_import_documents.py
python api/cpp/tests/test_import_documents.py
python api/rust/tests/test_import_documents.py
30. test_filter_search.py
Purpose: Search with filter operations
What it tests:
- Filtering by category
- Filtering by price range
- Multiple filter combinations
- Complex filter expressions
Filter Operations:
- Category filters
- Numeric range filters
- Boolean filters
- Combined filters with && and ||
Usage:
python api/perl/tests/test_filter_search.py
python api/php/tests/test_filter_search.py
python api/node/tests/test_filter_search.py
python api/cpp/tests/test_filter_search.py
python api/rust/tests/test_filter_search.py
31. test_sort_search.py
Purpose: Search with sorting options
What it tests:
- Sorting by price (ascending/descending)
- Sorting by rating
- Sorting by multiple fields
- Sort order validation
Sort Operations:
- Ascending sort (
:asc) - Descending sort (
:desc) - Multiple field sorting
- Sort with filters
Usage:
python api/perl/tests/test_sort_search.py
python api/php/tests/test_sort_search.py
python api/node/tests/test_sort_search.py
python api/cpp/tests/test_sort_search.py
python api/rust/tests/test_sort_search.py
How Tests Work
Test Structure
Each test script follows a consistent structure:
#!/usr/bin/env python3
"""
Test Description
"""
import sys
import os
# Change to script directory (working directory)
script_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(script_dir)
# Path setup to import client library
python_api_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(script_dir))), 'python')
sys.path.insert(0, python_api_path)
from lib import Client
BASE_URL = 'http://localhost:9200'
def test_feature():
"""Test function"""
print("=" * 70)
print("TEST: Feature Name")
print("-" * 70)
client = Client(BASE_URL)
tests_passed = 0
tests_failed = 0
# Test scenarios here
# ...
# Summary
print(f"Test Summary: {tests_passed} passed, {tests_failed} failed")
if __name__ == '__main__':
test_feature()
Key Feature: All test scripts automatically change to their own directory when executed using os.chdir(script_dir). This ensures:
- Tests can be run from any directory
- Relative paths work correctly
- Working directory is always the test directory
For detailed explanations of how tests work, see How Tests Work.
Test Execution Flow
- Setup: Test imports client library and sets base URL
- Execution: Runs test scenarios with pass/fail tracking
- Verification: Checks responses and validates results
- Cleanup: Removes test data (collections, documents)
- Reporting: Prints summary with pass/fail counts
Example: How test_search.py Works
Let's walk through how the enhanced search test works:
def test_search():
"""Test search functionality with multiple scenarios"""
# 1. Initialize client
client = Client('http://localhost:9200')
tests_passed = 0
tests_failed = 0
# 2. Get or create test collection
collections = client.list_collections(0, 1)
collection_name = None
if collections.is_success():
body = collections.get_body()
if body.get('collections'):
collection_name = body['collections'][0]['name']
# 3. Create test collection if needed
if not collection_name:
collection_name = 'test_search_' + str(int(time.time()))
schema = {
'fields': [
{'name': 'title', 'type': 'string'},
{'name': 'content', 'type': 'string'},
{'name': 'category', 'type': 'string'},
{'name': 'price', 'type': 'float'}
]
}
client.collections_api().create(collection_name, schema)
# Add test documents
test_docs = [
{'id': 'doc1', 'title': 'Test Document One', ...},
{'id': 'doc2', 'title': 'Test Document Two', ...},
{'id': 'doc3', 'title': 'Sample Document', ...}
]
for doc in test_docs:
client.documents_api().add(collection_name, doc)
# 4. Run test scenarios
# Test 1: Basic search
search_params = {'q': 'test', 'query_by': 'title,content', 'limit': 10}
results = client.search(collection_name, search_params)
if results.is_success():
tests_passed += 1
else:
tests_failed += 1
# Test 2: Filtered search
search_params = {'q': '*', 'query_by': 'title', 'filter_by': 'category:test', 'limit': 5}
results = client.search(collection_name, search_params)
# ... validation ...
# Test 3-5: More scenarios...
# 5. Cleanup
if created_collection:
client.collections_api().delete(collection_name)
# 6. Summary
print(f"Search Test Summary: {tests_passed} passed, {tests_failed} failed")
Example: How test_bulk_operations.py Works
def test_bulk_operations():
"""Test bulk document operations"""
client = Client(BASE_URL)
# 1. Create test collection
collection_name = 'test_bulk_' + str(int(time.time()))
schema = {'fields': [{'name': 'title', 'type': 'string'}]}
client.collections_api().create(collection_name, schema)
# 2. Prepare bulk documents
bulk_docs = [
{'id': 'bulk1', 'title': 'Bulk Document 1'},
{'id': 'bulk2', 'title': 'Bulk Document 2'},
{'id': 'bulk3', 'title': 'Bulk Document 3'},
# ... more documents
]
# 3. Bulk import
import_result = client.documents_api().import_documents(collection_name, bulk_docs)
if import_result.is_success():
print(f"✓ Bulk imported {len(bulk_docs)} documents")
# 4. Verify import
documents = client.list_documents(collection_name, {'offset': 0, 'limit': 10})
# Check document count matches
# 5. Bulk delete by filter
delete_result = client.documents_api().delete_by_filter(collection_name, 'category:bulk')
# 6. Cleanup
client.collections_api().delete(collection_name)
Example: How test_error_handling.py Works
def test_error_handling():
"""Test error handling scenarios"""
client = Client(BASE_URL)
# Test 1: Get non-existent collection (should return 404)
result = client.get_collection('__nonexistent_collection__')
if not result.is_success() and result.get_status_code() == 404:
print("✓ Correctly returned 404 error")
tests_passed += 1
# Test 2: Get non-existent document (should return 404)
result = client.get_document(collection_name, '__nonexistent_doc__')
if not result.is_success() and result.get_status_code() == 404:
print("✓ Correctly returned 404 error")
tests_passed += 1
# Test 3: Create collection with invalid schema (should return 400/422)
invalid_schema = {'invalid': 'data'}
result = client.collections_api().create('test_invalid', invalid_schema)
if not result.is_success() and result.get_status_code() in [400, 422]:
print("✓ Correctly rejected invalid schema")
tests_passed += 1
Example: How test_edge_cases.py Works
def test_edge_cases():
"""Test edge cases"""
client = Client(BASE_URL)
# Test 1: Document with special characters
special_doc = {
'id': 'special_123',
'title': 'Test & Special <Characters> "Quotes"',
'content': "Content with 'apostrophes' and \"quotes\""
}
result = client.documents_api().add(collection_name, special_doc)
if result.is_success():
print("✓ Document with special characters created")
# Test 2: Empty string values
empty_doc = {'id': 'empty_123', 'title': '', 'content': ''}
result = client.documents_api().add(collection_name, empty_doc)
# Test 3: Large limit value
result = client.list_documents(collection_name, {'offset': 0, 'limit': 10000})
# Test 4: Zero limit
result = client.list_documents(collection_name, {'offset': 0, 'limit': 0})
Running Tests
Individual Test Execution
Run any test script directly:
# From the API directory
cd api/python/tests
python test_auth.py
# Or from project root
python api/python/tests/test_auth.py
Example Test Output
When you run a test, you'll see output like this:
----------------------------------------------------------------==============================
TEST: Search Functionality
----------------------------------------------------------------------
✓ Created test collection: test_search_1234567890
✓ Added 3 test documents
Using collection: test_search_1234567890
Test 1: Basic search
✓ Found 2 results
Test 2: Search with filters
✓ Filtered search found 2 results
Test 3: Search with sorting
✓ Sorted search successful
Test 4: Search with pagination
✓ Paginated search returned 2 results
Test 5: Wildcard search
✓ Wildcard search successful
✓ Cleaned up test collection: test_search_1234567890
----------------------------------------------------------------==============================
Search Test Summary: 5 passed, 0 failed
----------------------------------------------------------------==============================
Running All Tests
Use the test runner script to execute all tests:
# From the tests directory
python run_all_tests.py
# Or from project root
python api/python/tests/run_all_tests.py
The test runner provides:
- Sequential execution of all tests
- Pass/fail reporting for each test
- Summary statistics
- Total execution time
- Error details for failed tests
Example Test Runner Output
When you run run_all_tests.py, you'll see output like this:
----------------------------------------------------------------==============================
hlquery API Test Suite
----------------------------------------------------------------==============================
Found 26 test files
Running tests...
Running test_auth.py...
✓ PASSED (0.45s)
Running test_search.py...
✓ PASSED (1.23s)
Running test_bulk_operations.py...
✓ PASSED (0.89s)
Running test_synonyms.py...
✓ PASSED (0.67s)
Running test_stopwords.py...
✓ PASSED (0.52s)
Running test_overrides.py...
✓ PASSED (0.61s)
Running test_aliases.py...
✓ PASSED (0.48s)
Running test_facets.py...
✓ PASSED (0.55s)
Running test_export.py...
✓ PASSED (0.43s)
Running test_delete_collection.py...
✓ PASSED (0.38s)
Running test_update_collection.py...
✓ PASSED (0.42s)
Running test_error_handling.py...
✓ PASSED (0.51s)
Running test_edge_cases.py...
✓ PASSED (0.47s)
Running test_data_types.py...
✓ PASSED (0.58s)
Running test_pagination.py...
✓ PASSED (0.64s)
Running test_list_documents.py...
✓ PASSED (0.49s)
... (more tests)
----------------------------------------------------------------==============================
TEST SUMMARY
----------------------------------------------------------------==============================
Total Tests: 26
Passed: 26
Failed: 0
Total Time: 15.23s
----------------------------------------------------------------==============================
Detailed Test Examples
Example 1: Running test_auth.py
$ python api/perl/tests/test_auth.py
Output:
----------------------------------------------------------------==============================
TEST: Authentication with Bearer Token (Perl API)
----------------------------------------------------------------------
Health check without auth: 200
Set bearer token: test_tok...
Health check with bearer token: 200
Set API key: test_tok...
Health check with API key: 200
✓ Authentication test completed
What happened:
- Test created a client without authentication
- Made a health check request (succeeded)
- Set a bearer token and tested again (succeeded)
- Changed to API key authentication and tested (succeeded)
Example 2: Running test_bulk_operations.py
$ python api/php/tests/test_bulk_operations.py
Output:
----------------------------------------------------------------==============================
TEST: Bulk Operations (PHP API)
----------------------------------------------------------------------
✓ Created test collection: test_bulk_php_1234567890
Test 1: Bulk import documents
✓ Bulk imported 5 documents
Test 2: Verify bulk import
✓ Found 5 documents in collection
Test 3: Bulk delete by filter
✓ Bulk delete by filter successful
✓ Cleaned up collection: test_bulk_php_1234567890
----------------------------------------------------------------==============================
Bulk Operations Test Summary: 3 passed, 0 failed
----------------------------------------------------------------==============================
What happened:
- Created a test collection
- Imported 5 documents in one operation
- Verified all 5 documents were imported
- Deleted all documents matching a filter
- Cleaned up the test collection
Example 3: Running test_error_handling.py
$ python api/node/tests/test_error_handling.py
Output:
----------------------------------------------------------------==============================
TEST: Error Handling (Node.js API)
----------------------------------------------------------------------
Test 1: Get non-existent collection
✓ Correctly returned error: 404
Test 2: Get non-existent document
✓ Correctly returned error: 404
Test 3: Delete non-existent collection
✓ Correctly returned error: 404
Test 4: Create collection with invalid schema
✓ Correctly rejected invalid schema: 400
Test 5: Search with invalid parameters
✓ Search with invalid params handled: 400
----------------------------------------------------------------==============================
Error Handling Test Summary: 5 passed, 0 failed
----------------------------------------------------------------==============================
What happened:
- Tried to get a collection that doesn't exist → Got 404 (correct)
- Tried to get a document that doesn't exist → Got 404 (correct)
- Tried to delete a non-existent collection → Got 404 (correct)
- Tried to create collection with invalid schema → Got 400 (correct)
- Tried search with invalid parameters → Got 400 (correct)
Example 4: Running test_data_types.py
$ python api/perl/tests/test_data_types.py
Output:
----------------------------------------------------------------==============================
TEST: Data Types (Perl API)
----------------------------------------------------------------------
✓ Created test collection: test_datatypes_perl_1234567890
Test 1: String field
✓ String field handled
Test 2: Float field
✓ Float field handled
Test 3: String array field
✓ String array field handled
Test 4: Float array field (vector)
✓ Float array field handled
Test 5: Integer field
✓ Integer field handled
✓ Cleaned up collection: test_datatypes_perl_1234567890
----------------------------------------------------------------==============================
Data Types Test Summary: 5 passed, 0 failed
----------------------------------------------------------------==============================
What happened:
- Created collection with multiple field types (string, float, int, arrays)
- Tested each data type by inserting documents
- Verified all data types are handled correctly
- Cleaned up test collection
Test Interaction Examples
Example: How Tests Create and Clean Up Data
Most tests follow this pattern:
# 1. CREATE test data
collection_name = 'test_feature_' + str(int(time.time()))
client.collections_api().create(collection_name, schema)
# 2. USE test data
# ... perform operations ...
# 3. CLEANUP test data
client.collections_api().delete(collection_name)
Why this matters:
- Each test is independent
- No leftover data after tests
- Tests can run in any order
- Safe to run multiple times
Example: How Tests Track Pass/Fail
tests_passed = 0
tests_failed = 0
# Test scenario
result = client.some_operation()
if result.is_success():
print(" ✓ Operation successful")
tests_passed += 1
else:
print(f" ✗ Operation failed: {result.get_status_code()}")
tests_failed += 1
# At the end
print(f"Test Summary: {tests_passed} passed, {tests_failed} failed")
Benefits:
- Clear pass/fail indicators (✓ and ✗)
- Detailed error information
- Summary statistics
- Easy to see what failed
Real-World Test Scenarios
Scenario 1: Testing Search with Real Data
# Create collection with realistic schema
schema = {
'fields': [
{'name': 'title', 'type': 'string'},
{'name': 'description', 'type': 'string'},
{'name': 'price', 'type': 'float'},
{'name': 'category', 'type': 'string'},
{'name': 'tags', 'type': 'string[]'}
]
}
# Add realistic documents
products = [
{
'id': 'prod1',
'title': 'Wireless Headphones',
'description': 'High-quality wireless headphones with noise cancellation',
'price': 99.99,
'category': 'electronics',
'tags': ['audio', 'wireless', 'headphones']
},
# ... more products
]
# Test various search scenarios
# 1. Search by text
results = client.search(collection_name, {
'q': 'headphones',
'query_by': 'title,description',
'limit': 10
})
# 2. Filter by category
results = client.search(collection_name, {
'q': '*',
'query_by': 'title',
'filter_by': 'category:electronics',
'limit': 10
})
# 3. Sort by price
results = client.search(collection_name, {
'q': '*',
'query_by': 'title',
'sort_by': 'price:asc',
'limit': 10
})
Scenario 2: Testing Bulk Operations
# Prepare large batch of documents
bulk_docs = []
for i in range(100):
bulk_docs.append({
'id': f'doc_{i}',
'title': f'Document {i}',
'content': f'Content for document {i}',
'category': 'test'
})
# Import all at once
result = client.documents_api().import_documents(collection_name, bulk_docs)
# Verify all imported
documents = client.list_documents(collection_name, {'offset': 0, 'limit': 1000})
assert len(documents.get_body()['documents']) == 100
# Bulk delete by category
delete_result = client.documents_api().delete_by_filter(collection_name, 'category:test')
Scenario 3: Testing Error Handling
# Test 1: Invalid collection name
result = client.get_collection('')
assert not result.is_success()
assert result.get_status_code() in [400, 404]
# Test 2: Invalid document ID
result = client.get_document(collection_name, '')
assert not result.is_success()
assert result.get_status_code() in [400, 404]
# Test 3: Invalid schema
invalid_schema = {'not': 'valid'}
result = client.collections_api().create('test', invalid_schema)
assert not result.is_success()
assert result.get_status_code() in [400, 422]
# Test 4: Missing required fields
incomplete_doc = {'id': 'doc1'} # Missing required fields
result = client.documents_api().add(collection_name, incomplete_doc)
# May succeed or fail depending on schema requirements
Test Configuration
Base URL
All tests use a default base URL: http://localhost:9200
To test against a different server, modify the BASE_URL constant in each test file:
BASE_URL = 'http://your-server:9200'
Authentication
Tests can be configured to use authentication by modifying the test scripts or passing tokens via environment variables.
For tests that require authentication:
- Set the token in the test script
- Or modify the client initialization to include auth
Example:
client = Client(BASE_URL)
client.set_auth_token('your_token_here', 'bearer')
Test Best Practices
1. Test Isolation
Each test script is designed to be independent:
- Creates its own test data when needed
- Cleans up after itself
- Doesn't depend on other tests
2. Error Handling
Tests include comprehensive error handling:
- Graceful failure for missing collections
- Clear error messages
- Proper cleanup even on failure
3. Data Cleanup
Tests that create data automatically clean up:
- Test collections are deleted after testing
- Test documents are removed
- No leftover test data
4. Real-World Scenarios
Tests simulate real usage:
- Create collections with realistic schemas
- Insert documents with meaningful data
- Perform actual searches and operations
Integration with CI/CD
Running Tests in CI
Example GitHub Actions workflow:
name: API Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Start hlquery server
run: |
# Start your hlquery server
./hlquery --daemon
- name: Run tests
run: |
python api/python/tests/run_all_tests.py
- name: Stop server
run: |
# Stop hlquery server
pkill hlquery
Exit Codes
0: All tests passed1: One or more tests failed
This makes the test suite suitable for CI/CD pipelines.
Extending the Test Suite
Adding New Tests
To add a new test:
-
Create a new file:
test_new_feature.py -
Follow the existing test structure:
#!/usr/bin/env python3"""Test Description"""import sysimport ossys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))from lib import ClientBASE_URL = 'http://localhost:9200'def test_new_feature():"""Test description"""print("=" * 70)print("TEST: New Feature")print("-" * 70)client = Client(BASE_URL)# Your test code hereprint("✓ Test completed\n")if __name__ == '__main__':test_new_feature() -
Make it executable:
chmod +x test_new_feature.py -
The test runner will automatically include it
Test Naming Convention
- All test files start with
test_ - Use descriptive names:
test_feature_name.py - Use underscores, not hyphens
Troubleshooting
Common Issues
1. Import Errors
Problem: ModuleNotFoundError: No module named 'lib'
Solution: Ensure you're running from the correct directory or the test script has the correct path setup.
2. Connection Refused
Problem: Connection refused errors
Solution:
- Ensure hlquery server is running
- Check the
BASE_URLmatches your server address - Verify firewall settings
3. Authentication Failures
Problem: 401 Unauthorized errors
Solution:
- Check if your server requires authentication
- Set the correct token in the test script
- Verify token format (bearer vs api-key)
4. Collection Not Found
Problem: Tests fail because collections don't exist
Solution:
- Some tests create their own collections
- Others require existing collections
- Check test documentation for requirements
Test Coverage
The comprehensive test suite covers:
Core Functionality (Tests 1-12)
- Authentication (bearer tokens, API keys)
- Collection management (create, read, update, delete, list)
- Document operations (insert, update, delete, retrieve, list)
- Search operations (basic, filtered, sorted, paginated, wildcard)
- Vector search (similarity search with embeddings)
- Multi-collection search
- Health and monitoring endpoints
Advanced Features (Tests 13-21)
- Bulk document operations (import, delete by filter)
- Synonyms management (create, read, update, delete)
- Stopwords management (add, list, delete)
- Search overrides (create, read, delete)
- Collection aliases (create, read, delete)
- Facet counts and aggregation
- Document export
- Collection deletion with verification
- Collection schema updates
Error Handling & Edge Cases (Tests 22-26)
- Error handling (404, 400, 422 responses)
- Edge cases (special characters, empty values, boundaries)
- Data type validation (strings, floats, integers, arrays, vectors)
- Pagination scenarios (various offset/limit combinations)
- Document listing operations (all variations)
Additional Operations (Tests 27-31)
- Get individual documents by ID
- Server statistics and metrics (cache, connections, RocksDB, doctotal)
- Document import operations (single and bulk)
- Filter search operations (category, price range, multiple filters)
- Sort search operations (ascending, descending, multiple fields)
Test Statistics
Per API Directory:
- Python API: 31 test files (30 tests + 1 runner)
- Node.js API: 31 test files (30 tests + 1 runner)
- Perl API: 31 test files (30 tests + 1 runner)
- PHP API: 31 test files (30 tests + 1 runner)
- Node API: 31 test files (30 tests + 1 runner)
- C++ API: 31 test files (30 tests + 1 runner)
- Rust API: 31 test files (30 tests + 1 runner)
Total Test Coverage:
- 60+ API endpoints tested
- 180+ individual test scenarios
- Comprehensive error handling
- Edge case validation
- Data type verification
- Filter and sort operations
- Statistics and metrics
Test Suite by API
Python API Tests
The Python API includes 31 test files covering comprehensive functionality:
- All core functionality tests
- Advanced feature tests (bulk ops, synonyms, stopwords, etc.)
- Error handling and edge case tests
- Data type validation tests
- Pagination and listing tests
- Document retrieval tests
- Statistics and metrics tests
- Filter and sort search tests
Node.js API Tests
The Node.js API includes 31 test files covering comprehensive functionality:
- All core functionality tests
- Advanced feature tests (bulk ops, synonyms, stopwords, etc.)
- Error handling and edge case tests
- Data type validation tests
- Pagination and listing tests
- Document retrieval tests
- Statistics and metrics tests
- Filter and sort search tests
Perl, PHP, Node, C++, and Rust API Tests
These APIs include the most comprehensive test suite with 31 test files each:
- All core functionality tests
- Advanced feature tests (bulk ops, synonyms, stopwords, etc.)
- Error handling and edge case tests
- Data type validation tests
- Pagination and listing tests
- Document retrieval tests
- Statistics and metrics tests
- Filter and sort search tests
Running Tests for Different APIs
# Python API
python api/python/tests/run_all_tests.py
# Perl API
python api/perl/tests/run_all_tests.py
# PHP API
python api/php/tests/run_all_tests.py
# Node API
python api/node/tests/run_all_tests.py
# C++ API
python api/cpp/tests/run_all_tests.py
# Rust API
python api/rust/tests/run_all_tests.py
All test suites use the Python client library and can be run from any API directory.
Language-Specific Test Guides
- Perl Tests Guide - Complete guide to Perl API tests with examples and patterns
- PHP Tests Guide - Complete guide to PHP API tests with examples and patterns
- Python Tests Guide - Complete guide to Python API tests with examples and patterns
- Node.js Tests Guide - Complete guide to Node.js API tests with examples and patterns
Related Documentation
- API Overview - General API information
- Complete API Reference - All endpoints
- Testing Examples - Detailed examples and how tests work
- Testing Detailed Guide - Complete walkthroughs and deep dives
- Python Client - Python client documentation
- Node.js Client - Node.js client documentation
- PHP Client - PHP client documentation
Contributing
When adding new API features, please:
- Add corresponding test scripts
- Update this documentation
- Ensure tests pass before submitting PRs
- Follow existing test patterns and conventions
Support
For issues with the test suite:
- Check the troubleshooting section above
- Review test script comments
- Check server logs for detailed error messages
- Open an issue on the project repository