marcandre
How to have uncaptured logger calls generate failures in ExUnit?
I’d like that any test that generates uncaptured log entries fails.
Is there an easy way to do this?
Otherwise, would adding a custom Logger backend work, i.e. would it not be called if there’s a @capture_log tag or if the test is wrapped in capture_log(...)?
Most Liked
Sebb
I was in the same situation, that I wanted to include logging in the tests. I ended up writing a little macro that gets some meta-data from __CALLER__ and generates log-tuples
assert [{:logger, :error, {4711, %{file: _, line: _}}}] = error(4711)
assert [{:logger, :warning, {'test', %{file: _, line: _}}}] = warning('test')
assert [{:logger, :debug, {[a: 1, b: 2], %{file: _, line: _}}}] = debug([a: 1, b: 2])
The advantage over capture_log is, that you can use structured logging while capture_log can only use the console backend. Also it’s absolutely pure (if you are strict and see logging as impure) so there are no problems with async. But you have to handle the log-data the core produces somehow in the shell (and do the real logging).
josevalim
There is no such feature at the moment. It would need to be added to Elixir. But keep in mind that, given your tests run concurrently, this could cause Heisenfailures as one test could incorrectly capture the logs of another test and not fail when it should fail (which is ok, it would not be ok to fail when it should not have).
marcandre
Here’s are examples of captured/uncaptured entries:
test "this is captured" do
assert capture_log(fn ->
Logger.warn("example")
end) =~ "example"
end
@tag capture_log
test "this is captured too" do
Logger.warn("example")
end
test "this is not captured and should fail" do
Logger.warn("example")
end
josevalim
Yeah, we could support a @tag :assert_no_log.
josevalim
This is where we check for capture log tag: elixir/lib/ex_unit/lib/ex_unit/runner.ex at main · elixir-lang/elixir · GitHub
We probably want to make it a tri-state: :capture, :none, :assert. And then fail the test if it passes but has a log in asset mode.







