ワンクリックで
testing
Testing standards and conventions for this project
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Testing standards and conventions for this project
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Standard skills and patterns an agent should apply when working in this codebase
Read-only access to WATER project Jira tickets for task context
Expectations and rules for making git commits in this project
| name | testing |
| description | Testing standards and conventions for this project |
vitest — not Jest, Mocha, Chai, or Sinonvitest runs with globals: false, so describe, it, expect, beforeAll, afterAll, beforeEach, afterEach, and vi must always be imported explicitly from 'vitest''use strict', no require() — use importTest files do not use JSDoc or @module. The top-of-file order is imports grouped by section comment:
// Test framework
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
// Test helpers
import SomeModelHelper from '../support/helpers/some-model.helper.js'
// Things we need to stub
import * as SomeDal from '../../app/dal/some.dal.js'
// Thing under test
import SubjectUnderTest from '../../app/services/subject-under-test.service.js'
Use these section comments in order, omitting any that are not needed:
// Test framework (omit entirely when only Vitest globals are needed — i.e. no other imports)// Test helpers// Things we need to stub// Thing under test// For running our service (controller tests only — the init import used to start the Hapi server)Alphabetical ordering within each section still applies (alanisms rule 2)
The top-level describe label must reflect the file's folder path. Each path segment is title-cased and joined with -, followed by the module type:
// test/services/notices/setup/fetch-notice.service.test.js
describe('Notices - Setup - Fetch Notice service', () => {
// ...
})
beforeAll and stop it in afterAll with await server.stop()Use vi.spyOn() and vi.fn() — vitest's built-in mocking, not Sinon.
import ReturnLogModel from '../../../app/models/return-log.model.js'
vi.spyOn(ReturnLogModel, 'query').mockReturnValue({
patch: vi.fn().mockReturnThis(),
findById: vi.fn().mockResolvedValue()
})
'default' property:import * as FetchBillService from '../../../app/services/bills/fetch-bill-service.js'
vi.spyOn(FetchBillService, 'default').mockResolvedValue(billData)
vi.restoreAllMocks() in afterEach whenever stubs are usedvi.mock() or vi.doMock(). They hoist to the top of the file, auto-mock every export, and behave inconsistently between CJS and ESM — they've caused real problems in this codebase and are bannedvi.spyOn() patterns above insteadvi.spyOn(Tar, 'create') against import * as Tar from 'tar'Proxyquire instead — see test/plugins/airbrake.plugin.test.js for an example. Don't reach for vi.mock()/vi.doMock() as a workaround.toEqual(), .toBe(), etc. directly on expect()expect() — assign them to a variable first, then wrap in the array at the assertion. Always leave a blank line between the assignment and the expect():// wrong
expect(results).to.equal([SomeSeeder.transform(record)])
// right
const expectedResult = SomeSeeder.transform(record)
expect(results).toEqual([expectedResult])
For comparing objects while ignoring specific fields (e.g. timestamps), use .toMatchObject():
// Checks all testRecord properties are present in result — ignores extra fields like createdAt
expect(result).toMatchObject(testRecord)
Use the docker exec wrapper to run tests. You can pass specific files or patterns as additional arguments:
docker compose exec dev /bin/bash -c 'cd /home/repos/water-abstraction-system && npm run test -- test/services/notices/setup/my-service.test.js'
docker compose exec dev /bin/bash -c 'cd /home/repos/water-abstraction-system && npm run test -- test/services/notices/setup/foo.test.js test/services/notices/setup/bar.test.js'
Do not use npx vitest directly.
test/ mirroring the app/ structure.test.js extension (e.g. delete-session.dal.test.js)describe.only() or it.only() in committed code — CI will fail on thesedescribe blocks to group scenarios (e.g. describe('when valid', ...), describe('when invalid', ...))