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

Check multiple ArchRules at once #78

Closed
rweisleder opened this issue Jun 11, 2018 · 2 comments
Closed

Check multiple ArchRules at once #78

rweisleder opened this issue Jun 11, 2018 · 2 comments

Comments

@rweisleder
Copy link
Contributor

I want to provide a shared library with common rules. These rules are used in different corporate projects. This is to ensure that every project is built the same way.
Example:

@Test
void checkCommonRules() {
    GeneralCodingRules.NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS.check(javaClasses);
    GeneralCodingRules.NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS.check(javaClasses);
    GeneralCodingRules.NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING.check(javaClasses);
}

This prints only the violations of the first violated rule.

Now I want to ensure that in every project every of those common rules is checked. If a new common rule is added to the library, every project should execute this new rule without further code modification.

I thought of something like this:

public ArchRules COMMON_RULES = ArchRules.of(
    GeneralCodingRules.NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS,
    GeneralCodingRules.NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS,
    GeneralCodingRules.NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING
);
@Test
void checkCommonRules() {
    GeneralCodingRules.COMMON_RULES.check(javaClasses);
}

This check should print all violations of all given rules.

@codecholeric
Copy link
Collaborator

I take it, you're not using the JUnit 4 support, are you? Because then you could simply aggregate Tests like

public class MyAggregatedRules {
    @ArchTest
    public static final ArchRules rules1 = ArchRules.in(FirstRuleSuite.class);

    @ArchTest
    public static final ArchRules rules2 = ArchRules.in(SecondRuleSuite.class);
}

(which works recursively, this is how we compose SpecificRules -> LessSpecificRules -> AllRules -> ConcreteTest)

This will work with the JUnit 5 support as well, once it's finished.
But if you're writing your tests as plain unit tests, ArchRules is not usable in a comfortable way, you're right about that. You can add something like this yourself in the following way:

public class RuleSuite implements ArchRule {
    private final List<ArchRule> rules;
    private String overriddenDescription;

    public RuleSuite(ArchRule... rules) {
        checkArgument(rules.length > 0, "A suite of 0 rules makes no sense");
        this.rules = Arrays.asList(rules);
    }

    @Override
    public void check(JavaClasses classes) {
        Assertions.check(this, classes);
    }

    @Override
    public ArchRule because(String reason) {
        rules.get(rules.size() - 1).because(reason);
        return this;
    }

    @Override
    public EvaluationResult evaluate(JavaClasses classes) {
        EvaluationResult result = new EvaluationResult(this, Priority.MEDIUM);
        for (ArchRule rule : rules) {
            result.add(rule.evaluate(classes));
        }
        return result;
    }

    @Override
    public String getDescription() {
        if (overriddenDescription != null) {
            return overriddenDescription;
        }

        List<String> descriptions = new ArrayList<>();
        for (ArchRule rule : rules) {
            descriptions.add(rule.getDescription());
        }
        return Joiner.on(lineSeparator() + " and ").join(descriptions);
    }

    @Override
    public ArchRule as(String newDescription) {
        overriddenDescription = newDescription;
        return this;
    }
}

This will join all rule descriptions and after that join all errors of all rules in one shot, instead of failing after the first.

I have pondered about making ArchRules usable in plain unit tests in a pretty similar fashion, but I have to see what the requirements of the JUnit test support are, once I'm done with the JUnit 5 support (since it was originally composed for that).

I think you're right though, that ArchUnit should offer a way out of the box to create such composite rules, even it no extra testing support is used. I'll think about it, where this could be added the best (whether it's ArchRules or another composite similar to the one above).

I hope you can use that POC for now though for your use case, let me know if you have trouble!!

@bogsi17 bogsi17 self-assigned this Dec 6, 2018
bogsi17 pushed a commit to bogsi17/ArchUnit that referenced this issue Dec 6, 2018
Issue: TNG#78
Signed-off-by: Moritz Bogs <moritz.bogs@tngtech.com>
bogsi17 pushed a commit to bogsi17/ArchUnit that referenced this issue Dec 9, 2018
…actory methods instead of constructors, make fields immutable.

Issue: TNG#78
Signed-off-by: Moritz Bogs <moritz.bogs@tngtech.com>
bogsi17 pushed a commit to bogsi17/ArchUnit that referenced this issue Dec 10, 2018
Multiple ArchRules can be checked at once via CompositeArchRule.of(rule1).and(rule2). Also added sample tests for both plain, junit4 and junit5

Issue: TNG#78
Signed-off-by: Moritz Bogs <moritz.bogs@tngtech.com>
codecholeric added a commit to bogsi17/ArchUnit that referenced this issue Dec 16, 2018
Issue: TNG#78
Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
codecholeric pushed a commit to bogsi17/ArchUnit that referenced this issue Dec 16, 2018
Multiple ArchRules can be checked at once via CompositeArchRule.of(rule1).and(rule2). Also added sample tests for both plain, junit4 and junit5

Issue: TNG#78
Signed-off-by: Moritz Bogs <moritz.bogs@tngtech.com>
codecholeric added a commit to bogsi17/ArchUnit that referenced this issue Dec 16, 2018
Issue: TNG#78
Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
@codecholeric
Copy link
Collaborator

Resolved by #128

codecholeric pushed a commit that referenced this issue Feb 21, 2021
Multiple ArchRules can be checked at once via CompositeArchRule.of(rule1).and(rule2). Also added sample tests for both plain, junit4 and junit5

Issue: #78
Signed-off-by: Moritz Bogs <moritz.bogs@tngtech.com>
codecholeric added a commit that referenced this issue Feb 21, 2021
Issue: #78
Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants