TSK-991: Add more architecture tests

(cherry picked from commit 760adb24b54d588e8a977853d092d5744781f496)
This commit is contained in:
Benjamin Eckstein 2020-02-03 16:27:31 +01:00
parent 68c016f5c8
commit 957feac270
1 changed files with 96 additions and 23 deletions

View File

@ -1,16 +1,25 @@
package pro.taskana;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS;
import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;
import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests;
import com.tngtech.archunit.lang.ArchRule;
import java.util.Collection;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;
/**
* Test architecture of classes in taskana. For more info and examples see
@ -22,22 +31,13 @@ class ArchitectureTest {
@BeforeAll
static void init() throws ClassNotFoundException {
// time intensive operation should only be done once
importedClasses = new ClassFileImporter().importPackages("pro.taskana");
importedClasses =
new ClassFileImporter()
.withImportOption(new DoNotIncludeTests())
.importPackages("pro.taskana");
}
@Test
@Disabled
void mapperShouldBePlacedInMappingsPackage() {
ArchRule myRule =
classes()
.that()
.haveSimpleNameEndingWith("Mapper")
.should()
.resideInAPackage("..mappings..");
myRule.check(importedClasses);
}
@Test
void apiClassesShouldNotDependOnInternalClasses() {
ArchRule myRule =
@ -47,7 +47,7 @@ class ArchitectureTest {
.and()
.haveSimpleNameNotEndingWith("BulkOperationResults")
.and()
.resideInAPackage("..api")
.resideInAPackage("..api..")
.should()
.onlyDependOnClassesThat()
.resideOutsideOfPackage("..internal..");
@ -69,8 +69,7 @@ class ArchitectureTest {
@Test
void onlyExceptionsShouldResideInExceptionPackage() {
ArchRule myRule =
classes().that().resideInAPackage("..exceptions").should()
.beAssignableTo(Throwable.class);
classes().that().resideInAPackage("..exceptions").should().beAssignableTo(Throwable.class);
myRule.check(importedClasses);
}
@ -84,20 +83,94 @@ class ArchitectureTest {
NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS.check(importedClasses);
}
@Test
/**
* Solution would be nice, but is not achievable without big changes
* https://www.archunit.org/userguide/html/000_Index.html#_cycle_checks
*/
@Disabled
@Test
void freeOfCycles() {
ArchRule myRule = slices().matching("pro.taskana.(*)..")
.should().beFreeOfCycles();
ArchRule myRule = slices().matching("pro.taskana.(*)..").should().beFreeOfCycles();
myRule.check(importedClasses);
}
/**
* Test for cycles with subpackages
* https://www.archunit.org/userguide/html/000_Index.html#_cycle_checks
*/
@TestFactory
Collection<DynamicTest> freeOfCycles_subpackages() {
Stream<String> packagesToTest =
Stream.of(
"pro.taskana.common.internal.(*)..",
"pro.taskana.common.api.(*)..",
"pro.taskana.classification.api.(*)..",
"pro.taskana.classification.internal.(*)..",
"pro.taskana.history.api.(*)..",
"pro.taskana.history.internal.(*)..",
// to be fixed soon
// "pro.taskana.report.api.(*)..",
"pro.taskana.report.internal.(*)..",
"pro.taskana.task.api.(*)..",
"pro.taskana.task.internal.(*)..",
"pro.taskana.workbasket.api.(*)..",
"pro.taskana.workbasket.internal.(*)..");
return packagesToTest
.map(
p ->
dynamicTest(
p.replaceAll(Pattern.quote("pro.taskana."), "") + " is free of cycles",
() -> slices().matching(p).should().beFreeOfCycles().check(importedClasses)))
.collect(Collectors.toList());
}
@Disabled("TBD")
@Test
@Disabled
void freeOfCyclicDependencies() {
ArchRule myRule = slices().matching("pro.taskana.(*)..").should()
.notDependOnEachOther();
void commonClassesShouldNotDependOnOtherDomainClasses() {
ArchRule myRule =
noClasses()
.that()
.resideInAPackage("..common..")
.should()
.dependOnClassesThat()
.resideInAnyPackage(
"..classification..", "..history..", "..report..", "..task..", "..workbasket..");
myRule.check(importedClasses);
}
@TestFactory
Collection<DynamicTest> classesShouldNotDependOnReportDomainClasses() {
Stream<String> packagesToTest =
Stream.of(
"..workbasket..",
"..history..",
// tasks are to be fixed ...
// "..task..",
"..classification..");
return packagesToTest
.map(
p ->
dynamicTest(
"Domain "
+ p.replaceAll(Pattern.quote("."), "")
+ " should not depend on reports",
() ->
noClasses()
.that()
.resideInAPackage(p)
.should()
.dependOnClassesThat()
.resideInAnyPackage("..report..")
.check(importedClasses)))
.collect(Collectors.toList());
}
@Disabled
@Test
void freeOfCyclicDependencies() {
ArchRule myRule = slices().matching("pro.taskana.(*)..").should().notDependOnEachOther();
myRule.check(importedClasses);
}
}