Пользовательские утверждения ExUnit и сопоставление с образцом

Я пишу гибкую библиотеку отслеживания ошибок на основе адаптера и предоставляю набор настраиваемых функций утверждения тестов, чтобы упростить работу с интеграционными тестами.

У меня есть что-то вроде

  # /lib/test_helpers.ex 

  ...

  @doc """
  Asserts specific exception and metadata was captured

  ## Example

      exception = %ArgumentError{message: "test"}
      exception |> MyApp.ErrorTracker.capture_exception(%{some_argument: 123})
      assert_exception_captured %ArgumentError{message: "test"}, %{some_argument: 123}
  """
  def assert_exception_captured(exception, extra) do
    assert_receive {:exception_captured, ^exception, ^extra}, 100
  end

Что передаст точное исключение assert_exception_captured, но это не работает при попытке сопоставления с шаблоном, например, в структуре исключения.

Я хотел бы иметь возможность сделать это

...
assert_exception_captured _any_exception, %{some_argument: _}

Как я могу заставить эту работу работать с сопоставлением с образцом?

Очень признателен


person Tarlen    schedule 21.11.2017    source источник
comment
Мне нравится твой код. Что делает MyApp.ErrorTracker.capture_exception?   -  person Dogbert    schedule 21.11.2017
comment
В настоящее время он просто отображает аргументы, используя передачу сообщений send self(), {:exception_captured, exception, extra}   -  person Tarlen    schedule 21.11.2017
comment
Это подходит для меня. Можете ли вы добавить полный тестовый пример, который вам не подходит?   -  person Dogbert    schedule 21.11.2017
comment
@Dogbert Я добавил пример того, что бы я хотел делать   -  person Tarlen    schedule 21.11.2017


Ответы (1)


Вам нужно будет использовать макросы, если вы хотите передать шаблон. Вот как вы можете реализовать это с помощью макроса:

defmacro assert_exception_captured(exception, extra) do
  quote do
    assert_receive {:exception_captured, ^unquote(exception), unquote(extra)}, 100
  end
end

Тестовое задание:

test "greets the world" do
  exception = %ArgumentError{message: "test"}
  send self(), {:exception_captured, exception, %{some_argument: 123}}
  assert_exception_captured exception, %{some_argument: _}
end

Выход:

$ mix test
.

Finished in 0.02 seconds
1 test, 0 failures
person Dogbert    schedule 21.11.2017
comment
Хм, для меня это приводит к ошибке unbound variable _ - person Tarlen; 21.11.2017
comment
Ах, nvm, я использовал bind_quoted: [...], но если я использую unquote, он работает. Я думал, что это то же самое - person Tarlen; 21.11.2017