ArchUnit: the example elides the rule it is demonstrating, and points at an empty section
A Java architecture test library, to specify and assert architecture rules in plain Java
At a glance
- What is it?
- ArchUnit checks architecture rules in Java by importing compiled bytecode into a code structure and asserting from an ordinary unit test, so it needs no build-system plugin and no annotation processor. The small amount of documentation it ships makes the point badly in one place, where the rule that the example exists to demonstrate is replaced by an ellipsis and a forward reference to a section with nothing in it.
- Who is it for?
- ArchUnit fits a Java team that wants its layering and package dependency rules enforced by the same test runner as everything else, without a new build plugin to install. Four things to settle before you adopt it.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- TNG/ArchUnit3,899 ★ · +56
| Repository | 2026-09-24 | 2026-11-14 |
|---|---|---|
| TNG/ArchUnit | 3.8k | 3.9k |
56 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
It reads bytecode rather than source
The mechanism is stated in two sentences at the top of the file and it decides everything else about the library. ArchUnit checks the architecture of Java code by analysing given Java bytecode and importing all classes into a code structure, and it can check dependencies between packages and classes, layers and slices, and cyclic dependencies. Because the input is compiled output rather than source text, the rules are expressed over a model that every build produces, and the library does not need to be wired into compilation at all. What it does need is a test scope: the declared dependency goes in as a test dependency in both build systems shown, which tells you the intended shape is a test that fails the build rather than a plugin that runs during it.
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;The example elides the rule and points at an empty section
The one worked example in the repository imports classes and then skips the interesting part. The test method calls an importer over a placeholder package, then assigns a rule from a static builder call and ends that line with an ellipsis and a comment telling you to see the next section for the rest. The next heading is a phrase about letting the API guide you, and it has no content under it. The heading after that sends you to the user guide and to a separate repository of test examples for the current release. So the sentence that would demonstrate the library's central abstraction is missing, and the pointer meant to replace it points at nothing. Everything around it is present: the class name, the method name, the import of the rule interface, the check call, and a placeholder package name.
The build coordinates do not match the repository owner
Both dependency snippets use a group identifier that is not the GitHub organisation. The repository lives under a three-letter organisation, the licence link points at that organisation's copy of the file, and the pull request and issue links do the same, while the artifact is published under a different, longer group identifier, and the badge in the header searches a package registry for that group. A reader following the badge will not land on the repository they cloned. Both snippets pin the same patch release, which happens to be the newest tag at the time of reading, so the example tracks the current release rather than an old one, and the Maven snippet marks the dependency as test scope to match the Gradle snippet's test configuration. The two snippets are otherwise identical in intent and differ only in syntax.
Six of the build's modules are test modules
The top level is a Gradle multi-project, and the module list is unusual in a way worth reading as a statement of priorities. Six of the directories are test modules: one for third-party integration, one for examples, one for integration testing, one for the Java module system's own tests, one named for Maven, and one that is a self-test library, meaning ArchUnit's architecture rules applied to ArchUnit itself. A seventh module is the JUnit integration. So the majority of the build exists to prove the library works under several test runners, in several build setups, and against itself. The Maven-named module is the one the documentation does not address: the file shows how to add the library as a test dependency and never mentions a plugin, so whether that module tests a plugin, an example, or something else is not answerable from what is written here.
The unit test framework is the host, not the alternative
The framing in the file is that ArchUnit's main focus is to automatically test architecture and coding rules using any plain Java unit testing framework. That makes the unit test runner the execution environment rather than a competitor, and the example is written accordingly: a public class with an annotated test method, no custom runner, no base class, no annotation of its own. The only thing ArchUnit contributes is the imported class collection and the rule object, and the assertion is a single call at the end. The JUnit integration exists as a module in the build, which is the one place the library reaches for more than the bare platform. Nothing in the file compares this approach to static analysis tools or to earlier bytecode inspection libraries, so a reader arriving from one of those has to work out the difference themselves.
Third-party licenses are named and the tree backs the claim
The licence section is unusually precise. ArchUnit itself is published under Apache 2.0, and the file then states that it redistributes two third-party libraries, naming a bytecode manipulation library under a BSD licence and a collection library under Apache 2.0, and directs the reader to a folder in the repository holding all the licences for both the project and what it bundles. The tree agrees: a licences directory and a notice file are both present at the root, next to the licence itself. The one detail a reader has to notice is that a project under one licence is shipping a library under another, which is permitted and is exactly why the notice file and the folder exist rather than being optional decoration.
A Gradle build with a wrapper, custom steps and three documentation trees
The build layout is conventional Gradle with a few additions that indicate real release engineering. There is a build file, a settings file, a properties file, a wrapper directory and both a Unix and a Windows wrapper script, plus a directory for custom build logic and a separate directory for build steps, which is where the versioning and packaging live. Alongside them are three documentation trees: one for the user guide, one for developer documentation, and one for release material, which is how a project of this size keeps its published website, its contributor documentation and its release process from colliding. Governance is in files at the root rather than only on the hosting site: a developer certificate of origin, a contributing guide, a licence and a notice. On cadence, the tags are close together, with a minor in August 2026 and a patch in September 2026, and the last commit to the default branch is dated 2 October 2026.
Editorial conclusion
ArchUnit fits a Java team that wants its layering and package dependency rules enforced by the same test runner as everything else, without a new build plugin to install. Four things to settle before you adopt it. It reads compiled bytecode, so rules can only be asserted about what survives compilation and about dependencies the class files actually record; source-level constructs are out of reach. The rule language is the hard part and the shipped example does not show it, so budget time for the user guide rather than expecting to copy the example. The coordinates in the example pin a specific patch release, so you will be updating them by hand. And the build is a Gradle multi-project with six test modules and a Maven-plugin module that the documentation never mentions.
Frequently asked questions
what is archunit
A free, extensible Java library for checking the architecture of Java code. It checks dependencies between packages and classes, layers and slices, and cyclic dependencies, by analysing given Java bytecode and importing all classes into a code structure, so it works on compiled output rather than on source.
how to use archunit
Add it as a test dependency, for Gradle as a test implementation line or for Maven as a dependency with test scope, both pinned to a named patch release. Then write an ordinary test that instantiates the class file importer over your package, build a rule, and pass the imported classes to the rule's check method.
what is archunit test
It is an ordinary Java unit test. The stated focus is to automatically test architecture and coding rules using any plain Java unit testing framework, so a test class needs one annotated method, an imported class collection, a rule object and a check call, with no custom runner or base class required.
archunit vs junit
They are not alternatives. The file describes ArchUnit as working with any plain Java unit testing framework, and the example is a normal annotated test method, so the runner is the host that executes the architecture check and fails the build when a rule is violated.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tng-archunit)Star history chart for your README
[](https://hysenlabs.com/projects/tng-archunit)Was this useful?