Search code examples
elixirelixir-mixelixir-iexex-unit

Make fixtures and testhelp functions available for ExUnit and iex


I am writing a project that I want to test, both automatically with ExUnit and interactivly with iex. Say my project look like this:

[mto@bgobuildwin8g sample]$ tree
.
├── config
│   └── config.exs
├── fixtures
│   └── complex_struct.exs
├── lib
│   └── the_function.ex
├── mix.exs
├── README.md
└── test
    └── the_test.exs

4 directories, 7 files
[mto@bgobuildwin8g sample]$ cat lib/the_function.ex 
defmodule TheFunction do
    def the_function ({a, b, c}) do
        a / b + c
    end
end
[mto@bgobuildwin8g sample]$ cat fixtures/complex_struct.exs 

defmodule ComplexStruct do
    def complex_struct do
        {2, 1, 1}
    end
end
[mto@bgobuildwin8g sample]$ cat test/the_test.exs 
defmodule IexandtestTest do
  Code.load_file("fixtures/complex_struct.exs")
  use ExUnit.Case
  doctest Iexandtest

  test "the test" do
    assert (TheFunction.the_function (ComplexStruct.complex_struct())) == 3
  end
end

I can now run mix test and it will find fixtures/complex_struct.exs so that the test executes successfully. I also like to debug my code using the following command

iex -S mix

That way I have access to lib/the_function.ex and can debug it.

iex(1)> TheFunction.the_function({1,2,3})
3.5

But I have no access to fixtures/complex_struct.exs unless I load it like this:

iex(1)> TheFunction.the_function(ComplexStruct.complex_struct())
** (UndefinedFunctionError) undefined function ComplexStruct.complex_struct/0 (module ComplexStruct is not available)
    ComplexStruct.complex_struct()
iex(1)> Code.load_file("fixtures/complex_struct.exs")
[{ComplexStruct,
  <<70, 79, 82, 49, 0, 0, 5, 28, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 137, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, 100, 0, ...>>}]
iex(2)> TheFunction.the_function(ComplexStruct.complex_struct())
3.0

What determines what get loaded by iex and how can I make all modules in lib and all fixtures available when i run iex -S mix?


Solution

  • Only the files in the directories specified by :elixirc_paths key of the return value of project/0 function of your mix.exs are compiled into your app. The default value of :elixirc_paths is ["lib"].

    To compile Elixir files in fixtures, you need to change the extension from exs to ex and then add fixtures to :elixirc_paths:

    def project do
      [app: :m,
       version: "0.1.0",
       ...,
       elixirc_paths: ["lib", "fixtures"]]
    end
    

    After this you will be able to access ComplexStruct from both iex and tests, and you won't need the call to Code.load_file in your test modules anymore.