Mocha
Set up Mocha for JavaScript testing and integrate test results with TestKase.
Overview
Mocha is a flexible JavaScript test framework for Node.js with support for BDD and TDD styles, asynchronous testing, and a wide range of assertion libraries. Its pluggable architecture lets you choose your preferred assertion library (Chai, Assert, Should.js) and reporter.
To integrate Mocha test results with TestKase, use mocha-junit-reporter to generate JUnit XML
output, then push results with:
--format junitPrerequisites
- Node.js 18 or later
- A TestKase account with a project, test cycle, and Automation IDs configured on your test cases
Installation
Install Mocha and an assertion library as dev dependencies:
npm install --save-dev mocha
npm install --save-dev chaiProject Setup
Directory Structure
my-mocha-project/
├── package.json
├── .mocharc.yml
└── test/
├── login.test.js
└── search.test.jsMocha Configuration
Create .mocharc.yml in your project root:
spec: test/**/*.test.js
timeout: 10000
recursive: truepackage.json Test Script
Add a test script to your package.json:
{
"scripts": {
"test": "mocha",
"test:junit": "mocha --reporter mocha-junit-reporter --reporter-options mochaFile=test-results/junit.xml"
}
}Writing Tests
Create a test file at test/login.test.js:
const { expect } = require('chai');
describe('Login', () => {
let authService;
beforeEach(() => {
// Set up test fixtures
authService = new AuthService();
});
it('[48271] should authenticate user with valid credentials', async () => {
const result = await authService.login('testuser', 'password123');
expect(result).to.have.property('success', true);
expect(result).to.have.property('token').that.is.a('string');
});
it('[48272] should reject invalid credentials', async () => {
const result = await authService.login('invalid', 'wrong');
expect(result).to.have.property('success', false);
expect(result).to.have.property('error', 'Invalid credentials');
});
it('[48273] should lock account after 5 failed attempts', async () => {
for (let i = 0; i < 5; i++) {
await authService.login('testuser', 'wrong');
}
const result = await authService.login('testuser', 'password123');
expect(result).to.have.property('success', false);
expect(result).to.have.property('error', 'Account locked');
});
});Each test name includes a 5-digit Automation ID in square brackets. The @testkase/reporter CLI
extracts these IDs using the regex \[(\d{5})\]. For the example above, the extracted Automation IDs are:
48271→ linked to the "valid credentials" test case in TestKase48272→ linked to the "invalid credentials" test case in TestKase48273→ linked to the "account lockout" test case in TestKase
The [XXXXX] pattern can appear anywhere in the it() name:
describe('Auth', () => {
describe('Login', () => {
it('[48271] should authenticate user', () => { /* ... */ });
// Reporter extracts ID: 48271
});
describe('Logout', () => {
it('[48274] should clear session', () => { /* ... */ });
// Reporter extracts ID: 48274
});
});Running Tests
Standard Run
npx mochaJUnit XML Output
Install the JUnit reporter:
npm install --save-dev mocha-junit-reporterRun tests with JUnit output:
npx mocha --reporter mocha-junit-reporter --reporter-options mochaFile=test-results/junit.xmlOr use the npm script defined earlier:
npm run test:junitThe JUnit XML report is written to test-results/junit.xml.
You can use multiple reporters simultaneously with mocha-multi-reporters. This lets you see
spec-style output in the terminal while also generating JUnit XML for TestKase.
TestKase Integration
After running your tests with JUnit output, use the @testkase/reporter CLI to push results
to TestKase:
npx @testkase/reporter report \
--token $TESTKASE_PAT \
--project-id PRJ-1 \
--org-id 1173 \
--cycle-id TCYCLE-5 \
--format junit \
--results-file test-results/junit.xml--cycle-id is optional. If not provided, results are reported to TCYCLE-1 — the master test cycle for the project.
Use --dry-run --verbose the first time to verify that your test names match the Automation IDs
you set in TestKase. This helps catch naming mismatches before pushing real results.
Automation ID Mapping
The reporter extracts 5-digit Automation IDs from Mocha test names using the [XXXXX] bracket pattern:
| Test Code | Extracted ID |
|---|---|
it('[48271] should authenticate user', ...) | 48271 |
it('[48272] should reject invalid credentials', ...) | 48272 |
describe('Auth', () => { it('[48273] should lock account', ...) }) | 48273 |
The [XXXXX] pattern can appear anywhere in the it() name. The describe block structure does
not affect the Automation ID — only the 5-digit number inside brackets matters.
Complete Example
This end-to-end example shows the full flow for a Mocha project.
1. Set Up the Project
mkdir mocha-testkase-demo && cd mocha-testkase-demo
npm init -y
npm install --save-dev mocha chai mocha-junit-reporterCreate .mocharc.yml:
spec: test/**/*.test.js
timeout: 10000
recursive: trueAdd scripts to package.json:
{
"scripts": {
"test": "mocha",
"test:junit": "mocha --reporter mocha-junit-reporter --reporter-options mochaFile=test-results/junit.xml"
}
}2. Write a Test
Create test/cart.test.js:
const { expect } = require('chai');
describe('Shopping Cart', () => {
let cart;
beforeEach(() => {
cart = new Cart();
});
it('[48271] should add item to cart', () => {
cart.addItem({ id: 1, name: 'Widget', price: 9.99 });
expect(cart.items).to.have.lengthOf(1);
expect(cart.items[0]).to.have.property('name', 'Widget');
});
it('[48272] should calculate total', () => {
cart.addItem({ id: 1, name: 'Widget', price: 9.99 });
cart.addItem({ id: 2, name: 'Gadget', price: 19.99 });
expect(cart.total()).to.equal(29.98);
});
it('[48273] should remove item from cart', () => {
cart.addItem({ id: 1, name: 'Widget', price: 9.99 });
cart.removeItem(1);
expect(cart.items).to.have.lengthOf(0);
});
});3. Set the Automation ID in TestKase
In your TestKase project, generate Automation IDs on the corresponding test cases, then embed them
in your it() names using the [XXXXX] bracket pattern.
4. Run the Tests
npm run test:junit5. Verify with Dry Run
npx @testkase/reporter report \
--token $TESTKASE_PAT \
--project-id PRJ-1 \
--org-id 1173 \
--cycle-id TCYCLE-5 \
--format junit \
--results-file test-results/junit.xml \
--dry-run --verbose6. Push Results
Remove the --dry-run flag to push results to TestKase:
npx @testkase/reporter report \
--token $TESTKASE_PAT \
--project-id PRJ-1 \
--org-id 1173 \
--cycle-id TCYCLE-5 \
--format junit \
--results-file test-results/junit.xmlTroubleshooting
Reporter option not recognized
Error: invalid reporter "mocha-junit-reporter"Cause: The mocha-junit-reporter package is not installed.
Fix: Install it as a dev dependency:
npm install --save-dev mocha-junit-reporterVerify the package is listed in your package.json under devDependencies. If you are using
a monorepo, ensure it is installed in the correct workspace.
Automation IDs not being extracted
Cause: The test names do not contain the [XXXXX] bracket pattern with a 5-digit Automation ID.
Example: For the following test structure:
describe('User Management', () => {
describe('Registration', () => {
it('should create new account', () => { /* ... */ });
});
});The Automation ID is User Management > Registration > should create new account, not just
Registration > should create new account.
Fix: Embed [XXXXX] Automation IDs in your it() names. Use --dry-run to verify which
IDs the reporter extracts from your results file.
Async test timeout
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called;
if returning a Promise, ensure it resolves.Cause: The default Mocha timeout (2000ms) is too short for async operations.
Fix: Increase the timeout in .mocharc.yml:
spec: test/**/*.test.js
timeout: 30000
recursive: trueOr set a per-test timeout:
it('should complete a slow operation', function () {
this.timeout(30000);
// test code...
});For tests using async/await, ensure you return the promise or use async functions directly:
// Correct — async function
it('should work', async () => {
const result = await someAsyncOperation();
expect(result).to.equal('expected');
});