Elixir Testing Reference
SkillAI & modelsWrite or repair Elixir tests with ExUnit, sandbox isolation, async reliability,
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Elixir Testing Reference skill
What this skill tells your AI
The instructions your AI receives, as published by oliver-kriska/claude-elixir-phoenix in targets/pi/skills/testing/SKILL.md and read by ahel’s review.
Ash projects: Use
DataCasewithAsh.Testhelpers; test actions via domain code interfaces, not directRepocalls. Seeash-frameworkskill.
Quick reference for Elixir testing patterns.
Iron Laws — Never Violate These
- ASYNC BY DEFAULT — Use
async: trueunless tests modify global state - SANDBOX ISOLATION — All database tests use Ecto.Adapters.SQL.Sandbox
- MOCK ONLY AT BOUNDARIES — Never mock database, internal modules, or stdlib
- BEHAVIOURS AS CONTRACTS — All mocks must implement a defined
@callbackbehaviour - BUILD BY DEFAULT — Use
build/2in factories;insert/2only when DB needed - NO PROCESS.SLEEP — Use
assert_receivewith timeout for async operations - VERIFY_ON_EXIT! — Always call in Mox tests setup
- FACTORIES MATCH SCHEMA REQUIRED FIELDS — Factory definitions must include all fields that have
validate_requiredin the schema changeset. Missing fields cause cascading test failures
Quick Decisions
Which Test Case?
| Testing | Use |
|---|---|
| Controller/API | use MyAppWeb.ConnCase |
| Context/Schema | use MyApp.DataCase |
| LiveView | use MyAppWeb.ConnCase + import Phoenix.LiveViewTest |
| Pure logic | use ExUnit.Case, async: true |
When to use async: true?
- ✅ Pure functions, no shared state
- ✅ Database tests with Sandbox (PostgreSQL)
- ❌ Tests modifying
Application.put_env - ❌ Tests using Mox global mode
Mock or not?
- ✅ Mock: External APIs, email services, file storage
- ❌ Don't mock: Database, internal modules, stdlib
build() or insert()?
- Use
build()by default for speed - Use
insert()only when you need DB ID, constraints, or persisted associations
Quick Patterns
# Setup chain
setup [:create_user, :authenticate]
# Pattern matching assertion
assert {:ok, %User{name: name}} = create_user(attrs)
# Async message assertion
assert_receive {:user_created, _}, 5000
# Mox setup
setup :verify_on_exit!
expect(MockAPI, :call, fn _ -> {:ok, "data"} end)
# LiveView async
html = render_async(view) # MUST call for assign_async
Common Anti-patterns
| Wrong | Right |
|---|---|
Process.sleep(100) | assert_receive {:done, _}, 5000 |
insert(:user) in factory | build(:user) in factory |
async: true with set_mox_global() | async: false |
| Mock internal modules | Test through public API |
References
For detailed patterns, see:
references/exunit-patterns.md- Setup, assertions, tagsreferences/mox-patterns.md- Behaviours, expect/stub, asyncreferences/liveview-testing.md- Forms, async, uploadsreferences/factory-patterns.md- ExMachina, sequences, traits
Signals
- GitHub stars
- 543
- Forks
- 38
- Last commit
- Sep 2026
- Hacker News mentions
- 20
Advanced
- Catalog kind
- skill
- Gateway key
testing-oliver-kriska- Source
- github.com/oliver-kriska/claude-elixir-phoenix