# Testing When testing resources: - Test your domain actions through the code interface - Use test utilities in `Ash.Test` - Test authorization policies work as expected using `Ash.can?` - 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.