Skip to content

Commit 6252801

Browse files
jakubmalekJakub Malek
authored andcommitted
README update
Checking dependencies in build action Configuration of jacoco plugin Encoding configuration Code cleanup
1 parent b3f2198 commit 6252801

20 files changed

+544
-276
lines changed

.github/workflows/build.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: build
2+
on:
3+
push:
4+
branches: [ "main" ]
5+
pull_request:
6+
branches: [ "main" ]
7+
permissions:
8+
contents: read
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v3
14+
- name: Set up JDK 11
15+
uses: actions/setup-java@v3
16+
with:
17+
java-version: '11'
18+
distribution: 'temurin'
19+
- uses: actions/cache@v3
20+
id: gradle-cache
21+
with:
22+
path: |
23+
~/.gradle/caches
24+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
25+
- uses: actions/cache@v3
26+
id: gradle-wrapper-cache
27+
with:
28+
path: |
29+
~/.gradle/wrapper
30+
key: ${{ runner.os }}-gradlewrapper-${{ hashFiles('gradle/wrapper/*') }}
31+
- name: Build
32+
uses: gradle/gradle-build-action@v2
33+
with:
34+
arguments: build
35+
- name: Dependency check
36+
uses: gradle/gradle-build-action@v2
37+
with:
38+
arguments: dependencyCheckAnalyze

.github/workflows/gradle.yml

Lines changed: 0 additions & 22 deletions
This file was deleted.

README.md

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,45 @@
11
# AssertJ - Async
22

3-
AssertJ extension for making asynchronous assertions.
3+
Extension for [AssertJ](https://github.com/assertj/assertj-core) API for making asynchronous assertions.
4+
5+
[![Build Status](https://github.com/Webfleet-Solutions/assertj-async/actions/workflows/build.yml/badge.svg?branch=main)](https://travis-ci.org/Webfleet-Solutions/oauth-java-example)
6+
[![license](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT)
47

58
## Usage
69

7-
The entry point for making asynchronous assertion is `AsyncAssertions` class.
10+
The entry point for making asynchronous assertion is `com.webfleet.assertj.AsyncAssertions` class.
11+
12+
To make the assertion first, you need to specify the timeout for your assertion:
13+
* `awaitAtMost(Duration.ofSeconds(5))`
14+
* `awaitAtMost(5, TimeUnit.SECONDS)`
15+
* `awaitAtMostOneSecond()`
16+
* `awaitAtMostTwoSeconds()`
17+
* `awaitAtMostFiveSeconds()`
18+
* `awaitAtMostFifteenSeconds()`
19+
* `awaitAtMostThirtySeconds()`
820

9-
Here is an example of test:
21+
Now you can optionally configure following parameters:
22+
* **Check interval** - the time to be waited in between assertion checks:
23+
* `.withCheckInterval(Duration.ofMillis(500))`
24+
* `.withCheckInterval(500, TimeUnit.MILLISECONDS)`
25+
* By default, it's configured to `100ms`
26+
* **Wait mutex** - the object to be used for check interval wait logic:
27+
* `.usingWaitMutex(mutex)`
28+
* It can be used to optimize the wait time with `notifyAll()` call on state change ending the wait and forcing assertion check
29+
30+
Finally, you can make your assertions by providing lambda consumer function for `SoftAssertions` object:
1031
```java
11-
class AsyncAssertionExampleTest
12-
{
13-
@Test
14-
void shouldReceiveChangeMessages() {
15-
// given
16-
var receivedMessages = new ConcurrentLinkedQueue<String>();
17-
18-
// when
19-
listenToChanges(receivedMessages::offer);
20-
21-
// then
22-
awaitAtMostOneSecond().untilAssertions(async -> async
23-
.assertThat(receivedMessages).containsExactly("A", "B", "C"));
24-
}
25-
26-
private static void listenToChanges(Consumer<String> consumer) {
27-
// simulation of asynchronous consumer
28-
var scheduler = Executors.newSingleThreadScheduledExecutor();
29-
scheduler.schedule(() -> consumer.accept("A"), 100L, TimeUnit.MILLISECONDS);
30-
scheduler.schedule(() -> consumer.accept("B"), 200L, TimeUnit.MILLISECONDS);
31-
scheduler.schedule(() -> consumer.accept("C"), 300L, TimeUnit.MILLISECONDS);
32-
}
33-
}
34-
```
32+
awaitAtMostOneSecond().untilAssertions(async -> {
33+
async.assertThat(condition1).isTrue();
34+
async.assertThat(condition2).isTrue();
35+
});
36+
```
37+
38+
The assertions will be periodically checked in provided check interval duration until success or exceeding the timeout.
39+
40+
When timeout is exceeded `AssertionError` will be thrown with error from last failed check.
41+
42+
43+
## License
44+
45+
This code is licensed under [MIT License.](https://opensource.org/licenses/MIT)

build.gradle.kts

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,36 @@ repositories {
2525
mavenCentral()
2626
}
2727

28+
contacts {
29+
addPerson("[email protected]", delegateClosureOf<Contact> {
30+
github = "jakubmalek"
31+
moniker = "Jakub Małek"
32+
role("owner")
33+
})
34+
}
35+
36+
sourceSets {
37+
register("junit4Test") {
38+
compileClasspath += sourceSets.main.get().output
39+
runtimeClasspath += sourceSets.main.get().output
40+
}
41+
}
42+
43+
configurations {
44+
"junit4TestImplementation" {
45+
extendsFrom(implementation.get())
46+
}
47+
"junit4TestAnnotationProcessor" {
48+
extendsFrom(annotationProcessor.get())
49+
}
50+
"junit4TestRuntimeOnly" {
51+
extendsFrom(runtimeOnly.get())
52+
}
53+
}
54+
55+
group to "com.webfleet"
56+
57+
2858
dependencies {
2959
// api
3060
api("org.assertj", "assertj-core", "[3.23.0,3.24.0[")
@@ -37,18 +67,58 @@ dependencies {
3767
// test
3868
testImplementation("org.junit.jupiter", "junit-jupiter", "[5.8.0,6.0.0[")
3969
testImplementation("org.mockito", "mockito-junit-jupiter", "[4.6.0,5.0.0[")
70+
71+
// junit4 test used to test optional dependency to opentest4j
72+
"junit4TestImplementation"("junit", "junit", "4.13.2")
4073
}
4174

4275
tasks {
76+
withType<JavaCompile> {
77+
options.encoding = "UTF-8"
78+
}
79+
// Test tasks
80+
val junit4Test = register<Test>("junit4Test") {
81+
group = LifecycleBasePlugin.VERIFICATION_GROUP
82+
description = "Test checking compatibility with JUnit4 API"
83+
systemProperty("file.encoding", "UTF-8")
84+
testLogging {
85+
events("passed", "skipped", "failed")
86+
}
87+
val sourceSet = sourceSets["junit4Test"]
88+
testClassesDirs = sourceSet.output.classesDirs
89+
classpath = configurations[sourceSet.runtimeClasspathConfigurationName] + sourceSet.output + sourceSets["main"].output
90+
}
4391
test {
4492
useJUnitPlatform()
93+
systemProperty("file.encoding", "UTF-8")
94+
finalizedBy(jacocoTestReport)
95+
finalizedBy(junit4Test)
96+
testLogging {
97+
events("passed", "skipped", "failed")
98+
}
99+
}
100+
// Jacoco tasks
101+
jacocoTestReport {
102+
dependsOn(test)
103+
executionData(fileTree(project.buildDir).include("jacoco/*.exec"))
104+
finalizedBy(jacocoTestCoverageVerification)
105+
reports {
106+
html.required to true
107+
xml.required to true
108+
}
109+
}
110+
jacocoTestCoverageVerification {
111+
executionData(fileTree(project.buildDir).include("jacoco/*.exec"))
112+
violationRules {
113+
rule {
114+
element = "PACKAGE"
115+
includes = listOf("com.webfleet.*")
116+
limit {
117+
counter = "INSTRUCTION"
118+
value = "COVEREDRATIO"
119+
minimum = "0.8".toBigDecimal()
120+
}
121+
}
122+
}
45123
}
46-
}
47-
48-
contacts {
49-
addPerson("[email protected]", delegateClosureOf<Contact> {
50-
github = "jakubmalek"
51-
moniker = "Jakub Małek"
52-
role("owner")
53-
})
54124
}

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
group=com.webfleet
2-
release.scope=major
1+
org.gradle.caching=true
2+
release.scope=patch
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.webfleet.assertj;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import java.time.Duration;
6+
import java.util.List;
7+
8+
import org.assertj.core.api.SoftAssertionError;
9+
import org.junit.Test;
10+
11+
12+
/**
13+
* Test checking compatibility with JUnit4.
14+
*/
15+
public class AsyncAssertionErrorCreatorJUnit4Test
16+
{
17+
private static final AsyncAssertAwaiConfig CONFIG = AsyncAssertAwaiConfig.withTimeout(Duration.ofSeconds(4));
18+
19+
@Test
20+
public void shouldCreateAsyncAssertionErrorForSingleError()
21+
{
22+
// given
23+
final var error = new AssertionError("test");
24+
25+
// when
26+
final var asyncAssertionError = AsyncAssertionErrorCreator.create(CONFIG, error);
27+
28+
// then
29+
assertThat(asyncAssertionError)
30+
.isInstanceOf(AssertionError.class)
31+
.hasMessage("Async assertion failed after exceeding 4000ms timeout\n"
32+
+ "test");
33+
}
34+
35+
@Test
36+
public void shouldCreateAssertionErrorForSingleSoftAssertionError()
37+
{
38+
// given
39+
final var multiErrors = new SoftAssertionError(List.of("my error"));
40+
41+
// when
42+
final var asyncAssertionError = AsyncAssertionErrorCreator.create(CONFIG, multiErrors);
43+
44+
// then
45+
assertThat(asyncAssertionError)
46+
.isInstanceOf(AssertionError.class)
47+
.hasMessage("Async assertion failed after exceeding 4000ms timeout\n"
48+
+ "my error");
49+
}
50+
51+
@Test
52+
public void shouldCreateAssertionErrorForMultipleErrors()
53+
{
54+
// given
55+
final var multiErrors = new SoftAssertionError(List.of("error-1", "error-2", "error-3"));
56+
57+
// when
58+
final var asyncAssertionError = AsyncAssertionErrorCreator.create(CONFIG, multiErrors);
59+
60+
// then
61+
assertThat(asyncAssertionError)
62+
.isInstanceOf(AssertionError.class)
63+
.hasMessage("Async assertion failed after exceeding 4000ms timeout (failures 3)\n"
64+
+ "-- failure 1 --error-1\n"
65+
+ "-- failure 2 --error-2\n"
66+
+ "-- failure 3 --error-3");
67+
}
68+
}

src/main/java/com/webfleet/assertj/AsyncAssert.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public interface AsyncAssert
5959
* @param unit the time unit of the check interval
6060
* @return new {@link AsyncAssert} with set check interval
6161
*/
62-
default AsyncAssert withWaitInterval(final long checkInterval, @NonNull final TimeUnit unit)
62+
default AsyncAssert withCheckInterval(final long checkInterval, @NonNull final TimeUnit unit)
6363
{
6464
return withCheckInterval(Duration.ofMillis(unit.toMillis(checkInterval)));
6565
}

src/main/java/com/webfleet/assertj/AsyncAssertTimeoutCondition.java renamed to src/main/java/com/webfleet/assertj/AsyncAssertAwaiConfig.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,25 @@
2020
@Getter
2121
@EqualsAndHashCode
2222
@ToString
23-
final class AsyncAssertTimeoutCondition
23+
final class AsyncAssertAwaiConfig
2424
{
2525
private static final Duration DEFAULT_CHECK_INTERVAL = Duration.ofMillis(100L);
2626
private static final Duration DEFAULT_SHORT_CHECK_INTERVAL = Duration.ofMillis(50L);
2727

2828
private final Duration timeout;
2929
private final Duration checkInterval;
3030

31-
static AsyncAssertTimeoutCondition withTimeout(@NonNull final Duration timeout)
31+
static AsyncAssertAwaiConfig withTimeout(@NonNull final Duration timeout)
3232
{
3333
if (timeout.compareTo(ZERO) <= 0)
3434
{
3535
throw new IllegalArgumentException("timeout must be greater than zero");
3636
}
3737
final var checkInterval = computeCheckInterval(timeout);
38-
return new AsyncAssertTimeoutCondition(timeout, checkInterval);
38+
return new AsyncAssertAwaiConfig(timeout, checkInterval);
3939
}
4040

41-
AsyncAssertTimeoutCondition withCheckInterval(@NonNull final Duration checkInterval)
41+
AsyncAssertAwaiConfig withCheckInterval(@NonNull final Duration checkInterval)
4242
{
4343
if (checkInterval.compareTo(ZERO) <= 0)
4444
{
@@ -48,15 +48,15 @@ AsyncAssertTimeoutCondition withCheckInterval(@NonNull final Duration checkInter
4848
{
4949
throw new IllegalArgumentException("checkInterval must be lower than or equal to timeout");
5050
}
51-
return new AsyncAssertTimeoutCondition(timeout, checkInterval);
51+
return new AsyncAssertAwaiConfig(timeout, checkInterval);
5252
}
5353

5454
Duration checkInterval(@NonNull final ElapsedTime elapsedTime)
5555
{
56-
final var elaspsedDuration = elapsedTime.get();
57-
if (elaspsedDuration.plus(checkInterval).compareTo(timeout) > 0)
56+
final var elapsedDuration = elapsedTime.get();
57+
if (elapsedDuration.plus(checkInterval).compareTo(timeout) > 0)
5858
{
59-
final var shortenedCheckInterval = timeout.minus(elaspsedDuration);
59+
final var shortenedCheckInterval = timeout.minus(elapsedDuration);
6060
return shortenedCheckInterval.isNegative() ? Duration.ZERO : shortenedCheckInterval;
6161
}
6262
return checkInterval;

0 commit comments

Comments
 (0)