Structural testing is the type of testing carried out to test the structure of the code. It is also known as White Box testing or Glass Box testing. This type of testing requires knowledge of the code, so, it is mostly done by the developers. It is more concerned with how the system does it rather than the functionality of the system. It provides more coverage to the testing. For example, to test certain error message in an application, we need to test the trigger condition for it, but there must be many triggers for it. It is possible to miss out one while testing the requirements drafted in SRS. But using this testing, the trigger is most likely to be covered since structural testing aims to cover all the nodes and paths in the structure of the code.
It is complementary to Functional Testing. Using this technique the test cases drafted according to system requirements can be first analyzed and then more test cases can be added to increase the coverage. It can be used on different levels such as unit testing, component testing, integration testing, functional testing etc. It helps in performing thorough testing on software. The structural testing is mostly automated.
What ist Structural Testing?
There are different criteria that are used to perform such testing. Before moving on to those, it is important to understand some terms.
Control Flow Graph:
It is a graphical representation of the program depicting all the paths that may be transverse during the execution. It contains
Basic Block or Node:
It is a sequence of statements such that control can only have one entry point and can exit the block only when all the statements have been executed.
Edge:
It shows the control flow.
For example, following is a control flow graph:
N1, N2, N3, N4, and N5 represents Basic Blocks or Nodes and E1, E2, E3, E4, and E5 represents Edges. We can also observe that N2, N3, N4, and N5 together represent an IF loop.
Adequacy Criterion: This term refers to the coverage provided by a test suite.
Structural Testing Techniques:
Let’s see the different structural testing techniques or coverage’s
now:
Statement Coverage:
It aims to test all the statements present in the program
Adequacy Criterion should be equal to 1 to ensure 100% coverage. It is a good measure of testing each part in terms of statements but it is not a good technique for testing the control flow. For example one node can be reached from multiple other nodes, but since the aim is to cover just the statements, those conditions are not covered. It can be understood from the help of the following example:
Here all the statements in the program can be covered using two flow
- E1->E2->E5
- E1->E3
But using these two statements the flow from N3 to N4 is not tested i.e. E4. It does not provide branch coverage. N3 has 2 exit points depending upon the decision statement in N3 i.e. true and false, but since N4 has already been covered, the testing for a decision statement is missed out.
Branch Coverage:
It is also known as Decision coverage testing. It aims to test all the branches or edges at least once in the test suite or to test each branch from a decision point at least once. It provides a solution for the problem faced in Statement coverage. Branch E4 will be covered here as we saw in the previous example.
Branch Testing provides better coverage than Statement testing but it too has its shortcomings. It doesn’t provide good coverage from different conditions that lead from node 1 to node 2 as it covers that branch only once. Let’s try to understand it better with the help of the following example.
In this case, the 100% branch coverage can be provided as follows
- E1->E2
- E3
But as we can see edge E1 can be tested for multiple conditions, but under branch testing, the aim is to just test the edge for one condition and not for multiple conditions associated to it. The different conditions can be:
- A>2 and B>8 (A True and B False)
- A<2 and B<8 (A False and B True) etc.
Condition Coverage:
It aims to test individual conditions with a possible different combination of Boolean input for the expression.
It is a modification of Decision coverage but it provides better coverage and the problem discussed under Branch coverage can be resolved here. Notice the different combination of inputs in the following table
S. No. |
A |
B |
A or B |
1 | 1 | 0 |
0 |
2 |
0 | 1 | 1 |
3 |
1 |
0 |
1 |
4 | 1 | 1 |
1 |
However when compound conditions are involved the no. of test cases may increase exponentially, which is not desired.
Modified Condition/Decision coverage:
It is a modification of condition coverage. Its adequacy criterion can be defined as N+1 test cases for N variables. The test cases are derived such that each variable independently affects the final output. So it provides coverage for different conditions without increasing the size of the test case suite.
Path Coverage:
It aims to test the different path from entry to the exit of the program, which is a combination of different decisions taken in the sequence.
The paths can be too many to be considered for testing, for example, a loop can go on and on. It can be avoided using cyclomatic complexity, whelps help in finding out the redundant test cases.
[Cyclomatic Complexity is a quantitative measure of no. of linearly independent paths through a program and is used to indicate the complexity of a program].
So, cyclomatic complexity helps aiming to test all linearly independent paths in a program at least once. These were some of the test coverage under this Testing.
Advantages of Structural Testing:
- Provides a more thorough testing of the software.
- Helps finding out defects at an early stage.
- Helps in eliminating dead code.
- Not time consuming as it is mostly automated.
Disadvantages of Structural Testing:
- Requires knowledge of the code.
- Requires training in the tool used for testing
- It is expensive.
Tools Required:
Some of the test tools that are used for the White box or Structural Testing are as follow:
- JBehave
- Cucumber
- Junit
- Cfix
JBehave
JBehave is a framework for Behavior-Driven Development (BDD). BDD is an evolution of test-driven development (TDD) and acceptance-test driven design, and is intended to make these practices more accessible and intuitive to newcomers and experts alike. It shifts the vocabulary from being test-based to behavior-based, and positions itself as a design philosophy.
The five-step overview
A quick overview in five steps. Clicking on each steps will show more details.
Cucumber
First, the developers, testers and business folks explore the problem domain, and collaborate to produce concrete examples that describe the behavior they want.
Sometimes that discussion is hard, because it throws up all the misunderstandings and assumptions you’d normally discover much later on.
But that’s a good thing.
Next, the team uses Cucumber to run those examples as automated acceptance tests.
As the team works on the solution, Cucumber tells you which examples are implemented and working, and warns you about the ones that aren’t.
Before you know it, you have one document that’s both the specification and the tests for your software.
Junit
Unit is a unit testing framework for Java programming language. JUnit has been important in the development of test-driven development, and is one of a family of unit testing frameworks collectively known as xUnit, that originated with JUnit.
This tutorial explains the use of JUnit in your project unit testing, while working with Java. After completing this tutorial you will gain sufficient knowledge in using the JUnit testing framework from where you can take yourself to next levels.
Cfix
cfix is an xUnit testing framework for C/C++, specialized for unmanaged Windows development (32/64 bit). cfix supports
development of both user and kernel mode unit tests.
cfix unit tests are compiled and linked into a DLL. The testrunner application provided by cfix allows selectively running tests of one or more of such test-DLLs. Execution and behavior in case of failing testcases can be highly customized. Moreover, cfix has been designed to work well in conjunction with the Windows Debuggers (Visual Studio, WinDBG).
As of cfix 1.3, the framework is source-compatible to WinUnit, i.e. a WinUnit test suite can be recompiled into a full-fledged cfix test suite.
Over to you:
So, we can summarize that Structural Testing also known as Glass box testing or white box testing or clear box testing is to validate the structure of the code. It requires deep knowledge of the code and is complementary to Functional Testing. It helps in providing more coverage under test suite using different coverage techniques such as Condition coverage, Decision coverage, path coverage etc. It can be used on any level of testing such as unit testing, component testing, integration testing etc.