How to hide logs in some tests but not in others?

Background

I have library that logs messages depending on the value of disable_logging:

unless Application.get(:my_app, :disable_logging, false), do:
  Logger.info("Hello World!")

Depending on MIX_ENV I have a config for each setup:

#test.config
use Mix.Config
config :my_app, disable_logging: true

Problem

The issue here is that I don’t want log messages all over my test results. So, naturally, I could set the disable_logging to true and be done with it.

However, if I do it, I can’t test whether or not the Logger is being called and if it’s being called with the correct values:

Question

So, given this I have some questions:

  1. Is there a way to activate logs but without outputting them to the terminal when I am running tests?
  2. Is there a way to only activate logs for some tests in my test suite?
1 Like

Sure. Disable logging generally in test.exs, but then for the tests where you want logs:

  1. Run them synchronously (no async: true)
  2. Application.put_env(:my_app, :disable_logging, false)
  3. capture log.
  4. At the end of the tests Application.put_env(:my_app, :disable_logging, true)

Alternatively update test_helper.exs to have ExUnit.start(capture_log: true) and then you can make assertions about logging with capture_log as per usual, but it won’t print the log output in tests where you don’t.

3 Likes

Nice!
Is there a way to run all tests asynchronously except the 2 or 3 that need to be sync because of the logs?

@lpil

Alternatively update test_helper.exs to have ExUnit.start(capture_log: true) and then you can make assertions about logging with capture_log as per usual, but it won’t print the log output in tests where you don’t.

An alternative that wouldn’t work in my scenario, mainly because I have logging logic in my app:

unless Application.get(:my_app, :disable_logging, false), do:
  Logger.info("Hello World!")

Now, if only there was a way to remove all those unless and ifs. I am not sure if Logger config can fix this.

I also have another question for you:

  • If I do it your way, will I be able to make my tests async again? Or the fact I am capturing logs means I can never have them be async?

This is built into the Elixir logger, users can purge logging statements from applications. :slight_smile:

You can remove your logging logic and instead instruct users to add this config if they wish to remove your logging.

config :logger,
  compile_time_purge_matching: [
    [application: :foo]
  ]

https://hexdocs.pm/logger/Logger.html#module-application-configuration

  • If I do it your way, will I be able to make my tests async again? Or the fact I am capturing logs means I can never have them be async?

Using capture log does not prevent you from being able to run your test async, I would run all the tests async using this method.

2 Likes