DevPad
← Back to blog
·regex, regular-expressions, testing, developer-tools

How to Test Regex Patterns: A Developer Guide

Learn how to test regular expressions effectively, match groups, flags, and common patterns. Includes JavaScript, Python, and online testing tools.

Regular expressions (regex) are powerful but notoriously tricky. A pattern that looks correct can silently fail on edge cases, or worse, cause catastrophic backtracking that freezes your application. Testing regex properly is essential.

Why Regex Testing Matters

A regex that works on your test string might fail on real-world input. Consider a simple email regex: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$. It passes basic tests but fails on addresses like user+tag@sub.domain.co.uk or name@192.168.1.1.

Testing means checking:

  • Does it match what it should?
  • Does it NOT match what it shouldn't?
  • Are capture groups extracting the right data?
  • How does it handle edge cases (empty strings, Unicode, very long inputs)?

Regex Fundamentals

Basic Syntax

| Pattern | Matches | |---------|---------| | abc | Literal string "abc" | | . | Any single character | | \d | Digit (0-9) | | \w | Word character (a-z, A-Z, 0-9, _) | | \s | Whitespace | | ^ | Start of string | | $ | End of string | | * | Zero or more | | + | One or more | | ? | Zero or one | | {n,m} | Between n and m times |

Capture Groups

Parentheses create capture groups:

const match = "2026-09-19".match(/(\d{4})-(\d{2})-(\d{2})/);
// match[1] = "2026" (year)
// match[2] = "09"   (month)
// match[3] = "19"   (day)

Named groups are more readable:

const match = "2026-09-19".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
// match.groups.year = "2026"

Flags

| Flag | Name | Effect | |------|------|--------| | g | Global | Find all matches, not just the first | | i | Case-insensitive | Ignore case when matching | | m | Multiline | ^ and $ match line starts/ends | | s | Dotall | . matches newlines |

Testing Strategies

1. Test Positive Cases (Should Match)

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

// These should all return true
emailRegex.test("user@example.com");    // true
emailRegex.test("name@domain.co.uk");   // true
emailRegex.test("user+tag@example.org"); // true

2. Test Negative Cases (Should NOT Match)

// These should all return false
emailRegex.test("");           // false
emailRegex.test("not-email");  // false
emailRegex.test("@no-user.com"); // false
emailRegex.test("user@");     // false

3. Test Edge Cases

// Unicode
emailRegex.test("usér@example.com");   // depends on your regex

// Very long input
emailRegex.test("a".repeat(100) + "@example.com");

// Special characters
emailRegex.test("user@sub.domain.co.uk");

4. Verify Capture Groups

const urlRegex = /^(?<protocol>https?):\/\/(?<host>[^/]+)(?<path>\/.*)?$/;
const match = urlRegex.exec("https://example.com/path?q=1");

console.log(match.groups.protocol); // "https"
console.log(match.groups.host);     // "example.com"
console.log(match.groups.path);     // "/path?q=1"

Common Regex Patterns

Email (Simple)

^[^\s@]+@[^\s@]+\.[^\s@]+$

URL

^https?:\/\/[^\s/$.?#].[^\s]*$

Phone Number (US)

^\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$

IP Address (v4)

^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$

Date (YYYY-MM-DD)

^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

Performance Pitfalls

Catastrophic Backtracking

Avoid nested quantifiers:

# BAD — can cause exponential backtracking
^(a+)+$

# GOOD — same match, no backtracking risk
^a+$

Greedy vs Lazy

Greedy (*, +) matches as much as possible. Lazy (*?, +?) matches as little as possible.

"<div>content</div>".match(/<div>(.*)<\/div>/);   // greedy: matches whole string
"<div>content</div>".match(/<div>(.*?)<\/div>/);  // lazy: matches "content"

Try It Now

Use our free Regex Tester to test patterns in real-time — with match highlighting, group extraction, and a library of common patterns.