Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions usage-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -1131,3 +1131,53 @@ When testing resources:
- Use `authorize?: false` in tests where authorization is not the focus
- Write generators using `Ash.Generator`
- Prefer to use raising versions of functions whenever possible, as opposed to pattern matching

### Preventing Deadlocks in Concurrent Tests

When running tests concurrently, using fixed values for identity attributes can cause deadlock errors. Multiple tests attempting to create records with the same unique values will conflict.

#### Use Globally Unique Values

Always use globally unique values for identity attributes in tests:

```elixir
# BAD - Can cause deadlocks in concurrent tests
%{email: "test@example.com", username: "testuser"}

# GOOD - Use globally unique values
%{
email: "test-#{System.unique_integer([:positive])}@example.com",
username: "user_#{System.unique_integer([:positive])}",
slug: "post-#{System.unique_integer([:positive])}"
}
```

#### Creating Reusable Test Generators

For better organization, create a generator module:

```elixir
defmodule MyApp.TestGenerators do
use Ash.Generator

def user(opts \\ []) do
changeset_generator(
User,
:create,
defaults: [
email: "user-#{System.unique_integer([:positive])}@example.com",
username: "user_#{System.unique_integer([:positive])}"
],
overrides: opts
)
end
end

# In your tests
test "concurrent user creation" do
users = MyApp.TestGenerators.generate_many(user(), 10)
# Each user has unique identity attributes
end
```

This applies to ANY field used in identity constraints, not just primary keys. Using globally unique values prevents frustrating intermittent test failures in CI environments.
Loading