Now, in basic path testing, we try to execute all of the independent paths that we have and feed the program at least once. What we're going to do is we're going to derive a logical complexity measure in terms of cyclomatic complexity for the code and then use this measure to define a basic set of execution paths. A set of independent paths that we're going to use for testing. What we're going to do is to add from the code. We're going to draw a flow graph. Then we're going to determine the psychometric complexity from the flow program. Then after that, we're going to determine a set of linearly independent paths based on the cyclomatic complexity. Then finally, we're going to prepare a set of test cases that we will execute independent paths that we have in the basic side. The first thing that we have to do is to draw a flow graph and this are the notations that we can use any flow graph. If this sequential execution of stamens one-by-one, we can use this drawing, okay, one statement after the other. If we have a conditional statement, then we can use this drawing. If the condition is true, we do something. Otherwise, we do something else, et cetera. If we have case or switch, then we can use this drawing. We have different conditions. If we have a do while loop, then we're going to draw this. Do something while something is true. Until the condition is not true, then we're going to exit the loop or do until loop. Do something until the condition is no longer true and we exit the loop. Now, let's try to draw a flow graph or this little procedure. We start with statement number 1, which is a do-while loop and if the condition is true, we're going to continue with statement number 2 and also statement number 3. Then statement number 3 is a conditional statement. If its true, then we're going to execute statement number 4 and 5. If it's false, then we're going to execute statements 6 and 7. Now, you can see that statement number 7 is out of conditional statement. If is true, then we're going to execute statement number 8. If its false, then we're going to execute statement number 9 and also number 10 in sequence and then finally, after we finish the statement, we can immerse them into number 11, which is endif. Then another statement for endif. Then finally, another statement for enddo. Then we go back to the do while loop and then do to check in again. Then we're going to check the condition again for this do-while loop. If the condition is true, we're going to execute statement number two, free et cetera. If its false, then we end the program and then we go to statement number 14. After you get the flow graph, the next thing that you have to do is to simplify the flow graph by combining those sequential statements together. In this example, we can see that no matter what, we're going to execute, for example, a statement number 2 and number 3 together. Then we can combine them together as one single node. Also, we will see that no matter what we have to execute, for example, statement 4 and 5 together and also statement 6 and 7 together and also statement 9 and 10 together and then 12 and 13 together. Now, we can combine them together as a single node and there are some rules that we can use for combining sequential statements together as a single node. We can start with a simple node and what is a definition of a simple node? A simpler node is going to be just a node with one single outgoing arrow. Now, we can see that for statement number 2, we only have one outgoing arrow. It's going to be a simple node. What if we have more than one outgoing arrows, for example, a statement number of 3, which can be either true or false? Then we have a predicate. No. Now, one rule that we can use for merging sequential statements together as single node is that we can start with a simple node, which is this one, until we see a predicate node and then we also include the predicate node into the group. As another example, statement number 6 is an out of simple node and then we keep merging until we see a predicate node. Or another route that we can use is that we start with a simple one and then we keep merging until we see a node. For example, a statement number 12, which is shared by two paths. This is like path number 1 and this is path number 2. This node is shared by two paths. Then what we're going to do is start with a simple node until we see a node which is shared by two paths, and then we don't include this shared node into the group. That's why in this group, we only have, for example, a Statement 4 and 5 together. But not Statement 12 because we don't include the shared node into the group. Then this is another example, we start with a simple node which is Statement Number 9, and then we merge until we see 11 which is shared and then we stop, and we don't include 11 into the group. These are some of the rules that you can use for merging sequential statements together as a group. After simplification, this is the flow graph that we're going to get. After we group the sequential statements together as a single node this is the simplified version of the flow graph. After we get the simplified version of the flow graph, don't forget about this mapping table because it's going to tout us for example for node Number 2 we are referring to Statement 2 and 3. Because in our original flow graph we can see that this group is actually for Statement 2 and 3. That's why when you draw a flow graph you need this simplified version of the flow graph together with a mapping table to tout us exactly for example, a node is going to map to which statements in our program. Then after you get the flow graph you have to determine the cyclomatic complexity of the flow graph, and the cyclomatic complexity which is denoted as V(G) is going to be a quantitative measure of the logical complexity of the source code. If your source code is logically complicated the cyclomatic complexity will go higher, just because you have so many independent paths within your program. Cyclomatic complexity is going to provide an upper bound on the number of paths that needs to be tested in the code. It's just an upper bound may be less than that. How to calculate cyclomatic complexity? There are a few ways that we can use for calculating cyclomatic complexity. The first one is to count how many regions that we have within the flow graph. Now, let's consider putting different colors onto different regions on this flow graph. Then we can put one color on Region 1 and then another color on Region Number 2, and then another color on Region Number 3, and don't forget about the outside region which is the background region, which is Region Number 2. If we are considering coloring this flow graph then we have four different regions. Then the cyclomatic complexity of this flow graph is going to be four. Or you can also use, for example, the number of edges minus the number of nodes plus two. If you count carefully you will find that we have 11 edges and nine nodes within this flow graph. Using this equation, number of edges minus number of nodes, plus two, you get the same cyclomatic complexity which is four. Or you can count the number of predicate nodes plus one, so in this flow graph we have node one as a predicate node because it has two branches going out. Then node Number 2 is also a predicate node, node Number 3 is also another predicate node because it has branches. Now you can see that in this flow graph we have three predicate nodes, and then using the equation that means the number of predicate nodes plus one we're going to get the same cyclomatic complexity which is four. Now we can see that for this particular flow graph V(G) the cyclomatic complexity is going to be four. That means the upper bound of the number of independent paths that we can have for this flow graph is going to be four. Then after we determine the cyclomatic complexity we have to determine a basic set of linearly independent paths from the flow graph. The definition of independent path is a path that introduces at least one new set of processing statements or a new condition, and an independent path must traverse at least one edge in the flow graph that has not been traversed before the path is defined. A basic set is the set of linearly independent paths through the code. Notice that a basic set is not unique. That means you may have more than one set of independent paths from the same code. Test cases derived from a basis set are guaranteed to execute every statement at least once during testing. That means using basic path testing is going to guarantee that every single statement that you have in the program is going to be executed in the test. Now, let's take a look at this example, and we can see that we have three regions in this flow graph and the cyclomatic complexity is three. Now the question is that how many independent paths that we have in the basic set? Remember that any independent path introduces at least one new set of statement or a new condition. That means it tri versus at least one new edge in the flow graph. The answer is two. Again, the basic set may not be unique so that means we're going to have more than one basic sets for the same code and for the same flow graph. Notice that the number of independent paths that we have in a basic set is smaller than the cyclomatic complexity because the cyclomatic complexity is going to be just an upper bar on the number of independent paths that we have for a flow graph. The number of independent paths that we have in a flow graph may be less than the cyclomatic complexity. In the first basic set, we have one path and then we have an outer path which is independent to the red one. Then in the second basic set, we have one path which is red one and then we have another path which is the green one which is independent to the red one. When we perform testing, we can choose to either use to first set or the second set. In this example, the basic sets is not unique and also the number of paths that we have in the basic set is less than the cyclomatic complexity. Again, just because the cyclomatic complexity is an upper bar on the number of independent paths that we have for a given flow graph. In this example that we have seen before, seems the cyclomatic complexity is flow. That means is we can have at most four independent paths into basic set. These are the independent paths that we have in this flow graph. We just line from statement 1-14, statement 1, 2, 3, 4, 5, 12, 13 and 14, and then 1, 2, 3, 6, 7, 8, 11, 12, 13 and 14, and then last one is 1, 2, 3, 6, 7,9, 10, 11, 12, 13, and 14. But notice that this Path 1 and then 14 is not really independent to the other paths because you can see that one and 14 already exist in the other paths. But still it's a good idea, even though is not an independent path. Is a good idea to test out his path when we perform testing. Why? Remember that the first daemon is a do-while kind of statement. While we have rickets in, for example, in array then we're going to perform something. Otherwise we're going to exit the program. When we perform testing, is a good idea that we're going to try it out. For example, with the program with an array which is empty without any record. For example, if there's no record in the array, then I'm going to exit the program immediately. We just like going from statement Number 1 and then 14. That's why even this Path 1 and then 14 is not independent to the other paths. It's a good idea to include it in our testing because it's going to test out a situation when the array is empty, and we don't have any record then we're going to exit the program immediately. Then after we get all the independent paths from our basic set, we can to prepare the test cases that force the execution of each path in the basic set. Notice that the basic set refers to the statement numbers in the program. For example in this example flow graph that we have, each path is going to be just a set of statements. Then we also have to count each logical task to make sure that we have covered all the predicate notes. All to conditional statements or statements with branches in our flow graph. Then finally, basic path testing should be applied to all components if possible, and to critical components always. You may ask, do we applied basic path testing to every single procedure that I have within my program? I always say no because drawing flow graphs is going to take time. If you have many procedures within your program, this is going to take a long time to finish all the basic path testing's within your program. That's why I say that when we perform basic path testing, we focus on critical components that are logically complicated. For example, if you have a procedure with many, many conditionals statement and also many, many loops and is logically complicated, then we should apply basic path testing on that particular procedure. Then let's say if you simply have a procedure which is sequential execution of a set of statements, then you may skip basic path testing on that procedure because is not logically complicated. But notice that in basic path testing, we do not test all the possible combinations of all the paths through the code. But instead, we simply test every path that we have in the flow graph at least once and that's all I want to cover in this lecture.