diff --git a/README.md b/README.md index 653b0c8..1ca4564 100644 --- a/README.md +++ b/README.md @@ -210,5 +210,8 @@ Unresolvable methods (no coverage information available): 1. exception: completely stateless `*Utils` classes with static methods only 1. utility classes must be `abstract` and have a private default constructor 1. exception: real constants with names in upper case delimited by underscores -1. `logger` has to be protected final but not static: `protected final Logger logger = LoggerFactory.getLogger(getClass());` +1. `logger` has to be protected final but not static: `protected final Logger logger = LoggerFactory.getLogger(getClass());` (see https://www.slf4j.org/faq.html#declared_static) 1. restrict file, method and lambda lengths to reasonable values +1. code dependency + 1. no code cycles on package level + 1. no dependencies between a package and any of its (sub-)sub-packages (only the other way around) diff --git a/test-gap-analysis-maven-plugin/src/main/java/com/scheible/testgapanalysis/maven/DebugCoverageResolutionMojo.java b/test-gap-analysis-maven-plugin/src/main/java/com/scheible/testgapanalysis/maven/DebugCoverageResolutionMojo.java index bba66d3..990c909 100644 --- a/test-gap-analysis-maven-plugin/src/main/java/com/scheible/testgapanalysis/maven/DebugCoverageResolutionMojo.java +++ b/test-gap-analysis-maven-plugin/src/main/java/com/scheible/testgapanalysis/maven/DebugCoverageResolutionMojo.java @@ -1,7 +1,7 @@ package com.scheible.testgapanalysis.maven; -import com.scheible.testgapanalysis.DebugCoverageResolution; -import com.scheible.testgapanalysis.DebugCoverageResolutionReport; +import com.scheible.testgapanalysis.debug.DebugCoverageResolution; +import com.scheible.testgapanalysis.debug.DebugCoverageResolutionReport; import com.scheible.testgapanalysis.jacoco.JaCoCoReportParser; import com.scheible.testgapanalysis.parser.JavaParser; diff --git a/test-gap-analysis-maven-plugin/src/main/java/com/scheible/testgapanalysis/maven/TestGapAnalysisMojo.java b/test-gap-analysis-maven-plugin/src/main/java/com/scheible/testgapanalysis/maven/TestGapAnalysisMojo.java index 549065c..60eecf7 100644 --- a/test-gap-analysis-maven-plugin/src/main/java/com/scheible/testgapanalysis/maven/TestGapAnalysisMojo.java +++ b/test-gap-analysis-maven-plugin/src/main/java/com/scheible/testgapanalysis/maven/TestGapAnalysisMojo.java @@ -2,8 +2,8 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.scheible.testgapanalysis.TestGapAnalysis; -import com.scheible.testgapanalysis.TestGapReport; +import com.scheible.testgapanalysis.analysis.testgap.TestGapAnalysis; +import com.scheible.testgapanalysis.analysis.testgap.TestGapReport; import com.scheible.testgapanalysis.analysis.Analysis; import com.scheible.testgapanalysis.git.GitDiffer; import com.scheible.testgapanalysis.jacoco.JaCoCoReportParser; diff --git a/test-gap-analysis/pom.xml b/test-gap-analysis/pom.xml index 5c4c6ac..ec579a0 100644 --- a/test-gap-analysis/pom.xml +++ b/test-gap-analysis/pom.xml @@ -104,6 +104,11 @@ archunit ${archunit.version} + + com.tngtech.archunit + archunit-junit4 + ${archunit.version} + org.eclipse.jgit @@ -163,6 +168,11 @@ archunit test + + com.tngtech.archunit + archunit-junit4 + test + com.scheible.pocketsaw.impl diff --git a/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/TestGapAnalysis.java b/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/analysis/testgap/TestGapAnalysis.java similarity index 94% rename from test-gap-analysis/src/main/java/com/scheible/testgapanalysis/TestGapAnalysis.java rename to test-gap-analysis/src/main/java/com/scheible/testgapanalysis/analysis/testgap/TestGapAnalysis.java index 0e8b250..de22a5e 100644 --- a/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/TestGapAnalysis.java +++ b/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/analysis/testgap/TestGapAnalysis.java @@ -1,4 +1,4 @@ -package com.scheible.testgapanalysis; +package com.scheible.testgapanalysis.analysis.testgap; import static java.util.Collections.emptySet; @@ -12,12 +12,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.scheible.testgapanalysis.TestGapReport.CoverageReportMethod; -import com.scheible.testgapanalysis.TestGapReport.NewOrChangedFile; -import com.scheible.testgapanalysis.TestGapReport.NewOrChangedFile.State; -import com.scheible.testgapanalysis.TestGapReport.TestGapMethod; import com.scheible.testgapanalysis.analysis.Analysis; import com.scheible.testgapanalysis.analysis.AnalysisResult; +import com.scheible.testgapanalysis.analysis.testgap.TestGapReport.CoverageReportMethod; +import com.scheible.testgapanalysis.analysis.testgap.TestGapReport.NewOrChangedFile; +import com.scheible.testgapanalysis.analysis.testgap.TestGapReport.NewOrChangedFile.State; +import com.scheible.testgapanalysis.analysis.testgap.TestGapReport.TestGapMethod; import com.scheible.testgapanalysis.common.FilesUtils; import com.scheible.testgapanalysis.git.GitDiffer; import com.scheible.testgapanalysis.git.RepositoryStatus; diff --git a/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/TestGapReport.java b/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/analysis/testgap/TestGapReport.java similarity index 99% rename from test-gap-analysis/src/main/java/com/scheible/testgapanalysis/TestGapReport.java rename to test-gap-analysis/src/main/java/com/scheible/testgapanalysis/analysis/testgap/TestGapReport.java index 54d71bd..c119560 100644 --- a/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/TestGapReport.java +++ b/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/analysis/testgap/TestGapReport.java @@ -1,4 +1,4 @@ -package com.scheible.testgapanalysis; +package com.scheible.testgapanalysis.analysis.testgap; import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableSet; diff --git a/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/DebugCoverageResolution.java b/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/debug/DebugCoverageResolution.java similarity index 98% rename from test-gap-analysis/src/main/java/com/scheible/testgapanalysis/DebugCoverageResolution.java rename to test-gap-analysis/src/main/java/com/scheible/testgapanalysis/debug/DebugCoverageResolution.java index 5b6f4b8..285a1b9 100644 --- a/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/DebugCoverageResolution.java +++ b/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/debug/DebugCoverageResolution.java @@ -1,4 +1,4 @@ -package com.scheible.testgapanalysis; +package com.scheible.testgapanalysis.debug; import java.io.File; import java.io.IOException; diff --git a/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/DebugCoverageResolutionReport.java b/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/debug/DebugCoverageResolutionReport.java similarity index 97% rename from test-gap-analysis/src/main/java/com/scheible/testgapanalysis/DebugCoverageResolutionReport.java rename to test-gap-analysis/src/main/java/com/scheible/testgapanalysis/debug/DebugCoverageResolutionReport.java index ecad37f..00ef482 100644 --- a/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/DebugCoverageResolutionReport.java +++ b/test-gap-analysis/src/main/java/com/scheible/testgapanalysis/debug/DebugCoverageResolutionReport.java @@ -1,4 +1,4 @@ -package com.scheible.testgapanalysis; +package com.scheible.testgapanalysis.debug; import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableSet; diff --git a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/CodeDependenciesTest.java b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/CodeDependenciesTest.java new file mode 100644 index 0000000..55831ed --- /dev/null +++ b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/CodeDependenciesTest.java @@ -0,0 +1,71 @@ +package com.scheible.testgapanalysis; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; +import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices; + +import org.junit.runner.RunWith; + +import com.tngtech.archunit.core.domain.Dependency; +import com.tngtech.archunit.core.domain.JavaClass; +import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.junit.ArchUnitRunner; +import com.tngtech.archunit.lang.ArchCondition; +import com.tngtech.archunit.lang.ArchRule; +import com.tngtech.archunit.lang.ConditionEvents; +import com.tngtech.archunit.lang.SimpleConditionEvent; +import com.tngtech.archunit.library.dependencies.SliceAssignment; +import com.tngtech.archunit.library.dependencies.SliceIdentifier; + +/** + * + * @author sj + */ +@RunWith(ArchUnitRunner.class) +@AnalyzeClasses(packagesOf = CodeDependenciesTest.class, importOptions = DoNotIncludeTests.class) +public class CodeDependenciesTest { + + private static class SlicePerPackage implements SliceAssignment { + + @Override + public SliceIdentifier getIdentifierOf(final JavaClass javaClass) { + return SliceIdentifier.of(javaClass.getPackageName()); + } + + @Override + public String getDescription() { + return "Every package is treated as a slice."; + } + } + + @ArchTest + static final ArchRule noPackageCyclesRule = slices().assignedFrom(new SlicePerPackage()).should().beFreeOfCycles(); + + private static class DependOnDescendantPackagesCondition extends ArchCondition { + + DependOnDescendantPackagesCondition() { + super("depend on descendant packages"); + } + + @Override + public void check(JavaClass clazz, ConditionEvents events) { + for (Dependency dependency : clazz.getDirectDependenciesFromSelf()) { + boolean dependencyOnDescendantPackage = isDependencyOnDescendantPackage(dependency.getOriginClass(), + dependency.getTargetClass()); + events.add(new SimpleConditionEvent(dependency, dependencyOnDescendantPackage, + dependency.getDescription())); + } + } + + private boolean isDependencyOnDescendantPackage(JavaClass origin, JavaClass target) { + String originPackageName = origin.getPackageName(); + String targetSubPackagePrefix = target.getPackageName(); + return targetSubPackagePrefix.contains(originPackageName + "."); + } + } + + @ArchTest + static final ArchRule packageLayeringRule = noClasses().should(new DependOnDescendantPackagesCondition()) + .because("lower packages shouldn't build on higher packages"); +} diff --git a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapAnalysisSubModule.java b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapAnalysisSubModule.java index 84b63d9..e08a43e 100644 --- a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapAnalysisSubModule.java +++ b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapAnalysisSubModule.java @@ -1,20 +1,12 @@ package com.scheible.testgapanalysis; import com.scheible.pocketsaw.api.SubModule; -import com.scheible.testgapanalysis.ExternalFunctionalities.Slf4j; -import com.scheible.testgapanalysis.analysis.AnalysisSubModule; -import com.scheible.testgapanalysis.common.CommonSubModule; -import com.scheible.testgapanalysis.git.GitSubModule; -import com.scheible.testgapanalysis.jacoco.JaCoCoSubModule; -import com.scheible.testgapanalysis.jacoco.resolver.JaCoCoResolverSubModule; -import com.scheible.testgapanalysis.parser.ParserSubModule; /** * * @author sj */ -@SubModule(includeSubPackages = false, uses = {AnalysisSubModule.class, JaCoCoSubModule.class, ParserSubModule.class, - JaCoCoResolverSubModule.class, Slf4j.class, GitSubModule.class, CommonSubModule.class}) +@SubModule(includeSubPackages = false) public class TestGapAnalysisSubModule { } diff --git a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/AnalysisSubModule.java b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/AnalysisSubModule.java index 5f0e0bc..95ec973 100644 --- a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/AnalysisSubModule.java +++ b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/AnalysisSubModule.java @@ -2,6 +2,7 @@ import com.scheible.pocketsaw.api.SubModule; import com.scheible.testgapanalysis.ExternalFunctionalities.Slf4j; +import com.scheible.testgapanalysis.common.CommonSubModule; import com.scheible.testgapanalysis.git.GitSubModule; import com.scheible.testgapanalysis.jacoco.JaCoCoSubModule; import com.scheible.testgapanalysis.jacoco.resolver.JaCoCoResolverSubModule; @@ -12,7 +13,7 @@ * @author sj */ @SubModule(uses = {JaCoCoSubModule.class, JaCoCoResolverSubModule.class, GitSubModule.class, ParserSubModule.class, - Slf4j.class}) + Slf4j.class, CommonSubModule.class}) public class AnalysisSubModule { } diff --git a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/AnalysisTestGapSubModule.java b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/AnalysisTestGapSubModule.java new file mode 100644 index 0000000..c56d1cd --- /dev/null +++ b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/AnalysisTestGapSubModule.java @@ -0,0 +1,20 @@ +package com.scheible.testgapanalysis.analysis.testgap; + +import com.scheible.pocketsaw.api.SubModule; +import com.scheible.testgapanalysis.ExternalFunctionalities.Slf4j; +import com.scheible.testgapanalysis.analysis.*; +import com.scheible.testgapanalysis.common.CommonSubModule; +import com.scheible.testgapanalysis.git.GitSubModule; +import com.scheible.testgapanalysis.jacoco.JaCoCoSubModule; +import com.scheible.testgapanalysis.jacoco.resolver.JaCoCoResolverSubModule; +import com.scheible.testgapanalysis.parser.ParserSubModule; + +/** + * + * @author sj + */ +@SubModule(uses = {JaCoCoSubModule.class, JaCoCoResolverSubModule.class, GitSubModule.class, ParserSubModule.class, + Slf4j.class, CommonSubModule.class}) +public class AnalysisTestGapSubModule { + +} diff --git a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapAnalysisTest.java b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/TestGapAnalysisTest.java similarity index 96% rename from test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapAnalysisTest.java rename to test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/TestGapAnalysisTest.java index d2fc06f..a2ad649 100644 --- a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapAnalysisTest.java +++ b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/TestGapAnalysisTest.java @@ -1,4 +1,4 @@ -package com.scheible.testgapanalysis; +package com.scheible.testgapanalysis.analysis.testgap; import static org.assertj.core.api.Assertions.assertThat; diff --git a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapReportTest.java b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/TestGapReportTest.java similarity index 91% rename from test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapReportTest.java rename to test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/TestGapReportTest.java index 3c016e2..ff56d65 100644 --- a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/TestGapReportTest.java +++ b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/analysis/testgap/TestGapReportTest.java @@ -1,4 +1,4 @@ -package com.scheible.testgapanalysis; +package com.scheible.testgapanalysis.analysis.testgap; import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; diff --git a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/DebugCoverageResolutionTest.java b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/debug/DebugCoverageResolutionTest.java similarity index 94% rename from test-gap-analysis/src/test/java/com/scheible/testgapanalysis/DebugCoverageResolutionTest.java rename to test-gap-analysis/src/test/java/com/scheible/testgapanalysis/debug/DebugCoverageResolutionTest.java index 2e948be..509bda0 100644 --- a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/DebugCoverageResolutionTest.java +++ b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/debug/DebugCoverageResolutionTest.java @@ -1,4 +1,4 @@ -package com.scheible.testgapanalysis; +package com.scheible.testgapanalysis.debug; import static org.assertj.core.api.Assertions.assertThat; diff --git a/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/debug/DebugSubModule.java b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/debug/DebugSubModule.java new file mode 100644 index 0000000..34a9119 --- /dev/null +++ b/test-gap-analysis/src/test/java/com/scheible/testgapanalysis/debug/DebugSubModule.java @@ -0,0 +1,16 @@ +package com.scheible.testgapanalysis.debug; + +import com.scheible.pocketsaw.api.SubModule; +import com.scheible.testgapanalysis.common.CommonSubModule; +import com.scheible.testgapanalysis.jacoco.JaCoCoSubModule; +import com.scheible.testgapanalysis.jacoco.resolver.JaCoCoResolverSubModule; +import com.scheible.testgapanalysis.parser.ParserSubModule; + +/** + * + * @author sj + */ +@SubModule(uses = {JaCoCoSubModule.class, ParserSubModule.class, JaCoCoResolverSubModule.class, CommonSubModule.class}) +public class DebugSubModule { + +}