Implementing Testing Workflows
1. Running Unit Tests
| Property | Description | Example |
|---|---|---|
| uses | Specifies the action to run, e.g., actions/checkout@v4 |
uses: actions/checkout@v4 |
| with | Parameters to pass into the action | with: token: ${{ secrets.GITHUB_TOKEN }} |
| steps | List of steps to run in the workflow | steps: - name: Run tests |
Example: Running Unit Tests with Jest
name: Run Unit Tests
on:
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
Note: Ensure your project's
package.json includes a test script like "test": "jest".
2. Running Integration Tests
| Property | Description | Example |
|---|---|---|
| jobs.<job_id>.steps | Defines the steps to run in a job, including integration tests. | |
| jobs.<job_id>.steps.run | Command to execute for running tests. | npm run test:integration |
| jobs.<job_id>.steps.env | Environment variables for test execution. | |
Example: Running Integration Tests in a Workflow
name: Integration Tests
on:
push:
branches: [ main ]
jobs:
integration-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run integration tests
run: npm run test:integration
env:
NODE_ENV: test
DATABASE_URL: ${{ secrets.DATABASE_URL }}
Note: Ensure that your integration tests are isolated and do not interfere with other test suites or production systems.
3. Running E2E Tests
| Option | Values | Description |
|---|---|---|
| uses | actions/checkout@v4 |
Checks out your repository code |
| uses | actions/setup-node@v4 |
Sets up Node.js environment |
| with.node-version | 20 |
Version of Node.js to use |
| run | npm install |
Installs project dependencies |
| run | npm run test:e2e |
Runs end-to-end tests |
Example: E2E Test Workflow
name: E2E Tests
on:
push:
branches: [ main ]
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm install
- run: npm run test:e2e
Note: Ensure your E2E tests are configured to run in a headless browser environment.
4. Generating Test Coverage
| Option | Values | Description |
|---|---|---|
| jest --coverage | true |
Enables coverage reporting in Jest |
| coverageDirectory | coverage |
Directory where coverage reports are stored |
| collectCoverageFrom | ["src/**/*.{js,ts}"] |
Patterns to include in coverage report |
Note: Coverage reports are generated in
coverage/lcov-report/index.html by default.
Example: Configuring coverage thresholds
{
"coverageThreshold": {
"global": {
"branches": 80,
"functions": 80,
"lines": 80,
"statements": 80
}
}
}
Test Coverage Tools Comparison
- Jest: Built-in coverage support, easy to configure
- Istanbul : Low-level coverage tool used by Jest and other tools
- C8: Simple, fast coverage tool for Node.js
5. Uploading Coverage Reports
Example: Upload coverage report to Codecov
name: Test and Upload Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests with coverage
run: npm run test -- --coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
| Property | Description | Default |
|---|---|---|
| file | Path to the coverage report file (e.g., coverage/lcov.info) |
./coverage/lcov.info |
| flags | Upload flags to categorize the report (e.g., unit, e2e) |
None |
| name | Custom name for the upload (optional) | None |
| token | Codecov upload token (optional, but recommended for private repos) | None |
Note: Ensure your test command outputs coverage data in a supported format (e.g.,
lcov, cobertura) for successful upload.
Warning: If
token is not provided, the upload will fail for private repositories.
6. Running Linters
| Tool | Configuration | Notes |
|---|---|---|
| ESLint | eslint --fix |
Automatically fixes fixable linting errors |
| Prettier | prettier --write . |
Formats code according to style guide |
| Stylelint | stylelint "**/*.css" --fix |
Lints CSS files for style issues |
Example: ESLint Configuration
{
"extends": ["eslint:recommended"],
"rules": {
"no-console": "warn",
"semi": ["error", "always"]
}
}
Workflow Steps for Linting
- Install dependencies using
npm install - Run linter checks with
npm run lint - Fix any issues reported by the linter
Note: Ensure that linting runs before tests to maintain code quality standards.
7. Running Code Formatters
| Formatter | Command | Notes |
|---|---|---|
| Prettier | npx prettier --write . |
Formats JavaScript, TypeScript, CSS, HTML, and more |
| ESLint | npx eslint . --fix |
Fixes linting issues automatically |
| Black | black . |
Python code formatter |
| gofmt | gofmt -w . |
Go code formatter |
Example: Prettier in GitHub Actions
name: Format Code
on: [push, pull_request]
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Prettier
run: npm install --save-dev prettier
- name: Format with Prettier
run: npx prettier --write .
Note: Ensure your formatter is installed in the workflow environment before running it.
8. Running Type Checkers
| Checker | Command | Notes |
|---|---|---|
| TypeScript | npx tsc --noEmit |
Checks TypeScript files for type errors without emitting JavaScript |
| ESLint with TypeScript | npx eslint . --ext .ts,.tsx |
Combines linting and type checking for TypeScript files |
| JSDoc Type Checker | npx jsdoc -c jsdoc.conf.json |
Validates JSDoc annotations in JavaScript files |
Example: Running TypeScript Checks in GitHub Actions
name: Type Check
on: [push, pull_request]
jobs:
type-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install
- run: npx tsc --noEmit
9. Using Test Reporters
| Reporter | Description | Usage | Notes |
|---|---|---|---|
| junit | Generates JUnit XML reports for test results | reporter: junit |
Commonly used with CI tools like Jenkins or TeamCity |
| json | Outputs test results in JSON format | reporter: json |
Useful for parsing and integrating with other systems |
| lcov | Generates coverage reports in LCOV format | reporter: lcov |
Used with tools like Codecov for coverage analysis |
| spec | Displays test results in a readable, spec-style format | reporter: spec |
Default for many test runners, easy to read in logs |
Example: Using JUnit Reporter
name: Test with JUnit
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests with JUnit reporter
run: |
npm install
npm test -- --reporter=junit
- name: Upload JUnit report
uses: actions/upload-artifact@v4
with:
name: junit-report
path: junit.xml
Note: Ensure that the test runner supports the specified reporter format. Some runners may require additional configuration or plugins to generate reports in specific formats.
10. Failing on Low Coverage
| Option | Values | Notes |
|---|---|---|
| coverage.threshold | 80 |
Minimum coverage percentage required to pass the workflow |
| coverage.fail-on-low | true |
Set to true to fail the workflow if coverage is below threshold |
| coverage.job | test |
The job name that generates coverage data |
Example: Configuring Coverage Failures
name: Test and Coverage
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests with coverage
run: |
npm install
npm test -- --coverage
- name: Fail if coverage is low
if: ${{ failure() }}
run: |
echo "Coverage below threshold"
exit 1
Note: Ensure your test suite generates coverage reports in a format compatible with tools like
nyc or cobertura.
11. Running Tests in Parallel
| Option | Values | Notes |
|---|---|---|
| strategy.matrix | max-parallel: 4 |
Maximum number of parallel jobs |
| strategy.fail-fast | true |
Stop running jobs if one fails |
| strategy.max-parallel | 8 |
Maximum number of parallel jobs (default: 4) |
Example: Parallel Test Jobs
jobs:
test:
strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
os: [ubuntu-latest, windows-latest]
max-parallel: 4
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Run Tests
run: npm test
Note: Parallel jobs run in separate environments and do not share state.
Warning: Ensure tests are isolated to prevent race conditions.
Best Practices for Parallel Testing
- Use
strategy.matrixto define test variations - Limit
max-parallelto avoid resource exhaustion - Ensure tests do not depend on each other's state
- Use
fail-fast: trueto stop on first failure
12. Using Test Fixtures
| Fixture Type | Description | Usage Example |
|---|---|---|
| Test Data | Static data used to set up test scenarios | |
| Mock Services | Simulated external services to isolate tests | |
| Database Snapshots | Predefined database states for consistent testing | |
Example: Setting Up a Test Fixture
- name: Prepare test environment
run: |
# Create a temporary directory for fixtures
mkdir -p ./fixtures
# Copy test data files
cp -r ./test-data/* ./fixtures/
# Set environment variables for test run
echo "FIXTURE_DIR=./fixtures" >> $GITHUB_ENV
Note: Fixtures should be lightweight and reproducible to ensure reliable test runs.
Warning: Avoid modifying global state or shared resources in fixtures as it can lead to test interference.