Fl4m3Ph03n1x

Fl4m3Ph03n1x

How do you setup up multiple test environments in your projects?

Background

So I have a personal project with 2 types of tests: unit tests and integration tests. It is my personal believe this is a rather common scenario for people who value testing or where testing makes sense.

How I do it

I use the config folder to put all of the configurations and my folder looks like the following:

├── config/
│   ├── config.exs
│   ├── dev.exs
│   ├── prod.exs
│   ├── integration.exs
│   └── test.exs
├── lib/

Each file has configurations for the env they use.
In my code, I make use of such configurations like the following:

defmodule MarketManager.Store.FileSystem do
 
  @products_filename Application.compile_env!(:market_manager, :products)

  def get_products_from_syndicate(syndicate),
    do:
      @products_filename
      |> File.read!()
      |> Jason.decode!()
      |> find_syndicate(syndicate)

# Rest of code...

end

This way if I run a test, I can pass in MIX_ENV=integration and it will fetch the values from integration.exs for example.

Drawabacks

The problem with this approach is that you either have to always prepend MIX_ENV=blabla to your commands and it encourages you to have a more convoluted mix.exs file if you want to avoid typing all the jargon before every command.

How do you do it?

I have seen some people in this forum mention they use a “Repo” file for this kind of thing, where they pass in dependencies. Others use a Settings file that is a wrapper for configuration.

How do you guys do it?

Most Liked

LostKobrakai

LostKobrakai

That’s imho a big misconception. But there are layers to the problem here:

Currently you’re changing the code executed by having a different config when running tests. This is fine if your tests need a single static setup of dependencies applied.
Now you’re wondering how to move to a place where the single static setup of dependencies is no longer enough for all your tests. One way to do that is changing the setup between sets of tests, which need a common setup.

You’re doing this via the MIX_ENV (could be something else you can check on in a config.exs file) + multiple separated testruns, which is the only way to affect config early enough so you can depend on it at compile time. This is great in terms of your application being statically configured by config and nothing is dynamic at runtime. This also means all the tests you run in one of such batches need to deal with the same setup.

If the above is not flexible enough you need to start setting up dependencies at runtime. And that point is reached earlier than one might expect. E.g. using Mox means you’re setting up a dependency at runtime (the module might be the same, but the functions are different) and you either need to run tests with async: false to have the correct mocked implementation called or you need to pass in something from your test to the callsite, which makes it call the mocked implementation. The same is true for any two concrete implementations you want to change between within the same testrun. If you’re actually using Mox or not is actually not relevant.

So unless you can configure everything statically at compile time you’re in a place where you’re handling multiple interchangeable implementations at runtime and you’re imo better of acknowledging that fact in your codebase instead of trying to ignore it – even if in production there’s only one implementation used.

LostKobrakai

LostKobrakai

I’d start with the question: Why do you need another mix env for your integration tests in the first place?
I’m aware that many things differ between unit and integration tests, but if config.exs seems like the only way to provide them you might want to re-evaluate your options on dependency injection.

LostKobrakai

LostKobrakai

All of those questions boil down to “how can I make my code do different things (at runtime)”. If you can do that the stubbing/predefined responses part becomes simple, as it’s just one of those “different things” (likely a mox module). To get to that point imagine building a system, where in production you need to be able to switch out those parts, which you want to be able to switch out in your tests. E.g. the code you posted in your first post won’t cut it, as the dependency is set at compile time, so it’s not changeable at runtime.

Where Next?

Popular in Discussions Top

blackode
Elixir Upgrading is so Simple in Ubuntu and It worked for me Ubuntu 16.04 git clone https://github.com/elixir-lang/elixir.git cd elixir...
New
jeramyRR
This is an interesting article to read. Elixir’s performance, like usual, is excellent. However, it seems like the high CPU usage is co...
New
arpan
Hello everyone :wave: Today I am very excited to announce a project that I have been working on for almost 3 months now. The project is...
New
ricklove
I was just introduced to Elixir and Phoenix. I was told about the 2 million websocket test that was done 2 years ago. From my research, t...
New
marciol
Please, let me know if this kind of discussion already took place in another topic . Hi all, how do you consider if is better to build ...
New
rms.mrcs
A couple of days ago I was discussing with a friend about different approaches to write microservices. He said that if he was going to w...
New
jesse
Hi everyone, I hesitated to post this here because I don’t want you to think I’m spamming, but I’ve been working on a Platform-as-a-Serv...
New
paulanthonywilson
I like Umbrella projects and pretty much always use them for personal Elixir stuff, especially Nerves things. But I don’t think this is ...
New
Markusxmr
Since Drab has been developed for a while in the open, introducing the Liveview functionality in a way it happend appears to undermine th...
New
slashdotdash
Phoenix Live View is now publicly available on GitHub. Here’s Chris McCord’s tweet announcing making it public.
New

Other popular topics Top

albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement