Current section
Files
Jump to
Current section
Files
lib/ab/module_validator.ex
defmodule AB.ModuleValidator do
@moduledoc """
Validates all public functions in a module against their typespecs.
This module provides functionality to automatically test all exported functions
in a module that have typespecs defined, ensuring comprehensive API validation.
"""
import ExUnit.Assertions
@doc """
Validates all public functions with typespecs in the given module.
Returns `:ok` on success or raises an ExUnit assertion failure.
"""
@spec run_validate_module(module(), keyword()) :: :ok
def run_validate_module(module, opts) do
case Code.ensure_loaded(module) do
{:module, _} ->
validate_all_module_functions(module, opts)
_ ->
flunk("Could not load module #{module}")
end
end
@spec validate_all_module_functions(module(), keyword()) :: :ok
defp validate_all_module_functions(module, opts) do
case Code.Typespec.fetch_specs(module) do
{:ok, specs} ->
public_functions = get_public_functions(module, specs)
run_tests_for_functions(module, public_functions, opts)
_ ->
flunk("Could not fetch typespecs for module #{module}")
end
end
@spec get_public_functions(module(), [any()]) :: [{atom(), non_neg_integer()}]
defp get_public_functions(module, specs) do
exported_functions = module.__info__(:functions)
specs
|> Enum.map(fn {{function_name, arity}, _} -> {function_name, arity} end)
|> Enum.filter(fn {function_name, arity} ->
{function_name, arity} in exported_functions
end)
end
@spec run_tests_for_functions(module(), [{atom(), non_neg_integer()}], keyword()) :: :ok
defp run_tests_for_functions(module, functions, opts) do
IO.puts("\n=== Validating #{length(functions)} public functions in #{module} ===")
Enum.each(functions, fn {function_name, _arity} ->
IO.puts("\nTesting #{module}.#{function_name}")
# Note: These calls will need to be imported from AB main module
AB.run_property_test(module, function_name, opts)
AB.validate_type_consistency(module, function_name)
end)
IO.puts("\n✓ All #{length(functions)} functions validated successfully")
end
end