Boundary Value Testing: Choose Inputs That Expose Bugs

By Xusheng Yang
5 min read

A workspace supports ten active members. Inviting the third member works. Inviting the eleventh also works, which is the problem. Testing another ordinary count would not have revealed the missing limit.

Boundary value testing concentrates on the edges of ordered input or state ranges, where behavior is expected to change. Its usefulness depends on finding the actual rule and choosing values immediately around its thresholds.

This is part 2 of Testing Methods in Practice. The seat policy below is an illustrative specification, not an executed test result.

Make the boundary precise before choosing data

For this example, the rule is: a workspace can contain at most ten active members; pending invitations do not reserve seats; accepting an invitation consumes a seat. An owner counts as an active member.

Those details decide where to test. A limit checked during invitation creation would test a different policy. Write down what is counted, when it is counted, and whether the endpoint is inclusive. Ask what should happen to an invitation when the workspace fills before it is accepted.

Boundary analysis is one of the black-box techniques covered by ISTQB's Foundation Level framework. Here we use a three-value neighborhood around the seat threshold to make the example easy to inspect.

Build cases around the operation that crosses the threshold

Starting active membersActionExpected result under this policy
8Accept a valid invitationMember joins; active count becomes 9
9Accept a valid invitationMember joins; active count becomes 10
10Accept a valid invitationAcceptance is rejected; count stays 10
10Remove one member, then acceptAcceptance succeeds; count returns to 10
10Create a pending invitationInvitation can be created; acceptance still requires capacity
A threshold scale and capacity limit highlight accepted values near an edge and a rejected value beyond it.

Open full size

Illustrative example: Test values immediately around a documented threshold, then verify both enforcement and the user's recovery path.

The input is a state count, not just a number typed into a form. Reset or independently prepare the starting count for each case so earlier executions do not move the next case away from its intended boundary.

For the rejected acceptance, verify that the invitee gains no workspace access and that no member record is partially activated. A disabled button alone does not prove enforcement. Use an authorized integration check for the server rule as well as a browser check for the explanation and recovery path.

Express units before testing file sizes

Suppose uploads allow a maximum of 10 MiB, defined as 10,485,760 bytes. Choose files of 10,485,759, 10,485,760, and 10,485,761 bytes that otherwise satisfy the same format requirements. Padding arbitrary bytes onto a document can corrupt it and accidentally turn a size check into a file-format check.

If the UI says “10 MB” while the service uses MiB, resolve that discrepancy before marking a near-limit file wrong. Record raw byte size with each fixture. Include a valid smaller file to distinguish a size defect from a generally broken upload path.

Keep size enforcement and feedback separate: an oversized upload should not become a durable record, and the user should understand why it was rejected. A browser test can verify the visible result; the API or storage layer may be needed to verify rejected data was not retained.

Apply the same method to dates and lengths

For an invitation that expires at a documented instant, test just before, exactly at, and just after expiry using a controllable server clock or prepared fixtures. Changing only the browser clock cannot establish server-side expiry behavior. The time-dependent testing guide covers that distinction.

For a name limited to 50 characters, first define what “character” means: bytes, Unicode code points, or user-perceived graphemes can differ. Use simple ASCII strings for the initial 49/50/51 check, then add a separate Unicode check against the agreed counting rule.

Watch for boundaries that move

A plan upgrade changes the seat threshold. A deletion frees capacity. Two users can accept invitations against the same final available seat. These are separate dimensions to add after the basic boundary cases are stable.

The concurrent case needs a coordinated experiment: both acceptance attempts must reach the capacity decision at overlapping times. Sequentially clicking twice does not establish protection against a race. Continue with concurrency testing when the limit depends on shared state.

A reusable boundary worksheet

For each limit, record the rule, units, inclusive or exclusive endpoint, operation under test, adjacent values, and expected side effects. Add how you establish and reset the starting state. Then identify one nearby valid case that confirms the feature still works after a rejection.

Your exercise: choose one real product limit and write three independent cases around its threshold. If you cannot state the expected result at the exact limit, you have found a requirement question worth resolving before automation.

Next in the series: Decision table testing.