jfpedroza / neotest-elixir

Neotest adapter for Elixir
MIT License
41 stars 10 forks source link

Running tests from umbrella root #41

Open piacsek opened 3 months ago

piacsek commented 3 months ago

Due to project setup constraints, I'm unable to run tests from the project root on my umbrella project, I have to cd to apps/sub_app and then run the test. I wonder if there's a way to configure the adapter in a way that it runs tests from the umbrella app root.

I tried to do that by modifying post_process_command to run the test through mix cmd --app my_app test path/to/test.exs. Here's my version of the run command:

elixir -r /Users/piacsek/.local/share/nvim/lazy/neotest-elixir/neotest_elixir/json_encoder.ex -r /Users/piacsek/.local/share/nvim/lazy/neotest-elixir/neotest_elixir/formatter.ex -S mix cmd --app my_app mix test --formatter NeotestElixir.Formatter --formatter ExUnit.CLIFormatter path/to/my/test.exs

But I when I run this command, the following output appears:

09:57:37.361 [error] CRASH REPORT Process <0.1422.0> with 0 neighbours crashed with reason: call to undefined function 'Elixir.NeotestElixir.Formatter':init([{include,[]},{exclude,[external,es_integration]},{max_cases,16},{seed,178117},{failures_manifest_file,...},...])
.....
Finished in 0.07 seconds (0.07s async, 0.00s sync)
5 tests, 0 failures

The tests pass, but the formatter fails to parse the results, making neotest consider the test as a failure.

PS: I'm currently trying to alter my project in a way that I can run any test from the root of the project, but having that as a configuration could come in handy not just to me but to other people in a similar situation.

piacsek commented 3 months ago

For reference, here's my plugin configuration :

require("neotest-elixir")({
    post_process_command = function(cmd)
        return {
            "elixir",
            "-r",
            "/Users/piacsek/.local/share/nvim/lazy/neotest-elixir/neotest_elixir/json_encoder.ex",
            "-r",
            "/Users/piacsek/.local/share/nvim/lazy/neotest-elixir/neotest_elixir/formatter.ex",
            "-S",
            "mix",
            "cmd",
            "--app",
            "my_app",
            "mix",
            "test",
            "--formatter",
            "NeotestElixir.Formatter",
            "--formatter",
            "ExUnit.CLIFormatter",
            "path/to/my/test_file.exs",
        }
    end,
}),
piacsek commented 3 months ago

Update: I've managed to get a working version.

Here's my post_process_command:

post_process_command = function(cmd)
  local test_file_path_from_root = cmd[#cmd]
  local current_umbrella_app = test_file_path_from_root:match("^apps/([^/]+)")
  local umbrella_relative_path_to_test =
    test_file_path_from_root:match("apps/" .. current_umbrella_app .. "/(.*)")

  return {
    "mix",
    "cmd",
    "--app",
    current_umbrella_app,
    "mix",
    "test",
    "--exit-status",
    "0",
    "--formatter",
    "NeotestElixir.Formatter",
    "--formatter",
    "ExUnit.CLIFormatter",
    umbrella_relative_path_to_test,
  }
end,

It has the unfortunate requirement to define both NeotestElixir.Formatter and NeotestElixir.JsonEncoder inside of my project and adding those files to .gitignore.

Previously I had tried to stick to the elixir -r path/to/file.ex -S rest_of_the_command, but I ended up having trouble with Zombie OS processes due to lingering DB connections after the tests had been executed.

It's not an ideal solution, but if you're in a rush like me trying to make neotest work with a legacy codebase that has just migrated to an umbrella structure, I hope it helps 🙏

jfpedroza commented 3 months ago

Where did you place the elixir -r ... -S part? At the beginning or after mix cmd?

You could try mix cmd --app current_umbrella_app elixir -r file.ex -S mix test ...

Also, before #30, the mix root would be the child app directory, which I think makes it so that the tests are run from the child app. Could you try the commit before that and see if it works?