Automated Testing Setup¶
Automated testing is crucial for maintaining the quality, stability, and security of the Gemforce platform across its smart contracts, cloud functions, and APIs. This document outlines the setup and best practices for implementing automated testing, ensuring continuous validation and rapid feedback on code changes.
1. Automated Testing Principles¶
- Shift Left: Integrate testing early in the development lifecycle.
- Comprehensive Coverage: Aim for high code coverage (though 100% is not always practical or beneficial).
- Fast Feedback: Tests should run quickly to provide developers rapid feedback.
- Reliability: Tests should be deterministic and produce consistent results.
- Maintainability: Tests should be organized, readable, and easy to update.
2. Smart Contract Automated Testing Setup¶
2.1. Tools and Frameworks¶
- Hardhat: A flexible development environment for compiling, deploying, testing, and debugging Ethereum software.
- Chai: A BDD/TDD assertion library for Node.js, commonly used with Hardhat for readable tests.
- Mocha: A feature-rich JavaScript test framework running on Node.js, used for structuring tests.
- ethers.js: A complete and compact JavaScript library for interacting with the Ethereum Blockchain and its ecosystem, used for contract interactions in tests.
- Solidity-coverage: Generates code coverage reports for Solidity contracts.
- Typechain: Automatically generates TypeScript typings for smart contracts, enhancing developer experience and reducing errors.
2.2. Test Directory Structure¶
contracts/
tests/
├── unit/ # Unit tests for individual contracts/facets
│ ├── MyContract.test.js
│ └── AnotherFacet.test.js
├── integration/ # Integration tests for inter-contract interactions
│ └── DiamondIntegration.test.js
└── scenarios/ # End-to-end user flow tests
└── UserFlow.test.js
2.3. Configuration (Hardhat)¶
hardhat.config.js:
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-ethers");
require("solidity-coverage");
require("@typechain/hardhat");
module.exports = {
solidity: {
version: "0.8.20", // or your contract's Solidity version
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
networks: {
hardhat: {
// Local development network configuration
},
// Other networks (sepolia, mainnet, etc.) can be configured here
},
paths: {
sources: "./contracts",
tests: "./tests", // Point to your test directory
cache: "./cache",
artifacts: "./artifacts",
},
typechain: {
outDir: "typechain", // Directory for generated typings
target: "ethers-v5", // or "web3-v1"
},
mocha: {
timeout: 100000, // Increase timeout for potentially long-running tests
}
};
2.4. Running Tests¶
- All tests:
npx hardhat test - Specific test file:
npx hardhat test tests/unit/MyContract.test.js - Coverage report:
npx hardhat coverage
3. Cloud Function and API Automated Testing Setup¶
3.1. Tools and Frameworks¶
- Jest: A delightful JavaScript Testing Framework with a focus on simplicity, often used for Node.js applications. Alternatives include Mocha/Chai.
- Supertest: A library for testing Node.js HTTP servers, used for making HTTP requests to API endpoints.
- MongoDB Test Data Setup: Mongoose for interacting with MongoDB, or direct MongoDB Node.js driver for test data setup/teardown.
- Mocking Libraries:
jest.mock,sinon(forMocha), ornockfor mocking external HTTP requests.
3.2. Test Directory Structure¶
cloud-functions/
├── src/
│ ├── auth/
│ │ └── authFunctions.js
│ └── trade-deal/
│ └── tradeDealFunctions.js
├── tests/
│ ├── unit/
│ │ ├── authFunctions.test.js # Unit tests for individual cloud functions
│ │ └── utilFunctions.test.js
│ └── integration/
│ └── TradeDealAPI.test.js # Integration tests for API endpoints
3.3. Configuration (Jest)¶
jest.config.js:
module.exports = {
testEnvironment: 'node',
setupFilesAfterEnv: ['./jest.setup.js'], // For global setup, e.g., connecting to test DB
testMatch: [
"**/tests/**/*.test.js", // Matches test files recursively
],
collectCoverage: true,
coverageDirectory: "coverage",
coveragePathIgnorePatterns: [
"/node_modules/",
],
forceExit: true, // Forces Jest to exit after tests complete
// Mocks any external dependencies with jest.mock
// example: moduleNameMapper: { 'axios': 'axios-mock-adapter' }
};
jest.setup.js: (Example for test DB setup)
const mongoose = require('mongoose');
const { MongoMemoryServer } = require('mongodb-memory-server');
let mongoServer;
beforeAll(async () => {
mongoServer = await MongoMemoryServer.create();
const uri = mongoServer.getUri();
await mongoose.connect(uri);
});
afterEach(async () => {
// Clear the database after each test
const collections = mongoose.connection.collections;
for (const key in collections) {
const collection = collections[key];
await collection.deleteMany();
}
});
afterAll(async () => {
await mongoose.disconnect();
await mongoServer.stop();
});
3.4. Running Tests¶
- All tests:
jestornpm test(if configured inpackage.json) - Specific test file:
jest tests/unit/authFunctions.test.js - Coverage report:
jest --coverage
4. Continuous Integration (CI) Setup¶
Integrate automated tests into your CI/CD pipeline (e.g., GitHub Actions, GitLab CI, Jenkins).
4.1. Example: GitHub Actions Workflow (.github/workflows/test.yml)¶
name: Run Tests
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
jobs:
smart-contract-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Hardhat dependencies
run: |
cd smart-contracts # Assuming your Hardhat project is here
npm install
- name: Run Hardhat tests
run: |
cd smart-contracts
npx hardhat test
cloud-function-api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Cloud Function dependencies
run: |
cd cloud-functions # Assuming your cloud functions project is here
npm install
- name: Run Jest tests
run: |
cd cloud-functions
npm test
By following these guidelines, the Gemforce development team can establish a robust, automated testing infrastructure that ensures high quality and security for all platform components.