feat: add architecture tests for enforcing module boundaries

Integrated a new `:platform:architecture-tests` module using ArchUnit to enforce backend and frontend architecture rules. Configured explicit dependencies to all relevant modules and implemented rules to prevent cross-dependencies between backend services and frontend features. Replaced legacy Gradle-based architecture guards with this robust solution. Updated CI pipeline to include these tests.
This commit is contained in:
2026-01-29 14:28:36 +01:00
parent fd7eba3589
commit 5feb42d973
8 changed files with 182 additions and 112 deletions
@@ -0,0 +1,30 @@
package at.mocode.archtests
import com.tngtech.archunit.core.domain.JavaClasses
import com.tngtech.archunit.junit.AnalyzeClasses
import com.tngtech.archunit.junit.ArchTest
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses
// Scan ALL project classes from the root package
@AnalyzeClasses(packages = ["at.mocode"])
class BackendArchitectureTest {
@ArchTest
fun `service modules should not depend on each other`(importedClasses: JavaClasses) {
val servicePackages = listOf(
"at.mocode.ping..",
"at.mocode.entries.."
// Add other service packages here as they are created
)
for (servicePackage in servicePackages) {
val otherServicePackages = servicePackages.filter { it != servicePackage }.toTypedArray()
if (otherServicePackages.isEmpty()) continue
noClasses()
.that().resideInAPackage(servicePackage)
.should().accessClassesThat().resideInAnyPackage(*otherServicePackages)
.check(importedClasses)
}
}
}
@@ -0,0 +1,20 @@
package at.mocode.archtests
import com.tngtech.archunit.core.domain.JavaClasses
import com.tngtech.archunit.junit.AnalyzeClasses
import com.tngtech.archunit.junit.ArchTest
import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices
// Scan ALL project classes from the root package
@AnalyzeClasses(packages = ["at.mocode"])
class FrontendArchitectureTest {
@ArchTest
fun `feature modules should not depend on each other`(importedClasses: JavaClasses) {
// The pattern must match the actual package structure, e.g., 'at.mocode.ping.feature'
slices()
.matching("at.mocode.(*).feature..")
.should().notDependOnEachOther()
.check(importedClasses)
}
}