# Windows - run all tests
.\test.ps1
# Linux / macOS - run all tests
./test.sh# Windows
.\test.ps1 python # Python fetcher tests
.\test.ps1 go # Go API + DB tests
.\test.ps1 frontend # Frontend Jest tests (requires Node.js)
.\test.ps1 backend # Python + Go (no frontend)
.\test.ps1 database # Python DB integration tests only
.\test.ps1 api # Go API handler tests only
.\test.ps1 e2e # E2E integration (builds server with test version + runs)# Linux / macOS
./test.sh python|go|frontend|backend|database|api|e2e| Suite | Framework | Tests | What it covers |
|---|---|---|---|
| Python fetcher | pytest | 127 | Feed parsing, config loading, adaptive tier logic, content cleaning, LanceDB integration |
| Migration | pytest | 7 | OPML export -> import round-trip (feeds, categories, hierarchy, idempotency) |
| DuckDB persistent | standalone | 7 | Persistent DuckDB process pool - validates the :memory: process approach for Windows reads (install, load, attach, rapid queries, performance comparison, pool round-robin, concurrent pool) |
| Go API | go test | 39 | All REST endpoints (feeds, articles, categories, mark read/star, pagination, status, server status) |
| Go DB | go test | 6 | SQL escaping, JSON field validation |
| Frontend | Jest + jsdom | 86 | HTML sanitization, relative time, feed activity, DOM structure, API patterns |
| E2E integration | standalone | ~290 checks | Full-stack: fetcher, server, every API endpoint, sanitization, logging, offline mode |
| Stress test | standalone | varies | Concurrency, rate limiting, security, chaos testing |
| Benchmark | standalone | - | Insert, sanitize, pipeline, and read performance |
The all build command runs tests after building:
# Full build with tests (default)
.\build.ps1 all
# Full build WITHOUT tests
.\build.ps1 -NoTests all./build.sh all # with tests
./build.sh --no-tests all # without tests| Suite | Requires |
|---|---|
| Python | Python 3.10+ with .venv set up (build.ps1 setup) |
| Migration | Python 3.10+ with .venv set up (same as Python) |
| Go | Go 1.21+, GCC/MinGW (Windows only, for CGo compilation) |
| Frontend | Node.js + npm (test-only dependency, not needed to run the app) |
If a required tool is missing, the test runner skips that suite with a [SKIP] message and continues.
The migration test (tests/python/test_opml_roundtrip.py) verifies that OPML export -> import preserves feeds, categories, hierarchy, and feed-category assignments. It also tests empty DB export and idempotent double-import.
# Windows
python -m pytest tests/python/test_opml_roundtrip.py -v
# Linux / macOS
python -m pytest tests/python/test_opml_roundtrip.py -vtests/python/test_duckdb_persistent.py validates the persistent DuckDB process approach planned for replacing the spawn-per-query pattern in lance_windows.go. It tests:
- One-shot
INSTALL lance(ensures extension is on disk) - Persistent
:memory:process withLOAD lance+ extension verification ATTACHdata directory and run real queries- Rapid-fire queries on a single process (20 queries)
- Performance comparison vs spawn-per-query (typically 15-23x speedup)
- Pool of 3 persistent processes with round-robin query distribution
- Concurrent queries via thread pool + DuckDB process pool (4 processes, 20 queries, 0 errors)
python tests/python/test_duckdb_persistent.pytests/e2e_test.py is a standalone script that exercises the full stack:
- Serves static RSS feeds via a local HTTP server
- Populates LanceDB using the Python fetcher
- Starts the real Go server against a temp database
- Hits every API endpoint (list, view, read, star, filter, paginate, sort)
- Verifies DB state via DuckDB CLI
- ~290 checks total
# Prerequisites: build the server and download DuckDB
.\build.ps1 server
.\build.ps1 duckdb
# Run E2E test
python tests/e2e_test.py
python tests/e2e_test.py --verbose # show HTTP details
python tests/e2e_test.py --keep # keep temp dir for debuggingThe e2e test supports --build-version <id> to verify the running server binary
matches the one that was just built. This catches stale binaries, accidental
overwrites from concurrent builds, and server crashes mid-test.
Automated (recommended):
# Windows -- generates a random test version, builds server, runs e2e
.\test.ps1 e2e
# Linux
./test.sh e2eManual:
# Windows
$env:BUILD_VERSION = "test-myid123"; .\build.ps1 server
python tests/e2e_test.py --build-version test-myid123
# Linux
BUILD_VERSION=test-myid123 ./build.sh server
python tests/e2e_test.py --build-version test-myid123The verification works as follows:
- Before any API tests run, queries
/api/server-statusand checksserver.build_version - If the version does not match, aborts with a message to rebuild
- After any test failures, re-checks the server version to detect:
- Server crash -- server unreachable, suggests rerunning the test
- Binary replaced -- version changed mid-test, warns about concurrent builds
======================================================================
Python Fetcher Tests
======================================================================
[PASS] test_config > TestConfigLoad::test_defaults
[PASS] test_config > TestConfigLoad::test_custom_values
[PASS] test_db > TestDBFeeds::test_add_feed
...
======================================================================
Go Server Tests
======================================================================
[PASS] api/TestListFeeds
[PASS] api/TestGetFeed
...
======================================================================
TEST SUMMARY
======================================================================
Suites: Python Fetcher Tests, Go Server Tests, Frontend Tests
Total: 265 tests
Passed: 265
ALL TESTS PASSED