Last Updated: 4/7/2026
Testing Guide
Agricultural Microworlds uses Jest as its testing framework to ensure code quality and maintain the Sprint 5 goal of 90%+ test coverage. This guide walks you through running tests, understanding the existing test structure, checking coverage, and writing new unit tests.
Prerequisites
Before running tests, ensure you have:
- Node.js and npm installed (handled automatically in the devcontainer)
- Dependencies installed via
npm installin theagricultural-microworlds.client/directory - Babel configured for ESM module transformation (already set up in
babel.config.js)
Running Tests
To run all tests in the project:
cd agricultural-microworlds.client
npm run testThis command executes Jest, which will discover and run all test files in the tests/ directory.
Checking Test Coverage
To generate a coverage report and verify you’re meeting the 90%+ coverage goal:
npm run test -- --coverageJest will output a detailed coverage report showing:
- Statements: Percentage of code statements executed
- Branches: Percentage of conditional branches tested
- Functions: Percentage of functions called
- Lines: Percentage of code lines covered
The coverage report also identifies which files need additional test coverage.
Existing Test Structure
Currently, the test suite focuses on core simulation data structures. All test files are located in the tests/ directory.
| Test File | Coverage Area | Purpose |
|---|---|---|
BitmapFieldState.test.js | BitmapFieldState class | Tests the binary array abstraction layer used for efficient field tile storage, including initialization, cloning, variable management, and tile access methods |
What Is Currently Tested
The existing test suite validates:
- Field State Initialization: Correct creation of typed arrays (Uint8Array, Float32Array) for tile properties
- Field Initialization: Proper population of all tiles with starting values
- Cloning: Deep copy functionality for field states
- Dynamic Variable Addition: Adding new properties to the field state at runtime
- Tile Manipulation: Setting and getting individual tile properties
- Variable Access: Reading and writing specific variables at tile coordinates
Writing a New Unit Test
To add a new test, create a .test.js file in the tests/ directory. Here’s the structure based on the existing test suite:
Example Test Structure
import BitmapFieldState from "../src/BinaryArrayAbstractionMethods/BitmapFieldState";
import {
CROP_GDDS,
CROP_STAGES,
CROP_TYPES,
} from "../src/States/StateClasses/CropState";
function CreateFieldState(rows, cols) {
const tileKey = {
["stage"]: {
size: 1,
type: "uint8",
},
["type"]: {
size: 1,
type: "uint8",
},
["currentGDD"]: {
size: 4,
type: "float32",
},
["requiredGDD"]: {
size: 4,
type: "float32",
},
["waterLevel"]: {
size: 4,
type: "float32",
},
["minerals"]: {
size: 4,
type: "float32",
},
};
return new BitmapFieldState(rows, cols, tileKey);
}
test("Initialization creates the correct arrays and values", () => {
const rows = 10;
const cols = 10;
const test = CreateFieldState(rows, cols);
const buffer1 = new ArrayBuffer(rows * cols * 1);
const array1 = new Uint8Array(buffer1);
expect(test.fieldProps["stage"]).not.toEqual(null);
expect(test.fieldProps["stage"]).not.toEqual(undefined);
expect(test.fieldProps["stage"].arr).toBeInstanceOf(Uint8Array);
});Test Writing Best Practices
- Import Dependencies: Import the module under test and any required constants or utilities
- Use Descriptive Test Names: Clearly describe what behavior is being tested
- Arrange-Act-Assert Pattern: Set up test data, execute the function, verify the result
- Test Edge Cases: Include tests for boundary conditions, empty inputs, and error states
- Isolate Tests: Each test should be independent and not rely on other tests
Common Jest Matchers
expect(value).toEqual(expected): Deep equality checkexpect(value).not.toEqual(unexpected): Negationexpect(array).toBeInstanceOf(ArrayType): Type checkingexpect(value).toBe(expected): Strict equality (===)expect(fn).toThrow(): Function throws an error
Babel Configuration for ESM Modules
Agricultural Microworlds uses ES modules ("type": "module" in package.json), which require Babel transformation for Jest. The babel.config.js file configures this:
export default {
presets: [["@babel/preset-env", { targets: { node: "current" } }]],
};This preset transforms modern JavaScript features to work with the current Node.js version during testing. The configuration is already set up and should not require modification for standard test cases.
Next Steps for Test Coverage
To reach the 90%+ coverage goal, consider adding tests for:
- Simulation Managers: WeatherManager, CropGrowthManager, WorkerManager
- State Classes: CropState, WeatherState, WorkerState
- Blockly Integration: Custom block definitions and code generation
- Rendering Pipeline: Canvas rendering and sprite management
- Command System: Worker command execution and validation
Run npm run test -- --coverage regularly to identify untested code paths and prioritize test development.
What’s Next
- Simulation Managers: Learn about the manager classes that orchestrate simulation behavior — great sources for new test targets
- State Management System: Understand how simulation state is structured and updated
- Creating Custom Blocks: Extend the Blockly interface with new programming blocks