top of page
Concrete

3-value Boundary Value Analysis: Misconception and Reality

  • giorgosvalamats
  • Jan 17
  • 9 min read


Not long ago, I encountered some examples of the 3-value Boundary Value Analysis (BVA) provided by various tutorials and community websites. Surprisingly, I found many cases where the supposedly “correct” answers did not implement the 3-value BVA accurately, either leading to missing test cases or resulting in exhaustive testing.


In this article, I aim to explain why misconceptions about the implementation of the 3-value BVA exist. By critically analysing the ISTQB Foundation syllabus and providing practical examples, we can better understand the correct approach to implementing the 3-value BVA.


Defining the Test Object

Let’s start by defining our test object: a password input field.

  • It will deny passwords that are shorter than 6 characters or longer than 16 characters, displaying an error message

  • For passwords 6–10 characters long, it will display the message “fair enough”

  • For passwords 11–16 characters long, it will display the message “excellent”


Equivalence Partitioning

First, we need to identify the equivalence partitions and their boundary values. The ISTQB Foundation mentions the following about the equivalent partitions:

…all the elements of a given partition are to be processed in the same way by the test object.

And about their boundary values:

The minimum and maximum values of a partition are its boundary values.

Based on the above, the equivalence partitions identified for our test object are:

Invalid - Short

Valid - fair

Valid - Excellent

Invalid - Long

(min) (max)

(min) (max)

(min) (max)

(min) (max)

0 .........5

6 ........... 10

11 .............. 16

17 ...........?

Where ? can be the maximum characters allowed to be written in the input field, or the max value of the integer type (e.g. for Java is Integer.MAX_VALUE)


2-value BVA

Before proceeding to the 3-value BVA, we’ll start with the simpler and indisputable 2-value BVA. The ISTQB Foundation provides the following information about it:

…for each boundary value there are two coverage items: this boundary value and its closest neighbor belonging to the adjacent partition.

Based on the above, we have identified the following coverage items:

Boundary value

Closest adj neighbour

0

n/a

5

6

6

5

10

11

11

10

16

17

17

16

?

?+1

In terms of test cases, we will have the following:

Test Cases

Coverage Item

Expected Result

01

0

password not accepted

02

5

password not accepted

03

6

password accepted - fair

04

10

password accepted - fair

05

11

password accepted - excellent

06

16

password accepted - excellent

07

17

password not accepted

08

?

password not accepted

09

?+1

password not accepted

So, in 2-value BVA the coverage items are the boundary values of each partition.


3-value BVA: The Misconception (?)

Now, let’s try to apply the 3-value BVA. Once again, the ISTQB Foundation provides the following information about 3-value BVA:

…for each boundary value there are three coverage items: this boundary value and both its neighbors. Therefore, in 3-value BVA some of the coverage items may not be boundary values.

Based on the above, we have identified the following coverage items:

Boundary - 1

Boundary value

Boundary + 1

n/a

0

1

4

5

6

5

6

7

9

10

11

10

11

12

15

16

17

16

17

18

?-1

?

?+1

Let’s simplify the above table and generate our test cases:

Test Cases

Coverage item

Expected Results

01

0

password not accepted

02

1

password not accepted

03

4

password not accepted

04

5

password not accepted

05

6

password accepted - fair

06

7

password accepted - fair

07

9

password accepted - fair

08

10

password accepted - fair

09

11

password accepted - excellent

10

12

password accepted - excellent

11

15

password accepted - excellent

12

16

password accepted - excellent

13

17

password not accepted

14

18

password not accepted

15

?-1

password not accepted

16

?

password not accepted

17

?+1

password not accepted

It is odd, right?

I guess that I’m not the only one who thinks that the above solution is quite odd. I imagine my OCD friends would already feel uneasy about the fact that for each boundary with the 3-value BVA we result in 4 coverage items.


On the other hand, the following example taken from the ISTQB Foundation, implies (?) that with the 3-value BVA we should only have 3 coverage items:

3-value BVA is more rigorous than 2-value BVA as it may detect defects overlooked by 2-value BVA. For example, if the decision “if (x ≤ 10) …” is incorrectly implemented as “if (x = 10) …”, no test data derived from the 2-value BVA (x = 10, x = 11) can detect the defect. However, x = 9, derived from the 3-value BVA, is likely to detect it.

Which is correct?

Consider this question: Which values should we pick as coverage items for the boundary 10|11?


a. 9, 10, 11

b. 10, 11, 12

c. 9, 10, 11, 12


I feel that most people would unconsciously choose the answer a. But after reading this, they would choose the answer c, but still they wouldn’t be fully convinced.


In my opinion, this confusion arises because the above ISTQB Foundation example is incomplete and requires further explanation to be fully understood.


Let’s think of it

In the ISTQB example, the decision “if (x ≤ 10)” represents the upper boundary of the 6–10 partition. If we examine this boundary in isolation, we should test the values 9, 10 and 11:- For 9 and 10 the test object has the behaviour “fair enough”- For 11 the test object has the behaviour “excellent


But what about the lower boundary of the adjacent partition (11–16)? Since the decision “if (x ≤ 10)” exists, there must be another decision block, like “else” or “else if”. That decision block can be tested by the values 10, 11 and 12:- For 10 the test object has the behaviour “fair enough”- For 11 and 12 the test object has the behaviour “excellent


At first glance, it seems logical that to efficiently test the boundary 10|11 from both sides, we should select 9, 10, 11, and 12 as coverage items.


Let’s dive deeper

In terms of coding, the boundary 10|11 can be expressed in various ways, but eventually all summarise into these options:


  • Expressions that can be used to express the left side of the boundary 10|11 (partition “Fair enough”):

passwordLength <= 10
passwordLength < 11
  • Expressions that can be used to express the right side of the boundary 10|11 (partition “Excellent”):

passwordLength > 10
passwordLength >= 11

Errors, errors, errors…

How many errors can someone do at the above logical expressions? If you think about how many ways there are to set things right, well, there’ll always be a whole lot more ways to muck it all up!


At the above logical expressions, the errors can occur:

  • at the comparison operators (<, <=, >, >=, ==)

  • at the boundary values (e.g. using 1 value below/above)

  • a combination of the above


So, let’s rewrite the above logical expressions containing all the possible errors. At the same time, let’s evaluate which of the coverage items (9, 10, 11, 12) would catch the bug.


6–10 partition upper boundary

As we already said, this boundary is expressed with one of the following logical expressions:

  • length ≤ 10

  • length < 11


So for the coverage items 9, 10 the above logical expressions should evaluate to TRUE, and for the coverage items 11, 12 to FALSE.


Let’s see in action how an error at these expressions relates to the coverage items. The tables below show different cases of possibly wrong implementations and the test results.


Cases of wrong implementation of the expressions length <= 10 and length < 11 and comparison of expected/actual results for the coverage items 9, 10, 11, 12


T: expression is true for the coverage item

F: expression is false for the coverage item

*/*: expected result of the coverage item for the original expression / actual result with the wrong expression

V: the error occurs at the value of the logical expression

O: the error occurs at the operator of the logical expression


only for length <= 10

no.

Expression

9

10

11

12

Error case

1

length <= 9

T/T

T/F

F/F

F/F

V

2

length < 9

T/F

T/F

F/F

F/F

O+V

3

length > 9

T/F

T/T

F/T

F/T

O+V

4

length >= 9

T/T

T/T

F/T

F/T

O+V

5

length = 9

T/T

T/F

F/F

F/F

O+V


only for length < 11

no.

Expression

9

10

11

12

Error case

6

length < 12

T/T

T/T

F/T

F/F

V

7

length <= 12

T/T

T/T

F/T

F/T

O+V

8

length > 12

T/F

T/F

F/F

F/F

O+V

9

length >= 12

T/F

T/F

F/F

F/T

O+V

10

length = 12

T/F

T/F

F/F

F/T

O+V


common for length <= 10 (A) and length < 11 (B)

no.

Expression

9

10

11

12

Error case

11

length <= 11

T/T

T/T

F/T

F/F

V: A

O: B

12

length > 11

T/F

T/F

F/F

F/T

O+V: A

O: B

13

length >= 11

T/F

T/F

F/T

F/T

O+V: A

O: B

14

length = 11

T/F

T/F

F/T

F/F

O+V: A

O: B

15

length < 10

T/T

T/F

F/F

F/F

O: A

V: B

16

length > 10

T/F

T/F

F/T

F/T

O: A

O+V: B

17

length >= 10

T/F

T/T

F/T

F/T

O: A

O+V: B

18

length = 10

T/F

T/T

F/F

F/F

O: A

O+V: B


11–16 partition lower boundary

As we already said, this boundary is expressed with one of the following logical expressions:

  • length > 10

  • length ≥11


So for the coverage items 9, 10 the above logical expressions should evaluate to FALSE, and for the coverage items 11, 12 to TRUE.


Cases of wrong implementation of the expressions length > 10 and length >= 11 and comparison of expected/actual results for the coverage items 9, 10, 11, 12


T: expression is true for the coverage item

F: expression is false for the coverage item

*/*: expected result of the coverage item for the original expression / actual result with the wrong expression

V: the error occurs at the value of the logical expression

O: the error occurs at the operator of the logical expression


only for length > 10

no.

Expression

9

10

11

12

Error case

19

length > 9

F/F

F/T

T/T

T/T

V

20

length >= 9

F/T

F/T

T/T

T/T

O+V

21

length < 9

F/F

F/F

T/F

T/F

O+V

22

length <= 9

F/T

F/F

T/F

T/F

O+V

23

length = 9

F/T

F/F

T/F

T/F

O+V


only for length >= 11

no.

Expression

9

10

11

12

Error case

24

length >= 12

F/F

F/F

T/F

T/T

V

25

length > 12

F/F

F/F

T/F

T/F

O+V

26

length < 12

F/T

F/T

T/T

T/F

O+V

27

length <= 12

F/T

F/T

T/T

T/T

O+V

28

length = 12

F/F

F/F

T/F

T/T

O+V


common for length > 10 (A) and length >= 11 (B)

no.

Expression

9

10

11

12

Error case

29

length >= 10

F/F

F/T

T/T

T/T

O: A

V: B

30

length < 10

F/T

F/F

T/F

T/F

O: A

O+V: B

31

length <= 10

F/T

F/T

T/F

T/F

O: A

O+V: B

32

length = 10

F/F

F/T

T/F

T/F

O: A

O+V: B

33

length > 11

F/F

F/F

T/F

T/T

V: A

O: B

34

length < 11

F/T

F/T

T/F

T/F

O+V: A

O: B

35

length <= 11

F/T

F/T

T/T

T/F

O+V: A

O: B

36

length = 11

F/F

F/F

T/T

T/F

O+V: A

O: B


Understanding the results

From the results above we see that:


For the 6–10 partition upper boundary:

  • Coverage item 9: It’s the only one that catches the case 18

  • Coverage item 10: It’s the only one that catches the cases 1, 5, 15

  • Coverage item 11: It’s the only one that catches the cases 6, 11

  • Coverage item 12: When it fails, any other of the previous coverage items fails too. So it doesn’t offer value in testing this side of the boundary

For the 11–16 partition lower boundary:

  • Coverage item 9: When it fails, any other of the previous coverage items fails too. So it doesn’t offer value in testing this side of the boundary

  • Coverage item 10: It’s the only one that catches the cases 19, 29

  • Coverage item 11: It’s the only one that catches the cases 24, 28, 33

  • Coverage item 12: It’s the only one that catches the case 36

Here are also some aggregated statistics:

  • Each coverage item (9, 10, 11, 12) detects 55.5% of cases (20 out of 36)

  • Each boundary value (10, 11) uniquely detects 13.9% of cases (5 out of 36)

  • Each neighbour value (9, 12) uniquely detects 2.8% of cases (1 out of 36)

  • 2-value BVA detects 94.4% of cases (34 out of 36)

  • 3-value BVA with 3 coverage items detects 97.2% of cases (35 out of 36)

  • 3-value BVA with 4 coverage items detects 100% of cases


3-value BVA: The Reality

According to the above results, we conclude that what seemed like a misconception is actually the correct approach to testing the boundaries of adjacent partitions.


The real misconception lies in the belief that 3-value BVA always results in 3 coverage items. If we limit ourselves to this approach (e.g., testing only 9, 10, 11 or 10, 11, 12), we risk reducing the bug detection rate by 2.8%.


Conclusion

To summarise, here’s a simple rule of thumb:

  • 2-value BVA: Always results in 2 coverage items (the boundary values themselves).

  • 3-value BVA:

    • For a single partition boundary (tested in isolation), results in 3 coverage items (the boundary value and its two neighbours).

    • For boundaries between two partitions, results in 4 coverage items (each partition’s boundary value and their respective neighbours).


Which to choose?

Which approach should you choose? The choice depends on the nature and criticality of your product. From my side, I hope this article has provided you with valuable insights to help you select the approach that best fits your needs and has given you a new perspective on the 3-value BVA test technique. :)

 
 
 

Comments


bottom of page