Does a describe block influence ExUnit test cases?

I’m currently in the middle of refactoring some of our API tests and changed our describe blocks from

describe "list contacts" do
end

describe "upsert contacts" do
end

to

describe "GET /contacts" do
end

describe "PUT /contacts" do
end

And suddenly one test is failing with a weird validation error, but what’s even weirder is the fact that when I change for example one of the descriptions to GET /contacts2, everything works again. Therefore the question: Does a describe block some influence ExUnit test cases? For example by setting a not so random seed?

Also weird… changing PUT to POT fixes it too… what is going on?

I don’t think so. we can change the description anytime in test cases without any influence on the test.
can you plz showcase your error? @ream88
OR
are you using any @moduletag :external, or any @describetag :endpoint in your test case. Kindly confirm that.

Nope not using this tags. I’m currently suspecting a setup block which creates a current user to work with prior of all tags to be the source of the problem. Because I’m getting a user related validation problem, and also adding some IO.inspect calls to the user creation process logs an already existing user when there should not be any. Looks like this setup block is called twice when using both GET and PUT in my descriptions.

where are you using the setup block? I mean are you using it on the top or under the described block?

On top

Note: describe blocks cannot be nested. Instead of relying on hierarchy for composition, you should build on top of named setups. For example:

defmodule UserManagementTest do
  use ExUnit.Case, async: true

  describe "when user is logged in and is an admin" do
    setup [:log_user_in, :set_type_to_admin]

    test ...
  end

  describe "when user is logged in and is a manager" do
    setup [:log_user_in, :set_type_to_manager]

    test ...
  end

  defp log_user_in(context) do
    # ...
  end
end

By forbidding hierarchies in favor of named setups, it is straightforward for you to glance at each described block and know exactly the setup steps involved.

2 Likes

Ok, found the problem… it really looks like the describe text influences the seed that :rand uses, and for whatever reason this broke my tests… We use the following function to generate random phone numbers for our user fixtures, and using PUT /contacts and GET /contacts simultaneously influenced it to generate twice the same phone number:

def random_string(charset, length) do
  for _ <- 1..length, into: "", do: <<Enum.random(charset)>>
end

Using System.unique_integer/1 fixed my problem not ever having the same phone number twice for different users.

1 Like

You can also use :crypto.strong_rand_bytes and build on top of that.