Basis path testing in software testing is a white box method where the tester examines the codebase to identify all possible paths that could be taken by the user to achieve their aims. These paths are then written as test cases to ensure all the different identified scenarios in the main branches are covered. Higher test coverage is then achieved when test cases are executed, typically through a form of unit testing.
The tester established a baseline by selecting the most critical, common, or obvious path through the code selection. Then, with each test case, the tester will choose different options through the baseline to change the outcomes. This enables the tester to create relevant test cases, ensuring branch coverage. It also prevents duplicate or overlapping tests by ensuring each decision is only covered once.
Steps to Performing Basis Path Testing
- The first step is to create a control flow graph for a specified code section. A control flow graph is a section of code displayed as a graph along with the possible paths that could be executed.
Here is a simplified control flow graph for an if-then-else statement. The circles are nodes that represent blocks, and the lines connecting them are edges, which represent control flow paths.
- The second step is to select a baseline path through the code. This baseline path should be the path most likely used. It is also the most critical path to test, as it will be the foundation for all other tests. Typically, a product manager will provide the baseline path labeled as the critical path.
- Once the baseline path is selected, generate the second path by changing the outcome of the first decision. Remember, you are not necessarily changing every decision along the path. The emphasis is on ensuring a different outcome after the decisions are made. The maximum number of decision outcomes should remain the same as the initial baseline path.
- Generate a third path by changing the outcome of the second decision on the path. When there are multiple options for a decision, each decision outcome should be exercised before moving on to the next decision.
- Continue generating new paths by repeating these steps. The most important outcome should be chosen first if new decisions are encountered.
- Finally, once all the decision outcomes on the baseline path have been covered, apply the same approach to all subsequent paths until all the decision outcomes in the specified code have been exercised.
An example may help for better understanding. Let’s say we want to perform basis path testing on a basic block of code. First, we will create our control flow graph.
x = 0 print(x) if x > 10 print (‘try again’) else print (‘success’) end
The control flow graph could look something like this:
However, we know that we often have a more complicated scenario than that. Let’s show what happens when we have a compound statement.
x = 0 while x < 10 if x > 2 print (x) else print ('x is less than 3') end x += 1 end
As you can see, this path is more involved and will require more testing than the first example. But how do we know how many test cases need to be created to ensure branch coverage?
For step 2, we will determine a baseline path using our control flow graph. Let’s say the most likely path looks like this:
This would be our first test case. We can use a simple equation called cyclomatic complexity to determine how many test cases we need for full branch coverage. Don’t let the word ‘complexity’ concern you because the equation is straightforward:
C = E – N + 2P
C = Cyclomatic Complexity = Number of test cases
E = the number of edges on the graph,
N = the number of nodes on the graph,
P = the number of connected components, which for a single program, or section of code, P will always equal 1.
The cyclomatic complexity tells you how ‘complex’ the code is, as it equals the number of linearly independent paths within the code, which equates to the number of required test cases. So, to determine the number of test cases, we can say, for our example:
C = E – N + 2P
C = 8 – 7+ 2×1
C = 3
For step 3, we will use our baseline path, but we will ensure that we have a different outcome. We also want to make certain we are prioritizing the outcomes. If necessary, we can use a risk-based approach for these decisions. Our new path could possibly look like this:
We can continue changing the paths until all outcomes are evaluated. By using our cyclomatic complexity equation, we know we have 3 different outcomes. Our final path could look like this:
Tools to use in basis path testing
If equations and creating graphs aren’t your specialty, you’ll probably be glad to know there are tools that can help with basis path testing in software testing.
- LucidChart – LucidChart has an easy, user-friendly interface for creating, editing, and collaborating on workflows. It is excellent for brainstorming across multiple teams or projects. There are free and paid versions available.
- Eclipse CFG Generator – Eclipse Control Flow Graph Generator is a plug-in for Eclipse IDE that can create control flow graphs based on the source code. It only works with Java and is open-source.
- OmniGraffle – OmniGraffle by The Omni Group is a powerful diagramming, prototyping, and design tool for Mac and iOS products that promotes collaboration with style. It has paid version available and offers a 14-day free trial.
Benefits and Challenges
There are benefits to basis path testing in software testing.
- Basis path testing increases test coverage by revealing outcomes that may not be otherwise evident without examination of the codebase. A tester should attempt to achieve different outcomes, but it can be difficult (especially for large or complex systems) to know all the possible outcomes.
- Basis path testing also ensures branch coverage. This is important because, in agile development, many developers work on branches of code before merging that code with the existing repository. They can also be assured they aren’t creating unnecessary or overlapping tests.
Basis path testing also comes with challenges.
- Today, many DevOps setups require a certain amount of unit coverage before deploying to the next environment. If this is not the case, enforcing this type of testing may be difficult because it can be considered unnecessary or extra work.
- If performed as a method other than unit testing, the tester must be able to understand the code, which could alienate some resources.
- Finally, basis path testing can be time-consuming, which may take away from further development or alternative testing methods.
Basis path testing is a white box testing method that ensures branch coverage by testing each outcome of a section of code. While it may seem complicated because of its mathematical association, the intent behind the math is to simplify testing. The tester must understand the code to be prepared to meet any unit testing requirements. Basis path testing may be time-consuming, but the outcomes are more beneficial because the code is covered.