Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:The BMSview project employs a multi-faceted testing strategy that combines automated unit and integration tests, a comprehensive live production diagnostics suite, and manual post-deployment verification. The testing framework is built around Jest. While there is a stated policy to test against real services to ensure production parity, the codebase also contains a significant and well-developed infrastructure for mocking dependencies, particularly for unit and integration tests of complex modules.
This approach allows for fast, isolated feedback during development via mocked tests, while also providing robust validation against live systems through integration tests and a dedicated admin diagnostics tool. The strategy covers everything from individual statistical functions to end-to-end user workflows and production environment health checks.
Sources: TESTING.md, TESTING_INFRASTRUCTURE_SUMMARY.md, CONTRIBUTING.md:183-204, ADMIN_DIAGNOSTICS_GUIDE.md
Testing Philosophy: A Dual Approach
The project's documentation presents two contrasting testing philosophies, suggesting an evolving or hybrid strategy.
-
"No Mock Data" Policy: The
TESTING.mdfile explicitly states a policy of running all tests against real services (Gemini API, MongoDB) to achieve true production parity. It highlights the advantages of validating real API behavior and catching integration issues early.
Sources: TESTING.md:3-5 -
Extensive Mocking Infrastructure: In practice, the project heavily relies on a sophisticated mocking infrastructure. The
TESTING_INFRASTRUCTURE_SUMMARY.mddetails comprehensive test suites for modules like forecasting, data aggregation, and analytics, all of which usejest.mockto isolate components and mock dependencies like MongoDB. This is further evidenced by incomplete tests being blocked by a lack of necessary mock implementations.
Sources: TESTING_INFRASTRUCTURE_SUMMARY.md:121-139, 12-2-todo.md:27-31
This duality suggests a pragmatic approach:
- Unit/Component Tests: Use mocks for speed and isolation during local development.
- Integration/E2E Tests: Use real services to validate the complete system, especially in CI/CD and production environments.
Test Framework and Execution
The project uses Jest as its primary testing framework. Tests are executed via npm scripts.
| Command | Description |
|---|---|
npm test | Runs all tests. In some contexts, this is described as running all integration tests against real services. |
npm run test:watch | Runs tests in watch mode for a fast feedback loop during development. |
npm run test:coverage | Generates a test coverage report. |
Sources: CONTRIBUTING.md:184-186, TESTING.md:32-42
The following diagram illustrates the overall testing workflow.
This diagram shows the different stages of testing, from local development with specific, often mocked tests, to comprehensive automated testing in CI/CD, and finally to live diagnostics and manual checks in the production environment.
Sources: CONTRIBUTING.md:65-71, DEPLOYMENT_CHECKLIST.md:100-143, TESTING.md:44-54
Test Structure and Organization
Tests are organized within the tests/ directory and follow standard conventions.
- Location: All test files are located in the
tests/directory at the project root. - Naming: Test files use the
.test.jsextension. - Structure: Tests are structured using
describeblocks to group related tests andtest(orit) blocks for individual test cases. A common pattern is to usebeforeEachfor setup code.
Sources: CONTRIBUTING.md:190-192, tests/
Example Test Structure
describe('Feature Name', () => {
beforeEach(() => {
// Setup
});
test('should do expected behavior', () => {
// Arrange
const input = { ... };
// Act
const result = functionToTest(input);
// Assert
expect(result).toBe(expected);
});
});
Sources: CONTRIBUTING.md:194-209
Types of Tests
Unit and Integration Testing
The project has a comprehensive suite of unit and integration tests covering core business logic and data processing pipelines. These tests heavily utilize mocking to ensure isolation and performance.
Key Tested Modules:
forecasting.test.js: Covers statistical analysis functions likelinearRegression()andpredictCapacityDegradation().data-aggregation.test.js: Tests utilities for aggregating hourly and daily data.comprehensive-analytics.test.js: Validates load profiling, energy balance, and battery health assessments.pattern-analysis.test.js: Tests for daily/weekly pattern analysis and anomaly detection.integration-pipeline.test.js: End-to-end tests for the data pipeline from MongoDB to analytics.
Sources: TESTING_INFRASTRUCTURE_SUMMARY.md:8-60
Test Suite Statistics
The test suite is extensive, with a high pass rate reported.
| Metric | Value |
|---|---|
| Total Test Suites | 64 |
| Total Tests | 672 |
| Passing Tests | 624 |
| Skipped Tests | 47 |
| Failing Tests | 1 (pre-existing) |
| Pass Rate | 92.8% |
Sources: TESTING_INFRASTRUCTURE_SUMMARY.md:66-69
Production Testing: Admin Diagnostics
A key feature of the testing strategy is the Admin Diagnostics tool, a live production testing suite accessible via the /.netlify/functions/admin-diagnostics endpoint. It provides 27 comprehensive tests that validate every critical function of the live application.
Sources: ADMIN_DIAGNOSTICS_GUIDE.md:4-6
Admin Diagnostics Workflow
The following diagram shows how the Admin Diagnostics tool is used.
This flow illustrates how an administrator can trigger either a full suite or a selection of tests against the live production environment and receive a detailed report.
Sources: ADMIN_DIAGNOSTICS_GUIDE.md:11-27
Test Categories
The diagnostic tests are organized into logical categories.
| Category | Description | Number of Tests |
|---|---|---|
| Infrastructure | MongoDB connection, Gemini API health | 2 |
| Core Analysis | Main analysis endpoints (sync, async, processing) | 5 |
| Insights Generation | Standard and tool-based insights generation | 3 |
| Data Management | History, systems, data aggregation, and export | 4 |
| Job Management | Job status polling and background processing | 2 |
| External Services | Weather, solar, and system analytics integrations | 3 |
| Utility & Admin | Contact form, security, IP management, etc. | 7 |
| Comprehensive Suite | Integration with the production test suite | 1 |
Sources: ADMIN_DIAGNOSTICS_GUIDE.md:32-67, tests/admin-diagnostics.test.js:39-55
Manual and Post-Deployment Testing
In addition to automated tests, the project relies on manual verification after deployment to ensure features work as expected in the production environment. The deployment checklist includes specific steps for testing functions, verifying database indexes, and performing end-to-end workflow tests.
Post-Deployment Verification Steps:
- Verify functions are deployed and listed correctly.
- Check that database indexes have been created.
- Test critical API endpoints (
analyze,get-job-status) usingcurl. - Verify structured logs are appearing correctly.
- Confirm performance benchmarks are met (e.g., query times, response times).
- Perform an end-to-end test by uploading an image and verifying the result in the UI.
Sources: DEPLOYMENT_CHECKLIST.md:100-143, FINAL_REPORT_TASK_COMPLETION.md:173-190
Mocking Strategy
Despite the "No Mocks" policy in TESTING.md, mocking is a well-established pattern, especially for database interactions.
MongoDB Mocking Pattern
Tests frequently mock the getCollection utility to provide controlled data sets and prevent tests from hitting a real database.
// From tests/pattern-analysis.test.js, adapted from TESTING_INFRASTRUCTURE_SUMMARY.md
jest.mock('../netlify/functions/utils/mongodb.cjs');
const { getCollection } = require('../netlify/functions/utils/mongodb.cjs');
function createMockCollection(data = []) {
return {
find: jest.fn().mockReturnValue({
sort: jest.fn().mockReturnThis(),
toArray: jest.fn().mockResolvedValue(data)
}),
findOne: jest.fn().mockResolvedValue(null)
};
}
getCollection.mockImplementation((collectionName) => {
if (collectionName === 'history') {
return Promise.resolve(createMockCollection(historyData));
}
return Promise.resolve(createMockCollection());
});
This pattern allows tests to simulate database responses without requiring a live MongoDB connection, making them faster and more reliable.
Sources: TESTING_INFRASTRUCTURE_SUMMARY.md:121-139