MixAffected.TestMap (MixAffected v0.1.0)

Copy Markdown View Source

Which source files each test file references, built by mix affected.map (see MixAffected.TestMap.Builder) and stored as an ETF file, by default at _build/test/mix_affected/test_map.etf.

Each test file has an entry:

  • :mode - how its references were found: :tracer (compiler tracer while requiring the file), :ast (the file failed to require; module references read from its AST, which misses what use injects, so the test runs whenever anything is affected), or :always (it does not parse either, or an affected_by glob was rejected: same)
  • :refs - root-relative source files of every module it references, including other test files that define modules it uses
  • :hashes - %{path => hash/1} of the test file and of every file in :refs, as they were when the map was built. An entry whose files changed since is stale/2: its references may be out of date (a map prebuilt on another commit, a test edited after the local map was built), so selecting it is a full run (see MixAffected.Run).
  • :unresolved - names of traced modules no file defines and none can be loaded (typically defined by a file deleted or edited before the map was built); any seed selects every test with any
  • :affected_by - its literal @moduletag affected_by: [globs] and @affected_by [globs], minus any MixAffected.Config.validate_glob/2 rejects (which make the entry :always)
  • :reads - globs of the repo files it reads itself (File.read!/1, Path.wildcard/1, ...: a guard scanning lib/**, a doc test), ["**"] when they cannot be pinned down, [] when it reads none (MixAffected.TestMap.Ast.reads/3)

:impls lists the project's protocol implementations as {impl_file, for_file}: protocol dispatch is a runtime lookup no xref edge records, so selection treats the for: type's file as depending on the impl file (for_file equals impl_file for an impl in its type's own file or from @derive). for_file is nil when the type is not defined in the project (Integer, Any, a dependency's struct): then nothing in the project can vouch for who dispatches to it.

Summary

Functions

The default map path under a build path such as _build/test.

The content hash the map stores for a file's content.

Marks the entries of the stale test files :always, so selection selects them whenever anything is affected instead of trusting their references.

A map from %{test_file => entry} and the project's protocol impls.

Reads a map written by write!/2 by the same map format version.

The test files, sorted, whose entry's recorded :hashes no longer match the files under root (changed or missing): their references may be out of date.

Writes map to path, creating its directory.

Types

entry()

@type entry() :: %{
  mode: mode(),
  refs: [path()],
  affected_by: [String.t()],
  hashes: %{optional(path()) => binary()},
  unresolved: [String.t()],
  reads: [String.t()]
}

impl()

@type impl() :: {impl_file :: path(), for_file :: path() | nil}

mode()

@type mode() :: :tracer | :ast | :always

path()

@type path() :: MixAffected.Graph.path()

t()

@type t() :: %MixAffected.TestMap{
  impls: [impl()],
  tests: %{optional(path()) => entry()}
}

Functions

default_path(build_path)

@spec default_path(Path.t()) :: Path.t()

The default map path under a build path such as _build/test.

hash(content)

@spec hash(binary()) :: binary()

The content hash the map stores for a file's content.

mark_stale(map, stale)

@spec mark_stale(t(), [path()]) :: t()

Marks the entries of the stale test files :always, so selection selects them whenever anything is affected instead of trusting their references.

new(tests, impls \\ [])

@spec new(%{optional(path()) => entry()}, [impl()]) :: t()

A map from %{test_file => entry} and the project's protocol impls.

read(path)

@spec read(Path.t()) :: {:ok, t()} | {:error, String.t()}

Reads a map written by write!/2 by the same map format version.

stale(test_map, root)

@spec stale(t(), Path.t()) :: [path()]

The test files, sorted, whose entry's recorded :hashes no longer match the files under root (changed or missing): their references may be out of date.

write!(test_map, path)

@spec write!(t(), Path.t()) :: :ok

Writes map to path, creating its directory.