- Published on
A practical method for testing JavaScript regular expressions
Build a JavaScript pattern in small steps, test edge cases and flags, inspect capture groups, and check replacements before using it.
- Authors

- Name
- Adam Johnston
- @admjski
A regular expression can look correct against one example and still fail on the next input. A useful test loop is small: state the exact text shape you want, write one part of the pattern, and try both matching and non-matching examples before adding more syntax.
This guide focuses on JavaScript regular expressions. Other languages use different engines and feature sets, so test the expression in the same runtime that will use it. The Regex Tester runs JavaScript patterns and exposes flags, match positions, capture groups and replacement output.
Start with examples, not syntax
Write down a few inputs that should match and a few that should not. For a date-like string, the desired shape might be four digits, a hyphen, two digits, another hyphen and two digits:
2026-10-06 should match
26-10-06 should not match
2026-1-06 should not match
2026-10-6 should not match
That gives a concrete first pattern:
const pattern = /\d{4}-\d{2}-\d{2}/
It finds a substring with that shape. To require the whole input to have that shape, add start and end anchors:
const wholeInput = /^\d{4}-\d{2}-\d{2}$/
This checks shape only; it does not validate calendar dates. For example, 2026-19-42 has the same character shape. In JavaScript, $ can also match immediately before a final line terminator, so handle that case explicitly if the input must end at that exact point. Use a date parser or explicit range checks when calendar validity matters.
Add structure with capture groups
Capture groups let you inspect parts of a match or reuse them in a replacement. Named groups make the intended fields easier to read:
const dateParts = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/
const match = '2026-10-06'.match(dateParts)
if (match?.groups) {
console.log(match.groups.year) // "2026"
console.log(match.groups.month) // "10"
console.log(match.groups.day) // "06"
}
Use (?:...) for grouping that should not create a capture. Every capture changes the numbered group positions, so non-capturing groups help keep replacement references stable when the group is only for precedence.
Test flags as part of the expression
Flags change how JavaScript evaluates a pattern. Try them deliberately against the actual test text:
gcontinues through the input to find multiple matches.iignores letter case.mmakes^and$work at line boundaries as well as the input boundaries.slets.match line terminators.uenables Unicode-aware pattern processing.yrequires a match at the currentlastIndexposition.
For example, /^error/im finds a line beginning with error, regardless of case. Without m, the start anchor applies only at the beginning of the entire string. When testing global or sticky expressions directly in code, remember that test() and exec() update lastIndex; repeated calls can therefore produce different results unless you reset the index or create a fresh expression.
Check groups, positions and replacements
For a reusable pattern, inspect more than the highlighted match. Check the start/end position, numbered and named groups, and how replacement tokens behave. JavaScript replacement strings support numbered captures such as $1 and named captures such as $<year>.
const formatted = '2026-10-06'.replace(dateParts, '$<month>/$<day>/$<year>')
// "10/06/2026"
Test replacement against more than one input, including a string with no match. This catches accidental partial matches and misplaced captures before the expression is used on a larger file or dataset.
Keep patterns understandable and bounded
Prefer a few clear groups over one expression that tries to parse an entire format. Regular expressions are useful for recognizing text patterns; they are not a substitute for a parser when nesting, quoting rules or semantic validation matter.
Patterns with nested, overlapping repetition can take a long time on certain inputs. Start with short examples, then try long and almost-matching inputs. The 404cache Regex Tester runs analysis in a Web Worker, caps the returned match count and reports slow/truncated result sets. A worker keeps the regular UI thread separate, but the current code checks elapsed time between global matches; it does not guarantee that a single expensive match will stop at the timeout. Those safeguards do not make an unsafe expression suitable for every application. Validate untrusted patterns and choose a parser or a safer pattern design for production workloads.
A compact test checklist
- Write positive and negative examples from the expected input.
- Add one pattern feature at a time and retest the examples.
- Check whether the pattern should match a substring or the whole input.
- Test the flags, groups and replacement output you will actually use.
- Try empty, long and near-matching inputs; use a parser for structured data or semantic validation.
The two older Regex Tester articles at /blog/Guides/build-your-own-regex-tester/ and /blog/Tools/regex-tester/ supplied the starting material for this consolidated guide. The current tool is the implementation reference: open Regex Tester.