Is it possible to run a persistent process before the tests starts?

Right now aliases usually have

      test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],

for new phoenix projects.

I need to run code before anything else has been executed, which runs a process that persists across the whole test session.

Problem is that you can’t just stick that process start inside test_helper.ex, because the ecto scripts depend on it and they run before test helper.

What I am talking about is really how to integrate something like Testcontainers for Elixir into Phoenix/Mix, in such a way that its easy to add and get going with testing, without having docker installed for ex when using Testcontainers Desktop that doesn’t require docker installed.

I have been thinking about manually creating the database and running migrations inside a macro, that I could supply with Testcontainers. But then I need to know how to manually create db and run migrations. It doesn’t look simple and doesn’t really need to, given how ecto have these default aliases which make it very convenient.

Does anyone know how to manually control/execute/dothesameas ecto.create and ecto.migrate in code ? I know that these scripts open and close the Repo, so it might not be easy to do in test helper.

EDIT: I think ill look into conditionally running a genserver that kicks off a container, at least worth a try.

I’m not sure your approach is worth chasing, as you are changing the core way application works, however on the topic on how to programmatically run migrations, you can use mix phx.gen.release that will generate a file called release.ex that will contain code that is able to perform migrations outside of mix task, they are usually used in a release where mix is not present.

1 Like

everything is possible …

  @impl true
  def start(_type, _args) do
    topologies = Application.get_env(:libcluster, :topologies) || []

    children =
      [
        ActivityPlannerWeb.Telemetry,
        run_postgres_container(
          ActivityPlanner.Repo,
          database: "activity_planner_test"
        ),
        {Phoenix.PubSub, name: ActivityPlanner.PubSub},
        {Finch, name: ActivityPlanner.Finch},
        ActivityPlannerWeb.Endpoint,
        {Cluster.Supervisor, [topologies, [name: ActivityPlanner.ClusterSupervisor]]}
      ]
      |> List.flatten()

    opts = [strategy: :one_for_one, name: ActivityPlanner.Supervisor]
    Supervisor.start_link(children, opts)
  end

and it works

edited previous reply, pretty nonintrusive the suggestion above dont you think @D4no0 ? :slight_smile:

EDIT: now its just naming the cat

1 Like

there is a PR here if anyone is interested in looking at how it will work

basically, in application.ex:

      import Testcontainers.Ecto

      @impl true
      def start(_type, _args) do
        start_postgres_container(app: :my_app),

        # .. other setup code
      ]

:wink:

1 Like