ArchTest.Conventions (ArchTest v0.2.0)

Copy Markdown View Source

Pre-built assertion helpers for common Elixir coding conventions.

Import this module (via use ArchTest.Conventions) to access pre-built rules that go beyond dependency checking.

Usage

defmodule MyApp.ConventionTest do
  use ExUnit.Case
  use ArchTest
  use ArchTest.Conventions

  test "no IO.puts in production code" do
    assert no_io_puts_in(modules_matching("MyApp.**"))
  end

  test "domain modules don't use Plug" do
    assert no_plug_in(modules_matching("MyApp.Domain.**"))
  end
end

Summary

Functions

Asserts that all public functions in subject modules have documentation.

Asserts that no module in subject calls Application.get_env/2,3 directly.

Asserts that no module in subject calls dbg/0,1,2 (Elixir 1.14+ debug macro).

Asserts that no module in subject has IO.puts or IO.inspect calls.

Asserts that no module in subject directly uses Plug.

Asserts that no module in subject calls Process.sleep/1.

Asserts that no module in subject raises a bare string (i.e., raise "message").

Functions

all_public_functions_documented(subject, opts \\ [])

@spec all_public_functions_documented(
  ArchTest.ModuleSet.t(),
  keyword()
) :: :ok

Asserts that all public functions in subject modules have documentation.

A public function is considered documented if its module has a @moduledoc and none of its functions are missing @doc (i.e., @doc false or missing docs are both treated as undocumented).

This check inspects :beam_lib chunk data.

no_application_get_env_in(subject, opts \\ [])

@spec no_application_get_env_in(
  ArchTest.ModuleSet.t(),
  keyword()
) :: :ok

Asserts that no module in subject calls Application.get_env/2,3 directly.

Direct Application.get_env calls scattered across the codebase make configuration harder to find and test. Centralize config access in a dedicated config module.

no_dbg_in(subject, opts \\ [])

@spec no_dbg_in(
  ArchTest.ModuleSet.t(),
  keyword()
) :: :ok

Asserts that no module in subject calls dbg/0,1,2 (Elixir 1.14+ debug macro).

dbg calls are debugging artifacts that must not appear in production code.

no_io_puts_in(subject, opts \\ [])

@spec no_io_puts_in(
  ArchTest.ModuleSet.t(),
  keyword()
) :: :ok

Asserts that no module in subject has IO.puts or IO.inspect calls.

These are debugging artifacts that should not appear in production modules.

no_plug_in(subject, opts \\ [])

@spec no_plug_in(
  ArchTest.ModuleSet.t(),
  keyword()
) :: :ok

Asserts that no module in subject directly uses Plug.

Useful to keep domain/application modules free from web framework coupling.

no_process_sleep_in(subject, opts \\ [])

@spec no_process_sleep_in(
  ArchTest.ModuleSet.t(),
  keyword()
) :: :ok

Asserts that no module in subject calls Process.sleep/1.

Process.sleep in production code is a code smell — it indicates polling, artificial delays, or race condition workarounds. Use proper synchronization mechanisms instead.

no_raise_string_in(subject, opts \\ [])

@spec no_raise_string_in(
  ArchTest.ModuleSet.t(),
  keyword()
) :: :ok

Asserts that no module in subject raises a bare string (i.e., raise "message").

Bare string raises produce RuntimeError with no structured data. Use typed errors (defexception) or raise MyError, key: value instead for better error handling and pattern matching.