O que vale automatizar?

Escolha regras objetivas e estáveis: domínio não referencia frameworks; módulos não acessam diretamente persistência de outros módulos; controllers dependem de portas de entrada; implementações de infraestrutura ficam fora do núcleo. Evite codificar preferências que mudam com frequência ou regras que não têm impacto arquitetural real.

Um teste útil explica a intenção no nome e produz falha compreensível. Comece por uma ou duas fronteiras que já causaram regressões; não transforme toda convenção de diretório numa lei sem discutir o benefício.

Uma regra de dependência com NetArchTest

Uma biblioteca como NetArchTest.Rules permite inspecionar assemblies e expressar regras de dependência. O exemplo abaixo é ilustrativo; nomes de assembly e namespaces devem refletir a solução:

[Fact]
public void Dominio_nao_deve_depender_de_infraestrutura()
{
    var resultado = Types
        .InAssembly(typeof(Pedido).Assembly)
        .That()
        .ResideInNamespace("Pedidos.Domain")
        .ShouldNot()
        .HaveDependencyOn("Pedidos.Infrastructure")
        .GetResult();

    Assert.True(resultado.IsSuccessful);
}

A regra acompanha referências de tipos que a ferramenta consegue analisar; ela não prova que o comportamento de negócio está correto nem substitui revisão de arquitetura. Verifique o relatório detalhado quando a asserção falhar, para que o time encontre a dependência concreta.

Limites entre módulos e convenções

Outras verificações podem exigir que tipos de controllers morem na camada de API, impedir referências entre namespaces de módulos ou identificar dependências circulares. Para módulos maiores, nomear explicitamente as APIs públicas e esconder implementações pode ser mais sustentável do que confiar apenas em convenções de nome.

Regras sobre reflexão, geração de código e assemblies dinâmicos podem exigir configuração extra. Mantenha os testes pequenos, rápidos e determinísticos; execute-os junto da suíte apropriada no pipeline.

Testes de arquitetura não são testes de integração

Testes arquiteturais verificam estrutura e dependências. Testes de integração validam fronteiras concretas como EF Core, HTTP e banco; testes unitários exercitam regras e comportamentos. As três perspectivas se complementam, mas não se substituem. Veja testes de integração com ASP.NET Core.

Evite a arquitetura congelada

Um teste pode preservar um desenho ruim se a regra já não servir ao produto. Toda falha deve levar a uma pergunta: a alteração violou um limite importante ou o limite precisa evoluir? Atualize a regra conscientemente quando a arquitetura mudar, em vez de desativá-la sem explicação.

Para decidir quais fronteiras proteger, leia Clean Architecture, arquitetura hexagonal e organização de projetos .NET.

Leituras relacionadas