admin管理员组

文章数量:1435859

What I would like to achieve is to write an ArchUnit rule to make sure our packages stay small enough.

For instance, suppose this:

natural
 ├─ goodpackage
 │  ├─ apple
 │  ├─ banana
 │  ├─ mango
 ├─ badpackage
 │  ├─ file1
 │  ├─ file2
 │  ├─ ...
 │  ├─ file10

For this example, let's say more than 9 files is too much, while up to 8 files is small enough.

This is also just for leaf packages, i.e. the most bottom level packages (if there are files in this package, but also sub packages, the test should aim to the sub packages)

I tried using the class com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes and was hoping to get a way to iterate inside a package. but no luck.

I also searched if we can directly get the packages from ArchUnit, something like:

    @Test
    void leafPackagesShouldNotHaveMoreThan9Files() {   }
        packages().that().areInSubPackages().shouldNot().have(moreThan9Files()).check(importedClasses);
    }

But also not possible.

How to check if there are less than N files in a leaf package with ArchUnit?

What I would like to achieve is to write an ArchUnit rule to make sure our packages stay small enough.

For instance, suppose this:

natural
 ├─ goodpackage
 │  ├─ apple
 │  ├─ banana
 │  ├─ mango
 ├─ badpackage
 │  ├─ file1
 │  ├─ file2
 │  ├─ ...
 │  ├─ file10

For this example, let's say more than 9 files is too much, while up to 8 files is small enough.

This is also just for leaf packages, i.e. the most bottom level packages (if there are files in this package, but also sub packages, the test should aim to the sub packages)

I tried using the class com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes and was hoping to get a way to iterate inside a package. but no luck.

I also searched if we can directly get the packages from ArchUnit, something like:

    @Test
    void leafPackagesShouldNotHaveMoreThan9Files() {   }
        packages().that().areInSubPackages().shouldNot().have(moreThan9Files()).check(importedClasses);
    }

But also not possible.

How to check if there are less than N files in a leaf package with ArchUnit?

Share Improve this question asked Feb 14 at 19:17 PatPandaPatPanda 5,04026 gold badges114 silver badges245 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

You can probably use something like this:

import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.domain.JavaPackage;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.AbstractClassesTransformer;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.ClassesTransformer;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.SimpleConditionEvent;

import static com.tngtech.archunit.base.DescribedPredicate.describe;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.are;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.all;
import static java.util.stream.Collectors.toSet;

...

@ArchTest
ArchRule leaf_packages_should_have_max_number_of_classes = all(packages())
        .that(are(describe("leaves", p -> p.getSubpackages().isEmpty())))
        .should(haveMaxNumberOfClasses(9));

static ClassesTransformer<JavaPackage> packages() {
    return new AbstractClassesTransformer<JavaPackage>("packages") {
        @Override
        public Iterable<JavaPackage> doTransform(JavaClasses javaClasses) {
            return javaClasses.stream().map(JavaClass::getPackage).collect(toSet());
        }
    };
}

static ArchCondition<JavaPackage> haveMaxNumberOfClasses(int maxNumberOfClasses) {
    return new ArchCondition<JavaPackage>("have at most " + maxNumberOfClasses + " classes") {
        @Override
        public void check(JavaPackage p, ConditionEvents events) {
            long numberOfClasses = p.getClasses().stream().count();
            boolean satisfied = numberOfClasses <= maxNumberOfClasses;
            String message = p.getDescription() + " contains " + numberOfClasses + " classes";
            events.add(new SimpleConditionEvent(p, satisfied, message));
        }
    };
}

本文标签: