Skip to content
Bugwise
Menu
Testing Fundamentals

Boundary Value Analysis

Bugs love edges. Learn why mistakes cluster at the limits of a rule, how to pick 2-value and 3-value boundary tests, and how to find off-by-one bugs in ages, passwords, dates, money, lists and prices.

beginner Mobile & web
Short on time? Switch to the quick version.

An online shop launches a summer promotion: “Free shipping on orders of €50 or more!” It’s tested, it ships, and the first weekend goes well. Then the support inbox fills up. Dozens of customers carefully filled their carts to exactly €50.00, and every single one was charged €4.99 for shipping.

The tester had checked a €35 cart (pays shipping) and an €80 cart (free shipping). Both passed. The bug lived in the one place nobody looked: the exact edge, €50.00. The developer had written “more than 50” instead of “50 or more”.

This is the most common kind of bug in the world, and there’s a technique built to catch it: boundary value analysisBoundary value analysisTesting values at and just around the edges of valid ranges, where bugs love to hide.Open in glossary → (BVA).

Why bugs cluster at the edges

In Equivalence Partitioning you learned to split values into groups that behave the same, like ages 17-and-under, 18–60 and 61-and-over in a fitness app’s sign-up form. A boundary is the edge of one of those groups: the smallest or largest value in a partition.

Developers turn requirements into comparisons like “greater than” or “less than or equal to”. Picking the wrong one, or a number that’s one too high or too low, is an off-by-one errorOff-by-one errorA bug where a count or boundary is wrong by exactly one, like counting days instead of nights.Open in glossary →. The code works for almost every value and fails only at the edge:

RequirementBug in the codeOnly caught by
Age 18 or olderage > 18 (should be >=)18
Free shipping from €50total > 50 (should be >=)€50.00
Password max 64 charslen <= 63 (should be 64)64 chars
Up to 10 itemsqty < 10 (should be <=)10 items

In every row, a value from the middle of the partition (35, €80, 20 characters, 5 items) passes perfectly. Only a value at the edge reveals the problem. That’s the whole case for BVA: test exactly where the behavior changes.

The quick version

2-value and 3-value BVA

For the age rule 18–60 there are two boundaries: 18 (the smallest valid age) and 60 (the largest).

2-value BVA tests each boundary plus its closest neighbor on the other side:

2-value BVA · age 18–60

≤ 17

Invalid

18 – 60

Valid

≥ 61

Invalid

1718
6061
Four tests: 17, 18, 60, 61.

3-value BVA tests each boundary plus its closest neighbors on both sides:

3-value BVA · age 18–60

≤ 17

Invalid

18 – 60

Valid

≥ 61

Invalid

171819
596061
Six tests: 17, 18, 19 and 59, 60, 61. The extra inner values catch a few sneakier bugs.

Most everyday testing uses 2-value BVA. Teams switch to 3-value for risky rules: money, security, legal age limits.

Boundaries are everywhere

  • Lengths: password 8–64 characters → 7, 8, 64, 65.
  • Dates: first and last day of a month, 29 February, 31 December, yesterday / today / tomorrow.
  • Money: €0.00, €0.01, and the maximum (a €1,000 transfer limit → €1,000.00 and €1,000.01).
  • Lists: 0 items, 1 item, the maximum, one more than the maximum.
  • Outputs: free shipping at €50.00, so test €49.99 and €50.00.

BVA and EP work together

EP picks one value from the middle of each partition (35); BVA tests the edges (17, 18, 60, 61). EP also covers partitions that have no edges at all, like an empty field or “abc”. Use both, every time.

Finding the boundaries step by step

  1. Start with your partitions. BVA builds on EP. For the age field: 17 or less, 18–60, 61 or more.
  2. Find the step size. What is the smallest possible change? 1 for whole years, 1 for characters, €0.01 for euros, 1 day for dates.
  3. Find each boundary. The smallest and largest value of each ordered partition: 18 and 60.
  4. Add the neighbors. One step outside each boundary (17, 61). For 3-value BVA, also one step inside (19, 59).
  5. Write the expected result for each value. 17 is rejected, 18 is accepted, and so on. A boundary test without an exact expected result is just a guess.

2-value BVA

For each boundary, test the boundary value itself and the closest value on the other side of the boundary (in the neighboring partition).

2-value BVA · age 18–60

≤ 17

Invalid

18 – 60

Valid

≥ 61

Invalid

1718
6061
ValueWhyExpected
17Last invalid value below the rangeRejected
18Lower boundary, first valid valueAccepted
60Upper boundary, last valid valueAccepted
61First invalid value above the rangeRejected

This catches the classic mistakes: > instead of >= at the lower edge (18 is wrongly rejected), age <= 61 instead of age <= 60 (61 is wrongly accepted), or age < 60 instead of age <= 60 (60 is wrongly rejected).

3-value BVA

For each boundary, test the boundary value and the closest value on both sides.

3-value BVA · age 18–60

≤ 17

Invalid

18 – 60

Valid

≥ 61

Invalid

171819
596061

The extra values (19 and 59) look redundant, but they catch bugs that 2-value BVA misses. Imagine a developer wrote age == 18 (exactly 18) instead of age >= 18 for the lower check:

ValueCorrect resultBuggy age == 18Caught?
17RejectedRejectedNo
18AcceptedAcceptedNo
19AcceptedRejectedYes

2-value BVA (17 and 18) passes and the bug ships. Only 19, the inside neighbor, exposes it.

MethodValues for 18–60TestsBest for
2-value17, 18, 60, 614Everyday features
3-value17, 18, 19, 59, 60, 616Money, security, legal limits

Boundaries are everywhere

Lengths

A banking app requires passwords of 8 to 64 characters. The step is one character.

Password length (8–64 characters)

0 – 7

Too short

8 – 64

Accepted

≥ 65

Too long

789
636465
2-value: 7, 8, 64, 65. 3-value adds 9 and 63. Don't forget 0 (empty), which EP covers.

Practical tips:

  • Count precisely. Prepare test strings of exact lengths in a notes file (for example Abcdef1! is 8 characters). A character counter tool helps for 64.
  • Watch for silent truncation. If the field stops accepting input after 64 characters, typing 65 just gives you 64. That’s often fine, but check that a pasted 65-character password isn’t silently cut to 64 and saved, so the user can never log in with what they typed. See truncationTruncationText that gets cut off because it doesn't fit its space.Open in glossary →.
  • Password managers generate long passwords. A real-world max-length bug (a limit of 63 instead of 64) hits exactly those careful users. More in Login and Sign-up.

Dates

Dates have more boundaries than any other data type. The step is usually one day (sometimes one minute).

BoundaryTest valuesTypical bug
Month end31 Jan → 1 Feb, 30 Apr“31 April” accepted, or a 30-day month gets 31
Leap day29 Feb 2028 (valid), 29 Feb 2027 (invalid)Leap year rule wrong, or a crash on 29 Feb
Year end31 Dec → 1 JanYear doesn’t roll over in a booking
“Not in the past”yesterday, today, tomorrowToday wrongly blocked, or yesterday allowed
Age from birth dateturned 18 today vs. turns 18 tomorrowOff by a day around the birthday

Midnight is a boundary too, and time zonesTime zoneThe local time of a region. Bugs appear when apps mix up the user's time zone with the server's.Open in glossary → move it: “today” for a hotel in Tokyo may still be “yesterday” for a user in New York. Daylight saving changes create days with 23 or 25 hours (see Daylight saving time (DST)Daylight saving time (DST)Moving clocks forward in spring and back in autumn, creating a skipped hour and a repeated hour.Open in glossary →). The Date Picker page has lots of examples.

Money

The step for euros, dollars and pounds is one cent (0.01). Some currencies, like the Japanese yen, have no cents in everyday use, so the step is 1.

A banking app allows transfers from €0.01 to €1,000.00 per day:

Transfer amount (€0.01–€1,000.00)

≤ €0.00

Rejected

€0.01 – 1,000

Sent

≥ €1,000.01

Over limit

0.000.01
1,000.001,000.01
Test €0.00, €0.01, €1,000.00 and €1,000.01. The upper pair is exactly the bug from the banking example in What Is Software Testing?

Also try amounts with more decimals than allowed (€10.999), very large numbers (€99,999,999), and think about rounding: does €0.005 become €0.01 or €0.00?

Lists and counts

Anything you can count has boundaries: items in a cart, photos in a review, results on a page, seats on a flight.

CountWhy it matters
0The empty stateEmpty stateThe screen a user sees when there is no content yet, like an empty cart or no search results.Open in glossary →: empty cart, no search results. Checkout must be disabled, a friendly message shown.
1Singular text (“1 item”, not “1 items”), lists that break with only one row.
MaxA review allows 5 photos: the 5th must upload.
Max + 1The 6th photo must be blocked with a clear message, not crash or silently vanish.

paginationPaginationSplitting a long list into pages that load one at a time.Open in glossary → is a great place to look: with 20 results per page, test 20 results (one page) and 21 results (a second page with a single item).

Outputs

Just like EP, BVA works on outputs. Find the input values that put you right at the edge of a different result.

Shipping cost (output boundaries)

under €20

€4.99

€20 – 49.99

€2.99

≥ €50

Free

19.9920.00
49.9950.00
Build carts worth exactly €19.99, €20.00, €49.99 and €50.00. Also check the message: 'Add €0.01 more for free shipping' should appear at €49.99.

Remember that outputs depend on the final number: a €55 cart with a €5 coupon is exactly €50.00. Does it still get free shipping? See Shopping Cart and Checkout.

Classic boundary bugs

#BugWhat you seeTypical severity
1> instead of >=An 18-year-old can’t sign upHigh
2Free shipping at “more than” €50€50.00 cart pays €4.99Medium
3Max length one too short64-char password rejectedMedium
4Leap day not handledBooking for 29 Feb crashesHigh
5Limit check on the wrong side€1,000.01 transfer goes throughCritical
6Count off by oneA 6th photo uploads although the limit is 5Low–Medium

How BVA complements EP

Equivalence partitioningBoundary value analysis
PicksOne value from inside each partitionValues at and next to each edge
Age 18–6012, 35, 7217, 18, 60, 61
CatchesWhole partitions handled wronglyOff-by-one and wrong comparisons
Also coversEmpty, “abc”, 25.5 (no edges)Only ordered values

Together, a strong test set for the age field is: 35 (valid, EP), 17, 18, 60, 61 (BVA), plus empty, abc, 25.5 (EP partitions without edges). That’s 8 tests. You could drop 12 and 72, since 17 and 61 already represent those partitions.

Writing test cases from BVA

  1. One boundary value per test when it’s invalid, and keep every other field valid, so you know which value caused the error (the same rule as in EP).
  2. Put the exact value in the title or data. “Sign-up accepts age 18 (lower boundary)” is far clearer than “Test age boundary”.
  3. Write an exact expected result. Not “works”, but “Account is created and the Goals screen opens”.
  4. Valid boundaries can be combined when the fields are independent: 1 night, 1 guest and check-in today in one booking. If it fails, split it up.
  5. Link back to the requirement, so anyone can see why 64 and 65 matter.

You’ll find complete examples below, and more on the format in How to Write Test Cases. When a boundary test fails, report the exact value and what you expected; the bug report almost writes itself (see How to Write Bug Reports).

See also: Error Guessing and Checklists, which picks up where the boundaries stop: zero, negatives, other number formats and time zones.

Practice: pick the boundary values

Choose a rule and a mode, then tap the values you would test. After checking, the underline shows which values are valid (green) and invalid (red).

🎯 Boundary game: pick the edge values

Tap the values you would test. Then check your picks.

Fitness app · sign-up

Age must be from 18 to 60 (inclusive).

2-value BVA: for each boundary, test the boundary value and its closest neighbor on the other side. Values move in steps of 1.

Around 18

Around 60

Find the off-by-one bugs

Three of these six rules were implemented with an off-by-one bug; the other three are correct. You can’t see the code, only the results. Test each rule with boundary values, decide whether it’s buggy, then check your verdicts.

🐞 Buggy implementation mode

Some of these six rules have an off-by-one bug. Use boundary values to find out which, then give your verdict.

  • Sign-up age

    Ages 18 to 60 can sign up.

    years
    • Cart quantity

      You can buy 1 to 10 of one item.

      items
      • Free shipping

        Shipping is free from €50.00.

        €
        • Password length

          Passwords must be 8 to 64 characters.

          characters
          • Hotel stay

            A booking is 1 to 30 nights.

            nights
            • Promo code length

              Codes are 6 to 10 characters.

              characters

              0/6 verdicts given

              Exercise: a hotel booking form

              Time to combine both techniques. Derive EP partitions and BVA values for this small travel app spec, type them in, and compare with the model answer.

              ✍️ Exercise: hotel booking form

              Write the EP and BVA values you would test for each field, then compare with the model answer.

              Spec · Travel app · "Book a room"

              • Nights: 1 to 30 whole nights.
              • Guests: 1 to 4 guests per room.
              • Check-in date: not in the past; at most 365 days ahead.
              • All three fields are required.

              Separate values with commas. Type empty for a blank field and any word (like abc) for non-numeric input.

              Example test cases

              TC-BVA-01Sign-up accepts age 18 (lower boundary)

              Preconditions

              • Fitness app is on the Create account screen

              Steps

              1. Enter a valid email and password
              2. Enter age 18
              3. Tap Continue

              Test data

              age: 18

              Expected result

              No error is shown and the Choose your goals screen opens.

              TC-BVA-02Sign-up rejects age 17 (just below the lower boundary)

              Preconditions

              • Fitness app is on the Create account screen

              Steps

              1. Enter a valid email and password
              2. Enter age 17
              3. Tap Continue

              Test data

              age: 17

              Expected result

              'You must be at least 18 to sign up' appears under Age and the account is not created.

              TC-BVA-03Order of exactly €50.00 gets free shipping

              Preconditions

              • Shop cart is empty
              • Free shipping threshold is €50.00

              Steps

              1. Add products worth exactly €50.00 to the cart
              2. Open the cart

              Test data

              cart total: €50.00

              Expected result

              Shipping shows 'Free' and the order total is €50.00.

              TC-BVA-04Order of €49.99 pays standard shipping

              Preconditions

              • Shop cart is empty
              • Free shipping threshold is €50.00

              Steps

              1. Add products worth €49.99 to the cart
              2. Open the cart

              Test data

              cart total: €49.99

              Expected result

              Shipping shows €2.99 and the message 'Add €0.01 more for free shipping' is displayed.

              TC-BVA-05Password of exactly 64 characters is accepted (upper boundary)

              Preconditions

              • Banking app is on the Set new password screen

              Steps

              1. Paste a 64-character password into New password and Confirm password
              2. Tap Save
              3. Log out and log in with the same password

              Test data

              password: 64 characters (letters, digits and symbols)

              Expected result

              The password is saved, and logging in with all 64 characters works.

              TC-BVA-06Password of 65 characters is rejected (just above the upper boundary)

              Preconditions

              • Banking app is on the Set new password screen

              Steps

              1. Paste a 65-character password into New password
              2. Tap Save

              Test data

              password: 65 characters

              Expected result

              'Password must be at most 64 characters' is shown and nothing is saved. If the field cuts pasted text to 64 characters instead, the user is clearly told; a silently shortened password is a bug.

              Tip: click a test case to expand it.

              Boundary value analysis checklist

              0 of 10 checked

              Check your understanding

              Quick quiz

              0/6 answered · 0 correct

              1. 1.Age must be 18 to 60. What is the 2-value BVA set?

              2. 2.Which extra values does 3-value BVA add for the same 18–60 rule?

              3. 3.Free shipping applies to orders of €50.00 or more. Which pair of tests is most likely to find a '>' vs '>=' bug?

              4. 4.A review lets you attach up to 5 photos. Which counts should you test with BVA?

              5. 5.Why doesn't BVA apply to a list of payment methods (Card, PayPal, Pay on delivery)?

              6. 6.A hotel booking says check-in can't be in the past. Which dates are the boundary tests?

              Key takeaways

              • Bugs cluster at edges because developers easily mix up > and >=, or type a limit one too high or too low (an off-by-one error).
              • A boundary is the smallest or largest value of an ordered partition. Find the step size first (1, €0.01, one day).
              • 2-value BVA: the boundary and its neighbor outside (17, 18 / 60, 61). 3-value BVA adds the neighbor inside (17, 18, 19 / 59, 60, 61).
              • Boundaries hide in lengths, dates, money, counts and outputs, and in technical limits nobody wrote down.
              • BVA complements Equivalence Partitioning: EP covers the middle and edge-less partitions; BVA covers the edges.
              • Write each boundary test with the exact value and an exact expected result.

              Finished this page?Nice work, this page is complete!

              Mark it as done to track your progress. It's saved in this browser, no account needed.

              Its review cards are now in Bites ⚡
              Esc

              Type to search the whole site.