I am using FunWithFlags
(fun_with_flags
) in an application, and have created a scenario that I think should cause tests to interfere with one another, but they don’t. I am very confused as to why, and hoping that someone can shed some light on it.
The app uses the Ecto persistence adapter, with a Postgres database.
I’ve created a public repo example app demonstrating this for anyone interested in looking at it.
Here is the test:
defmodule FwfAsyncTest do
defmodule FWFAsync_1 do
use FwfAsync.TestCase, async: true
test "enables flag" do
name = "enables flag"
:timer.sleep(1000)
IO.puts("(#{name} - #{now()}) enabling foo")
{:ok, true} = FunWithFlags.enable(:foo)
IO.puts("(#{name} - #{now()}) enabling foo - done")
:timer.sleep(3000)
IO.puts("(#{name} - #{now()}) assert FunWithFlags.enabled?(:foo)")
assert FunWithFlags.enabled?(:foo)
end
end
defmodule FWFAsync_2 do
use FwfAsync.TestCase, async: true
test "disables flag" do
name = "disables flag"
IO.puts("(#{name} - #{now()}) disabling foo")
{:ok, false} = FunWithFlags.disable(:foo)
IO.puts("(#{name} - #{now()}) disabling foo - done")
:timer.sleep(2000)
IO.puts("(#{name} - #{now()}) refute FunWithFlags.enabled?(:foo)")
refute FunWithFlags.enabled?(:foo)
:timer.sleep(3000)
end
end
end
The tests pass, and the output is:
(disables flag - 1634762854) disabling foo
(enables flag - 1634762855) enabling foo
(disables flag - 1634762856) refute FunWithFlags.enabled?(:foo)
.(enables flag - 1634762862) assert FunWithFlags.enabled?(:foo)
.
Finished in 8.1 seconds
2 tests, 0 failures
Two things are curious about this to me:
- The tests pass. I would expect the “refute” test to fail, because it occurs after the flag has been enabled.
- The time between the refute and assert is 6 seconds. I would expect it to only be 2 seconds.
I have looked through the FunWithFlags code, and done lots of inspecting in my code, and have found that the FunWithFlags PID, Cache PID, and underlying ETS table reference are the same in both tests.
Clearly there is something I’m misunderstanding about ExUnit and/or OTP. Or perhaps I just set up my async code incorrectly
Can anyone help me understand:
- Why do the tests pass?
- Why is the time between the final two outputs 6 seconds rather than 2 seconds?