How to ignore classes in test class with ArchUnit
Asked Answered
G

2

41

I wrote my first ArchUnit test:

import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.*;
// more non-static imports

@RunWith(ArchUnitRunner.class)
@AnalyzeClasses(packages = "my.domain.project")
public class PackageStructureTests {

    @ArchTest public static final ArchRule NO_CYCLES = slices().matching("my.domain.project.(**)")
            .namingSlices("package:$1").should().beFreeOfCycles();

}

The problem is that it also analyzes classes in tests, which don't follow that simple dependency constraint.

How do I limit the test to the "production" classes?

The project gets built with Maven, so the classes are in separate directories.

It is not sufficient to separate classes with names ending in "Tests" or something because there are many classes that aren't tests, but are only present on the test classpath.

Gomes answered 20/6, 2017 at 13:25 Comment(0)
E
50

It seems that the API is not guiding very well with respect to this, because you're not the first one wondering about this (this was also issue #1 on Github https://github.com/TNG/ArchUnit/issues/1).

To answer the question though, the Annotation @AnalyseClasses has an extra attribute importOptions, which takes arbitrary implementations of ImportOption. There you can specify which Location (basically the URI) to include.

Since excluding tests is rather common, this ImportOption is already predefined (for Maven and Gradle < 4.0), so you can write

@AnalyzeClasses(..., importOptions = ImportOption.DoNotIncludeTests.class)
public class MyTest{ ... }

I don't think, there is a generic solution for all setups (thus the freedom to just write your own ImportOption to decide which locations to include). However, for standard Maven and Gradle setups, it should be working.

Epley answered 21/6, 2017 at 16:47 Comment(1)
DontIncludeTests is deprecated (checked in ArchUnit 0.10.2). Use DoNotIncludeTests (different spelling).Demand
A
14

In case you are not using archunit-junit (ArchUnit's JUnit4-support as time of writing), but using "native" ArchUnit, use (for example)

com.tngtech.archunit.core.domain.JavaClasses classes 
  = new com.tngtech.archunit.core.importer.ClassFileImporter()
    .withImportOption(
      new com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests())
    .importPackages("my.random.package");
Andro answered 17/5, 2018 at 14:20 Comment(2)
ImportOption.DontIncludeTests() is deprecated use instead: ImportOption.DoNotIncludeTests()Pretended
It is available via Enum: ImportOption.Predefined.DO_NOT_INCLUDE_TESTSCannady

© 2022 - 2024 — McMap. All rights reserved.