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

ArchUnit rule for package consistency for test classes #20

Closed
JensPiegsa opened this issue Sep 8, 2017 · 3 comments
Closed

ArchUnit rule for package consistency for test classes #20

JensPiegsa opened this issue Sep 8, 2017 · 3 comments

Comments

@JensPiegsa
Copy link

After some refactorings, I want to ensure that all (.*)Test classes reside in the same package as their corresponding classes-under-test. How to achieve this with ArchUnit?

@codecholeric
Copy link
Collaborator

I think there are several ways to test this. I don't know, if you really need the fluent API for this use case, so you could just do this test on a lower level: (for the case of simplicity, I'll assume that the simple name is unique and no class is called sth. like 'FooTestTest' or just 'Test')

@ArchTest
public static void test_classes_should_reside_in_the_correct_package(JavaClasses classes) {
  Map<String, String> simpleTestNameToPackage = new HashMap<>();
  // First collect all tests
  for (JavaClass clazz : classes) {
    if (clazz.getName().endsWith("Test")) {
      simpleTestNameToPackage.put(clazz.getSimpleName(), clazz.getPackage());
    }
  }
  
  // Then check for all classes that a possibly existing test is in the same package
  for (JavaClass clazz : classes) {
    String possibleTestName = clazz.getSimpleName() + "Test";
    String correspondingTestPackage = simpleTestNameToPackage.get(possibleTestName);
    boolean testExistsButIsInWrongPackage = correspondingTestPackage != null
        && !correspondingTestPackage.equals(clazz.getPackage());
            
    if (testExistsButIsInWrongPackage) {
      Assert.fail(String.format("Test class %s.%s is in the wrong package",
          correspondingTestPackage, possibleTestName));
    }
  }
}

You'll probably have to refine this a little more, for example you could consider 'JavaClass.getSource()' to find out if the class you're checking is in main or test.

If you want to use the fluent API at all costs 😉 , you could initialize a custom condition by overriding init(..), and write it in the following way (the logic would be something similar to the low level case, I think)

classes().should(new ArchCondition<JavaClass>("have their test in the same package") {
  @Override
  public void init(Iterable<JavaClass> allClasses) {
    // find all tests to begin with, and store them
  }

  @Override
  public void check(JavaClass item, ConditionEvents events) {
    // check every class with respect to the stored classes from init()
  }
});

(of course it would look neater, if the condition was declared in a separate method)

@codecholeric
Copy link
Collaborator

Can you give me an update, if you were able to figure out your issue? (Because then I could close this issue 😉 )

@JensPiegsa
Copy link
Author

Many thanks for coming back to this. Your provided solution is working for us!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants