1
1
defmodule ExUnit.DocTest do
2
- @ moduledoc """
2
+ @ moduledoc ~S """
3
3
Extract test cases from the documentation.
4
4
5
5
Doctests allow us to generate tests from code examples found
@@ -131,7 +131,7 @@ defmodule ExUnit.DocTest do
131
131
132
132
You can also showcase expressions raising an exception, for example:
133
133
134
- iex(1) > raise "some error"
134
+ iex> raise "some error"
135
135
** (RuntimeError) some error
136
136
137
137
Doctest will look for a line starting with `** (` and it will parse it
@@ -141,6 +141,19 @@ defmodule ExUnit.DocTest do
141
141
Therefore, it is possible to match on multiline messages as long as there
142
142
are no empty lines on the message itself.
143
143
144
+ Asserting on the full exception message might not be possible because it is
145
+ non-deterministic, or it might result in brittle tests if the exact message
146
+ changes and gets more detailed.
147
+ Since Elixir 1.19.0, doctests allow the use of an ellipsis (`...`) at the
148
+ end of messages:
149
+
150
+ iex> raise "some error in pid: #{inspect(self())}"
151
+ ** (RuntimeError) some error in pid: ...
152
+
153
+ iex> raise "some error in pid:\n#{inspect(self())}"
154
+ ** (RuntimeError) some error in pid:
155
+ ...
156
+
144
157
## When not to use doctest
145
158
146
159
In general, doctests are not recommended when your code examples contain
@@ -565,7 +578,7 @@ defmodule ExUnit.DocTest do
565
578
"Doctest failed: expected exception #{ inspect ( exception ) } but got " <>
566
579
"#{ inspect ( actual_exception ) } with message #{ inspect ( actual_message ) } "
567
580
568
- actual_message != message ->
581
+ not error_message_matches? ( actual_message , message ) ->
569
582
"Doctest failed: wrong message for #{ inspect ( actual_exception ) } \n " <>
570
583
"expected:\n " <>
571
584
" #{ inspect ( message ) } \n " <>
@@ -588,6 +601,17 @@ defmodule ExUnit.DocTest do
588
601
end
589
602
end
590
603
604
+ defp error_message_matches? ( actual , expected ) when actual == expected , do: true
605
+
606
+ defp error_message_matches? ( actual , expected ) do
607
+ if String . ends_with? ( expected , "..." ) do
608
+ ellipsis_removed = binary_slice ( expected , 0 .. - 4 // 1 )
609
+ String . starts_with? ( actual , ellipsis_removed )
610
+ else
611
+ false
612
+ end
613
+ end
614
+
591
615
defp test_import ( _mod , false ) , do: [ ]
592
616
defp test_import ( mod , _ ) , do: [ quote ( do: import ( unquote ( mod ) ) ) ]
593
617
0 commit comments