Top pick: run the Luhn checksum against processor-published sandbox numbers, then layer field-format checks on top. That combination tests a validator with public test data, gives repeatable results, and never exposes a live account. The criteria behind the pick are simple: the test data must be published by a payment processor, the result must be deterministic so it can run in CI, and the whole flow must keep real card numbers out of your logs.
Luhn checksum as the baseline test
The Luhn formula, also called the mod 10 algorithm, is the check digit rule most card brands apply to the account number. A validator test starts here because it is arithmetic: no network call, no issuer lookup, no live number required.
- Pros: deterministic output, runs offline, catches single-digit typos and most adjacent transpositions, easy to unit test.
- Pros: you can generate valid-shaped numbers from a seed for fuzzing.
- Cons: a number that passes Luhn is not an issued account. Passing the checksum proves formatting, nothing else.
- Cons: it says nothing about brand rules, CVV length, or expiry.
Use it as the first gate in a test suite, not as proof that a card exists.
Sandbox test numbers from your processor
Every major processor publishes test card numbers for its sandbox, covering approvals, declines, and specific error responses. This is the option most teams should reach for after Luhn, because it exercises the full validation path: brand detection, expiry parsing, and CVV acceptance.
- Pros: published for testing, safe to commit to a repo, no real cardholder data.
- Pros: reproduces decline codes and 3D Secure outcomes on demand.
- Cons: tied to one processor's sandbox behavior, so switching providers means rewriting fixtures.
- Cons: sandbox rules drift over time, so fixtures need a review pass each year.
Recommendation: use sandbox numbers for integration tests, and keep them in a fixture file labeled as test data.
CVV, expiry, and brand-length edge cases
A credit card validator test is incomplete without the surrounding fields. Check that the form rejects a two-digit month, a past year, and a CVV of the wrong length. Visa, Mastercard, and Discover use a three-digit CVV; American Express uses four. Card number lengths vary by brand, so a hardcoded 16-digit rule will reject valid Amex and some co-branded ranges.
- Pros: catches the bugs users actually hit at checkout.
- Cons: brand tables need maintenance as ranges change.
What a validator test must never do
Do not test with card numbers you do not own. Do not build or run a checker that queries an issuer to see whether a number is live. Do not store CVV values after authorization. PCI DSS treats the CVV as sensitive authentication data that must not be retained once a transaction is authorized, and using card data you have no right to is fraud in the United States and most other jurisdictions. A legitimate validator test uses published sandbox values only.
Recommended workflow
For a form under development, run Luhn unit tests first, then sandbox integration tests, then a manual pass on CVV and expiry edge cases, and finish with a log review to confirm no full card number or CVV appears in plain text. If you are auditing an existing validator, start with the sandbox fixtures and work backward to the checksum code.