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 :skipor@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 :externalso 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. ![]()
Most Liked
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
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 Linuxperformance- similar, but only run on Linux as the other CI’s are too slowmillisecond_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
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:
-
:unitUnit tests. These tests are exercising implementations as expressed by module public functions; while these functions are public in the sense that they use
defin 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. -
:integrationIntegration 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.
-
:doctestThis is exactly what it sounds like, it just tests documentation examples. In most respects the examples are expected to behave like the
:unittests 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.
Popular in Discussions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









