애플리케이션의 아키텍처를 테스트 할 수 있는 오픈 소스 라이브러리로, 패키지, 클래스, 레이어, 슬라이스 간의 의존성을 확인할 수 있는 기능을 제공한다.
를 보면 직관적으로 이해할 수 있다.
ArchUnit 설치 및 실행
의존성 추가하고 사용하면 끝이다.
Copy // https://mvnrepository.com/artifact/com.tngtech.archunit/archunit
implementation group: 'com.tngtech.archunit', name: 'archunit', version: '1.0.1'
아래는 강의에서 사용된 예제 코드이다.
Copy @Test
public void Services_should_only_be_accessed_by_Controllers() {
JavaClasses importedClasses = new ClassFileImporter().importPackages("com.mycompany.myapp");
ArchRule myRule = classes()
.that().resideInAPackage("..service..")
.should().onlyBeAccessed().byAnyPackage("..controller..", "..service..");
myRule.check(importedClasses);
}
아래 흐름대로 진행하면 된다.
1. 특정 패키지에 해당하는 클래스를 (바이트코드를 통해) 읽어들이고
2. 확인할 규칙을 정의하고
3. 읽어들인 클래스들이 그 규칙을 잘 따르는지 확인한다.
아래는 공식문서의 유스케이스의 일부이다.
아래와 같이 조금 더 간편하게 테스트를 수행할 수 있다.
Copy @AnalyzeClasses: 클래스를 읽어들여서 확인할 패키지 설정
@ArchTest: 확인할 규칙 정의
Copy @AnalyzeClasses(packagesOf = App.class)
public class ArchTests {
@ArchTest
ArchRule domainPackageRule = classes().that().resideInAPackage("..domain..")
.should().onlyBeAccessed().byClassesThat()
.resideInAnyPackage("..study..", "..member..", "..domain..");
@ArchTest
ArchRule memberPackageRule = noClasses().that().resideInAPackage("..domain..")
.should().accessClassesThat().resideInAPackage("..member..");
@ArchTest
ArchRule studyPackageRule = noClasses().that().resideOutsideOfPackage("..study..")
.should().accessClassesThat().resideInAnyPackage("..study..");
@ArchTest
ArchRule freeOfCycles = slices().matching("..inflearnthejavatest.(*)..")
.should().beFreeOfCycles();
}
마치며
이건 참 신기하긴 했는데, 실무 환경에서 이걸 쓸 일이 있을까 싶다. 일단 요구사항이나 기능이 자꾸 추가되고 변경되는데 이에 따라 설계나 구조가 바뀔 여지가 너무 크다. 그래서 저렇게 일일이 설계에 대한 테스트코드를 짜면 설계가 바뀌었을때 수정비용이 오히려 추가가 된다.
이러한 수정 비용을 감안하고서라도 테스트 코드를 짠다고 했을때 그 의미도 좀 크지 않은 것 같다. 로직에 대한 테스트 코드도 설계나 로직이 바뀌면 바뀔 여지가 생긴다는 측면에서 동일한 비용이 있지만, 그래도 로직에 대한 테스트 코드는 개발자가 코드를 만들때 미처 생각하지 못한 케이스도 찾아주기도 하고 다른 사람이 기능 변경을 하고서 기존 요구사항을 변경된 버전이 만족하는지 돌려볼 수도 있고 여러모로 장점이 많다.
이에 반해 설계 테스트 코드는 특별히 의미가 없는 것 같아서 개인적으로 크게 쓸 일이 없어 보인다.