Hi Jose,
Good point! I actually didn't pay much attention to the behavior testing
part because the code that was pointing out the use case was the one that
was commented out. So, here goes another try. What do you think about the
following code?
*By the way, I really appreciate you taking out the time to look at the
code. I know you have a packed schedule. :)*
Best,
Adi
CODE SNIPPET:
```ex
defmodule Behavior do
defmacro __using__(options) do
fun = Keyword.get(options, :fun, :fun)
quote do
def __some_function__, do: :something
def __some_other_function__, do: :something
def unquote(fun)(), do: :fun
end
end
end
defmodule TestSubject1 do
use Behavior, fun: :fun1
end
defmodule TestSubject2 do
use Behavior, fun: :fun2
end
defmodule TestSubject3 do
use Behavior
end
defmodule TestSubject4 do
use Behavior, fun: :fun4
end
## Tests
ExUnit.start()
# This test should sufficiently test Behavior module's functions and use
cases
defmodule BehaviorTest do
use ExUnit.Case
defmodule TestWithFun do
use Behavior, fun: :test
end
defmodule TestWithoutFun do
use Behavior
end
describe "__using__/1" do
test "defines static functions along with `fun/0 `is no fun provided" do
assert TestWithoutFun.__some_function__() == :something
assert TestWithoutFun.__some_other_function__() == :something
assert TestWithoutFun.fun() == :fun
end
test "defines static functions along with `test/0 ` when fun is :test"
do
assert TestWithFun.__some_function__() == :something
assert TestWithFun.__some_other_function__() == :something
assert TestWithFun.test() == :fun
end
end
end
defmodule TestSubject1Test do
use ExUnit.Case
# This test is re-testing `Behavior.__using__/1` instead of just testing
# its usage
describe "uses Behavior" do
test "defines static functions along with `fun1/0`" do
assert TestSubject1.__some_function__() == :something
assert TestSubject1.__some_other_function__() == :something
assert TestSubject1.fun1() == :fun
end
end
# `@__using__` attribute will allow us to do something like this, instead
# of testing `Behavior.__using__/1` again.
# describe "use Behavior" do
# test "uses Behavior with fun option" do
# uses = TestSubject1.__info__(:attributes)[:__using__]
#
# assert {Behavior, [fun: :fun1]} in uses
# end
# end
end
## --- More tests for TestSubject2, TestSubject3 and TestSubject4
```
Now that we have tested how `Behavior.__using__/1` behaves (by calling the
actual functions), testing whether `TestSubject1` has correct attributes
set should be sufficient, right?
On Monday, 8 March 2021 at 15:58:11 UTC-5 José Valim wrote:
> Hi Adi,
>
> I don’t think this is a good idea. All of your tests are testing that it
> defined a function or uses something but it really doesn’t test that any of
> that *behaves* as you would want.
>
> Since we don’t want to promote such tests, it is not something we see in
> the language.
>
> Thank you,
>
> On Mon, Mar 8, 2021 at 21:53 Adi <[email protected]> wrote:
>
>> Hi Jose,
>>
>> Sorry if I'm not doing a good job explaining it. I'll share some code
>> below.
>>
>> Hi Wojtek, Great idea using compile-time tracers! Unfortunately, I don't
>> see them capturing information related to the arguments being passed to the
>> macro. If there's a way to do that, it would satisfy my use case.
>>
>> Either way, I have shared the code snippet below. Let me know what both
>> of your thoughts are.
>>
>> Best,
>> Adi
>>
>> CODE SNIPPET:
>>
>> ```ex
>> defmodule Behavior do
>> defmacro __using__(options) do
>> fun = Keyword.get(options, :fun, :fun)
>>
>> quote do
>> def __some_function__, do: :something
>> def __some_other_function__, do: :something
>> def unquote(fun)(), do: :fun
>> end
>> end
>> end
>>
>> defmodule TestSubject1 do
>> use Behavior, fun: :fun1
>> end
>>
>> defmodule TestSubject2 do
>> use Behavior, fun: :fun2
>> end
>>
>> defmodule TestSubject3 do
>> use Behavior
>> end
>>
>> defmodule TestSubject4 do
>> use Behavior, fun: :fun4
>> end
>>
>> ## Tests
>> ExUnit.start()
>>
>> # This module should sufficiently test Behavior module's functions and
>> use cases
>> defmodule BehaviorTest do
>> use ExUnit.Case
>>
>> defmodule TestWithFun do
>> use Behavior, fun: :test
>> end
>>
>> defmodule TestWithoutFun do
>> use Behavior
>> end
>>
>> describe "__using__/1" do
>> test "defines static functions along with `fun/0 `is no fun provided"
>> do
>> assert {:__some_function__, 0} in
>> TestWithoutFun.__info__(:functions)
>> assert {:__some_other_function__, 0} in
>> TestWithoutFun.__info__(:functions)
>> assert {:fun, 0} in TestWithoutFun.__info__(:functions)
>> end
>>
>> test "defines static functions along with `test/0 ` when fun is
>> :test" do
>> assert {:__some_function__, 0} in TestWithFun.__info__(:functions)
>> assert {:__some_other_function__, 0} in
>> TestWithFun.__info__(:functions)
>> assert {:test, 0} in TestWithFun.__info__(:functions)
>> end
>> end
>> end
>>
>> defmodule TestSubject1Test do
>> use ExUnit.Case
>>
>> # This test is re-testing `Behavior.__using__/1` instead of simply
>> testing
>> # its usage.
>> describe "uses Behavior" do
>> test "defines static functions along with `fun1/0`" do
>> assert {:__some_function__, 0} in TestSubject1.__info__(:functions)
>> assert {:__some_other_function__, 0} in
>> TestSubject1.__info__(:functions)
>> assert {:fun1, 0} in TestSubject1.__info__(:functions)
>> end
>> end
>>
>> # `@__using__` attribute will allow us to do something like this,
>> instead
>> # of testing `Behavior.__using__/1` again.
>> # describe "use Behavior" do
>> # test "uses Behavior with fun option" do
>> # uses = TestSubject1.__info__(:attributes)[:__using__]
>> #
>> # assert {Behavior, [fun: :fun1]} in uses
>> # end
>> # end
>> end
>>
>> ## --- Similar tests for TestSubject2, TestSubject3 and TestSubject4
>> ```
>>
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "elixir-lang-core" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>>
> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/elixir-lang-core/6fe63cce-2b4c-4af9-a9af-4e473f63533an%40googlegroups.com
>>
>> <https://groups.google.com/d/msgid/elixir-lang-core/6fe63cce-2b4c-4af9-a9af-4e473f63533an%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>
--
You received this message because you are subscribed to the Google Groups
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-core/51f9ff7a-7a4f-46f2-a19e-fc21d18826a5n%40googlegroups.com.