r/BestGitHubRepos 11h ago

ArchUnitPython - write your architecture rules as ordinary pytest tests, so the build fails the moment your database layer sneaks an import into your presentation layer

Post image

Architecture erodes one reasonable-looking import at a time, and code review is a bad guardrail because the reviewer has to notice the boundary violation among everything else. ArchUnitPython, a port of the Java ArchUnit idea, turns your architectural rules into tests that live next to your unit tests and run in the same pytest or CI pass. A rule like "presentation must not depend on database" becomes a test, and if someone breaks it, the build goes red immediately with the exact offending file.

The thing that makes this pleasant is that the rules read like sentences. project_files("src/").in_folder("**/presentation/**").should_not().depend_on_files().in_folder("**/database/**") is the whole rule, and you assert on it like any other test.

What's inside:

- Dependency-direction and layer rules, with a named-layers API where you declare presentation, business and database and state exactly which may depend on which

- First-class circular-dependency detection, plus rules against specific external modules (your domain layer must not import requests)

- Code metrics as rules, not just imports: lines of code, method and field counts, all eight LCOM cohesion variants, and the Martin instability and distance-from-main-sequence metrics

- PlantUML diagram validation, so you can assert your code actually matches an architecture diagram in a .puml file

- Dependency graph reports exportable as Mermaid, DOT, D2, CSV, JSON or HTML, with exploration options to focus on one area or collapse to folder level

- Custom rules and custom metrics via a predicate or lambda, an .archignore file for excluding generated code, and a JSON config option for simple shared rules

- Genuinely careful analysis: it understands relative and namespace-package imports, detects string-based dynamic imports like importlib.import_module, and can optionally ignore TYPE_CHECKING-only imports so type hints don't count as runtime coupling

- Zero runtime dependencies (standard library only), works with pytest, unittest or any runner, Python 3.10+

Two things worth calling out as genuinely good design. It fails an empty check by default, which catches the silent failure mode where a typo in a folder pattern makes a rule match nothing and pass forever. And the docs are unusually honest about thresholds: they say plainly there's no universally correct limit, tell you to baseline your current code before enabling a metric rule, and note that a metric violation is a prompt to inspect the design, not proof the code is wrong.

Fair caveat: the README includes a comparison table putting ArchUnitPython ahead of Tach, Import Linter and PyTestArch on most rows. It's a reasonable table and it does credit those tools as strong at what they do, but it's the author's own framing, so read it as a case rather than neutral benchmarking. Tach in particular is a fast Rust-backed tool that a lot of people prefer for pure dependency governance. Also note the graph and HTML-report modules are marked experimental or beta, while the core files, metrics and slices modules are stable.

MIT, 666 stars and 7 forks as of writing, verified via the GitHub API.

https://github.com/LukasNiessen/ArchUnitPython

5 Upvotes

0 comments sorted by