Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add pitest support #462

Merged
merged 2 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,30 @@ The Scaffolding Clean Architecture plugin will allow you run 8 tasks:

## Generate Project

The **`cleanArchitecture | ca`** task will generate a clean architecture structure in your project, this task has four optional parameters; `package` , `type`, `name` and `coverage`.
If you run this task on an existing project it will override the `main.gradle`, `build.gradle` and `gradle.properties` files.
The **`cleanArchitecture | ca`** task will generate a clean architecture structure in your project.

- **`package`** `= <package.we.need>`: You can specify the main or default package of your project. `Default Value = co.com.bancolombia`
**Caution**: If you run this task on an existing project it will override the `main.gradle`, `build.gradle` and `gradle.properties` files.

- **`type`** `= <imperative | reactive>`: With this parameter the task will generate a POO project. `Default Value = reactive`

- **`name`** `= NameProject`: This parameter is going to specify the name of the project. `Default Value = cleanArchitecture`
| Parameter | Description | Usage | Default Value |
|-------------|--------------------------------------------------------------------------|----------------------------------------------|----------------------|
| package | You can specify the main or default package of your project | `--package=<desired.base.package>` | `co.com.bancolombia` |
| type | Define if project shoud be created around reactive or imperative aproach | `--type=<imperative or reactive>` | `reactive` |
| name | Sets projects name | `--name=<Project name>` | `cleanArchitecture` |
| lombok | Specify if you want to use this plugin | `--lombok=<true or false>` | `true` |
| metrics | Specify if you want to enable this feature with micrometer | `--metrics=<true or false>` | `true` |
| mutation | Specify if you want to enable mutation testing framework on this project | `--mutation=<true or false>` | `true` |
| javaVersion | Sets Java version | `--javaVersion= <VERSION_17 or VERSION_21>` | `VERSION_17` |


- **`lombok`** `= <true | false>`: Specify if you want to use this plugin . `Default Value = true`
Examples:

- **`metrics`** `= <true | false>`: Specify if you want to enable this feature with micrometer . `Default Value = true`
```shell
gradle cleanArchitecture --package=co.com.bancolombia --type=reactive --name=NameProject --lombok=true
gradle ca --package=co.com.bancolombia --type=reactive --name=NameProject --lombok=true
```

- **`javaVersion`** `= <VERSION_17 | VERSION_21>`: Java version . `Default Value = VERSION_17`

```shell
gradle cleanArchitecture --package=co.com.bancolombia --type=reactive --name=NameProject --lombok=true
gradle ca --package=co.com.bancolombia --type=reactive --name=NameProject --lombok=true
```

**_The structure will look like this for java:_**
**_The generated structure will look like this for java:_**

```bash
📦NameProject
Expand Down
1 change: 1 addition & 0 deletions src/main/java/co/com/bancolombia/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public final class Constants {
public static final String COBERTURA_VERSION = "4.0.0";
public static final String PLUGIN_VERSION = "3.17.8";
public static final String DEPENDENCY_CHECK_VERSION = "9.2.0";
public static final String PITEST_VERSION = "1.15.0";
// custom
public static final String GRADLE_WRAPPER_VERSION = "8.8";

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/co/com/bancolombia/factory/ModuleBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,10 @@ public boolean withMetrics() {
return getABooleanProperty("metrics", true);
}

public boolean withMutation() {
return getABooleanProperty("mutation", false);
}

@SafeVarargs
public final <T extends Validation> void runValidations(Class<T>... validations)
throws ValidationException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ArchitectureValidation {
Expand Down Expand Up @@ -37,21 +36,9 @@ private static String toOSPath(String os, File projectDir) {
return projectDir.toString();
}

private static void prepareParams(Project project, Project appService, ModuleBuilder builder) {
boolean hasSpringWeb =
appService.getConfigurations().stream()
.map(Configuration::getIncoming)
.flatMap(d -> d.getDependencies().stream())
.map(d -> d.getGroup() + ":" + d.getName())
.anyMatch(dep -> dep.equals("org.springframework:spring-web"));
project.getLogger().debug("hasSpringWeb: {}", hasSpringWeb);
builder.addParam("hasSpringWeb", hasSpringWeb);
}

@SneakyThrows
private static void generateArchUnitFiles(
Project project, Project appService, ModuleBuilder builder) {
prepareParams(project, appService, builder);
project
.getLogger()
.lifecycle("Injecting ArchitectureTest in module {}", appService.getProjectDir().getName());
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/co/com/bancolombia/task/GenerateStructureTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class GenerateStructureTask extends AbstractCleanArchitectureDefaultTask
private String name = "cleanArchitecture";
private BooleanOption lombok = BooleanOption.TRUE;
private BooleanOption metrics = BooleanOption.TRUE;
private BooleanOption mutation = BooleanOption.TRUE;
private BooleanOption force = BooleanOption.FALSE;
private BooleanOption withExample = BooleanOption.FALSE;
private JavaVersion javaVersion = JavaVersion.VERSION_17;
Expand Down Expand Up @@ -53,6 +54,13 @@ public void setMetrics(BooleanOption metrics) {
this.metrics = metrics;
}

@Option(
option = "mutation",
description = "Set if this project should include mutation tests configuration")
public void setMutation(BooleanOption mutation) {
this.mutation = mutation;
}

@Option(option = "javaVersion", description = "Set Java version")
public void setJavaVersion(JavaVersion javaVersion) {
this.javaVersion = javaVersion;
Expand Down Expand Up @@ -106,6 +114,7 @@ public void execute() throws IOException, CleanException {
builder.addParam("lombok", lombok == BooleanOption.TRUE);
builder.addParam("metrics", metrics == BooleanOption.TRUE);
builder.addParam("example", withExample == BooleanOption.TRUE);
builder.addParam("mutation", mutation == BooleanOption.TRUE);
builder.addParam("javaVersion", javaVersion);
builder.addParam("java17", javaVersion == JavaVersion.VERSION_17);
builder.addParam("java21", javaVersion == JavaVersion.VERSION_21);
Expand All @@ -119,6 +128,7 @@ public void execute() throws IOException, CleanException {
builder.addParam(REACTIVE, builder.isReactive());
builder.addParam("lombok", builder.isEnableLombok());
builder.addParam("metrics", builder.withMetrics());
builder.addParam("mutation", builder.withMutation());
if (builder.isEnableLombok()) {
builder.setupFromTemplate("structure/restructure");
} else {
Expand Down
17 changes: 16 additions & 1 deletion src/main/java/co/com/bancolombia/task/ValidateStructureTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.UnknownConfigurationException;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
Expand Down Expand Up @@ -47,7 +48,7 @@ public void execute() throws IOException, CleanException {
logger.lifecycle("Clean Architecture plugin version: {}", Utils.getVersionPlugin());
getModules().forEach(d -> logger.lifecycle("Submodules: " + d.getKey()));
logger.lifecycle("Project Package: {}", packageName);

checkForSpringWebDependency();
ArchitectureValidation.inject(getProject(), builder);

if (!validateModelLayer()) {
Expand All @@ -62,6 +63,20 @@ public void execute() throws IOException, CleanException {
logger.lifecycle("The project is valid");
}

private void checkForSpringWebDependency() {
boolean hasSpringWeb = false;
try {
hasSpringWeb =
getProject().getChildProjects().get(APP_SERVICE).getConfigurations()
.getByName("testImplementation").getDependencies().stream()
.anyMatch(d -> d.getName().equals("spring-web"));
} catch (UnknownConfigurationException e) {
logger.warn("configuration testImplementation not present");
}
logger.lifecycle("has spring-web dependency to run validations: {}", hasSpringWeb);
builder.addParam("hasSpringWeb", hasSpringWeb);
}

private boolean validateModelLayer() {
if (validateExistingModule(MODEL_MODULE)) {
logger.lifecycle("Validating Model Module");
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/structure/root/build.gradle.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ buildscript {
springBootVersion = '{{SPRING_BOOT_VERSION}}'
sonarVersion = '{{SONAR_VERSION}}'
jacocoVersion = '{{JACOCO_VERSION}}'
{{#mutation}}
pitestVersion = '{{PITEST_VERSION}}'
{{/mutation}}
{{#lombok}}
lombokVersion = '{{LOMBOK_VERSION}}'
{{/lombok}}
Expand All @@ -29,6 +32,9 @@ plugins {
id "org.owasp.dependencycheck" version "{{DEPENDENCY_CHECK_VERSION}}" apply false
{{/example}}
id 'org.springframework.boot' version "${springBootVersion}" apply false
{{#mutation}}
id 'info.solidsoft.pitest' version "${pitestVersion}" apply false
{{/mutation}}
id 'org.sonarqube' version "${sonarVersion}"
id 'jacoco'
}
Expand Down
28 changes: 28 additions & 0 deletions src/main/resources/structure/root/main.gradle.mustache
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{{#mutation}}
apply plugin: 'info.solidsoft.pitest.aggregator'
{{/mutation}}

allprojects {
repositories {
mavenCentral()
Expand All @@ -10,10 +14,17 @@ subprojects {
apply plugin: 'java'
apply plugin: 'jacoco'
apply plugin: 'io.spring.dependency-management'
{{#mutation}}
apply plugin: 'info.solidsoft.pitest'
{{/mutation}}

compileJava.dependsOn validateStructure
sourceCompatibility = JavaVersion.{{javaVersion}}

{{#mutation}}
//build.dependsOn 'pitest'
{{/mutation}}

test {
useJUnitPlatform()
}
Expand Down Expand Up @@ -50,6 +61,23 @@ subprojects {

test.finalizedBy(project.tasks.jacocoTestReport)

{{#mutation}}
pitest {
targetClasses = ['{{package}}.*']
excludedClasses = []
excludedTestClasses = []
verbose = true
outputFormats = ['XML', 'HTML']
threads = 8
exportLineCoverage = true
timestampedReports = false
fileExtensionsToFilter.addAll('xml', 'orbit')
junit5PluginVersion = '1.2.1'
failWhenNoMutations = false
jvmArgs = ["-XX:+AllowRedefinitionToAddDeleteMethods"]
}
{{/mutation}}

jacocoTestReport {
dependsOn test
reports {
Expand Down
Loading