Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:
The OnChainSage project employs a multi-layered testing strategy to ensure the reliability and correctness of its various components, including the NestJS backend, the Python data processing pipelines, and the Starknet smart contracts. The strategy encompasses unit, integration, and end-to-end (E2E) tests, utilizing frameworks appropriate for each technology stack. This ensures that individual functions, service interactions, and the application as a whole behave as expected.
Contributors are expected to write and maintain tests for their changes, ensuring that all tests pass before submitting a pull request. The project provides a suite of scripts and configurations to streamline the testing process across its different applications.
Sources: CONTRIBUTING.md:38-39, apps/backend/README.md:92-102, ARCHITECTURE.md:104-109
Backend Testing (NestJS)
The backend, built with NestJS, uses Jest as its primary testing framework for unit, integration, and E2E tests.
Sources: apps/backend/README.md:20, apps/backend/package.json:84-95
Configuration and Scripts
Testing is configured in jest.config.ts and executed via npm scripts defined in package.json.
Jest Configuration
The core Jest configuration specifies the test environment, file patterns, and code transformation.
| Key | Value | Description |
|---|---|---|
moduleFileExtensions | ["js", "json", "ts"] | Specifies the file extensions Jest will look for. |
rootDir | "src" | Sets the root directory for tests to the src folder. |
testRegex | ".*\\.spec\\.ts$" | A regex pattern to detect test files (any file ending in .spec.ts). |
transform | `{"^.+\.(t | j)s$": "ts-jest"}` |
collectCoverageFrom | `["**/*.(t | j)s"]` |
coverageDirectory | "../coverage" | The directory where coverage reports will be generated. |
testEnvironment | "node" | Specifies that tests will run in a Node.js environment. |
Sources: apps/backend/jest.config.ts
Test Scripts
The apps/backend/package.json file defines several scripts for running different types of tests.
| Script | Command | Description |
|---|---|---|
test | jest | Runs all unit and integration tests (.spec.ts). |
test:watch | jest --watch | Runs tests in watch mode, re-running on file changes. |
test:cov | jest --coverage | Runs tests and generates a code coverage report. |
test:e2e | jest --config ./test/jest-e2e.json | Runs end-to-end tests located in the test/ directory. |
Sources: apps/backend/package.json:11-15
Unit Testing
Unit tests focus on individual services, controllers, or providers in isolation. The @nestjs/testing package is used to create a testing module that mocks dependencies, allowing for focused testing of a single unit.
The following diagram illustrates the typical setup for a service unit test, where dependencies like repositories and other services are replaced with mock implementations.
This diagram shows how a test module is created with the actual service and its mocked dependencies to isolate the unit under test.
Sources: apps/backend/src/social-engagement-module/social-engagement/social-engagement.service.spec.ts:16-41
Example: SocialEngagementService Unit Test
In social-engagement.service.spec.ts, the SocialEngagementService is tested.
- Mocks:
SocialEngagementRepository,EventEmitter2, andRateLimiterServiceare provided as mock objects withjest.fn()to simulate their behavior. - Test Module:
Test.createTestingModulecompiles a module with the actualSocialEngagementServiceand its mocked dependencies. - Test Cases: Each
describeblock tests a specific method (e.g.,createEngagement,removeEngagement). - Assertions:
expectis used to verify that the service calls its dependencies correctly and returns the expected result. For instance, it checks ifrateLimiter.checkLimitandmockRepository.createOrUpdateEngagementare called with the correct arguments.
Sources: apps/backend/src/social-engagement-module/social-engagement/social-engagement.service.spec.ts
End-to-End (E2E) Testing
E2E tests verify the behavior of the application as a whole by making live HTTP requests to its endpoints. The supertest library is used for this purpose.
Example: Rate Limiting E2E Test
The rate-limit.e2e-spec.ts file tests the application's rate-limiting functionality.
- Test Application Setup: An
INestApplicationinstance is created usingTest.createTestingModule. This setup includes the mainAppModuleand a special configuration for the test environment, such as an in-memory SQLite database and restrictiveThrottlerModulesettings (limit: 2). - HTTP Requests:
supertest(request(app.getHttpServer())) is used to send a series of requests to protected endpoints. - Assertions: The test asserts that the first two requests succeed (status code is not 429) and the third request is blocked with a
429 Too Many Requestsstatus. It also tests that different users (identified by IP or a wallet address header) have separate rate limits.
Sources: apps/backend/test/rate-limit.e2e-spec.ts:12-42, apps/backend/test/rate-limit.e2e-spec.ts:69-100
The sequence diagram below shows the flow of an E2E test that exceeds the rate limit.
This diagram illustrates how supertest makes repeated requests until the rate limit is hit, triggering a 429 response from the application.
Sources: apps/backend/test/rate-limit.e2e-spec.ts:58-68, apps/backend/src/middleware/rate-limit.middleware.spec.ts:79-106
Data Processing Testing (Python)
The Python data processing layer uses pytest for testing. The code is structured into modular, often pure, functions that are easy to test in isolation.
Sources: ARCHITECTURE.md:107
Example: forum_pipeline.py
This script demonstrates a testable data processing pipeline. Although a formal pytest file is not provided in the context, the structure of forum_pipeline.py is designed for testability.
- Modular Functions: The pipeline is broken down into small, single-responsibility functions like
parse_forum_call,get_current_price, andcompute_profitability. - Dummy Data and Mocks: The
get_current_priceandget_sentiment_scorefunctions use hardcoded dummy data, which is a common practice for unit testing pipelines without making external API calls. Thesend_to_signal_systemfunction logs the data instead of making a real HTTP request, simulating the interaction with another service. - Testable Entry Point: The
if __name__ == "__main__":block provides a simple way to run and manually test the entire pipeline with an example input.
Sources: apps/data-processing/processors/forum_pipeline.py:9-35, apps/data-processing/processors/forum_pipeline.py:107-110
The flowchart below visualizes the logic within the process_forum_call function.
This diagram shows the step-by-step execution of the data processing pipeline for a forum call.
Sources: apps/data-processing/processors/forum_pipeline.py:83-105
Dojo (Starknet) Testing
The Starknet smart contracts, built with the Dojo framework, have their own dedicated testing setup. The project uses both Dojo's native testing tools and Starknet Foundry.
Sources: apps/dojo/README.md:26-31
Tooling and Scripts
Testing is managed through a combination of sozo, snforge, and shell scripts.
| Command | Description |
|---|---|
./scripts/test.sh | A convenience script that runs all available tests. |
sozo test | Runs the test suite using Dojo's built-in test runner. |
snforge test | Runs tests using Starknet Foundry, an alternative testing framework. |
Sources: apps/dojo/README.md:62-68
The development workflow involves building the contracts with sozo build before running the tests. For local development, a Katana node (local Starknet devnet) is used to deploy and test contracts in a simulated environment.
Sources: apps/dojo/README.md:56-59, apps/dojo/README.md:78-84