33[ ![ GitHub Workflow Status] ( https://img.shields.io/github/actions/workflow/status/pavelicii/allpairs4j/build-checkstyle.yaml?branch=master&logo=GitHub )] ( https://github.com/pavelicii/allpairs4j/actions/workflows/build-checkstyle.yaml )
44[ ![ Maven Central] ( https://img.shields.io/maven-central/v/io.github.pavelicii/allpairs4j )] ( https://search.maven.org/artifact/io.github.pavelicii/allpairs4j )
55
6- AllPairs4J is an open source Java library for generation of minimal set of test combinations.
6+ AllPairs4J is an open source Java library for generation of minimal set of test combinations.
77
8- AllPairs4J is a Java port of [ allpairspy] ( https://github.com/thombashi/allpairspy ) project
9- (with some [ improvements and bugfixes] ( https://github.com/thombashi/allpairspy/pull/10 ) )
10- developed by MetaCommunications Engineering and Tsuyoshi Hombashi.
8+ ## Pairwise Testing • [ pairwise.org] ( https://www.pairwise.org/ )
119
12- ## Pairwise Testing
13-
14- In computer science, _ all-pairs testing_ or _ pairwise testing_ is a combinatorial method of software testing that, for
15- each pair of input parameters to a system, tests all possible discrete combinations of those parameters. For example,
16- if you want to create a test suite for browser testing, the domain can be described by the following parameters:
10+ Assuming you want to create test cases for web browser testing, the domain can be described by the following parameters:
1711
1812``` text
1913Browser: Chrome, Firefox, Safari, Edge
2014OS: Windows, Linux, macOS
2115RAM: 1024, 2048, 4096, 8192, 16384
2216Drive: HDD, SSD
17+ Screen: 1024x768, 1366x768, 1680x1050, 1920x1080, 2560x1440, 3840x2160
2318```
2419
25- There are hundreds of possible combinations of these values. Instead of spending unreasonable amount of time testing
26- them all, pairwise suggests testing all possible pairs of values. For example, ` {Chrome, Windows} ` is one pair,
27- ` {4096, SSD} ` is another; together they represent a test case that covers many pairs: ` {Chrome, Windows, 4096, SSD} ` .
28- In the end, you have good coverage while the number of test cases remains manageable.
29-
30- With AllPairs4J, you are also able to add limitations on the domain to restrict generation of certain pairs.
31- For example, specify that ` Safari ` can only be paired with ` macOS ` , and ` Edge ` can only be paired with ` Windows ` .
20+ There are hundreds of possible combinations of these values. However, usually most faults are caused by interactions
21+ of at most two factors, therefore testing all pairs is an effective alternative to exhaustive testing.
22+ For example, ` {Chrome, Windows} ` is one pair, ` {4096, SSD} ` is another; together they can represent a test case
23+ that also covers many other pairs: ` {Chrome, Windows, 4096, SSD, 2560x1440} ` . In the end, you have good
24+ coverage while the number of test cases remains manageable.
3225
33- For more info on pairwise testing see https://www.pairwise.org/ .
26+ With AllPairs4J, you are also able to add ** constraints** - limitations on the domain to restrict generation of certain
27+ pairs. For example, specify that ` Safari ` can only be paired with ` macOS ` , and ` Edge ` can only be paired with ` Windows ` .
28+ Or you can go beyond pairs.
3429
3530## Features
3631
@@ -50,7 +45,7 @@ Java 8 or higher.
5045
5146``` groovy
5247dependencies {
53- implementation ' io.github.pavelicii:allpairs4j:1.0.0'
48+ implementation(" io.github.pavelicii:allpairs4j:1.0.1")
5449}
5550```
5651
@@ -60,7 +55,7 @@ dependencies {
6055<dependency >
6156 <groupId >io.github.pavelicii</groupId >
6257 <artifactId >allpairs4j</artifactId >
63- <version >1.0.0 </version >
58+ <version >1.0.1 </version >
6459</dependency >
6560```
6661
@@ -109,10 +104,11 @@ System.out.println(allPairs);
109104
110105</details >
111106
112- ### Generate Filtered Pairwise Combinations
107+ ### Constraints: Generate Filtered Pairwise Combinations
113108
114- To limit generated pairs, you need to describe Constraints. Each Constraint is a Predicate that is tested against
115- each generated Case. If it evaluates to ` true ` , the Case is deleted from the result.
109+ To filter out unwanted combinations, you need to describe Constraints. Each potential test Case is tested against them.
110+ If any test evaluates to ` true ` , the Case under test won't be present in the result and the algorithm will search
111+ for another Case, so that in the end all possible pairs are covered (considering all the Constraints).
116112
117113For example, let's create limitations so that:
118114* ` Browser=Safari ` can only be paired with ` OS=macOS `
@@ -132,10 +128,7 @@ AllPairs allPairs = new AllPairs.AllPairsBuilder()
132128 .withConstraint(c - > (int ) c. get(" RAM" ) < 4000 )
133129 .build();
134130
135- int index = 1 ;
136- for (Case c : allPairs) {
137- System . out. printf(" %3d: %s%n" , index++ , c);
138- }
131+ System . out. println(allPairs);
139132```
140133
141134#### Output:
@@ -158,6 +151,31 @@ for (Case c : allPairs) {
158151
159152</details >
160153
154+ #### Constraints tips:
155+
156+ Try to simplify constraints as much as possible. Too complicated constraints might cause longer algorithm processing
157+ time, especially on a large input of Parameters.
158+
159+ For example, for the following input:
160+
161+ ```
162+ Browser: Chrome
163+ OS: Linux, macOS
164+ Drive: HDD, SSD
165+ ```
166+
167+ Consider two different constraints:
168+
169+ ``` java
170+ // filter out 'Chrome-Linux-HDD' combination:
171+ complicatedConstraint = c - > c. get(" Browser" ). equals(" Chrome" ) && c. get(" OS" ). equals(" Linux" ) && c. get(" Drive" ). equals(" HDD" )
172+ // filter out 'Linux-HDD' pair:
173+ simplifiedConstraint = c - > c. get(" OS" ). equals(" Linux" ) && c. get(" Drive" ). equals(" HDD" )
174+ ```
175+
176+ It is better to use ` simplifiedConstraint ` , because the usage of ` complicatedConstraint ` implies there might be pairs
177+ including non-` Chrome ` browsers, while in fact there is only one possible browser.
178+
161179### Generate Triplewise Combinations
162180
163181You can specify test combination size to go beyond pairs.
@@ -174,7 +192,7 @@ AllPairs allPairs = new AllPairs.AllPairsBuilder()
174192 new Parameter (" Drive" , " HDD" , " SSD" )))
175193 .build();
176194
177- System . out. println(allPairs. toString() );
195+ System . out. println(allPairs);
178196```
179197
180198#### Output:
@@ -234,30 +252,30 @@ System.out.println(allPairs.toString());
234252
235253</details >
236254
237- ### Configuration summary
255+ ### Configuration Summary
238256
239- #### Sample code :
257+ #### Builder :
240258
241259``` java
242260AllPairs allPairs = new AllPairs .AllPairsBuilder ()
243- .withParameters( List< Parameter > ) // required
244- .withParameter( Parameter ) // alternative way to specify Parameters one by one
245- .withConstraints( List< Predicate<Case > > ) // not required , default is no Constraints
246- .withConstraint( Predicate<Case > ) // alternative way to specify Constraints one by one
247- .withTestCombinationSize( int ) // not required , default is 2
248- .printEachCaseDuringGeneration() // not required , useful for debug
261+ .withParameter( Parameter ) // specifies 1 Parameter
262+ .withParameters( List< Parameter > ) // alternative way to specify multiple Parameters as List
263+ .withConstraint( Predicate<ConstrainableCase > ) // specifies 1 Constraint , default is no Constraints
264+ .withConstraints( List< Predicate<ConstrainableCase > > ) // alternative way to specify multiple Constraints as List
265+ .withTestCombinationSize( int ) // specifies test combination size , default is 2 (pair)
266+ .printEachCaseDuringGeneration() // prints Cases during generation , useful for debug
249267 .build();
250268
251- List<Case > generatedCases = allPairs. getGeneratedCases();
269+ List<Case > generatedCases = allPairs. getGeneratedCases(); // work with resulting List of Cases
270+ for (Case c : allPairs) { ... } // or use Iterator
252271```
253272
254273#### Data types:
255274
256- * ** Parameter** : Named ` List<Object> ` storing all input values.
275+ * ** Parameter** : named ` List<Object> ` storing all input values
257276* ** Case** : ` Map<String, Object> ` storing one generated test case,
258- where ` key ` is mapped to the ` Parameter ` name, ` value ` is mapped to one of the ` Parameter ` values.
259- * ** Predicate\< Case\> ** : constraint to test against ` Case ` . When evaluates to ` true ` , the ` Case ` is considered invalid
260- and is filtered out form the resulting set.
277+ where ` key ` is mapped to the ` Parameter ` name, ` value ` is mapped to one of the ` Parameter ` values
278+ * ** Predicate\< ConstrainableCase\> ** : constraint
261279
262280## Contributing
263281
@@ -266,4 +284,4 @@ Pull requests are welcome. For major changes, please open an issue first to disc
266284Please make sure to update tests as appropriate.
267285
268286[ SemVer] ( https://semver.org/ ) is used for versioning. For the versions available,
269- see the [ releases on this repository ] ( https://github.com/pavelicii/allpairs4j/releases ) .
287+ see the [ releases] ( https://github.com/pavelicii/allpairs4j/releases ) on this repository .
0 commit comments