Skip to content

Commit 0a048c0

Browse files
authored
Add extension module for kotest property testing (#234)
1 parent 021b952 commit 0a048c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1752
-90
lines changed

.github/workflows/publish_snapshot.yml

+4
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ jobs:
2424
filters: |
2525
core:
2626
- '.github/workflows/**'
27+
- 'bom/**'
28+
- 'buildSrc/**'
2729
- 'core/**'
30+
- 'extension/**'
2831
- 'faker/**'
32+
- 'gradle/**'
2933
- '*gradle*'
3034
- 'set-version.sh'
3135

CHANGELOG.adoc

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
[discrete]
1010
=== Added
1111

12+
* https://github.com/serpro69/kotlin-faker/pull/234[#234] (:extension) Add extension module for kotest property testing
1213
* https://github.com/serpro69/kotlin-faker/pull/232[#232] (:core) Add support for alternative primary key when resolving values
1314
* https://github.com/serpro69/kotlin-faker/pull/227[#227] Add BOM to manage faker versions
1415
* https://github.com/serpro69/kotlin-faker/issues/222[#222] (:faker:databases) Create new Databases faker module

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ See [bom/README.md](bom/README.md) for more details.
9797

9898
Extra fakers covering a wide range of domains are available as separate dependencies. See [faker](faker) submodules in this repo for more details about each faker.
9999

100+
### Third-Party Extensions
101+
102+
Faker provides extensions for some third-party testing libraries. See [extension](extension) submodules in this repo for more details about each extension.
103+
100104
## Usage
101105

102106
Full usage documentation for kotlin-faker is available at [serpro69.github.io/kotlin-faker/](https://serpro69.github.io/kotlin-faker/).

build.gradle.kts

+5-14
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,13 @@ plugins {
1414
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.15.0-Beta.1"
1515
}
1616

17-
repositories {
18-
mavenCentral()
19-
}
20-
2117
group = "io.github.serpro69"
2218

19+
val lib = project.libs
20+
2321
subprojects {
2422
group = rootProject.group.toString()
2523

26-
repositories {
27-
mavenCentral()
28-
}
29-
3024
apply {
3125
plugin("com.github.ben-manes.versions")
3226
}
@@ -44,12 +38,9 @@ subprojects {
4438
val testImplementation by configurations
4539
val testRuntimeOnly by configurations
4640
// common-for-all dependencies go here
47-
platform(kotlin("bom"))
48-
implementation(kotlin("stdlib-jdk8"))
49-
implementation(kotlin("reflect"))
50-
testImplementation("io.kotest:kotest-runner-junit5:5.7.2")
51-
testImplementation("io.kotest:kotest-assertions-core:5.7.2")
52-
testImplementation("io.kotest:kotest-property-jvm:5.7.2")
41+
implementation(platform(lib.kotlin.bom))
42+
implementation(lib.bundles.kotlin)
43+
testImplementation(lib.bundles.test.kotest)
5344
}
5445

5546
configure<JavaPluginExtension> {

buildSrc/build.gradle.kts

+7-12
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
plugins {
22
`kotlin-dsl`
3-
}
4-
5-
repositories {
6-
mavenCentral()
7-
gradlePluginPortal()
3+
kotlin("jvm") version embeddedKotlinVersion
84
}
95

106
dependencies {
7+
//https://github.com/gradle/gradle/issues/15383#issuecomment-779893192
8+
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
9+
implementation(platform(libs.kotlin.bom))
1110
// needed to be able to apply external plugin
1211
// https://docs.gradle.org/current/userguide/custom_plugins.html#applying_external_plugins_in_precompiled_script_plugins
13-
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20")
14-
implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.9.10")
15-
implementation("com.github.johnrengelman:shadow:8.1.1")
12+
implementation(libs.bundles.gradle.plugins)
1613
// used by yaml-to-json buildSrc plugin
17-
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3")
14+
implementation(libs.jackson.databind)
1815
// use snakeyaml instead of jackson-dataformat-yaml to properly handle yaml anchors and write them as actual values to json
19-
implementation("org.yaml:snakeyaml:2.2")
20-
// NB! remember to set same version in settings.gradle.kts:13
21-
implementation("io.github.serpro69:semantic-versioning:0.13.0")
16+
implementation(libs.snakeyaml)
2217
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// shared repository definitions for both the main project and buildSrc
2+
3+
@Suppress("UnstableApiUsage") // Central declaration of repositories is an incubating feature
4+
dependencyResolutionManagement {
5+
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
6+
7+
repositories {
8+
mavenCentral()
9+
gradlePluginPortal()
10+
}
11+
12+
pluginManagement {
13+
repositories {
14+
gradlePluginPortal()
15+
mavenCentral()
16+
}
17+
}
18+
}

buildSrc/settings.gradle.kts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
2+
3+
rootProject.name = "buildSrc"
4+
5+
apply(from = "./repositories.settings.gradle.kts")
6+
7+
dependencyResolutionManagement {
8+
versionCatalogs {
9+
create("libs") {
10+
from(files("../gradle/libs.versions.toml"))
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import io.github.serpro69.semverkt.gradle.plugin.tasks.TagTask
2+
import org.gradle.accessors.dm.LibrariesForLibs
3+
import org.jetbrains.dokka.gradle.DokkaTask
4+
import java.util.Locale
5+
6+
plugins {
7+
base
8+
kotlin("jvm")
9+
id("org.jetbrains.dokka")
10+
`maven-publish`
11+
signing
12+
}
13+
14+
val libs = the<LibrariesForLibs>()
15+
16+
/**
17+
* For additional providers, use a combination of rootProject and subproject names for artifact name and similar things.
18+
* i.e. kotlin-faker-books, kotlin-faker-movies, kotlin-faker-tv, ...
19+
*
20+
* The "core" lib retains the same name as before: kotlin-faker
21+
*/
22+
private val fullName: String = "${rootProject.name}-${project.name}"
23+
24+
val isDev = provider { version.toString().startsWith("0.0.0") }
25+
val isSnapshot = provider {
26+
// QUESTION do we need to check if rootProject is also set to snapshot?
27+
// Likely not, since "isRelease" will not just check for the version, but also for the actual tag creation
28+
// rootProject.version.toString().endsWith("SNAPSHOT") &&
29+
version.toString().endsWith("SNAPSHOT")
30+
}
31+
val isRelease = provider {
32+
val tag = project.tasks.getByName("tag", TagTask::class)
33+
/* all fakers have their own tags, so checking if tag.didWork is enough for them,
34+
':core' shares the tag with 'root', ':bom' and ':cli-bot' modules,
35+
and hence the tag might already exist and didWork will return false for ':core' */
36+
val tagCreated = if (project.name != "core") tag.didWork else tag.didWork || tag.tagExists
37+
!isDev.get() && !isSnapshot.get() && tagCreated
38+
}
39+
40+
configurations {
41+
create("integrationImplementation") { extendsFrom(configurations.getByName("testImplementation")) }
42+
create("integrationRuntimeOnly") {
43+
extendsFrom(
44+
configurations.getByName("testRuntimeOnly"),
45+
)
46+
}
47+
}
48+
49+
// configure sourceSets as extension since it's not available here as `sourceSets` is an extension on `Project`
50+
// https://docs.gradle.org/current/userguide/kotlin_dsl.html#project_extensions_and_conventions
51+
configure<SourceSetContainer> {
52+
create("integration") {
53+
resources.srcDir("src/integration/resources")
54+
compileClasspath += main.get().compileClasspath + test.get().compileClasspath
55+
runtimeClasspath += main.get().runtimeClasspath + test.get().runtimeClasspath
56+
}
57+
main {
58+
resources {
59+
this.srcDir("build/generated/src/main/resources")
60+
}
61+
}
62+
}
63+
64+
dependencies {
65+
val implementation by configurations
66+
implementation(libs.bundles.kotlin)
67+
}
68+
69+
val integrationTest by tasks.creating(Test::class) {
70+
testClassesDirs = sourceSets["integration"].output.classesDirs
71+
classpath = sourceSets["integration"].runtimeClasspath
72+
dependsOn(tasks.test)
73+
}
74+
75+
tasks.withType<Jar> {
76+
archiveBaseName.set(fullName)
77+
78+
manifest {
79+
attributes(
80+
mapOf(
81+
"Implementation-Title" to fullName,
82+
"Implementation-Version" to project.version,
83+
/*
84+
* We can't add this here because this resolves the configuration,
85+
* after which it effectively becomes read-only and we'll get an error
86+
* Cannot change dependencies of dependency configuration ':core:implementation' after it has been included in dependency resolution
87+
* if we try to add more dependencies in the module's build.gradle file directly
88+
*/
89+
// "Class-Path" to project.configurations.compileClasspath.get().joinToString(" ") { it.name }
90+
)
91+
)
92+
}
93+
94+
dependsOn(integrationTest)
95+
}
96+
97+
val sourcesJar by tasks.creating(Jar::class) {
98+
archiveClassifier.set("sources")
99+
from(sourceSets.getByName("main").allSource)
100+
from("${rootProject.rootDir.resolve("LICENSE.adoc")}") {
101+
into("META-INF")
102+
}
103+
}
104+
105+
val dokkaJavadocJar by tasks.creating(Jar::class) {
106+
archiveClassifier.set("javadoc")
107+
dependsOn(tasks.dokkaJavadoc)
108+
from(tasks.dokkaJavadoc.get().outputDirectory.orNull)
109+
}
110+
111+
artifacts {
112+
archives(sourcesJar)
113+
archives(dokkaJavadocJar)
114+
}
115+
116+
val publicationName =
117+
"faker${project.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}"
118+
119+
publishing {
120+
publications {
121+
create<MavenPublication>(publicationName) {
122+
groupId = project.group.toString()
123+
artifactId = fullName
124+
version = project.version.toString()
125+
from(components["java"])
126+
artifact(sourcesJar)
127+
artifact(dokkaJavadocJar) //TODO configure dokka or use defaults?
128+
129+
pom {
130+
packaging = "jar"
131+
name.set(fullName)
132+
description.set("Generate realistically looking fake data such as names, addresses, banking details, and many more, that can be used for testing and data anonymization purposes.")
133+
url.set("https://github.com/serpro69/kotlin-faker")
134+
scm {
135+
connection.set("scm:git:https://github.com/serpro69/kotlin-faker")
136+
developerConnection.set("scm:git:https://github.com/serpro69")
137+
url.set("https://github.com/serpro69/kotlin-faker")
138+
}
139+
issueManagement {
140+
url.set("https://github.com/serpro69/kotlin-faker/issues")
141+
}
142+
licenses {
143+
license {
144+
name.set("MIT")
145+
url.set("https://opensource.org/licenses/mit-license.php")
146+
}
147+
}
148+
developers {
149+
developer {
150+
id.set("serpro69")
151+
name.set("Serhii Prodan")
152+
}
153+
}
154+
}
155+
}
156+
}
157+
}
158+
159+
tasks {
160+
assemble {
161+
dependsOn(integrationTest)
162+
dependsOn(jar)
163+
}
164+
}
165+
166+
signing {
167+
sign(publishing.publications[publicationName])
168+
}
169+
170+
tasks.withType<DokkaTask>().configureEach {
171+
onlyIf("Not dev") { !isDev.get() }
172+
onlyIf("Release or snapshot") { isRelease.get() || isSnapshot.get() }
173+
}
174+
175+
tasks.withType<PublishToMavenRepository>().configureEach {
176+
dependsOn(project.tasks.getByName("tag"))
177+
dependsOn(project.tasks.withType(Sign::class.java))
178+
onlyIf("Not dev") { !isDev.get() }
179+
onlyIf("Release or snapshot") { isRelease.get() || isSnapshot.get() }
180+
}
181+
182+
tasks.withType<PublishToMavenLocal>().configureEach {
183+
onlyIf("In development") { isDev.get() || isSnapshot.get() }
184+
}
185+
186+
tasks.withType<Sign>().configureEach {
187+
dependsOn(project.tasks.getByName("tag"))
188+
onlyIf("Not dev and snapshot") { !isDev.get() && !isSnapshot.get() }
189+
onlyIf("Release") { isRelease.get() }
190+
}

buildSrc/src/main/kotlin/faker-lib-conventions.gradle.kts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import com.github.jengelman.gradle.plugins.shadow.ShadowExtension
22
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
33
import io.github.serpro69.semverkt.gradle.plugin.tasks.TagTask
4+
import org.gradle.accessors.dm.LibrariesForLibs
45
import org.jetbrains.dokka.gradle.DokkaTask
56
import java.util.*
67

78
plugins {
9+
base
810
`java-library`
911
kotlin("jvm")
1012
id("org.jetbrains.dokka")
@@ -13,6 +15,8 @@ plugins {
1315
signing
1416
}
1517

18+
val libs = the<LibrariesForLibs>()
19+
1620
/**
1721
* For additional providers, use a combination of rootProject and subproject names for artifact name and similar things.
1822
* i.e. kotlin-faker-books, kotlin-faker-movies, kotlin-faker-tv, ...
@@ -69,8 +73,7 @@ dependencies {
6973
val testImplementation by configurations
7074
val testRuntimeOnly by configurations
7175
val integrationImplementation by configurations
72-
shadow(kotlin("stdlib-jdk8"))
73-
shadow(kotlin("reflect"))
76+
shadow(libs.bundles.kotlin)
7477
testRuntimeOnly("ch.qos.logback:logback-core:1.3.4") {
7578
version { strictly("1.3.4") /* last stable for java 8 */ }
7679
}
@@ -79,8 +82,8 @@ dependencies {
7982
}
8083
testRuntimeOnly("org.codehaus.groovy:groovy:3.0.19")
8184
// we're shadowing these so they need to be available for test runtime
82-
testRuntimeOnly("com.ibm.icu:icu4j:73.2")
83-
testRuntimeOnly("com.github.mifmif:generex:1.0.2")
85+
testRuntimeOnly(libs.icu4j)
86+
testRuntimeOnly(libs.generex)
8487
}
8588

8689
val integrationTest by tasks.creating(Test::class) {

0 commit comments

Comments
 (0)