In this lesson you will learn how to verify behavior using tests.
More importantly:
Tests are used to prove when code is working correctly.
By the end of this lesson you should be able to:
- Write unit tests using Vitest
- Explain how tests pass and fail
- Identify normal, edge, and invalid cases
- Use tests to prove implementations do not match their documentation
0.1 + 0.2 === 0.3
// false- Why is this surprising?
- What assumption is being violated?
What test would you write for this behavior?
A test checks that code behaves as expected.
test('adds numbers', () => {
expect(2 + 3).toBe(5)
})- A test passes when no error is thrown
- A test fails when an error is thrown
test('empty', () => {
const x = 2 + 2
})This test passes because nothing fails.
👉 A test must include expect() to be useful.
- Normal cases — typical inputs
- Edge cases — boundaries (empty, limits)
- Invalid inputs — incorrect or unexpected inputs
Given:
function multiply(nums: number[]): number {
return nums.reduce((acc, n) => acc * n, 1)
}Write:
- 1 normal test
- 1 edge case
- 1 invalid input test
Write tests based on intended behavior, not the current code.
If your tests do not fail, they are not useful.
function sum(nums: number[]): number {
return nums.reduce((acc, n) => acc + n, 1)
}Write tests that prove this is incorrect.
function isEven(n: number): boolean {
return n % 2 === 1
}Write tests for even and odd numbers.
function first<T>(arr: T[]): T {
return arr[1]
}Write tests for different array sizes.
- What inputs revealed the bugs?
- Why did your tests fail?
In the lab, many bugs come from string handling. Regex helps you describe patterns, not just individual characters.
You don’t need to master regex today — just learn how to read and use common patterns.
Regex = pattern matching language for text
Instead of checking characters one by one, you describe a pattern:
/hello/ // match "hello"
/\d+/ // one or more digitsString methods alone get messy:
text.replace(' ', ' ') // only fixes one caseRegex handles patterns in one step:
text.replace(/\s+/g, ' ') // all whitespace👉 You use regex when:
- input is inconsistent
- patterns repeat
- you don’t know exact positions
- Originated in the 1950s (formal language theory)
- Popularized in Unix tools like
grep - Now built into JavaScript, Python, etc.
👉 It exists because text processing is everywhere
Take a few minutes and read this guide to regex: https://coderpad.io/blog/development/the-complete-guide-to-regular-expressions-regex/
Regex is built from small building blocks:
\s // whitespace
\w // word character
. // any character
[] // character set
^ // start of string
$ // end of string
+ // one or more
* // zero or moreCombine them:
/\s+/ // one or more whitespace
/[^\w\s]/ // NOT word or whitespace (punctuation)👉 The “secret”: Regex is just combining small rules into patterns
// collapse whitespace
text.replace(/\s+/g, ' ')
// remove punctuation
text.replace(/[^\w\s]/g, '')
// split into words
text.split(/\s+/)- Predict the output:
"Hello, world!!!".replace(/[^\w\s]/g, '')"one two\nthree".split(/\s+/)- Discuss:
- Why does this work better than
.split(' ')? - What bug would this prevent?
- When would regex be better than string methods?
- When might regex make code harder to read?
👉 Regex is powerful, but should be used carefully.
In the lab, bugs come from:
- incorrect whitespace handling
- punctuation not being removed
- splitting strings incorrectly
Regex helps you:
- implement correctly
- write better tests
Open your lab repo.
npm testNotice:
- all tests pass
- but they do not test anything useful
Replace placeholder tests with real tests that:
- reflect the documented behavior
- fail with the current implementation
Then:
- fix the functions
- run tests until all pass
Write answers:
- How do tests detect bugs?
- What is an edge case?
- What makes a test useful?