fabioticconi
Understanding __using__, with a practical problem
Hi all,
I’m trying to solve a practical problem - make an ExUnit “data case” with async true as default, instead of false.
So if a user does this:
use MyTestCase
Then async will be true, but if the user specifies use MyTestCase, async: false then it will be respected.
It seems to me that it should be fairly easy to inject code into the ExUnit.CaseTemplate to make it happen, but my understanding of Elixir metaprogramming is limited and have been stuck.
In my datacase, the first thing I do is to use ExUnit.CaseTemplate. This will import some callbacks and assertions and inject an __using__, overridable macro. As can be seen here: elixir/lib/ex_unit/lib/ex_unit/case_template.ex at v1.13.4 · elixir-lang/elixir · GitHub
Now, I thought I could do something like:
defmodule MyTestCase
use ExUnit.CaseTemplate
using opts do quote do
# modify opts keyword list, put async true if not present
end
end
But the __proxy__ function is called before evaluating the provided block (it’s the using/1 helper function in ExUnit.CaseTemplate that I’m leveraging). This means that the opts will have already been processed so I can’t know, at that point, whether the user had specified async: true or async: false.
What am I missing? Can I work with this or do I need to essentially drop the use ExUnit.CaseTemplate line and replicate what is does but in the way I need?
Marked As Solved
LostKobrakai
You likely want this:
defmodule MyTestCase
use ExUnit.CaseTemplate
defmacro __using__(opts) do
opts
|> Keyword.put_new(:async, true)
|> super()
end
end
For overwriting a overwritable __using__ macro, you need to implement exactly that macro. To call the injected implementation with your changes you can use super(). There’s no need to fiddle with quote in this case as you never need to convert text of code into AST.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









