arcanemachine

arcanemachine

What test tags do you use in your Elixir projects?

I’m writing some tests and I want to build a “common language” for writing test tags. I’m using this post to document my findings as I learn about the built-in test tags, while also seeing what custom tags the Elixir community uses in their tests.

Built-In Tags

ExUnit has quite a few built-in tags:

  • @tag :skip or @tag skip: "some reason to skip" - Tests that should be skipped (unless run with --only skip). Support for this tag is built-in to ExUnit.

Custom Tags

Here are some of the custom tags I use or have encountered:

  • @tag :slow - Tests that take a long time to run.

  • @tag :external - Tests that call an external service or API

  • @tag :mock - Indicates that a test uses a mock to pass. (This tag can be paired with another test that uses @tag :external so there is an option to run a “live” version of the mocked test.)

  • @tag :fixme - A temporary placeholder tag that I use when I’m working on one specific test and only want it to run.


What test tags do you commonly use? Post them here so we can all speak the same language!

Other @tag tips, tricks, and hacks are welcome here too. :slight_smile:

Most Liked

RudManusachi

RudManusachi

Other than what’s written in docs I’d like to point to the trick that allows to “generate” very similar tests from a matrix..

setup %{role: role, status: status} do
  %{user: insert_user(role, status)}
end

for role <- [:admin, :guest],
    {status, color} <- [{:online, "green"}, {:offline, "gray"}, {:away, "yello"}] do
  @tag role: role, status: status, color: color
  test "#{role} renders #{color} badge when #{status}", tags do
    %{role: role, status: status, color: color} = tags
    # render and  assert on role, status, color
  end
end

Though, arguably these tests are now become a bit less clear.. as instead of

assert user.status == :online
assert user.role == :admin

now we would have something like

assert user.status == status
assert user.role == role
PragTob

PragTob

You don’t need tags for that though - you can use any custom module attribute or use escaping to embed the values in the test.


As for the original quesiton, benchee has a few, mostly dealing with different CI platforms/systems to run on:

  • needs_fast_function_repetition - as that is not triggered on Linux, they essentially they are skipped when running tests on Linux
  • performance - similar, but only run on Linux as the other CI’s are too slow
  • millisecond_resolution_clock - property of the system
  • another one that deals with whether we can run our memory measurement tests

For the interested: benchee/test/test_helper.exs at main · bencheeorg/benchee · GitHub

One that I don’t have yet but wanna built, benchee needs to retry things in some circumstances due to its nature. I’d like to move that from a function call to a tag.

sbuttgereit

sbuttgereit

I’m using (mostly) @moduletag rather than individual @tag attributes; the tests are organized to facilitate that sort of general handling.

My use is pretty simplistic/naïve. Most of the Elixir testing I have works with Elixir applications which can be thought of a libraries and the testing reflect this assumption. I have three values into which my tests are categorized:

  • :unit

    Unit tests. These tests are exercising implementations as expressed by module public functions; while these functions are public in the sense that they use def in their definitions, they are in practice considered internal or private API. These test run asynchronously and if they involve persistent data (i.e. a database) then they have test data either seeded or generated specifically so that they don’t depend on/interfere with other tests that might be running.

  • :integration

    Integration tests. This testing is focused on two goals: testing the Public API of each Elixir project and testing end-to-end, business process/data flows. These tests are synchronous and are run with a set random seed (of 0) so that ordering is deterministic. It is expected that data created or manipulated in earlier tests are to be used in later tests; any test related data seeding or pre-test data generation either is non-existent or there to populate data for dependencies of the project being tested. We really want to see that data being created in one process can be used in other downstream processes.

  • :doctest

    This is exactly what it sounds like, it just tests documentation examples. In most respects the examples are expected to behave like the :unit tests described above, except that only the “Public API” functions rather than internally facing functions are tested; this is because those are the only functions which have documented examples.

All three of these test modes are run during CI and need to pass prior to merging into the release branch (and yes, this project is release oriented, not CD oriented).

Naturally, “unit testing” and “integration testing” are terms which are a bit loaded and tend to mean different things depending on who you’re speaking with. In this case, don’t read too much into those terms… I’m not thinking of any specific formalism beyond what is described above. While there are many faults that can be found in our testing strategy, and someday more rigor may be required, but for now this is good enough.

Where Next?

Popular in Discussions Top

blackode
Elixir Upgrading is so Simple in Ubuntu and It worked for me Ubuntu 16.04 git clone https://github.com/elixir-lang/elixir.git cd elixir...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
Fl4m3Ph03n1x
Background A few days ago I was listening to The future of Elixir from Elixir Talks, with Dave Thomas (@pragdave ) and Brian Mitchell. I...
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
sashaafm
Piggy backing a bit on @dvcrn topic BEAM optimization for functions with static return type?, I’ve been trying to understand in a deeper ...
New
mmmrrr
Just saw that dhh announced https://hotwire.dev/ Is it just me or is this essentially live view? :smiley: Although I like the “iFrame-e...
New
praveenperera
How We Replaced React with Phoenix By: Thought Bot
New
New
Owens
Hello all, I am developing a new mobile app with Flutter frontend and Phoenix backend. The mobile app has real-time task management and c...
New
paulanthonywilson
I like Umbrella projects and pretty much always use them for personal Elixir stuff, especially Nerves things. But I don’t think this is ...
New

Other popular topics Top

malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
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
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36128 110
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47930 226
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

We're in Beta

About us Mission Statement