Skip to main content

Testing Strategy

Table of Contents

Introduction

This testing strategy document is designed for test engineers and developers, systematically organizing and implementing Sparrow's testing methods, covering unit testing, integration testing, and end-to-end testing. It details the testing support of the dependency injection container, creation and usage of mock objects, test data preparation and cleanup, and provides testing examples for HTTP middleware, task scheduling, authentication and authorization, event bus, and messaging components. It also provides test coverage analysis, continuous integration configuration recommendations, automated testing process practices, as well as performance testing and security testing strategies.

Project Structure

Sparrow's tests are distributed across module sub-packages, following a "domain-driven" organization approach:

  • Dependency Injection and Application Lifecycle: bootstrap
  • HTTP Middleware: adapter/http/middlewares
  • Task Scheduling: tasks
  • Storage Repository: persistence/repo (badger, memory, etc.)
  • Event Bus and Messaging: eventbus, messaging
  • Configuration Loading: config
  • Authentication and Tokens: auth
  • Utilities: utils

The diagram below shows the distribution and responsibility mapping of test files in the code tree:

Core Components

  • Dependency Injection Container: Provides registration, named resolution, dependency injection, singleton behavior, error handling, and performance benchmarking capabilities.
  • Application Scheduler: Provides immediate, scheduled, and recurring task execution, task cancellation, retry, and concurrent/sequential strategies.
  • HTTP Middleware: JWT authentication and RSA client authentication, covering format validation, expiration, signature method mismatch, and other edge cases.
  • Repository Layer: CRUD, pagination, conditional queries, random retrieval, and existence checks for Badger and memory repositories.
  • Event Bus and Messaging: Publish-subscribe, multi-aggregate event handling, and graceful shutdown for memory bus and NATS JetStream bus.
  • Configuration Loading: .env and YAML configuration merging, default values, and invalid file error handling.
  • Authentication and Tokens: JWT generation, refresh, scope, and expiration time validation.
  • Utilities: Type name retrieval, entity sorting, and other auxiliary functions.

The diagram below shows key interactions from a testing perspective: test-driven application startup, container dependency resolution, middleware request interception, task scheduler execution, event bus/messaging system publish-subscribe, repository layer data persistence, configuration loading, and authentication token generation.

Detailed Component Analysis

Dependency Injection Container Testing

  • Registration and Resolution: Anonymous and named service registration, instance resolution, and resolution by name.
  • Dependency Injection: Container automatically resolves constructor function dependencies, validates injection chain.
  • Singleton Behavior: Multiple resolutions return the same instance.
  • Error Handling: Registering non-functions, no return values, resolving non-existent dependencies, passing nil or non-pointers, etc.
  • Complex Dependency Chains: Multi-layer struct dependency chain validation.
  • Performance Benchmarks: Container resolution performance benchmarking.
  • Custom Types: Supports registration and resolution of custom types like int, string, []string, etc.

Task Scheduler Testing

  • Immediate Tasks: RunTask executes immediately, validates execution status.
  • Scheduled Tasks: RunTaskAt executes at specified time, validates non-execution before time, execution at time.
  • Recurring Tasks: RunTaskRecurring repeats at intervals, validates cancellation and execution count.
  • Failure Retry: Task retries with exponential backoff after failure, validates attempt count.
  • Scheduler Types: Hybrid scheduler, single scheduler, concurrent/sequential strategies.
  • Task Type Strategy: Chooses concurrent or sequential execution by task type, validates execution order and timing differences.
  • Concurrent vs Sequential Comparison: Concurrent tasks start almost simultaneously at the same time, sequential tasks start one after another.

HTTP Middleware Testing

  • JWT Authentication: Missing Authorization, format error, invalid token, expired token, signature method mismatch, valid token.
  • Context User Information: Validates middleware writes user information to request context.
  • RSA Client Authentication: Missing header, invalid client ID, invalid signature, expired timestamp, configurable middleware, replay attack protection.

Task Scheduler Implementation Testing

  • Concurrent Scheduler: Maximum concurrent limit, concurrent execution, task status query, cancel non-existent task.
  • Sequential Scheduler: Tasks execute serially in submission order.
  • Hybrid Scheduler: Chooses concurrent or sequential execution by task type.
  • Retry Mechanism: Default retry count, exponential backoff, early success termination.
  • Timeout Control: Context-based timeout, task status is failed or cancelled.
  • Wrapper Functions: RunTaskWithID, RunTypedTaskWithID, GetTaskStatus, ListTasks, CancelTask, RunTaskAt, RunTaskRecurring.

Repository Layer Testing

  • Badger Repository: Save/update/delete/find, batch operations, pagination, conditional queries, counting, random retrieval, existence checks.
  • Memory Repository: Same as above, but based on memory storage, suitable for quick testing and concurrent stress testing.
  • Error Paths: Empty ID, non-existent entity, empty parameters, etc.

Event Bus and Messaging Testing

  • Memory Event Bus: Subscribe/publish, multiple subscribers, unsubscribe, close bus, statistics, handler timeout and error handling.
  • NATS JetStream: TestContainers starts NATS, creates stream, publishes/subscribes to multi-aggregate events, validates event type and aggregate ID consistency.
  • JetStream Publish-Subscribe: Publisher/Subscriber and EventSubscriber collaboration, publishes aggregate uncommitted events, validates field consistency.

Configuration Loading Testing

  • .env and YAML Merging: Validates loading process, default values, invalid file error handling.
  • No .env File: Validates default values take effect.
  • Invalid .env File: Validates error handling.

Authentication and Token Testing

  • Token Generator: Create generator, generate JWT and token pairs, refresh tokens, invalid token handling, custom expiration time.
  • JWT and Refresh: Access token and refresh token parsing, scope and expiration time validation, content consistency after refresh.

Utility Testing

  • Type Name Retrieval: Type name assertions for basic types, structs, pointers, slices, maps.
  • Entity Sorting: Sort by creation time, field ascending/descending order, sorting entities without timestamps.

Dependency Analysis

  • Test Coupling and Cohesion: Module tests are relatively independent, decoupled through public interfaces (like event bus interface, repository interface).
  • External Dependencies: NATS, Badger, JWT, TestContainers, etc., isolated through containers or memory implementations in tests.
  • Circular Dependencies: No direct circular dependencies found, tests avoid coupling through interface abstraction.
  • Interface Contracts: Event bus, message publish-subscribe, task scheduler all have clear interface contracts, easy to replace implementations.

Performance Considerations

  • Container Resolution Performance: Provides benchmark tests for evaluating container resolution overhead.
  • Task Scheduling Concurrency: Balances throughput and consistency through maximum concurrent limits and sequential strategies.
  • Event Bus: Memory bus suitable for local testing, NATS JetStream suitable for integration testing and end-to-end testing.
  • Repository Layer: Badger suitable for persistence testing, memory repository suitable for high-concurrency stress testing.
  • Timeout and Retry: Reasonably set task timeout and retry strategies to avoid resource leaks and cascading failures.

Troubleshooting Guide

  • Container Errors: Registering non-functions, no return values, resolving non-existent dependencies, passing nil or non-pointers all trigger clear error messages.
  • JWT Middleware: Missing header, format error, invalid token, expired token, signature method mismatch all have corresponding assertions.
  • RSA Client Authentication: Missing header, invalid client ID, invalid signature, expired timestamp, replay attack protection.
  • Task Scheduling: Failure retry, task cancellation, scheduled/recurring tasks, concurrent/sequential strategy exceptions.
  • Event Bus: Publish/subscribe/unsubscribe fails after closing; handler returning error doesn't affect publishing; invalid event data error handling.
  • Configuration Loading: .env and YAML merging, default values, invalid file error handling.

Conclusion

Sparrow's testing system covers the entire testing chain from underlying containers, task scheduling, HTTP middleware to event bus and messaging systems, combining memory and external dependencies (NATS, Badger) to achieve unit, integration, and end-to-end testing collaboration. Through clear interface contracts, comprehensive error handling, and benchmark testing, it ensures system stability and maintainability during development and operations. It is recommended to introduce coverage statistics and automated testing pipelines in CI to continuously improve quality gates and delivery efficiency.

Appendix

  • Test Coverage Analysis: Recommend using Go's built-in coverage tool and third-party platforms (like Codecov) to generate reports in CI and set thresholds.
  • Continuous Integration Configuration: Execute unit tests, integration tests (including TestContainers), and end-to-end tests in CI, with separate timeout and retry strategies.
  • Automated Testing Process: Layered execution (unit → integration → end-to-end), fast failure feedback, retain test logs and artifacts.
  • Performance Testing: Benchmark and stress testing for container resolution, task scheduling, event bus, and messaging systems.
  • Security Testing: Focus on validating JWT and RSA authentication boundary conditions, replay attack protection, timeout and retry security.