Learn how to set up a Test Driven Development (TDD) environment using Jest in Visual Studio Code (VS Code) to ensure code quality and reliability.
Test Driven Development (TDD) is a software development approach where tests are written before the actual code. This method helps ensure that the code meets its requirements and behaves as expected. In this guide, we will set up a TDD environment using Jest, a popular testing framework, in Visual Studio Code (VS Code). This setup is divided into several steps to help get started with TDD effectively. Assuming you have Node.js and npm installed, follow these steps:
Test Driven Development (TDD) is a software development approach where tests are written before the actual code. This method helps ensure that the code meets its requirements and behaves as expected. In this guide, we will set up a TDD environment using Jest, a popular testing framework, in Visual Studio Code (VS Code). This setup is divided into several steps to help get started with TDD effectively.This setup includes multiple components working together:
Prerequisites: Ensure you have Node.js (version 16 or higher) and npm installed on your system, along with Visual Studio Code.
Open your terminal and create a new directory for your project. Navigate into the directory and run the following command to initialize a new Node.js project:
1mkdir my-tdd-project
2cd my-tdd-project
3npm init -y
Install the following extensions from the VS Code marketplace for optimal TDD experience:
To install cSpell and Jest for manual testing, run the following command:
1npm install --save-dev jest cspell @cspell/dict-software-terms
To verify that the extensions and packages are installed correctly, you can check the installed extensions in VS Code by navigating to the Extensions view (Ctrl+Shift+X or Cmd+Shift+X on Mac) and searching for the names mentioned above. For npm packages, you can check your package.json file to ensure that jest and cspell are listed under devDependencies.
1 "devDependencies": {
2 "@cspell/dict-software-terms": "^5.1.8",
3 "cspell": "^9.2.1",
4 "jest": "^30.1.3"
5 }
Create the following folder structure in your project directory:
1my-tdd-project/
2├── docs/
3├── .vscode/
4│ └── settings.json
5├── __tests__/
6├── package.json
7└── package-lock.json
Create a .vscode folder in the root of your project and add a settings.json file with the following content to configure VS Code settings for Jest and cSpell:
1{
2 "editor.formatOnSave": true,
3 "cSpell.language": "en-GB",
4 "cSpell.enabledFileTypes": {
5 "markdown": true,
6 "plaintext": true
7 },
8 "jest.runMode": "watch"
9}
Note
Use other settings to enhance the jest setup but they only work if jest extension is installed.
1 "scripts": {
2 "test": "jest",
3 "test:watch": "jest --watch",
4 "test:spell": "jest spellcheck",
5 "spell:check": "cspell \"docs/**/*.md\"",
6 "spell:check:verbose": "cspell \"docs/**/*.md\" --no-progress --no-summary"
7 }
To test other script, create a spell.md file with some spelling mistakes in the docs folder and run the following commands to check if cSpell is working fine. Run first script npm run test to check if jest is working fine. It should say the following
1npm run test
2
3> vscode-jest-tdd-cspell@1.0.0 test
4> jest
5
6No tests found, exiting with code 1
7Run with `--passWithNoTests` to exit with code 0
8In /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell
9 3 files checked.
10 testMatch: **/__tests__/**/*.?([mc])[jt]s?(x), **/?(*.)+(spec|test).?([mc])[jt]s?(x) - 0 matches
11 testPathIgnorePatterns: /node_modules/ - 3 matches
12 testRegex: - 0 matches
13Pattern: - 0 matches
npm run spell:check to check if cSpell is working fine. It should say the following 1npm run spell:check
2
3> vscode-jest-tdd-cspell@1.0.0 spell:check
4> cspell "docs/**/*.md"
5
6
71/1 docs/spell.md 484.05ms X
8docs/spell.md:3:6 - Unknown word (fyle)
9docs/spell.md:3:15 - Unknown word (obvios)
10docs/spell.md:3:22 - Unknown word (spellin)
11CSpell: Files checked: 1, Issues found: 3 in 1 file.
The contnes of the spell.md file is as follows
1# Spelling Error
2
3This fyle has obvios spellin errors.
Setting up configuration files for Jest and cSpell.
cspell.config.yaml to have our configuration setup present in ths file.cspell.json via import property. The global file resides in /home/ag-sayyed/.config/cspell/ folder. it access already existing global dictionaries present in the same folder.cspell.config.yaml file 1schema: <https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json>
2 version: '0.2'
3 language: 'en-GB'
4 import: '/home/ag-sayyed/.config/cspell/cspell.json'
5 dictionaryDefinitions:
6 - name: project-words
7 path: './.vscode/project-words.txt'
8 addWords: true
9 dictionaries:
10 - en_GB
11 - project-words
12 noConfigSearch: true
13 allowCompoundWords: false
14 ignorePaths:
15 - 'node_modules/**'
16 - 'package-lock.json'
17 - 'package.json'
18 - '.git/**'
19 ignoreRegExpList:
20 - '\\{\\{.*?\\}\\}'
21 - '\\[\\[.*?\\]\\]'
22 - '\\$\\{.*?\\}'
23 - 'href=[\"''].*?[\"'']'
24 - 'src=[\"''].*?[\"'']
Running npm run spell:check should give the same output as before. If things do not work, use verbose mode to see more details.
1 npx cspell docs/spell.md --verbosenpx cspell docs/spell.md --verbose
2
3cspell;
4Date: Fri, 19 Sep 2025 14:47:46 GMT
5Options:
6 verbose: Yes
7 config: default
8 exclude: node_modules/**
9 files: docs/spell.md
10 wordsOnly: No
11 unique: No
12
13Config Files Found:
14 /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/cspell.config.yaml
15
16Exclusion Globs:
17 Glob: package-lock.json from /home/ag-sayyed/.config/cspell/cspell.json
18 Glob: node_modules from /home/ag-sayyed/.config/cspell/cspell.json
19 Glob: .git from /home/ag-sayyed/.config/cspell/cspell.json
20 Glob: .vscode/** from /home/ag-sayyed/.config/cspell/cspell.json
21 Glob: **/.vscode/** from /home/ag-sayyed/.config/cspell/cspell.json
22 Glob: **/*.code-workspace from /home/ag-sayyed/.config/cspell/cspell.json
23 Glob: settings.json from /home/ag-sayyed/.config/cspell/cspell.json
24 Glob: **/settings.json from /home/ag-sayyed/.config/cspell/cspell.json
25 Glob: node_modules/** from /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/cspell.config.yaml
26 Glob: package-lock.json from /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/cspell.config.yaml
27 Glob: package.json from /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/cspell.config.yaml
28 Glob: .git/** from /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/cspell.config.yaml
29 Glob: node_modules/** from command line
30
31Checking: /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/docs/spell.md, File type: auto, Language: default
32Checked: /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/docs/spell.md, File type: markdown, Language: en-GB ... Issues: 2 570.15ms
33Config file Used: /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/cspell.config.yaml
34Dictionaries Used: aws, companies, cryptocurrencies, filetypes, public-licenses, softwareTerms, coding-compound-terms, computing-acronyms, software-term-suggestions, software-tools, web-services, en_GB, misc, typescript, node, html, css, personal, hbstack-site, project-words, en-common-misspellings, en-gb-common-misspellings, en-gb, html-symbol-entities, npm
351/1 docs/spell.md 570.15ms X
36docs/spell.md:3:15 - Unknown word (obvios)
37docs/spell.md:3:22 - Unknown word (speling) fix: (spelling)
38CSpell: Files checked: 1, Issues found: 2 in 1 file.
Running command with verbose flag shows more details about the configuration files being used and the dictionaries being loaded. It also shows that our configuration files are present and newly created files are detected and used with the exact location of the spelling mistakes in the file. Aslo it tells us which dictionaries are being used.
1Dictionaries Used: aws, companies, cryptocurrencies, filetypes, public-licenses, softwareTerms, coding-compound-terms, computing-acronyms, software-term-suggestions, software-tools, web-services, en_GB, misc, typescript, node, html, css, `personal, hbstack-site`, project-words, en-common-misspellings, en-gb-common-misspellings, en-gb, html-symbol-entities, npm
The above list shows that our global and custom dictionaries named personal, hbstack-site and project-words are being used.
Simply run the command npm run spell:check to see the same output. The output should be the same as before.
To ignore words, which are part of this project, create a file named project-words.txt in the .vscode folder, if not created yet, and add the words to be ignored in this file. For example, add the following words to the file. Run the test again to see if the words are ignored.
jest.config.js in the root of your project with the following content:1module.exports = {
2 testEnvironment: 'node',
3 testMatch: ['**/__tests__/**/*.js', '**/?(*.)+(spec|test).js'],
4 verbose: true,
5 testTimeout: 15000 // Increased timeout for spell checking operations
6}
The above configuration sets up Jest to use the Node.js environment, specifies the test file patterns, enables verbose output, and increases the default timeout to accommodate spell-checking operations. This file is necessary for jest to run tests. The actual tests are to be written in the __tests__ folder.
spellcheck.test.js in the __tests__ folder with the following content: 1const { exec } = require('child_process')
2const fs = require('fs')
3const path = require('path')
4const util = require('util')
5
6const execPromise = util.promisify(exec)
7
8/**
9 * Helper function to run cspell on specified files
10 * @param {string} files - Glob pattern or specific file path to check
11 * @returns {Promise<Object>} - The result of running cspell
12 */
13async function runCSpell(files) {
14 try {
15 const { stdout } = await execPromise(`npx cspell ${files}`)
16 return { success: true, output: stdout }
17 } catch (error) {
18 return { success: false, output: error.stdout, error: error.stderr }
19 }
20}
The above code sets up a helper function to run cSpell using Node.js’s child_process module. It uses util.promisify to convert the exec function into a promise-based function for easier async/await usage. It also includes error handling to capture both standard output and error output.
tdd or test driven development, tests are written first before the actual code. So, we will write a test to check if the configuration file cspell.config.yaml is present in the root of the project. Since we have already created this file, for the process to be followed we changed its name to cspell.config.yaml.bak and then run the test. The test should fail since the file is not present. After that we will rename the file back to its original name and run the test again. This time it should pass. 1describe('CSpell Configuration', () => {
2 test('cspell.config.yaml exists and is valid', () => {
3 const cspellConfigPath = path.join(process.cwd(), 'cspell.config.yaml')
4 expect(fs.existsSync(cspellConfigPath)).toBe(true)
5
6 // Read YAML file as text to check basic validity
7 const configContent = fs.readFileSync(cspellConfigPath, 'utf8')
8 expect(configContent).toContain('version:')
9 expect(configContent).toContain("language: 'en-GB'")
10 expect(configContent).toContain('dictionaries:')
11 })
12})
As the file is not present, the test should fail with the following output
1 vscode-jest-tdd-cspell@1.0.0 test
2> jest --testLocationInResults --json --useStderr --outputFile /tmp/jest_runner_vscode_jest_tdd_cspell_1000_2.json --testNamePattern CSpell Configuration cspell\.config\.yaml exists and is valid$ --no-coverage --reporters default --reporters /home/ag-sayyed/.vscode/extensions/orta.vscode-jest-6.4.4/out/reporter.js --colors --watchAll=false --testPathPatterns /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/__tests__/spellcheck\.test\.js
3
4 FAIL __tests__/spellcheck.test.js
5 CSpell Configuration
6 ✕ cspell.config.yaml exists and is valid (3 ms)
7
8 ● CSpell Configuration › cspell.config.yaml exists and is valid
9
10 expect(received).toBe(expected) // Object.is equality
11
12 Expected: true
13 Received: false
14
15 26 | test('cspell.config.yaml exists and is valid', () => {
16 27 | const cspellConfigPath = path.join(process.cwd(), 'cspell.config.yaml');
17 > 28 | expect(fs.existsSync(cspellConfigPath)).toBe(true);
18 | ^
19 29 |
20 30 | // Read YAML file as text to check basic validity
21 31 | const configContent = fs.readFileSync(cspellConfigPath, 'utf8');
22
23 at Object.toBe (__tests__/spellcheck.test.js:28:45)
24
25Test Suites: 1 failed, 1 total
26Tests: 1 failed, 1 total
27Snapshots: 0 total
28Time: 0.13 s, estimated 1 s
29Ran all test suites matching /home/ag-sayyed/Documents/projects/vscode-setups/vscode-jest-tdd-cSpell/__tests__/spellcheck\.test\.js with tests matching "CSpell Configuration cspell\.config\.yaml exists and is valid$".
The test fails as expected. To make the test pass, rename the file back to its original name and watchAll settings will pickup the changes. This time it should pass. You can make a note on many different places that it passes.
Test Results panel at the bottom of VS Code window.1 PASS __tests__/spellcheck.test.js
2 CSpell Configuration
3 ✓ cspell.config.yaml exists and is valid (3 ms)
Write more test to make sure that required setup meets the criteria and if it fails the test starts to fail and you get alerted. Add following tests.
project-word.txt exist.cspell commands.Once the tests are written, run the tests to see if they pass or fail. If they fail, fix the issues and run the tests again. Repeat this process until all tests pass. Here is the TEST RESULTS panel output after adding all the tests and making sure they pass.
1 TestRun "[vscode-jest-tdd-cSpell] watch-all-tests:4:scheduled:4 (6)" started
2 PASS __tests__/spellcheck.test.js
3 CSpell Configuration
4 ✓ cspell.config.yaml exists and is valid (4 ms)
5 ✓ project-words.txt exists in .vscode directory
6 ✓ can run cspell command with configuration (403 ms)
7 Valid Documents
8 ✓ should pass spell check on well-formed documents (949 ms)
9 Documents With Spelling Errors
10 ✓ should detect spelling errors in test-errors.md (954 ms)
11 ✓ should detect spelling errors in spell.md (965 ms)
12 Custom Dictionary
13 ✓ should recognize custom words added to project dictionary (950 ms)
14 Ignore Patterns
15 ✓ cspell configuration has ignore patterns defined (1 ms)
16 ○ skipped should ignore specified patterns in content
17
18Test Suites: 1 passed, 1 total
19Tests: 1 skipped, 8 passed, 9 total
20Snapshots: 0 total
21Time: 4.503 s, estimated 5 s
22Ran all test suites.PASS __tests__/