fireproofsocks

fireproofsocks

Referencing files from tests -- __DIR__ is evaluated at compile time, so paths can break

This is a problem I’ve come across now and then… in an app, I have a few directories containing .json files (e.g. for example requests or responses). I put these files into directories inside of test/support/ and then in my mix.exs I reference the test/support/ directory as follows:

    def project do
    [
      # ...
      elixirc_paths: elixirc_paths(Mix.env()),
      # ...
    ]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

The problem revolves around the __DIR__ variable because it is resolved at compile time. I can include files in my setup fixtures doing something like this:

 # example setup inside `test/support/conn_case.ex`
  defp append_mutation(%{mutation: mutation} = context) do
    data =
      "#{__DIR__}/mutations/#{mutation}.json"  # <-- resolves to /full/path/to/test/support/mutations/something.json
      |> File.read!()
      |> Jason.decode!()

    %{context | mutation: data}
  end

When I run tests locally, the path gets converted to paths that make sense on my local machine, so tests pass. However, if I then try to run tests in a containerized environment (e.g. via docker-compose), the paths are not the same, so tests fail.

One option is to do mix compile --force before running the tests, but that’s slow – I have to recompile everything every time I switch environments.

I seem to remember something about the https://hexdocs.pm/elixir/Application.html#app_dir/1 working in certain cases here… but I don’t see how it’s working its magic. Even with my mix.exs set to compile my test/support/ folder, none of my supporting .json files end up in the _build/ folder, so I don’t think I can reference them there.

Can someone educate me on a better way to dealing with this?

Thanks!

Marked As Solved

kip

kip

ex_cldr Core Team

I would be very unusually to put test files in priv, yes. For accessing support files in tests I typically just rely on the fact that tests are being run when the working directory is the root of the project. Therefore just "test/support/mutations/#{mutation}.json"

Also Liked

kip

kip

ex_cldr Core Team

Yes, thats my normal strategy. It breaks if you have tests that change working directory - and there are some functions in Mix that do that if you are messing around with dependencies (which is not something I’d recommend and wouldn’t normally be an issue).

joshtaylor

joshtaylor

Can you do:

Path.join([:code.priv_dir(:my_otp_app), "#{mutation}.json"])

?
https://erlang.org/doc/man/code.html#priv_dir-1

kip

kip

ex_cldr Core Team

the .po files are compiled into functions in the module that use Gettext, otp_app: ___ so they don’t need to be in a release.

The behaviour of the priv dir is controlled by the build_embedded: Mix.env() == :prod, line in mix.exs. In development the priv dir is symlinked to the _build directory and in production it is copied. So I would expect your /path/to/my_app/_build/test/lib/my_app/priv/ is a symlink on your dev machine?

For example, for one of my libs:

$ ls -al _build/test/lib/ex_cldr/priv
lrwxr-xr-x  1 kip  staff  16  8 Jan 06:09 _build/test/lib/ex_cldr/priv -> ../../../../priv
NobbZ

NobbZ

So, as they are only relevant to testing, and during testing usually your full sources are available from where you run mix, why not just use relative path from CWD?

Where Next?

Popular in Questions Top

Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
kostonstyle
Hi all I want to have a unix time, from the current time plus 1 hour. DateTime.now + 1 hour How to get it in elixir? Thanks
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

Other popular topics Top

belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New

We're in Beta

About us Mission Statement