Repository: jhipster/jhipster-lite
Pull request #9606 (2024-04-22 09:28:15)

Module: Property-based testing using jqwik


Patch:
diff --git a/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/package-info.java b/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/package-info.java
new file mode 100644
index 000000000..735fba130
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/package-info.java
@@ -0,0 +1,2 @@
+@tech.jhipster.lite.BusinessContext
+package tech.jhipster.lite.generator.server.javatool.pbt;
diff --git a/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteModuleSlug.java b/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteModuleSlug.java
index 777ef5ac5..471bbdb58 100644
--- a/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteModuleSlug.java
+++ b/src/main/java/tech/jhipster/lite/generator/slug/domain/JHLiteModuleSlug.java
@@ -56,6 +56,7 @@ public enum JHLiteModuleSlug implements JHipsterModuleSlugFactory {
   JAVA_MEMOIZERS("java-memoizers"),
   JIB("jib"),
   JPA_PAGINATION("jpa-pagination"),
+  JQWIK("jqwik"),
   KIPE_AUTHORIZATION("kipe-authorization"),
   KIPE_EXPRESSION("kipe-expression"),
   LICENSE_APACHE("license-apache"),
diff --git a/src/main/resources/generator/dependencies/pom.xml b/src/main/resources/generator/dependencies/pom.xml
index 432824d80..6058ef0d6 100644
--- a/src/main/resources/generator/dependencies/pom.xml
+++ b/src/main/resources/generator/dependencies/pom.xml
@@ -44,6 +44,7 @@
     <testcontainers.version>1.19.7</testcontainers.version>
     <archunit-junit5.version>1.3.0</archunit-junit5.version>
     <cucumber.version>7.17.0</cucumber.version>
+    <jqwik.version>1.8.3</jqwik.version>
     <!-- Maven Plugins -->
     <os-maven-plugin.version>1.7.1</os-maven-plugin.version>
     <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
@@ -336,6 +337,12 @@
         <artifactId>pulsar-client</artifactId>
         <version>${pulsar.version}</version>
       </dependency>
+      <dependency>
+        <groupId>net.jqwik</groupId>
+        <artifactId>jqwik</artifactId>
+        <version>${jqwik.version}</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 </project>


Test patch:
diff --git a/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/application/PropertyBasedTestingApplicationService.java b/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/application/PropertyBasedTestingApplicationService.java
new file mode 100644
index 000000000..2f62cf692
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/application/PropertyBasedTestingApplicationService.java
@@ -0,0 +1,20 @@
+package tech.jhipster.lite.generator.server.javatool.pbt.application;
+
+import org.springframework.stereotype.Service;
+import tech.jhipster.lite.generator.server.javatool.pbt.domain.PropertyBasedTestingModuleFactory;
+import tech.jhipster.lite.module.domain.JHipsterModule;
+import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
+
+@Service
+public class PropertyBasedTestingApplicationService {
+
+  private final PropertyBasedTestingModuleFactory propertyBasedTesting;
+
+  public PropertyBasedTestingApplicationService() {
+    propertyBasedTesting = new PropertyBasedTestingModuleFactory();
+  }
+
+  public JHipsterModule build(JHipsterModuleProperties properties) {
+    return propertyBasedTesting.build(properties);
+  }
+}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/domain/PropertyBasedTestingModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/domain/PropertyBasedTestingModuleFactory.java
new file mode 100644
index 000000000..de111b95f
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/domain/PropertyBasedTestingModuleFactory.java
@@ -0,0 +1,23 @@
+package tech.jhipster.lite.generator.server.javatool.pbt.domain;
+
+import static tech.jhipster.lite.module.domain.JHipsterModule.*;
+
+import tech.jhipster.lite.module.domain.JHipsterModule;
+import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
+import tech.jhipster.lite.shared.error.domain.Assert;
+
+public class PropertyBasedTestingModuleFactory {
+
+  public JHipsterModule build(JHipsterModuleProperties properties) {
+    Assert.notNull("properties", properties);
+
+    //@formatter:off
+    return moduleBuilder(properties)
+      .documentation(documentationTitle("Property Based Testing"), from("server/javatool/pbt/property-based-testing.md"))
+      .javaDependencies()
+        .addTestDependency(groupId("net.jqwik"), artifactId("jqwik"), versionSlug("jqwik"))
+        .and()
+      .build();
+    //@formatter:on
+  }
+}
diff --git a/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/infrastructure/primary/PropertyBasedTestingModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/infrastructure/primary/PropertyBasedTestingModuleConfiguration.java
new file mode 100644
index 000000000..1e0b3a6ee
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/generator/server/javatool/pbt/infrastructure/primary/PropertyBasedTestingModuleConfiguration.java
@@ -0,0 +1,25 @@
+package tech.jhipster.lite.generator.server.javatool.pbt.infrastructure.primary;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import tech.jhipster.lite.generator.server.javatool.pbt.application.PropertyBasedTestingApplicationService;
+import tech.jhipster.lite.generator.slug.domain.JHLiteFeatureSlug;
+import tech.jhipster.lite.generator.slug.domain.JHLiteModuleSlug;
+import tech.jhipster.lite.module.domain.resource.JHipsterModuleOrganization;
+import tech.jhipster.lite.module.domain.resource.JHipsterModulePropertiesDefinition;
+import tech.jhipster.lite.module.domain.resource.JHipsterModuleResource;
+
+@Configuration
+class PropertyBasedTestingModuleConfiguration {
+
+  @Bean
+  JHipsterModuleResource jqwikModule(PropertyBasedTestingApplicationService propertyBasedTesting) {
+    return JHipsterModuleResource.builder()
+      .slug(JHLiteModuleSlug.JQWIK)
+      .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().build())
+      .apiDoc("Advanced testing", "Add jqwik library for Property Based Testing")
+      .organization(JHipsterModuleOrganization.builder().addDependency(JHLiteFeatureSlug.JAVA_BUILD_TOOL).build())
+      .tags("server", "testing")
+      .factory(propertyBasedTesting::build);
+  }
+}
diff --git a/src/main/resources/generator/server/javatool/pbt/property-based-testing.md b/src/main/resources/generator/server/javatool/pbt/property-based-testing.md
new file mode 100644
index 000000000..be4514b2a
--- /dev/null
+++ b/src/main/resources/generator/server/javatool/pbt/property-based-testing.md
@@ -0,0 +1,28 @@
+# Property based testing with jqwik
+
+Property-based testing takes a very different approach from classical example-based testing: a single test is run hundreds of times with randomly generated inputs.
+It allows checking that the system under test abides by certain properties that should hold true for all possible inputs.
+
+Here are two (surprisingly failing) examples of simple property-based tests from [jqwik User Guide](https://jqwik.net/docs/current/user-guide.html):
+
+```java
+import static org.assertj.core.api.Assertions.assertThat;
+
+import net.jqwik.api.*;
+
+class PropertyBasedTests {
+
+  @Property
+  boolean absoluteValueOfAllNumbersIsPositive(@ForAll int anInteger) {
+    return Math.abs(anInteger) >= 0;
+  }
+
+  @Property
+  void lengthOfConcatenatedStringIsGreaterThanLengthOfEach(@ForAll String string1, @ForAll String string2) {
+    String concatenated = string1 + string2;
+    assertThat(concatenated.length()).isGreaterThan(string1.length());
+    assertThat(concatenated.length()).isGreaterThan(string2.length());
+  }
+}
+
+```
diff --git a/src/test/features/server/javatool/property-based-testing.feature b/src/test/features/server/javatool/property-based-testing.feature
new file mode 100644
index 000000000..918e017be
--- /dev/null
+++ b/src/test/features/server/javatool/property-based-testing.feature
@@ -0,0 +1,6 @@
+Feature: Property-based testing module
+
+  Scenario: Should apply jqwik module in maven project
+    When I apply "jqwik" module to default project with maven file
+      | packageName | tech.jhipster.chips |
+    Then I should have "<artifactId>jqwik</artifactId>" in "pom.xml"
diff --git a/src/test/java/tech/jhipster/lite/generator/server/javatool/pbt/domain/PropertyBasedTestingModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/server/javatool/pbt/domain/PropertyBasedTestingModuleFactoryTest.java
new file mode 100644
index 000000000..7bb9ebde7
--- /dev/null
+++ b/src/test/java/tech/jhipster/lite/generator/server/javatool/pbt/domain/PropertyBasedTestingModuleFactoryTest.java
@@ -0,0 +1,37 @@
+package tech.jhipster.lite.generator.server.javatool.pbt.domain;
+
+import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.*;
+
+import org.junit.jupiter.api.Test;
+import tech.jhipster.lite.TestFileUtils;
+import tech.jhipster.lite.UnitTest;
+import tech.jhipster.lite.module.domain.JHipsterModule;
+import tech.jhipster.lite.module.domain.JHipsterModulesFixture;
+import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties;
+
+@UnitTest
+class PropertyBasedTestingModuleFactoryTest {
+
+  private final PropertyBasedTestingModuleFactory factory = new PropertyBasedTestingModuleFactory();
+
+  @Test
+  void shouldBuildJqwikModule() {
+    JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(TestFileUtils.tmpDirForTest()).build();
+
+    JHipsterModule module = factory.build(properties);
+
+    assertThatModuleWithFiles(module, pomFile())
+      .hasFiles("documentation/property-based-testing.md")
+      .hasFile("pom.xml")
+      .containing(
+        """
+            <dependency>
+              <groupId>net.jqwik</groupId>
+              <artifactId>jqwik</artifactId>
+              <version>${jqwik.version}</version>
+              <scope>test</scope>
+            </dependency>
+        """
+      );
+  }
+}
diff --git a/tests-ci/generate.sh b/tests-ci/generate.sh
index 78a997734..83e32140e 100755
--- a/tests-ci/generate.sh
+++ b/tests-ci/generate.sh
@@ -58,6 +58,7 @@ spring_boot() {
   "github-actions-${java_build_tool}" \
   "java-base" \
   "checkstyle" \
+  "jqwik" \
   "protobuf" \
   "protobuf-backwards-compatibility-check" \
   "jacoco-with-min-coverage-check" \