We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Structure context tests with `describe` blocks
almirsarajcic
Phoenix context test files grow fast. A single accounts_test.exs can easily reach 300+ lines, and without structure it becomes hard to find tests, spot missing coverage, or understand what a function is supposed to do.
ExUnit.Case has a describe/2 macro built in. Use it to mirror your context’s public API:
defmodule MyApp.AccountsTest do
use MyApp.DataCase, async: true
alias MyApp.Accounts
describe "get_user/1" do
test "returns the user when found" do
user = user_fixture()
assert Accounts.get_user(user.id) == user
end
test "returns nil when not found" do
refute Accounts.get_user(-1)
end
end
describe "create_user/1" do
test "creates a user with valid attributes" do
assert {:ok, user} = Accounts.create_user(%{email: "alice@example.com"})
assert user.email == "alice@example.com"
end
test "returns an error changeset with invalid attributes" do
assert {:error, %Ecto.Changeset{}} = Accounts.create_user(%{email: nil})
end
end
describe "delete_user/1" do
test "deletes the user" do
user = user_fixture()
assert {:ok, _} = Accounts.delete_user(user)
refute Accounts.get_user(user.id)
end
end
end
Each describe block becomes its own named scope. Test names in output include the block name, so failures read as "create_user/1 returns an error changeset with invalid attributes" — immediately actionable.
A few practical benefits:
- Coverage gaps become obvious — if
describe "update_user/1"doesn’t exist, you know it’s untested - Setup is scoped — use
setupinside adescribeblock and it only runs for those tests - Tags apply to the group —
@describetag :integrationskips or includes the whole block at once
describe "send_welcome_email/1" do
@describetag :integration
test "sends an email to the user" do
user = user_fixture()
assert {:ok, _} = Accounts.send_welcome_email(user)
end
end
One describe block per public function is a good default. It won’t stay perfectly organised forever, but it gives every test a home and makes the file scannable at a glance.
copied to clipboard