# `MixAffected.Selection`
[🔗](https://github.com/mnox/mix_affected/blob/v0.1.0/lib/mix_affected/selection.ex#L1)

Picks the test files to run from the seeds of a change (changed sources the
graph knows, plus changed test files) and the test map.

It walks one graph whose edges point from a file to whatever it may change:

  * source -> source: `MixAffected.Graph` reverse edges (any kind)
  * file -> test: the test references a module defined in the file (the
    file may itself be a test file that defines helper modules)
  * file -> test: one of the test's `affected_by` globs (tag or attribute) matches the file
  * file -> test: a config mapping's source glob matches the file and one of
    its test globs matches the test
  * any seed -> test: the test references a module that resolves to
    nothing (the changed or deleted file, source or test, may have defined it)
  * seed -> test: one of the test's `reads` globs (files it reads from the
    repo, such as a guard scanning `lib/**`) matches the seed. Only a seed's
    content changed, so a file the walk merely reaches does not count.

`read_only` files (changed files the config ignores) select only the tests
whose `reads` match them, and tests the map does not know (which may read
anything); they seed nothing else.

Every test file it reaches is selected, and so is every test file a
selected test needs loaded: one defining a module the selected test
references (otherwise `mix test <files>` would fail on it). Tests the map
marks `:always` or `:ast` (the AST fallback misses `use`-injected
references), and test files the map does not know at all, are selected
whenever there is any seed (`MixAffected.Run` turns selecting an unknown or
stale entry into a full run). The walk is breadth-first in sorted order, so
each selected test's explain chain is one shortest path `changed file -> ... -> test`.

# `path`

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

# `result`

```elixir
@type result() :: %{tests: [path()], explain: %{optional(path()) =&gt; [path()]}}
```

# `select`

```elixir
@spec select(
  MixAffected.Graph.t() | nil,
  [path()],
  [path()],
  MixAffected.TestMap.t(),
  MixAffected.Config.t(),
  [path()]
) :: result()
```

`test_files` are the test files that exist now; map entries for other
files are ignored. `graph` may be `nil` when every seed is a test file.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
