lok0613
Passing parameters into defmacros
Hello all,
I’m recently doing something similar to ExUnit, keeping a bunch of variables on “setup” block and then pass it to the next block which is “test” just like below.
defmodule MyTest do
use ExUnit.Case, async: true
setup do
{:ok, %{message: "hi"}}
end
test "my test title", %{message, msg} do
IO.puts(msg)
end
end
However, I didn’t managed to do this on my own.
defmodule XUnit do
defmacro __using__(_opts) do
quote do
import XUnit
@setups []
@tests []
@before_compile XUnit
def run() do
IO.puts("Running....")
run_setups()
run_displays()
end
end
end
defmacro setup(do: block) do
fn_name = String.to_atom("setup")
quote do
def unquote(fn_name)(), do: unquote(block)
@setups [unquote(fn_name) | @setups]
end
end
defmacro test(message, var, do: block) do
var = Macro.escape(var)
quote bind_quoted: [message: message, var: var, block: block] do
fn_name = String.to_atom("test " <> message)
def unquote(fn_name)(unquote(var)), do: unquote(block)
@tests [{fn_name, var} | @tests]
end
end
defmacro __before_compile__(_opts) do
quote do
def run_setups() do
@setups
|> Enum.each(fn setup_fn -> apply(__MODULE__, setup_fn, []) end)
end
def run_displays() do
@tests
|> Enum.each(fn {test_fn, params} ->
apply(__MODULE__, test_fn, [params])
end)
end
end
end
end
defmodule Test do
use XUnit
setup do
%{message: "hi"}
end
test "my test title", %{message: msg} do
IO.puts("print from test, #{msg}")
end
end
Test.run()
It turns out this error message.
warning: variable "msg" does not exist and is being expanded to "msg()", please use parentheses to remove the ambiguity or change the variable name
Main.exs:64: Test
** (CompileError) Main.exs:64: undefined function msg/0
(elixir) src/elixir_bitstring.erl:142: :elixir_bitstring.expand_expr/4
(elixir) src/elixir_bitstring.erl:27: :elixir_bitstring.expand/8
(elixir) src/elixir_bitstring.erl:20: :elixir_bitstring.expand/4
expanding macro: XUnit.test/3
I tried many ways but it still not really work as my expectation. This is my first question on elixir forum, so please could anyone give me some idea how to mimic the way that ex_unit was doing?
Thanks so much
Marked As Solved
Kabie
Ahh, I was overthinking, this should works already.
defmacro test(message, param, do: block) do
quote do
def unquote(:"test_#{message}")(unquote(param)) do
unquote(block)
end
end
end
But your problem is you didn’t pass results that setup returns to tests, something like:
def run_tests() do
setup_result = @setups
|> Enum.reduce(%{}, fn setup_fn, params
-> apply(__MODULE__, setup_fn, [params])
end)
@tests
|> Enum.each(fn test_fn ->
apply(__MODULE__, test_fn, [setup_result])
end)
end
1
Also Liked
kokolegorille
Hello and welcome,
You do have a syntax error,
It should be…
test "my test title", %{message: msg} do
2
Kabie
There is a trick:
defmacro test(message, param, do: block) do
quote do
def unquote(:"test_#{message}")(param) do
unquote(param) = param
unquote(block)
end
end
end
1
Last Post!
Popular in Questions
Hi guys, i’m new in the Elixir world, and i have to say, that i love it!
i’m having some problem to understand anonymous functions with ...
New
I would like to know what is the best IDE for elixir development?
New
Hi everyone!
I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: )
Hello all, this is ...
New
i’m a new one to elixir
which editor can i use
vs code? or atom?
Thanks! :smiley:
New
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors:
[WARN] - (starship::utils): Executing command ...
New
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Other popular topics
Hi,
I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
Hello, how can I check the Phoenix version ?
Thanks !
New
Lets say I have map like this fetching from my database
%{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
Hey,
Just curious what are the main benefits of Elixir compared to Clojure?
When is Elixir more useful than Clojure and vice versa?
Th...
New
After calling mix ecto.create I get this error:
17:00:32.162 [error] GenServer #PID<0.412.0> terminating
** (Postgrex.Error) FATAL...
New
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
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
- #api
- #forms
- #metaprogramming
- #security
- #hex









