The Equivalence Partitioning Testing technique is one of the popular software testing techniques. It reduces the number of test cases by creating boundaries that ensure code paths are not executed for specific input data values.
Equivalence Partitioning helps you divide input data into several partitions based on the characteristics of the inputs, each having the same set of boundary values for one variable but all having different sets of boundary values for another variable. In other words, each partition is a collection of inputs with the same value(s) and different values for another variable.
Here, only equivalence classes are considered in which the input changes significantly from one member to another. Equivalence classes can be created for each variable in the input data set or a combination of variables.
The approach should ensure no boundary values between equivalence classes that cause differences when processed. The boundaries used should not have any “trivial” inputs on either side of them that differ by one bit. Boundaries should be chosen so the inputs do not fall on the boundary.
After partitioning, you will have two test cases: Boundary value Test Cases and Partition Insertion Point Test Cases.
Boundary Value Test cases are designed to exercise each of these partitions completely, from its lower boundary to its upper boundary.
Partition insertion point test cases are designed to exercise the partition as it exists in code, ignoring any input values outside the partition boundaries.
Rationale for Equivalence Partitioning Testing Technique:
Partitioning is a sound software design technique. It can be applied anytime there are significant input differences, and the outputs are difficult to predict.
Partitioning can be created at any location where different inputs result in significantly different behavior, even if the program source code does not reflect it. Creating test cases is often easier than fully analyzing and understanding a program’s source code.
The benefit of using the Equivalence Partitioning Testing technique:
It helps you create fewer test cases by ensuring that each logical input subset is tested in one test case. It reduces the conditions your tests must handle while exercising all code paths used for inputs inside a partition.
It makes it easier to create test cases by providing specific boundaries in the form of “insert points” (boundaries) at which you can choose to insert your input values. It is less time-consuming as you don’t have to generate all boundary values and search for valid/invalid results. It makes it easier to debug test cases by focusing on the code path executed for a given input data value.
It reduces the number of boundary values to be tested significantly, which can result in fewer bugs. It helps you identify discrepancies between source code and actual behavior.
Types of Partitions:
There are several types of partitions, but the most useful ones are:
- Equivalence Partitioning
- Complementary Partitioning
- Hybrid Partitioning (This is a combination of both)
Equivalence Partitioning: Creating partitions by splitting every set of input values into two sub-sets so each partition contains input values with different boundaries for one variable but the same boundary for another variable.
Complementary Partitioning: Creating partitions by splitting every set of input values into two sub-sets so each partition contains inputs with the same boundaries for one variable and different boundaries for another variable.
Hybrid Partitioning is a combination of both Equivalence and Complementary Partitioning.
Limitations:
The major limitation is that Partitioning can help reduce the number of test cases only if a formal method for partitioning has been defined.
Converting existing test cases into boundary value or partition insertion point test cases is difficult and time-consuming. Because of this, the technique is most appropriate for use when constructing new test sets from scratch.
The poor maintainability of test data can cause implementation problems
A formal method must be created to specify equivalence classes and their boundaries. This can be very difficult for large and complicated modules.
Partitioning can be effective only if you have tested all the partitions in which your program may behave as expected.
Recommendations:
Partitioning is an excellent technique for reducing the test data set size, especially when working on a maintenance project where you want to eliminate bugs in existing code or when you are working on modules with a lot of complex code.
Summary of Equivalence Partitioning Testing Technique:
- Identify equivalence classes of each variable in the input domain.
- Create test cases for each partition, including boundary values and value combinations that span partitions.
Note: No two test cases should exercise a single code path more than once unless they are boundary value test cases. - If the partitions of a single variable do not cover all values in its equivalence class, additional test cases may be needed to fully exercise code paths that have been identified as significant but that are outside of any partition.
- Test performance is not significantly improved when using this technique because it does not reduce the total number of test cases.
- The technique can be used with other testing techniques to help create a complete test set.
- When using this technique, you can test both equivalence classes and partitions. How you handle equivalence classes depends mainly on the requirements of your project. You might want to analyze the code for each class individually or create test cases that check combinations of individual tests.
Note: If the number of input values is small, a better approach is to test the code once for each input value. - A formal method must be created to specify equivalence classes and their boundaries” (Testing Computer Software, Magnant & Paul, 1996)
How To Implement Equivalence Partitioning Testing Technique:
Determine Variables with Significant Differences :
Test design is ineffective if you do not first determine the significant differences in your input domain. This can be done by reviewing the requirements, existing test cases, and any design specifications that relate to variables with significant differences.
Partition Variables Into Equivalence Classes:
Determine Qualitative Differences.
i.e., Determine which values can be considered qualitatively different from one another for a given variable. (This might not necessarily mean you must create separate classes for all of them.)
Example: A simple Qualitative Partition Example is the Age variable where we would put ages 18, 19, and 20 in one class, 21-30 in another, and 31-40 in the third class.
Qualitative Difference Thresholds: You can partition individual values by determining a threshold value for each variable, such as an age cut-off at which you deem individuals to be adults with one set of privileges or minors (with different privileges). The threshold values can be determined and agreed upon during the requirements elicitation phase.
Determine Strictly Related Variables
Determine which variables are strictly related – independent input variables that cannot have different values without changing the behavior or outputs of a program/function being tested. Their relationship is direct and is not mediated by other variables. These are like the primary key of a database record that relates it to other records in its table.
The techniques you use to identify strictly related variables greatly depend on how your program is organized and developed.
You can also create classes based on the environment or context in which the variable operates (i.e., offline, online) or the environment or context in which you will test your program. This is sometimes required for databases.
Create Test Cases for Each Partition
Identify Multiple Boundary Conditions:
When creating test cases for partitions, identify possible and relevant boundaries to each partition.
Select Boundary Conditions for Each Partition
Select boundary conditions that are representative of each partition. You might be able to use the same boundary value for all values in a partition. If your program allows different but related sets of inputs, then you might consider using real-world data to identify test cases.
Test cases should be created for each partition. Each test case should have different input values from the remaining partitions. In other words, a test case that uses values less than the lowest value of a partition should not be used with values greater than or equal to the highest value of another partition.
You can create a test suite based on different partitions. The simplest way is to create one test suite for each partition if you are testing a system where acceptable input values can also be related.
- You might consider creating multiple test suites that are organized based on the relationships between your input variables (i.e., one test suite for each partition)
- You might consider creating test suites that use combinations of inputs from multiple partitions within a single suite (s).
Example: Create test cases for ages 18, 19, and 20 in one class.
Note: If you determine qualitative differences during the partitioning process, then create test cases based on those values and the other boundary conditions.
Create Test Cases for Each Class:
- Determine Output Values: The output values you test should be based on your requirements analysis and validation process.
- Subjectively Consider How Different Each Value Is From The One Before It: . For example, there might not be a big difference between the ages of 18 and 19, but there is a significant change between the ages of 20 and 21. You cannot test the transition from age 20 to 21 with values greater than 20 (such as age 22) or less than 19 (such as age 17).
Test Cases should be created for each class. Each test case should have one input value from each partition. In other words, a test case that uses values less than or/equal to the lowest value of a partition should not be used with values greater than or equal to the highest value of another partition.
For example, age 18 should be tested with values of 17 and 19.
- If you create a test suite for each partition, there is no need to identify test cases for age 18 from partitions other than the one on which the class was created.
- If you are testing a system where acceptable input values can also be related, then..
- You might consider creating multiple test suites that are organized based on the relationships between your input variables (i.e., one test suite for each partition) OR
- You might consider creating a single, combined test suite with values from different partitions within a single suite.
Example: Create a class to determine if Jane is an appropriate age for donating blood and add values for ages 18, 19, and 20.
Create Test Cases Based on Classes:
- Determine Output Values: The output values you test should be based on your requirements analysis and validation process.
- Subjectively Consider How Different Each Value Is From The One Before It: . For example, there might not be a big difference between the ages of 18 and 19, but there is a significant change between the ages of 20 and 21. You cannot test the transition from age 20 to 21 with values greater than 20 (such as age 22) or less than 19 (such as age 17).
- Test Cases should be created for each class. Each test case should have one input value from each partition. In other words, a test case that uses values less than or/equal to the lowest value of a partition should not be used with values greater than or equal to the highest value of another partition.
A given class should be tested with every input value from the other classes.
For example, age 18 should be tested with values of 17 and 19.
If you created a single test case for each partition, there is no need to identify test cases for age 18 from partitions other than the one on which the class was created.