Couchbase TestRunner is a Python-based integration test framework for Couchbase Server. It validates 8+ services (KV, Query/N1QL, GSI, FTS, Eventing, Analytics, Backup, XDCR) against on-premises clusters, cluster_run sandboxes, and cloud deployments (Capella, AWS, Azure).
# Single test with cluster_run (requires ../ns_server/)
./testrunner -i b/resources/dev.ini -t setgettests.MembaseBucket.value_100b
# Suite execution with cluster setup
python3 scripts/start_cluster_and_run_tests.py MAKE <ini_file> <conf_file> <VERBOSE> <DEBUG>
# Service-specific make targets
make e2e-kv-single-node # KV smoke (1-node cluster_run)
make test-gsi-integrations-tests PARAMS=... # GSI (4-node, n1ql+gsi services)
make test-fts # FTS (4-node, fts service)
make test-eventing-sanity-tests # Eventing (4-node)
make test-viewquery # Views (4-node)
make test-xdcr-merge # XDCR (4-node)
# Flexible execution
make any-test NODES=<ini_file> TEST=<test>
make any-suite NODES=<ini_file> SUITE=<conf_file>
# Dependencies
pip3 install -r requirements.txt
make init-submodules # java_sdk_client, lib/capellaAPI, magma_loader/DocLoader, gsi_utils| Path | Description |
|---|---|
pytests/ |
Test suites by service: gsi/ (65), tuqquery/ (120+), fts/, eventing/, xdcr/, security/, cbas/, backup/ |
conf/ |
147 test suite configs + 28 service subdirectories |
lib/ |
Framework core: membase/api/ (REST), remote/ (SSH), couchbase_helper/, tasks/, Cb_constants/ |
scripts/ |
Orchestration: start_cluster_and_run_tests.sh/.py, install.py, cloud_provision.py, dispatchers |
b/resources/ |
153 cluster INI templates (topology, credentials, services) |
testrunner.py |
Main CLI entry point (47KB) |
Makefile |
Service-specific make targets |
Test inheritance: pytests/basetestcase.py -> service base (e.g., gsi/base_gsi.py) -> test module
- Python: 3.10.13 (migrated from Python 3.7.6)
- Python 3.10 Migration Notes:
- Use Python 3.10+ compatible APIs throughout the codebase
- All tests are integration tests requiring a running Couchbase cluster
- cluster_run needs
../ns_server/sibling directory built viamake - Working directory must be project root for imports (
lib/,pytests/on sys.path) - No linting or type checking configured (no flake8, pylint, mypy, ruff, black)
- No CI/CD pipeline visible in the repo (no
.github/, Jenkinsfile, or.gitlab-ci.yml) - No pytest.ini or tox.ini; framework uses custom
testrunner.pyrunner based onpytest - Tests create
tmp-<timestamp>/directories with logs and xunit XML reports (not auto-cleaned) - INI files define cluster topology; conf files define test suites and parameters
Before completing changes:
- Framework changes:
make e2e-kv-single-node - Query/GSI changes:
make test-gsi-integrations-tests - Service-specific changes: run the matching make target or conf file
- Verify
tmp-<timestamp>/contains xunit XML and test logs - Check pass/fail summary in test runner output
Code quality rules:
- Follow existing naming patterns in
pytests/(e.g.,gsi/plasma_basic_ops.py) - Reuse base classes and
lib/helpers; do not reinvent - Match the coding style of surrounding code
Never commit:
- INI files with real cluster IPs, credentials, or SSH keys (use templates in
b/resources/) - API keys, tokens, or cloud credentials
- Test logs containing cluster data
Sensitive operations:
scripts/install.py-- installs Couchbase on remote machines via SSHscripts/cloud_provision.py-- manages cloud infrastructure, requires cloud credentialspytests/security/-- RBAC, LDAP, SSL, x.509 tests needing special cluster configs
- No documented CI/CD pipeline; tests appear to be triggered externally
- No linting or formatting standards enforced
cluster_runsetup requirements beyond../ns_server/are undocumented
docs/architecture.agents.md-- module boundaries and runtime flowsdocs/agent-context/repo-inventory.md-- languages, packages, key directoriesdocs/agent-context/build-test-matrix.md-- exact validation commands per servicedocs/agent-context/domain-glossary.md-- Couchbase services, test types, terminologydocs/agent-context/troubleshooting.md-- common cluster_run and test execution failuresdocs/tools/AGENTS.md-- dispatcher SDK tools and installer index (task routing for agents)docs/elastic_search/AGENTS.md-- Elasticsearch integration for FTS query validationpytests/upgrade/AGENTS.md-- upgrade test framework detailed contextpytests/eventing/AGENTS.md-- eventing test framework detailed context
This repository uses git submodules for specialized components. When working with code that spans these submodules, use conditional logic to route work to the appropriate repository.
| Submodule | Path | Repository | Purpose |
|---|---|---|---|
| java_sdk_client | java_sdk_client/ |
github.com/couchbaselabs/java_sdk_client | Java SDK client for multi-language testing |
| capellaAPI | lib/capellaAPI/ |
github.com/couchbaselabs/CapellaRESTAPIs | Capella (cloud) REST API clients |
| DocLoader | magma_loader/DocLoader/ |
github.com/couchbaselabs/DocLoader.git | High-performance document loading for Magma storage |
| gsi_utils | gsi_utils/ |
github.com/couchbaselabs/gsi_utils.git | GSI utilities and helper functions |
Initialize submodules before development:
make init-submodules
# OR
git submodule init && git submodule update --init --force --remoteUpdate existing submodules to latest:
make update-submodules
# OR
git submodule update --init --force --remoteWhen working with code that spans submodules, use conditional logic to route to the appropriate repository:
import os
def route_to_repository(task):
"""
Determine which repository should handle the given task
Args:
task (str): Description of the code work needed
Returns:
str: Repository/submodule path where work should be done
"""
task_lower = task.lower()
# Java SDK Client routing
if any(keyword in task_lower for keyword in [
'java sdk', 'javaclient', 'java_client',
'sdk client java', 'couchbase java sdk',
'java sdk client', 'multilanguage testing'
]):
return 'java_sdk_client'
# Capella REST API routing
elif any(keyword in task_lower for keyword in [
'capella api', 'capellarestapi', 'capella rest',
'cloud api', 'managed cloud', 'dbaas',
'lib/capellaapi', 'capella rest client'
]):
return 'lib/capellaAPI'
# DocLoader routing (Magma storage)
elif any(keyword in task_lower for keyword in [
'docloader', 'document loader', 'magma loader',
'magma document loading', 'high-performance loading',
'doc generator', 'magma_loader/docloader',
'document generation', 'magma doc loader'
]):
return 'magma_loader/DocLoader'
# GSI Utilities routing
elif any(keyword in task_lower for keyword in [
'gsi utilities', 'gsi_utils', 'gsi helper',
'global secondary index utilities', 'gsi base class',
'gsi utility functions'
]):
return 'gsi_utils'
# Default to main testrunner repository
else:
return 'testrunner'
# Example usage
if __name__ == "__main__":
while True:
user_task = input("Enter task description (or 'quit' to exit): ")
if user_task.lower() in ['quit', 'exit']:
break
repo_path = route_to_repository(user_task)
print(f"\nNavigate to: {repo_path}/")
print(f"\nTo initialize submodules if needed:")
print(f" cd testrunner")
print(f" make init-submodules")
print(f" cd {repo_path}")
print()# Example 1: Routing documentation work
task = "Update Java SDK client for new SDK version"
repo = route_to_repository(task)
print(f"Work in: {repo}") # Output: Work in: java_sdk_client
# Example 2: Routing bug fixes
task = "Fix Capella REST API authentication issue"
repo = route_to_repository(task)
print(f"Work in: {repo}") # Output: Work in: lib/capellaAPI
# Example 3: Routing feature requests
task = "Add high-performance document loading for Magma"
repo = route_to_repository(task)
print(f"Work in: {repo}") # Output: Work in: magma_loader/DocLoader- Identify the scope first: Determine which repository owns the code before starting work
- Navigate to submodule: Change directory to the appropriate submodule before making changes
- Test in context: Run tests within the submodule's own testing framework when applicable
- Document cross-module dependencies: If changes affect multiple submodules, document the relationships
- Keep submodules synchronized: Always ensure submodules are up-to-date before committing changes
# Example workflow for Java SDK client work
cd testrunner
git submodule update --init --force --remote
cd java_sdk_client
# Make changes to java_sdk_client files
cd ..
git add java_sdk_client
git commit -m "Update Java SDK client for XYZ feature"