The basis path testing technique d is one of a number of techniques for control structure testing. Although basis path testing is simple and highly effective, it is not sufficient in itself. Other variations on control structure testing helps in broadening testing coverage and improve quality of white-box testing.

**Condition Testing**

Condition testing is a test case design method that exercises the logical conditions contained in a program module. A simple condition is a Boolean variable or a relational expression, possibly preceded with one NOT (¬) operator. A relational expression takes the form

**E1 <relational-operator> E2**

where E1 and E2 are arithmetic expressions and <relational-operator> is one of the following: <, ≤, =, ≠ (nonequality), >, or ≥. A compound condition is composed of two or more simple conditions, Boolean operators, and parentheses. We assume that Boolean operators allowed in a compound condition include OR (|), AND (&) and NOT (¬). A condition without relational expressions is referred to as a Boolean expression.

Therefore, the possible types of elements in a condition include a Boolean operator, a Boolean variable, a pair of Boolean parentheses (surrounding a simple or compound condition), a relational operator, or an arithmetic expression.

If a condition is incorrect, then at least one component of the condition is incorrect. Therefore, types of errors in a condition include the following:

**•**Boolean operator error (incorrect/missing/extra Boolean operators).

**•**Boolean variable error.

**•**Boolean parenthesis error.

**•**Relational operator error.

**•**Arithmetic expression error.

The condition testing method focuses on testing each condition in the program. Condition testing strategies generally have two advantages. First, measurement of test coverage of a condition is simple. Second, the test coverage of conditions in a program provides guidance for the generation of additional tests for the program.

The purpose of condition testing is to detect not only errors in the conditions of a program but also other errors in the program. If a test set for a program P is effective for detecting errors in the conditions contained in P, it is likely that this test set is also effective for detecting other errors in P. In addition, if a testing strategy is effective for detecting errors in a condition, then it is likely that this strategy will also be effective for detecting errors in a program.

A number of condition testing strategies have been proposed. Branch testing is probably the simplest condition testing strategy. For a compound condition C, the true and false branches of C and every simple condition in C need to be executed at least once .

Domain testing requires three or four tests to be derived for a relational expression. For a relational expression of the form

**E1 <relational-operator> E2**

three tests are required to make the value of E1 greater than, equal to, or less than that of E2 . If <relational-operator> is incorrect and E1 and E2 are correct, then these three tests guarantee the detection of the relational operator error. To detect errors in E1 and E2, a test that makes the value of E1 greater or less than that of E2 should make the difference between these two values as small as possible.

For a Boolean expression with n variables, all of 2n possible tests are required (n > 0). This strategy can detect Boolean operator, variable, and parenthesis errors, but it is practical only if n is small.

Error-sensitive tests for Boolean expressions can also be derived . For a singular Boolean expression (a Boolean expression in which each Boolean variable occurs only once) with n Boolean variables (n > 0), we can easily generate a test set with less than 2n tests such that this test set guarantees the detection of multiple Boolean operator errors and is also effective for detecting other errors.

Tai suggests a condition testing strategy that builds on the techniques just outlined. Called BRO (branch and relational operator) testing, the technique guarantees the detection of branch and relational operator errors in a condition provided that all Boolean variables and relational operators in the condition occur only once and have no common variables.

The BRO strategy uses condition constraints for a condition C. A condition constraint for C with n simple conditions is defined as (D1, D2, . . ., Dn), where Di (0 < i ≤ n) is a symbol specifying a constraint on the outcome of the ith simple condition in condition C. A condition constraint D for condition C is said to be covered by an execution of C if, during this execution of C, the outcome of each simple condition in C satisfies the corresponding constraint in D.

For a Boolean variable, B, we specify a constraint on the outcome of B that states that B must be either true (t) or false (f). Similarly, for a relational expression, the symbols >, =, < are used to specify constraints on the outcome of the expression.

As an example, consider the condition

**C1: B1 & B2**

where B1 and B2 are Boolean variables. The condition constraint for C1 is of the form (D1, D2), where each of D1 and D2 is t or f. The value (t, f) is a condition constraint for C1 and is covered by the test that makes the value of B1 to be true and the value of B2 to be false. The BRO testing strategy requires that the constraint set {(t, t), (f, t), (t, f)} be covered by the executions of C1. If C1 is incorrect due to one or more Boolean operator errors, at least one of the constraint set will force C1 to fail.

As a second example, a condition of the form

**C2: B1 & (E3 = E4)**

where B1 is a Boolean expression and E3 and E4 are arithmetic expressions. A condition constraint for C2 is of the form (D1, D2), where each of D1 is t or f and D2 is >, =, <. Since C2 is the same as C1 except that the second simple condition in C2 is a relational expression, we can construct a constraint set for C2 by modifying the constraint set {(t, t), (f, t), (t, f)} defined for C1. Note that t for (E3 = E4) implies = and that f for (E3 = E4) implies either < or >. By replacing (t, t) and (f, t) with (t, =) and (f, =), respectively, and by replacing (t, f) with (t, <) and (t, >), the resulting constraint set for C2 is {(t, =), (f, =), (t, <), (t, >)}. Coverage of the preceding constraint set will guarantee detection of Boolean and relational operator errors in C2.

As a third example, we consider a condition of the form

**C3: (E1 > E2) & (E3 = E4)**

where E1, E2, E3, and E4 are arithmetic expressions. A condition constraint for C3 is of the form (D1, D2), where each of D1 and D2 is >, =, <. Since C3 is the same as C2 except that the first simple condition in C3 is a relational expression, we can construct a constraint set for C3 by modifying the constraint set for C2, obtaining

**{(>, =), (=, =), (<, =), (>, >), (>, <)}**

Coverage of this constraint set will guarantee detection of relational operator errors in C3.