Proposal: `def assert_raise(exception, error_code, function) when is_atom(error_code)`

29 views
Skip to first unread message

Kevin Johnson

unread,
Dec 27, 2019, 6:59:34 PM12/27/19
to elixir-lang-core
As mentioned in the documentation, `assert_raise/3` in all its glory allows us to supply a `message` as a `String` or even as a `Regex`.

I personally have a preference to abstract away from specific message content in my tests as tests should not fail on account 
of an update to the grammar/phrasal of a given error message. 

To illustrate with a practical example, instead of writing a test like this:
    test "Required presence `Feature`-token" do
      assert_raise(SyntaxError, "Missing `Feature`-token", fn ->
        """
        #language:en
        """
        |> parse
      end)
    end

One could instead abstract away as follows:
    test "Required presence `Feature`-token" do
      assert_raise(SyntaxError, :missing_feature_token, fn ->
        """
        #language:en
        """
        |> parse
      end)
    end

That one `error_code` `:missing_feature_token` essentially summarizes the entire error message I may wish to benevolently display to the end-user-in-agony
which may be a short phrase or even a concise paragraph. Whatever may be, none of that prose needs to leak inside the dark corners of my test suite and an 'error code'
seems to be very helpful to achieve this objective.

My suggestion, if it deems your approval, would require:
  1. Introduction of `error_code`(or whatever is semantically more sane) inside the relevant defexception
  2. Modification of def assert_raise
Above, I have volunteered my suggestion in the context of a practical need which happens to be fulfilled by resorting to an `error_code` as an `atom`.
I have a limited imagination, so I hope that others can help explore/share better alternatives.


Kevin Johnson

unread,
Jan 15, 2020, 11:37:02 PM1/15/20
to elixir-lang-core
Any perspectives on this proposal?

Fernando Tapia Rico

unread,
Jan 20, 2020, 2:20:52 AM1/20/20
to elixir-lang-core
Hi Kevin,

Thanks for your proposal!

You can include any additional fields when defining exceptions, for example:

defmodule MyError do
 
defexception [message: "Ups!", code: :unknown]
end

and then give values to those additional fields in raise:

raise MyError, code: :my_error_code

 assert_raise returns the rescued exception, so you can assert on any field after that:

error = assert_raise MyError, fn ->
 raise MyError, code: :my_error_code
end)

assert error.code == :my_error_code

 Would that work for you? :)

Kevin Johnson

unread,
Jan 20, 2020, 2:25:42 PM1/20/20
to elixir-l...@googlegroups.com
Hi Fernando!

Thank you for the suggestion. I did not realize it was possible to `error = assert_raise MyError, fn`, so that workaround would certainly be plausible!

In the meanwhile, I wrote a small macro that does what I want it to do, so I am certainly not blocked.

However, I still feel that first class support of this would be in spirit of what `assert_raise/3` is for.
Reply all
Reply to author
Forward
0 new messages