AllPairs4J is an open source Java library for generation of minimal set of test combinations.
AllPairs4J is a Java port of allpairspy project (with some improvements and bugfixes) developed by MetaCommunications Engineering and Tsuyoshi Hombashi.
In computer science, all-pairs testing or pairwise testing is a combinatorial method of software testing that, for each pair of input parameters to a system, tests all possible discrete combinations of those parameters. For example, if you want to create a test suite for browser testing, the domain can be described by the following parameters:
Browser: Chrome, Firefox, Safari, Edge
OS: Windows, Linux, macOS
RAM: 1024, 2048, 4096, 8192, 16384
Drive: HDD, SSD
There are hundreds of possible combinations of these values. Instead of spending unreasonable amount of time testing
them all, pairwise suggests testing all possible pairs of values. For example, {Chrome, Windows} is one pair,
{4096, SSD} is another; together they represent a test case that covers many pairs: {Chrome, Windows, 4096, SSD}.
In the end, you have good coverage while the number of test cases remains manageable.
With AllPairs4J, you are also able to add limitations on the domain to restrict generation of certain pairs.
For example, specify that Safari can only be paired with macOS, and Edge can only be paired with Windows.
For more info on pairwise testing see https://www.pairwise.org/.
- Specify constraints to add limitations on the test combinations generation.
- Generate pairwise, triplewise, n-wise test combinations.
- Integrate with any Java project. There are pairwise tools that can sometimes be faster or generate smaller set covering all the test combinations (pict is probably your best choice). However, they are missing features mentioned above and/or do not integrate with Java.
Java 8 or higher.
dependencies {
implementation 'io.github.pavelicii:allpairs4j:1.0.0'
}<dependency>
<groupId>io.github.pavelicii</groupId>
<artifactId>allpairs4j</artifactId>
<version>1.0.0</version>
</dependency>You can configure AllPairs generation using AllPairsBuilder. After it is built, the test cases are generated.
As a minimal setup, you need to describe Parameters to generate test combinations from.
AllPairs allPairs = new AllPairs.AllPairsBuilder()
.withParameters(Arrays.asList(
new Parameter("Browser", "Chrome", "Safari", "Edge"),
new Parameter("OS", "Windows", "Linux", "macOS"),
new Parameter("RAM", 2048, 4096, 8192, 16384),
new Parameter("Drive", "HDD", "SSD")))
.build();
System.out.println(allPairs);Show
1: {Browser=Chrome, OS=Windows, RAM=2048, Drive=HDD}
2: {Browser=Safari, OS=Linux, RAM=4096, Drive=HDD}
3: {Browser=Edge, OS=macOS, RAM=8192, Drive=HDD}
4: {Browser=Edge, OS=Linux, RAM=16384, Drive=SSD}
5: {Browser=Safari, OS=Windows, RAM=16384, Drive=SSD}
6: {Browser=Chrome, OS=macOS, RAM=4096, Drive=SSD}
7: {Browser=Chrome, OS=Linux, RAM=8192, Drive=SSD}
8: {Browser=Safari, OS=macOS, RAM=2048, Drive=SSD}
9: {Browser=Edge, OS=Windows, RAM=4096, Drive=HDD}
10: {Browser=Edge, OS=Windows, RAM=2048, Drive=HDD}
11: {Browser=Safari, OS=macOS, RAM=16384, Drive=HDD}
12: {Browser=Chrome, OS=Linux, RAM=16384, Drive=SSD}
13: {Browser=Safari, OS=Linux, RAM=8192, Drive=SSD}
14: {Browser=Chrome, OS=Windows, RAM=8192, Drive=HDD}
15: {Browser=Edge, OS=Linux, RAM=2048, Drive=HDD}
To limit generated pairs, you need to describe Constraints. Each Constraint is a Predicate that is tested against
each generated Case. If it evaluates to true, the Case is deleted from the result.
For example, let's create limitations so that:
Browser=Safarican only be paired withOS=macOSBrowser=Edgecan only be paired withOS=WindowsRAMcan't be less than4000
AllPairs allPairs = new AllPairs.AllPairsBuilder()
.withParameter(new Parameter("Browser", "Chrome", "Safari", "Edge"))
.withParameter(new Parameter("OS", "Windows", "Linux", "macOS"))
.withParameter(new Parameter("RAM", 2048, 4096, 8192, 16384))
.withParameter(new Parameter("Drive", "HDD", "SSD"))
.withConstraint(c -> c.get("Browser").equals("Safari") && !c.get("OS").equals("macOS"))
.withConstraint(c -> c.get("Browser").equals("Edge") && !c.get("OS").equals("Windows"))
.withConstraint(c -> (int) c.get("RAM") < 4000)
.build();
int index = 1;
for (Case c : allPairs) {
System.out.printf("%3d: %s%n", index++, c);
}Show
1: {Browser=Chrome, OS=Windows, RAM=4096, Drive=HDD}
2: {Browser=Safari, OS=macOS, RAM=8192, Drive=HDD}
3: {Browser=Edge, OS=Windows, RAM=16384, Drive=SSD}
4: {Browser=Edge, OS=Windows, RAM=8192, Drive=SSD}
5: {Browser=Safari, OS=macOS, RAM=4096, Drive=SSD}
6: {Browser=Chrome, OS=Linux, RAM=16384, Drive=HDD}
7: {Browser=Edge, OS=Windows, RAM=4096, Drive=HDD}
8: {Browser=Chrome, OS=macOS, RAM=16384, Drive=SSD}
9: {Browser=Safari, OS=macOS, RAM=16384, Drive=HDD}
10: {Browser=Chrome, OS=Linux, RAM=8192, Drive=SSD}
11: {Browser=Chrome, OS=Linux, RAM=4096, Drive=SSD}
You can specify test combination size to go beyond pairs.
AllPairs allPairs = new AllPairs.AllPairsBuilder()
.withTestCombinationSize(3)
.withParameters(Arrays.asList(
new Parameter("Browser", "Chrome", "Safari", "Edge"),
new Parameter("OS", "Windows", "Linux", "macOS"),
new Parameter("RAM", 2048, 4096, 8192, 16384),
new Parameter("Drive", "HDD", "SSD")))
.build();
System.out.println(allPairs.toString());Show
1: {Browser=Chrome, OS=Windows, RAM=2048, Drive=HDD}
2: {Browser=Safari, OS=Linux, RAM=4096, Drive=HDD}
3: {Browser=Edge, OS=macOS, RAM=8192, Drive=HDD}
4: {Browser=Edge, OS=macOS, RAM=16384, Drive=SSD}
5: {Browser=Safari, OS=Linux, RAM=16384, Drive=SSD}
6: {Browser=Chrome, OS=Windows, RAM=8192, Drive=SSD}
7: {Browser=Chrome, OS=Windows, RAM=4096, Drive=HDD}
8: {Browser=Safari, OS=Linux, RAM=2048, Drive=HDD}
9: {Browser=Edge, OS=macOS, RAM=2048, Drive=HDD}
10: {Browser=Edge, OS=macOS, RAM=4096, Drive=HDD}
11: {Browser=Safari, OS=Linux, RAM=8192, Drive=SSD}
12: {Browser=Chrome, OS=Windows, RAM=16384, Drive=SSD}
13: {Browser=Chrome, OS=Windows, RAM=16384, Drive=HDD}
14: {Browser=Safari, OS=Linux, RAM=4096, Drive=SSD}
15: {Browser=Edge, OS=macOS, RAM=2048, Drive=SSD}
16: {Browser=Edge, OS=macOS, RAM=8192, Drive=SSD}
17: {Browser=Safari, OS=Linux, RAM=8192, Drive=HDD}
18: {Browser=Chrome, OS=Windows, RAM=2048, Drive=SSD}
19: {Browser=Chrome, OS=Windows, RAM=4096, Drive=SSD}
20: {Browser=Safari, OS=Linux, RAM=16384, Drive=HDD}
21: {Browser=Edge, OS=macOS, RAM=16384, Drive=HDD}
22: {Browser=Edge, OS=macOS, RAM=4096, Drive=SSD}
23: {Browser=Safari, OS=Linux, RAM=2048, Drive=SSD}
24: {Browser=Chrome, OS=Windows, RAM=8192, Drive=HDD}
25: {Browser=Chrome, OS=Linux, RAM=8192, Drive=HDD}
26: {Browser=Safari, OS=macOS, RAM=2048, Drive=SSD}
27: {Browser=Edge, OS=Windows, RAM=4096, Drive=SSD}
28: {Browser=Edge, OS=Windows, RAM=16384, Drive=HDD}
29: {Browser=Safari, OS=macOS, RAM=16384, Drive=HDD}
30: {Browser=Chrome, OS=Linux, RAM=4096, Drive=SSD}
31: {Browser=Chrome, OS=Linux, RAM=2048, Drive=SSD}
32: {Browser=Safari, OS=macOS, RAM=8192, Drive=HDD}
33: {Browser=Edge, OS=Windows, RAM=8192, Drive=HDD}
34: {Browser=Safari, OS=macOS, RAM=4096, Drive=SSD}
35: {Browser=Edge, OS=Windows, RAM=2048, Drive=SSD}
36: {Browser=Chrome, OS=Linux, RAM=16384, Drive=HDD}
37: {Browser=Chrome, OS=macOS, RAM=16384, Drive=HDD}
38: {Browser=Edge, OS=Linux, RAM=2048, Drive=SSD}
39: {Browser=Safari, OS=Windows, RAM=4096, Drive=SSD}
40: {Browser=Safari, OS=Windows, RAM=8192, Drive=HDD}
41: {Browser=Edge, OS=Linux, RAM=8192, Drive=HDD}
42: {Browser=Chrome, OS=macOS, RAM=4096, Drive=SSD}
43: {Browser=Chrome, OS=macOS, RAM=2048, Drive=SSD}
44: {Browser=Edge, OS=Linux, RAM=16384, Drive=HDD}
45: {Browser=Safari, OS=Windows, RAM=16384, Drive=HDD}
46: {Browser=Safari, OS=Windows, RAM=2048, Drive=SSD}
47: {Browser=Edge, OS=Linux, RAM=4096, Drive=SSD}
48: {Browser=Chrome, OS=macOS, RAM=8192, Drive=HDD}
AllPairs allPairs = new AllPairs.AllPairsBuilder()
.withParameters( List<Parameter> ) // required
.withParameter( Parameter ) // alternative way to specify Parameters one by one
.withConstraints( List<Predicate<Case>> ) // not required, default is no Constraints
.withConstraint( Predicate<Case> ) // alternative way to specify Constraints one by one
.withTestCombinationSize( int ) // not required, default is 2
.printEachCaseDuringGeneration() // not required, useful for debug
.build();
List<Case> generatedCases = allPairs.getGeneratedCases();- Parameter: Named
List<Object>storing all input values. - Case:
Map<String, Object>storing one generated test case, wherekeyis mapped to theParametername,valueis mapped to one of theParametervalues. - Predicate<Case>: constraint to test against
Case. When evaluates totrue, theCaseis considered invalid and is filtered out form the resulting set.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
SemVer is used for versioning. For the versions available, see the releases on this repository.