Skip to content

Commit 97b6cba

Browse files
authored
Speed up algorithm processing, update deps, update docs (#1)
- Speed up AllPairs algorithm processing time - Optimize AllPairs algorithm resources usage - Update dependencies - Update documentation
1 parent 406cbc8 commit 97b6cba

18 files changed

Lines changed: 571 additions & 346 deletions

File tree

.github/workflows/build-checkstyle.yaml

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,22 @@ jobs:
66
runs-on: ubuntu-latest
77
steps:
88
- name: Checkout
9-
uses: actions/checkout@v2.4.0
9+
uses: actions/checkout@v4
10+
11+
- name: Validate Gradle Wrapper
12+
uses: gradle/wrapper-validation-action@v1
1013

1114
- name: Setup JDK 8
12-
uses: actions/setup-java@v2.5.0
15+
uses: actions/setup-java@v3
1316
with:
1417
distribution: temurin
1518
java-version: 8
1619

17-
- name: Validate Gradle Wrapper
18-
uses: gradle/wrapper-validation-action@v1.0.4
20+
- name: Setup Gradle
21+
uses: gradle/gradle-build-action@v2
1922

20-
- name: Run Build
21-
uses: gradle/gradle-build-action@v2.1.3
22-
with:
23-
arguments: build
23+
- name: Run Build and Tests
24+
run: ./gradlew clean build
2425

2526
- name: Run Checkstyle
26-
uses: gradle/gradle-build-action@v2.1.3
27-
with:
28-
arguments: checkstyle
27+
run: ./gradlew checkstyle

.github/workflows/tag-release-publish.yaml

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@ jobs:
66
runs-on: ubuntu-latest
77
steps:
88
- name: Checkout
9-
uses: actions/checkout@v2.4.0
9+
uses: actions/checkout@v4
10+
11+
- name: Validate Gradle Wrapper
12+
uses: gradle/wrapper-validation-action@v1
1013

1114
- name: Setup JDK 8
12-
uses: actions/setup-java@v2.5.0
15+
uses: actions/setup-java@v3
1316
with:
1417
distribution: temurin
1518
java-version: 8
1619

17-
- name: Run Build
18-
uses: gradle/gradle-build-action@v2.1.3
19-
with:
20-
arguments: build
20+
- name: Setup Gradle
21+
uses: gradle/gradle-build-action@v2
22+
23+
- name: Run Build and Tests
24+
run: ./gradlew clean build
2125

2226
- name: Get version from build.gradle.kts
2327
run: |
@@ -39,15 +43,13 @@ jobs:
3943
run: git tag -m ${{ env.tag }} ${{ env.tag }} && git push origin ${{ env.tag }}
4044

4145
- name: Release to GitHub
42-
uses: softprops/action-gh-release@v0.1.14
46+
uses: softprops/action-gh-release@v1
4347
with:
4448
tag_name: ${{ env.tag }}
4549
files: build/libs/allpairs4j-${{ env.version }}.jar
4650

4751
- name: Publish to Sonatype
48-
uses: gradle/gradle-build-action@v2.1.3
49-
with:
50-
arguments: publish
52+
run: ./gradlew publish
5153
env:
5254
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.OSSRH_USERNAME }}
5355
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.OSSRH_PASSWORD }}

NOTICE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
AllPairs4J
2-
Copyright 2022 Pavel Nazimok - @pavelicii
2+
Copyright 2023 Pavel Nazimok - @pavelicii
33

44
This product is derived from the work by MetaCommunications Inc.
55
It can be obtained at:

README.md

Lines changed: 59 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,29 @@
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
1913
Browser: Chrome, Firefox, Safari, Edge
2014
OS: Windows, Linux, macOS
2115
RAM: 1024, 2048, 4096, 8192, 16384
2216
Drive: 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
5247
dependencies {
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

117113
For 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

163181
You 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
242260
AllPairs 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
266284
Please 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.

build.gradle.kts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ plugins {
77
}
88

99
group = "io.github.pavelicii"
10-
version = "1.0.0"
10+
version = "1.0.1"
1111

1212
repositories {
1313
mavenCentral()
@@ -21,7 +21,7 @@ java {
2121
}
2222

2323
checkstyle {
24-
toolVersion = "9.3"
24+
toolVersion = "9.3" // Latest version compatible with Java 8
2525
sourceSets = listOf() // Don't check anything with Checkstyle during 'check' task
2626
}
2727
tasks.register("checkstyle", Checkstyle::class) {
@@ -30,13 +30,20 @@ tasks.register("checkstyle", Checkstyle::class) {
3030
}
3131

3232
dependencies {
33-
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
34-
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
35-
testImplementation("org.assertj:assertj-core:3.22.0")
33+
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
34+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
35+
testImplementation("org.assertj:assertj-core:3.24.2")
3636
}
3737

3838
tasks.test {
3939
useJUnitPlatform()
40+
testLogging {
41+
events("passed", "skipped", "failed")
42+
}
43+
}
44+
45+
tasks.withType<Javadoc> {
46+
(options as StandardJavadocDocletOptions).addStringOption("Xdoclint:none", "-quiet")
4047
}
4148

4249
publishing {
@@ -59,7 +66,7 @@ publishing {
5966
licenses {
6067
license {
6168
name.set("The Apache License, Version 2.0")
62-
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
69+
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
6370
}
6471
}
6572
developers {

0 commit comments

Comments
 (0)