msimonborg

msimonborg

phx_test

Inspired by this topic by @caleb-bb, I’ve been working on a little experiment called phx_test. The question was “how do I write tests for my LiveView development tool, without turning my libary into a Phoenix project?”. I don’t know where this project will go in the future, so I’d love your thoughts and feedback.

Problem

In order to build packages for Phoenix applications, it may be necessary to load a running Phoenix project in development and tests. However, when you ship your library you want to be sure that neither the Phoenix test app nor any of its dependencies are leaked into your distribution.

Solution

It is possible to embed a Phoenix project into a subdirectory of your project as a dev and test dependency, with full access to its modules and dependencies in your tests and dev environment. You can even start the server directly from your root project directory with mix phx.server or iex -S mix phx.server, just as you would in a normal Phoenix project.

The path to making this work is not too complex, but it’s not obviously apparent either. Setting this up can save you from starting a separate Phoenix project and importing your libary just so you can perform tests. Now you can manage both your core project and the Phoenix app you use for testing in one repo.

mix phx_test.new

When you add phx_test as a dev/test dependency to your project, you get the mix phx_test.new task to set this up with one command. When you run this task with no arguments you will get a Phoenix project named phx_test_app installed in the priv/ subdirectory, and some additional code injected into mix.exs, config/config.exs, and test/test_helper.exs to hook everything up. Notably you will have the following dev/test dependencies added to your project’s mix.exs:

{:phx_test_app, path: "./priv/phx_test_app", only: [:test, :dev]},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:floki, ">= 0.30.0", only: :test}

You can customize the test app’s name and location with options: mix phx_test.new bar --sub-directory foo will create a Phoenix app called Bar in the foo/bar directory. The app name and all other options besides --sub-directory are passed directly to mix phx.new, so you can do things like mix phx_test.new bar --no-ecto --no-mailer --no-dashboard --no-gettext --sub-directory foo. The only option that does not work with mix phx_test.new is --umbrella, but I don’t think that’s going to hold anyone back from running some tests :slight_smile:

Feedback!

̶R̶i̶g̶h̶t̶ ̶n̶o̶w̶ ̶t̶h̶i̶s̶ ̶i̶s̶ ̶j̶u̶s̶t̶ ̶a̶v̶a̶i̶l̶a̶b̶l̶e̶ ̶o̶n̶ ̶[̶g̶i̶t̶h̶u̶b̶]̶(̶h̶t̶t̶p̶s̶:̶/̶/̶g̶i̶t̶h̶u̶b̶.̶c̶o̶m̶/̶m̶s̶i̶m̶o̶n̶b̶o̶r̶g̶/̶p̶h̶x̶_̶t̶e̶s̶t̶)̶,̶ ̶a̶n̶d̶ ̶i̶s̶ ̶n̶o̶t̶ ̶p̶u̶b̶l̶i̶s̶h̶e̶d̶ ̶t̶o̶ ̶h̶e̶x̶.̶ ̶Y̶o̶u̶ ̶c̶a̶n̶ ̶a̶d̶d̶ ̶i̶t̶ ̶t̶o̶ ̶y̶o̶u̶r̶ ̶d̶e̶p̶s̶ ̶w̶i̶t̶h̶ ̶̶{̶:̶p̶h̶x̶_̶t̶e̶s̶t̶,̶ ̶g̶i̶t̶:̶ ̶"̶h̶t̶t̶p̶s̶:̶/̶/̶g̶i̶t̶h̶u̶b̶.̶c̶o̶m̶/̶m̶s̶i̶m̶o̶n̶b̶o̶r̶g̶/̶p̶h̶x̶_̶t̶e̶s̶t̶"̶,̶ ̶o̶n̶l̶y̶:̶ ̶[̶:̶d̶e̶v̶,̶ ̶:̶t̶e̶s̶t̶]̶}̶̶.̶ This is available on hex, and you can addit to your project with {:phx_test, "~> 0.1.0", only: [:dev, :test]}. So far this has been sort of an experiment for my own learning and enjoyment, and I may put it down if there’s not much interest from the Elixir community, so I’m curious:

  • Is doing something like this even a good idea?
  • Does it seem useful enough in the real world to keep developing it?
  • Is there anything like this already?
  • Are there any gotchas I’m not aware of?
  • Can you think of anything that would make this better if I continue working on it?

Thanks for reading!

Showing Posts 1 to 6

msimonborg

msimonborg OP

Oops I slipped and hit my head on the keyboard and when I woke up v.0.1.0 had been published to hex.

nikokozak

nikokozak

Hey @msimonborg this is a really interesting project, and was wondering if there’s any way I could maybe contribute to it. I’ve run into this problem again and again, and have yet to find an easy/organic way around having to set up new phoenix instances and inject tests into them in order to make sure my library works (until I came across this).

trisolaran

trisolaran

Cool idea! I found myself wanting something like this recently while developing a LV library (not released yet, but hopefully soon).

My solution has been in fact to turn my library repo into a phoenix app and exclude the phoenix app from the hex package and the docs. It should work, but using something like phx_test seems more elegant and less hacky.

AHBruns

AHBruns

Going to try using this to test a new library I’m writing that’s meant to be used in live views. Will report back any issue I run into. This 100% solves a need, and I hope you continue working on it!

AHBruns

AHBruns

Just reporting back. The setup was mostly flawless though I do get warnings during testing of missing modules. Basically, if you’re developing a library then your test phoenix application will have code using your library, but you library’s modules won’t be exist when your test phoenix application is compiled resulting in warnings about missing modules. Of course, at runtime the library modules exists and everything works as expected. So, nothing really bad, just annoying to see compile time warnings I can’t fix. Otherwise, it was a great development experience.

Going to use this for all my phoenix related libraries going forward! Can’t wait to see it expanded with stuff like generating multiple phoenix applications and/or different application scaffolds. E.g. maybe with commanded, or with a few simple live views, controllers, etc. Great work!

AHBruns

AHBruns

Also, I’ve been using this alias to make testing a little less painful:

      test: [
        "cmd command cd my_sub_dir/my_app && mix test --color",
        "test"
      ]

Not only does this ensure my test app’s db is setup, it also runs my test app’s tests which is nice. No use running my tests which depend on my test app, if my test app isn’t functioning properly to begin with.

— All posts loaded —

Where Next? Top

Trending in Announcing Top

wojtekmach
Hey everyone! Req is an HTTP client for Elixir that I’ve been working on for quite some time. There is already a lot of HTTP clients out...
New
handnot2
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application. This library uses Erlang esaml to provide plug enabl...
New
woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
fuelen
Hi all! I want to present a small library which provides a mix task for generating an Entity-Relationship Diagram for Ecto schemas. You...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mudasobwa
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
sorenone
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New
akoutmos
@hugobarauna, Dr. Dimitrios Koutmos (my brother) and I (Alex Koutmos) have been hard at work on writing a book on how you can use Elixir ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews