Genory
Banking formats

Test IBANs: Examples and a Practical Testing Checklist

Build useful IBAN test cases, distinguish public format examples from provider sandbox credentials, and test the failures that a happy-path demo misses.

Your payment form accepts one example IBAN, the success message appears, and the feature looks finished. Then someone pastes a value with spaces, another customer uses letters in the bank segment, and a provider refuses an account that passed your local check. Useful test data should expose those differences before customers do.

Three kinds of IBAN test input

Input type Suitable use Important limit
Public registry example Repeatable format and checksum tests Not guaranteed unassigned or accepted by a provider sandbox
Generated synthetic value Exploring supported patterns and varied inputs Generation does not prove account nonexistence
Provider-documented test value A named scenario in that provider’s test environment Meaning depends on provider, method and environment

Label fixtures by their intended use, not merely as “valid.” A value can pass MOD-97 while violating a national character pattern. Another can match the full format but fail a provider’s sandbox expectations. Those are different outcomes, and collapsing them into one boolean makes failures difficult to diagnose.

Isolated parsing tests use registry or generated examples; provider sandbox tests use designated scenario inputs. Neither flows into live payments.
Use registry or synthetic fixtures for isolated format tests, and provider-designated inputs for sandbox integration. Both remain separated from live payment execution.

Genory’s IBAN generator creates test data within its displayed coverage. Read the selected mode and limitations before using the output. The generator does not issue bank accounts, establish that a value is unused, or turn arbitrary output into a payment provider’s reserved test credential.

A small set of public format examples

These examples come from the SWIFT IBAN Registry. They are useful because their expected structural properties are documented. Treat them as public reference values for isolated tests, not as destination accounts or guaranteed fictitious banking details. Spaces below are only for readability.

Format Public example Property to exercise
Germany DE89 3704 0044 0532 0130 00 Numeric BBAN and leading zeros
Netherlands NL91 ABNA 0417 1643 00 Alphabetic bank identifier
United Kingdom GB29 NWBK 6016 1331 9268 19 Bank letters, sort code and account segment

Give each example a stable name in your fixture library, such as de_registry_format, and store the source and expected checks beside it. A test failure then points to a specific rule. If you need more countries, consult our IBAN format comparison and select formats that add a genuinely different property.

Turn one good value into focused negative cases

A negative test should have an intentional defect. If you alter the country, length and checksum at once, the test may pass simply because the validator rejects the first problem it sees. Start with one documented value, change one feature where possible, and assert the relevant validation layer.

Fixture Change Expected outcome
Lowercase and spaces Change presentation only Same normalized value if the input contract permits it
Missing final character Shorten the example by one character Length check fails
Changed check digit DE89 becomes DE88; body unchanged International checksum fails
Punctuation Add a hyphen inside the value Reject under Genory’s documented input rules
Empty string Remove the value entirely Required-field handling in the surrounding form
Wrong national pattern Put digits in a required bank-letter field and recompute checksum Checksum may pass; national pattern still fails
Validation matrix: allowed spacing normalizes; truncation fails length; changing DE89 to DE88 fails checksum; a recomputed checksum does not repair a wrong national pattern.
Separate presentation changes from structural defects. A checksum-valid value can still fail the national pattern; assert those checks independently.

That last case is particularly revealing. A validator that checks only length and MOD-97 can accept the wrong national character layout. Keep a specifically constructed pattern-negative fixture instead of assuming that a random typo will test the same boundary. Our validation guide explains the arithmetic and the order of checks.

A readable fixture shape

{
  "id": "de_wrong_check_digit",
  "input": "DE88370400440532013000",
  "expected": {
    "country": true,
    "length": true,
    "bban": true,
    "checksum": false
  },
  "use": "isolated validation only"
}

This is an example fixture schema, not a promise that every library returns those field names. Adapt it to your application’s contract. The important part is keeping the input, the reason for the case and the expected result together. A future maintainer should not need to reverse-engineer why a mysterious number appears in a test.

Test the form a person actually uses

Begin with typing and pasting. Check that a mobile keyboard does not prevent required letters, that grouping spaces behave consistently, and that moving focus does not discard the input. Submit using both the button and the keyboard. Then verify that the error identifies the field and explains a useful next action.

Test correction as well as rejection. Enter a deliberately invalid checksum, submit, then replace it with the valid reference example. The stale error should clear according to your form’s interaction model. Also verify that changing another field does not accidentally remove the IBAN or reuse an outdated validation result.

A masked confirmation screen deserves its own case. The user should be able to recognize the intended account without your interface exposing full bank details unnecessarily. Test the visible suffix and selected beneficiary together. Masking is a presentation choice; do not send the masked value to a downstream API that expects the complete identifier.

Worked QA scenario: saving a supplier account

Consider a fictional purchasing app with a supplier form and a separate payment screen. In an isolated test environment, create a supplier named Example Workshop and paste the spaced Dutch registry example into the account field. Save it, reopen the supplier and compare the normalized value with the fixture. Then open the payment preview without sending a payment. The same account should appear with the product’s documented masking and display spacing.

Now repeat the journey with the German wrong-check-digit fixture shown above. The form should explain the failure without creating a usable payment destination. Correct the input, submit again and confirm that the record contains the corrected value once. This sequence tests recovery, persistence and the preview together; a unit test of the checksum alone cannot establish those behaviors.

Finally, simulate a failed save response. Decide beforehand whether the app retains the unsaved input and how it distinguishes it from the last saved value. Reopening the record must not present an unsaved edit as confirmed account information. Record the expected result for each step so that another tester can repeat the scenario without relying on your memory.

Keep the fixture supplier and its account values inside the test environment. If the next test involves an actual provider integration, replace the local reference value with that provider’s designated scenario input. Reusing a familiar number is convenient, but it does not establish that the provider assigns the same meaning to it.

Test API, import and export boundaries

Run the same normalization cases through each supported entry point. A browser and CSV importer that treat spaces differently can create duplicate-looking records or surprising failures. Preserve identifiers as text in spreadsheets and serialization. Leading zeros are data, and an exported value should return unchanged when imported under the documented format.

For bulk input, mix accepted and rejected rows deliberately. Check row numbering, partial-success behavior and the correction path. Decide whether the whole batch fails or individual rows can be retried, and assert that policy. An error report that points at the wrong row is a product bug even if the underlying checksum calculation is correct.

For asynchronous operations, distinguish “request received,” “processing” and the eventual outcome. Simulate a timeout after your service has accepted a request, then verify your duplicate-prevention policy before retrying. Use the provider’s supported idempotency mechanism where applicable. Do not infer that no work happened just because the browser stopped waiting.

A useful fixture tells you which behavior failed. A large pile of plausible account numbers usually does not.

Use a provider sandbox for payment scenarios

Payment providers document their own test environments and scenario inputs. For example, Stripe’s testing documentation directs developers to method-specific values for non-card payments. Read the current instructions for your exact payment method rather than copying a number from an unrelated tutorial.

Build an integration checklist around the scenarios your provider supports: acceptance, refusal, delayed results, authentication or mandate requirements where applicable, and event delivery. Assert your application’s response to each outcome. A test that merely receives an HTTP success response may not establish that the business operation reached its final state.

Release review connects input tests, integration behavior, and data handling: test correction, retries, webhooks, masking and environment boundaries.
A release check follows the data through input, validation, sandbox behavior and reporting. Keep the expected result attached to each test case.

Keep environment configuration explicit. A test fixture labelled “sandbox” is not a technical barrier if the application still holds live credentials. Separate credentials and endpoints, disable live-payment paths in isolated tests, and review the environment before running an integration suite. Synthetic-looking digits do not provide that isolation for you.

Keep the fixture library maintainable

  1. Name the behavior. Prefer a label such as “Dutch bank letters preserved” over an anonymous example number.
  2. Record the source. Include the registry version or provider documentation and the date reviewed.
  3. State the expected layer. Distinguish formatting, country structure, checksum, national checks and provider behavior.
  4. Preserve a failing input. Save the exact synthetic case needed to reproduce a bug rather than relying on a fresh random draw.
  5. Review when rules change. Update expectations deliberately and keep a short explanation of what changed.

Use a compact deterministic set for routine regressions, then add generated variations where they can reveal new behavior. If a generated case fails, promote a minimal reproducible example into the fixed set. This gives you both exploration and reliable debugging without making every build depend on a different unexplained collection of inputs.

As a practical handoff, give reviewers a small table with the fixture name, input boundary, expected result and evidence. A screenshot may demonstrate error placement; an assertion can demonstrate exact normalization. These support different claims. Neither needs to contain real customer banking data to be useful.

Common questions about test IBANs

Can a generated IBAN accidentally match a real account?

A format generator cannot rule that out simply by generating digits. Treat its output as unverified and keep it isolated from live payments. “Synthetic” describes how you produced the value, not a checked claim about every account in the banking system.

Why does a sandbox reject an IBAN that passes validation?

The sandbox may expect provider-designated test inputs or additional method-specific requirements. Structural validity and sandbox acceptance are separate contracts. Check the provider’s documented scenario rather than weakening your validator or trying random accounts until one appears to work.

Should I test every country?

Test every country your product claims to support at the appropriate level, and use representative formats for fast unit tests. A full support claim requires more than three examples. Keep the support matrix explicit, especially where national algorithms or bank reference data have narrower coverage.

Can I share the fixture set with colleagues?

Share intentionally prepared reference and synthetic fixtures with their labels and test-only purpose. Remove secrets, live customer records and provider credentials from the package. A useful starting point is the IBAN generator, followed by a check of each intended property in the IBAN validator.

Tools for this guide

Test IBANs: Examples and Payment-Form Testing · Genory