dart_arch_test
ArchUnit-inspired architecture testing for Dart & Flutter. Enforce layer boundaries, slice isolation, cycles, coupling metrics, and violation baselines — all in plain Dart tests.
0.3.1
4.8K downloads/mo
#3913 most downloaded on pub.dev
yoavgeva/dart_arch_test
What this package is like to depend on
Last release 5 months ago
12 Mar 2026
Too new to tell
only 1 release windows
Nearly every release is documented
notes for 5 of 5 stable releases
Nothing withdrawn
no release was ever pulled
5 months old
5 releases · first in 2026
5 releases in the last 12 months
see the full history below
Release timeline
5 releases · Mar 2026 to Mar 2026Releases
latest 5-
0.3.112 Mar 2026Release notes
Open source →Bug fixes / performance:
- Cycle detection performance —
Collector.cyclesnow uses adoneset (DFS memoisation) to avoid re-exploring already-completed subtrees, reducing worst-case complexity from O(n!) to O(n + e). _globMatchrefactor —assertions.dartnow delegates to the sharedmatchesGlobhelper inpattern.dart, removing duplicated glob logic.
- Cycle detection performance —
-
0.3.010 Mar 2026Release notes
Open source →New features:
-
Variadic
union()— now accepts 2–5 selectors instead of exactly 2, eliminating the need for deep nesting:// Before (0.2.x) union(a, union(b, union(c, d))) // Now union(a, b, c, d) -
difference(a, b)— new top-level set operation returning libraries inabut not inb:// All feature files except generated code difference(filesMatching('features/**'), filesMatching('features/**/*.g.dart')) -
except:parameter on all assertion functions — exclude a subset of subjects from a rule without splitting it into two tests:shouldNotDependOn( filesMatching('shared/**'), filesMatching('features/**'), graph, except: filesMatching('shared/guards/**'), // guards are a bridge by design ); shouldNotTransitivelyDependOn(subject, object, graph, except: filesMatching('...')); shouldOnlyDependOn(subject, allowed, graph, except: filesMatching('...')); shouldNotBeCalledBy(object, callers, graph, except: filesMatching('...')); shouldOnlyBeCalledBy(object, allowed, graph, except: filesMatching('...')); -
Content-based selectors (
extending,implementing,withAnnotation) — select libraries by what their classes declare, not just by file path:// Every ChangeNotifier subclass must live in a providers/ folder shouldHaveUriMatching(extending('ChangeNotifier'), '**/providers/**', graph); // UnreadCountSource implementations must stay in shared/ shouldNotDependOn(implementing('UnreadCountSource'), filesMatching('features/**'), graph); // @immutable models must not import services shouldNotTransitivelyDependOn(withAnnotation('immutable'), filesMatching('**/services/**'), graph);Root path is inferred from the nearest
pubspec.yamlwalking up from CWD, or overridden via theDART_ARCH_TEST_ROOTenvironment variable.
Exports:
difference,extending,implementing,withAnnotationare now exported frompackage:dart_arch_test/dart_arch_test.dart. -
-
0.2.210 Mar 2026Release notes
Open source →Bug fix:
- Fixed
Collector.buildGraphcrashing underflutter testwithPathNotFoundExceptiononartifacts/engine/versionandlib/_internal/libraries.dart. Underflutter test,Platform.resolvedExecutableisflutter_tester(notdart), so theanalyzerpackage'sgetSdkPath()resolved to the wrong directory.Collectornow walks up the directory tree to find the real Dart SDK (bin/cache/dart-sdk/) before falling back to the previous behaviour.
- Fixed
-
0.2.108 Mar 2026Release notes
Open source →Bug fix:
Collector.buildGraphnow compiles against analyzer ≥9.0.0: switched fromresult.element2(experimental in 7.x, removed in 9.x) toresult.element(deprecated in 7.x, stable in 9.x). The// ignore: deprecated_member_usesuppression keeps the code clean on both analyzer ranges.
-
0.2.008 Mar 2026Release notes
Open source →New features:
-
Metrics— Robert C. Martin coupling metrics from the import graph:Metrics.coupling(uri, graph)— afferent coupling (Ca), efferent coupling (Ce), instability, abstractness, distance for a single libraryMetrics.instability(uri, graph)— convenience shorthand forCe / (Ca + Ce)Metrics.martin(pattern, graph)— bulk report for all libraries matching a glob patternCouplingMetrics— immutable data class holding all five metric fields
-
Freeze— violation baseline / snapshot support:freeze(ruleId, () { ... })— top-level convenience function; passes if violations match the baseline, fails withFreezeFailureon new violationsFreeze.freeze(ruleId, assertion, {storeDir})— class-based API with optional custom store directoryFreeze.updateFreeze()— returnstruewhenDART_ARCH_TEST_UPDATE_FREEZE=1is setFreeze.storePath()— returns the baseline directory (envDART_ARCH_TEST_FREEZE_STOREortest/arch_test_violations/)FreezeFailure— exception type thrown when new violations are detected
-
Slicesadditions:allLibrariesCoveredBy(scope, graph, {except})— asserts every library inscopebelongs to at least one declared slice;exceptaccepts glob patterns to skipsliceCycles(graph)— returns all dependency cycles at the slice levelshouldBeFreeOfSliceCycles(graph)— throwsArchTestFailureif any slice-level cycle exists
Exports:
CouplingMetrics,Metrics,Freeze,FreezeFailure,freezeare now exported frompackage:dart_arch_test/dart_arch_test.dart. -