Ideally, your system pushes this kind of "global" configuration down from the 
top of the supervision tree, rather than reading global state like this in a 
bunch of places. I would definitely encourage you to try and build your system 
with that in mind. Then, all of your tests can pass specific configuration to 
the part of the system under test, rather than relying on global state.

But as an alternative approach for your use case: you could implement a simple 
wrapper function around `System.get_env` (etc.) that reads/writes to a special 
key in the process dictionary, falling through to calling the `System` APIs if 
the process dictionary doesn't have the `:env` key (or whatever you want to 
call it).

Then, all you need to do in your tests, is store the env vars you want in the 
process dictionary of the test, and those will override the global `System` 
values.

Things get a bit trickier when spawning processes is involved, but there are 
various approaches for this (I believe ExUnit abuses these pretty heavily 
itself IIRC). One of them is to look at the ancestors of the current process 
until you either reach the root process, or you find one with the specified key 
in the process dictionary.

The reason why implementing this in ExUnit itself is likely to see pushback, is 
because there are just so many ways for this kind of global state to find its 
way into a program, and ExUnit cannot handle them all. Furthermore, I believe 
José wants to encourage good system design by making it harder to do things in 
a not-recommended way, i.e. in this case, not relying on global configuration 
deep inside your system. As a practical matter, it would also require adding 
the sort of wrapper code I mentioned to `System.get_env`, which isn't 
particularly palatable I would imagine.

Anyway, hope that helps/gives you some ideas!

Paul

On Wed, Mar 27, 2024, at 11:14 AM, Daniel Kukula wrote:
> Currently, tests that use env variables can't be run async because the 
> environment is shared. My proposal is to introduce a with_env function that 
> will accept a function to execute and a mapping of params that the functions 
> in System will accept as env variables:
> Now: System.put_env("PORT", "4000")
> assert some logic
> System.delete_env("PORT")
> 
> after
> 
> with_env(%{"PORT" => "4000}, fn -> 
> assert some logic
> end)
> 
> 
> -- 
> 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 elixir-lang-core+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/elixir-lang-core/3e7dcf24-ae69-47b0-a7b5-281055c70726n%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/elixir-lang-core/3e7dcf24-ae69-47b0-a7b5-281055c70726n%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 elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/1392a7b4-dc96-4593-a2f5-3307ff66a5cd%40app.fastmail.com.

Reply via email to