arch_dart 0.0.3 copy "arch_dart: ^0.0.3" to clipboard
arch_dart: ^0.0.3 copied to clipboard

Dart/Flutter Architectural Testing Framework inspired by ArchUnit for Java.

Darto logo

ArchDart



Dart/Flutter Architectural Testing Framework inspired by ArchUnit for Java.


Support πŸ’– #

If you find ArchDart useful, please consider supporting its development 🌟Buy Me a Coffee.🌟 Your support helps us improve the framework and make it even better!



Note: Some rules in ArchDart have not been thoroughly tested and may contain potential errors. Please report any issues or unexpected behavior to the project repository for further investigation and improvement.

ArchDart is a Dart and Flutter package inspired by Java's ArchUnit, designed to enforce architectural rules in your projects. It provides a fluent, expressive API to validate the structure, naming conventions, dependencies, and other architectural aspects of your Dart/Flutter codebase. ArchDart helps ensure that your project adheres to clean architecture principles, domain-driven design, or custom architectural patterns.

Table of Contents #

Installation #

Add ArchDart to your project by including it in your pubspec.yaml:

dev_dependencies:
  arch_dart: ^[latest-version]

Run flutter pub get to install the package.

Usage #

ArchDart provides a fluent API to define architectural rules and validate them against your Dart/Flutter codebase. Rules are defined using selectors, scopes, filters, and assertions, and are executed using the check method. The package integrates with flutter_test for writing test cases.

Here’s a basic example:

import 'package:arch_dart/arch_dart.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('Repositories should end with Repository', () async {
    await classes()
        .inFolder('infra/repositories')
        .shouldHaveNameEndingWith('Repository')
        .check();
  });
}

Selectors #

Selectors define the type of elements to validate:

Selector Description
classes() Selects all classes
enums() Selects all enums
methods() Selects all methods
functions() Selects all top-level functions
features() Selects feature directories

Scopes #

Scopes narrow down the elements to a specific location in the project:

Method Description
inPackage('name') Logical package (e.g., controller, service)
inFolder('path') Directory path in the project (e.g., lib/core)
inDirectory('path') Alias for inFolder
inFile('file.dart') Specific Dart file

Filters #

Filters select a subset of elements based on specific criteria:

Method Description
withNameEndingWith('suffix') Names ending with the specified suffix
withNameContaining('text') Names containing the specified text
withAnnotation('name') Elements with the specified annotation
withLineCountGreaterThan(n) Classes with more than n lines of code
withValueCountGreaterThan(n) Enums with more than n values

Assertions #

Assertions define the rules that elements must satisfy. They are prefixed with should....

Modifiers and Types #

Method Description
shouldBePublic() Must be public
shouldBePrivate() Must be private
shouldBeFinal() Must be final
shouldBeAbstract() Must be abstract
shouldBeSealed() Must be sealed
shouldBeBase() Must be base
shouldBeMixin() Must be a mixin
shouldBeEnum() Must be an enum
shouldBeRecord() Must be a record
shouldBeAnnotatedWith('X') Must have the @X annotation

Inheritance and Implementation #

Method Description
shouldExtend('SuperClass') Must extend the specified class
shouldExtendAnyOf([...]) Must extend one of the specified classes
shouldImplement('Interface') Must implement the specified interface
shouldImplementOnly([...]) Must implement only the specified interfaces

Structure, Naming, and Constructors #

Method Description
shouldHaveNameEndingWith('X') Name must end with X
shouldHaveOnlyPrivateConstructors() All constructors must be private
shouldRequireAllParams() Constructors must have all required parameters
shouldHaveOnlyNamedRequiredParams() Constructors must have only named required parameters
shouldHaveMethodThat() Methods must satisfy specific criteria (e.g., name, return type)

Dependencies and Layers #

Method Description
shouldOnlyDependOn([...]) Can only depend on the specified packages
shouldOnlyBeAccessedBy([...]) Can only be accessed by the specified packages
shouldBeInPackage('X') Must reside in the specified package
shouldBeInAnyPackage([...]) Must reside in one of the specified packages
shouldBeInFolder('path') Must reside in the specified folder
shouldNotHaveImports([...]) Must not import the specified packages
shouldNotBeImportedIn('file') Must not be imported in the specified file
shouldBeIndependent() Features must not reference each other

File Content #

Method Description
shouldContain('text') File must contain the specified text
shouldNotBeExportedIn('file') File must not be exported in the specified file

Negations #

Negations are assertions prefixed with shouldNot... to ensure elements do not meet certain criteria:

Method Description
shouldNotBe(type) Must not be of the specified type/modifier
shouldNotDependOn('package') Must not depend on the specified package
shouldNotAccessPackage('package') Must not access the specified package
shouldNotHaveImports([...]) Must not import the specified packages
shouldNotContain('text') File must not contain the specified text
shouldNotBeExportedIn('file') Must not be exported in the specified file

Utilities #

Utilities help control rule execution and chaining:

Method Description
check() Executes the rule validation
andAlso() Chains multiple rules with AND logic
orElse() Chains multiple rules with OR logic
shouldFail() Marks the rule as expected to fail (for negative testing)

Examples #

Below are example test cases demonstrating common use cases for ArchDart:

Enforcing Naming Conventions #

Ensure all enums in lib/core/enums have a stringToEnum method and end with Enum:

test('All enums should have stringToEnum method', () async {
  await enums()
      .inFolder('lib/core/enums')
      .shouldHaveMethodThat()
      .hasMethodNamed('stringToEnum')
      .andAlso()
      .shouldHaveNameEndingWith('Enum')
      .check();
});

Enforcing Layer Dependencies #

Ensure classes in the presentation package do not depend on infra:

test('Presentation should not access Infra', () async {
  await classes()
      .inPackage('presentation')
      .shouldNotDependOn('infra')
      .check();
});

Enforcing Clean Architecture #

Ensure use cases in domain/usecases have an execute method:

test('UseCases should have an execute method', () async {
  await classes()
      .inFolder('domain/usecases')
      .shouldHaveMethodThat()
      .hasMethodNamed('execute')
      .check();
});

Enforcing Feature Isolation #

Ensure features are independent of each other:

test('Features should not reference each other', () async {
  await features()
      .shouldBeIndependent()
      .check();
});

Enforcing Constructor Rules #

Ensure entities in domain/entities use only named required parameters:

test('Entities should have all required named parameters', () async {
  await classes()
      .inFolder('domain/entities')
      .shouldHaveOnlyNamedRequiredParams()
      .check();
});

Enforcing Layer Structure #

Ensure the project follows the expected layer structure:

test('Layers should follow the expected structure', () async {
  await layers(['presentation', 'domain', 'infra', 'core'])
      .onlyStructure()
      .allowMissingLayers()
      .check();
});

Use ArchRule Type #

Use the ArchRule type to define custom rules:

test('Custom rule example', () async {
  ArchRule rule = classes()
    .inPackage('presentation')
    .shouldNotDependOn('infra');

  await rule.check();
});

Contributing #

Contributions to ArchDart are welcome! Please submit issues or pull requests to the project repository. When contributing, ensure that:

  • New rules are thoroughly tested.
  • Documentation is updated to reflect new features.
  • Code follows Dart best practices and includes appropriate comments.

License #

ArchDart is licensed under the MIT License. See the LICENSE file for details.

5
likes
140
points
153
downloads

Publisher

verified publisherevandersondev.com.br

Weekly Downloads

Dart/Flutter Architectural Testing Framework inspired by ArchUnit for Java.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, path, yaml

More

Packages that depend on arch_dart