Skip to content

Commit 333af93

Browse files
committed
chore: introduce selfie for unit testing
1 parent dfa0ea1 commit 333af93

6 files changed

Lines changed: 119 additions & 1 deletion

File tree

build-logic/src/main/groovy/buildlogic.java-common-conventions.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ plugins {
88
// Apply the java Plugin to add support for Java.
99
id 'java'
1010
id 'buildlogic.spotless-java-conventions'
11+
id 'buildlogic.java-selfie-tests-conventions'
1112
}
1213

1314
repositories {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
plugins {
2+
id 'java'
3+
}
4+
5+
tasks.withType(Test).configureEach {
6+
it.environment project.properties.subMap(["selfie"]) // optional, see "Overwrite everything" below
7+
it.inputs.files(fileTree("src/test") {
8+
// optional, improves up-to-date checking
9+
include "**/*.ss"
10+
})
11+
}

gradle/libs.versions.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ durian = "1.2.0"
66
junit = "5.8.1"
77
native-include-googleJavaFormat = "1.24.0"
88
picocli = "4.7.6"
9+
selfie = "2.5.1"
910
slf4j = "2.0.17"
1011
spotless-lib = "3.1.0"
1112

@@ -21,6 +22,7 @@ junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", vers
2122
native-include-googleJavaFormat = { module = "com.google.googlejavaformat:google-java-format", version.ref = "native-include-googleJavaFormat" }
2223
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
2324
picocli-codegen = { module = "info.picocli:picocli-codegen", version.ref = "picocli" }
25+
selfie = { module = "com.diffplug.selfie:selfie-runner-junit5", version.ref = "selfie" }
2426
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
2527
slf4j-binding = { module = "org.slf4j:slf4j-jdk14", version.ref = "slf4j" }
2628
spotless-lib = { module = "com.diffplug.spotless:spotless-lib", version.ref = "spotless-lib" }
@@ -32,4 +34,4 @@ native-includes = [
3234
"native-include-googleJavaFormat"
3335
]
3436
spotless-libs = ["spotless-lib", "spotless-lib-extra"]
35-
test-libs = ["assertj-core", "junit-jupiter-api"]
37+
test-libs = ["assertj-core", "junit-jupiter-api", "selfie"]

testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import org.assertj.core.api.AbstractCharSequenceAssert;
3636
import org.assertj.core.util.CheckReturnValue;
37+
import org.junit.jupiter.api.BeforeEach;
3738
import org.junit.jupiter.api.io.TempDir;
3839

3940
import com.diffplug.common.base.Errors;
@@ -52,6 +53,13 @@ public class ResourceHarness {
5253
@TempDir
5354
File folderDontUseDirectly;
5455

56+
SelfieExpectations selfieExpectations;
57+
58+
@BeforeEach
59+
void initSelfie() {
60+
selfieExpectations = SelfieExpectations.create(rootFolder());
61+
}
62+
5563
/** Returns the root folder (canonicalized to fix OS X issue) */
5664
public File rootFolder() {
5765
return Errors.rethrow().get(() -> folderDontUseDirectly.getCanonicalFile());
@@ -71,6 +79,10 @@ public File newFolder(String subpath) throws IOException {
7179
return targetDir;
7280
}
7381

82+
public SelfieExpectations selfie() {
83+
return selfieExpectations;
84+
}
85+
7486
/**
7587
* List the resources found in the specified path (directory) on the classpath
7688
* @param path - absolute path using unix-style file separators (if it is relative, it will be made absolute before class path scanning)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2025 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless;
17+
18+
import java.io.File;
19+
import java.nio.file.Files;
20+
import java.util.Objects;
21+
22+
import org.jetbrains.annotations.NotNull;
23+
24+
import com.diffplug.selfie.Camera;
25+
import com.diffplug.selfie.Selfie;
26+
import com.diffplug.selfie.Snapshot;
27+
import com.diffplug.selfie.StringSelfie;
28+
29+
public class SelfieExpectations {
30+
31+
@NotNull private final File rootFolder;
32+
33+
private SelfieExpectations(@NotNull File rootFolder) {
34+
this.rootFolder = Objects.requireNonNull(rootFolder);
35+
}
36+
37+
public static SelfieExpectations create(@NotNull File rootFolder) {
38+
Objects.requireNonNull(rootFolder);
39+
if (!rootFolder.isDirectory()) {
40+
throw new IllegalArgumentException("Root folder must be a directory: " + rootFolder);
41+
}
42+
return new SelfieExpectations(rootFolder);
43+
}
44+
45+
private static final Camera<Resource> RESOURCE_CAMERA = (Resource resource) -> {
46+
File file = new File(resource.rootFolder(), resource.resourcePath());
47+
if (!file.exists()) {
48+
throw new IllegalArgumentException("Resource not found: " + file);
49+
}
50+
return Snapshot.of(ThrowingEx.get(() -> Files.readString(file.toPath())));
51+
};
52+
53+
record Resource(File rootFolder, String resourcePath) {}
54+
55+
public StringSelfie expectResource(String resourcePath) {
56+
return Selfie.expectSelfie(new Resource(rootFolder, resourcePath), RESOURCE_CAMERA);
57+
}
58+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2025 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package selfie;
17+
18+
import java.io.File;
19+
20+
import org.jetbrains.annotations.NotNull;
21+
22+
import com.diffplug.selfie.junit5.SelfieSettingsAPI;
23+
24+
public class SelfieSettings extends SelfieSettingsAPI {
25+
26+
@Override
27+
public @NotNull File getRootFolder() {
28+
File f = new File(System.getProperty("user.dir"), "src/test/resources");
29+
if (f.exists()) {
30+
return f;
31+
}
32+
return super.getRootFolder(); // fallback to default
33+
}
34+
}

0 commit comments

Comments
 (0)