Testing and Telemetry events: how to test if they are sent?

Ii finally end up with this:

defmodule MyApp.MetricsCase do
  @moduledoc """
  This module defines the setup for tests requiring metrics tests.
  """
  use ExUnit.CaseTemplate

  using do
    quote do
      import Sharon.MetricsCase
    end
  end

  @doc """
  Add a tag for metrics testing.
  Takes a list of metrics as paramater.

  ## Usage

      @tag metrics: [[:my_app, :metrics1], [:my_app, :metrics2, :sub]]
  """
  setup tags do
    if metrics = tags[:metrics] do
      self = self()

      :telemetry.attach_many(
        tags[:test],
        metrics,
        fn name, measurements, metadata, _ ->
          send(self, {:telemetry_event, name, measurements, metadata})
        end,
        nil
      )
    end

    :ok
  end

  @doc """
  Assert that given event has been sent.
  """
  defmacro assert_metrics(name, measurements, metadata \\ %{}),
    do: do_assert_metrics(name, measurements, metadata)

  defp do_assert_metrics(name, measurements, %{}) do
    do_assert_metrics(name, measurements, Macro.escape(%{}))
  end

  defp do_assert_metrics(name, measurements, metadata) do
    quote do
      assert_receive {:telemetry_event, unquote(name), unquote(measurements), unquote(metadata)}
    end
  end
end

which can be used in both test support file and test file.

My example test is now:

@tag metrics: [[:user, :create], [:user, :registration]]
test "user creation ok" do
  Repo.insert!(user_data)
  
  assert_metrics([:user, :create], %{count: 1})
  assert_metrics([:user, :registration], %{count: 1}, %{stage: :creation})
end
3 Likes