diff options
| -rw-r--r-- | doc/misc/ert.texi | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi index 4617453d06d..35128fcfeb0 100644 --- a/doc/misc/ert.texi +++ b/doc/misc/ert.texi | |||
| @@ -535,6 +535,7 @@ help ERT find the defining call to the macro by putting the property | |||
| 535 | * Useful Techniques:: Some examples. | 535 | * Useful Techniques:: Some examples. |
| 536 | * erts files:: Files containing many buffer tests. | 536 | * erts files:: Files containing many buffer tests. |
| 537 | * Syntax Highlighting Tests:: Tests for face assignment. | 537 | * Syntax Highlighting Tests:: Tests for face assignment. |
| 538 | * Helper Functions:: Various helper functions. | ||
| 538 | @end menu | 539 | @end menu |
| 539 | 540 | ||
| 540 | 541 | ||
| @@ -950,6 +951,7 @@ non-@code{nil} value, the test will be skipped. | |||
| 950 | If you need to use the literal line single line @samp{=-=} in a test | 951 | If you need to use the literal line single line @samp{=-=} in a test |
| 951 | section, you can quote it with a @samp{\} character. | 952 | section, you can quote it with a @samp{\} character. |
| 952 | 953 | ||
| 954 | |||
| 953 | @node Syntax Highlighting Tests | 955 | @node Syntax Highlighting Tests |
| 954 | @section Syntax Highlighting Tests | 956 | @section Syntax Highlighting Tests |
| 955 | 957 | ||
| @@ -1082,6 +1084,304 @@ The @code{ert-font-lock-deftest} and @code{ert-font-lock-deftest-file} | |||
| 1082 | macros accept the same keyword parameters as @code{ert-deftest} i.e., | 1084 | macros accept the same keyword parameters as @code{ert-deftest} i.e., |
| 1083 | @code{:tag} and @code{:expected-result}. | 1085 | @code{:tag} and @code{:expected-result}. |
| 1084 | 1086 | ||
| 1087 | |||
| 1088 | @node Helper Functions | ||
| 1089 | @section Various Helper Functions | ||
| 1090 | |||
| 1091 | The package @file{ert-x.el} contains some macros and functions useful | ||
| 1092 | for writing tests. | ||
| 1093 | |||
| 1094 | @subsection Test Buffers | ||
| 1095 | |||
| 1096 | @defmac ert-with-test-buffer ((&key ((:name name-form))) &body body) | ||
| 1097 | This macro creates a test buffer and runs @var{body} in that buffer. If | ||
| 1098 | @var{body} finishes successfully, the test buffer is killed; if there is | ||
| 1099 | an error, the test buffer is kept around for further inspection. | ||
| 1100 | |||
| 1101 | The test buffer name is derived from the name of the ERT test and the | ||
| 1102 | result of @var{NAME-FORM}. Example: | ||
| 1103 | |||
| 1104 | @lisp | ||
| 1105 | (ert-deftest backtrace-tests--variables () | ||
| 1106 | (ert-with-test-buffer (:name "variables") | ||
| 1107 | @dots{})) | ||
| 1108 | @end lisp | ||
| 1109 | |||
| 1110 | This uses the test buffer @t{"*Test buffer (backtrace-tests--variables): | ||
| 1111 | variables*"}. | ||
| 1112 | @end defmac | ||
| 1113 | |||
| 1114 | @defmac ert-with-buffer-selected (buffer &body body) | ||
| 1115 | The macro display a buffer in a temporary selected window and runs | ||
| 1116 | @var{body}. If @var{buffer} is @code{nil}, the current buffer is used. | ||
| 1117 | |||
| 1118 | The buffer is made the current buffer, and the temporary window | ||
| 1119 | becomes the @code{selected-window}, before @var{body} is evaluated. The | ||
| 1120 | modification hooks @code{before-change-functions} and | ||
| 1121 | @code{after-change-functions} are not inhibited during the evaluation | ||
| 1122 | of @var{body}, which makes it easier to use @code{execute-kbd-macro} to | ||
| 1123 | simulate user interaction. The window configuration is restored | ||
| 1124 | before returning, even if @var{body} exits nonlocally. The return | ||
| 1125 | value is the last form in @var{body}. Example: | ||
| 1126 | |||
| 1127 | @lisp | ||
| 1128 | (with-temp-buffer | ||
| 1129 | (ert-with-buffer-selected nil | ||
| 1130 | @dots{})) | ||
| 1131 | @end lisp | ||
| 1132 | |||
| 1133 | This displays a temporary buffer @t{" *temp*-739785"*}. | ||
| 1134 | @end defmac | ||
| 1135 | |||
| 1136 | @defmac ert-with-test-buffer-selected ((&key name) &body body) | ||
| 1137 | This creates a test buffer, switches to it, and runs @var{body}. | ||
| 1138 | |||
| 1139 | It combines @code{ert-with-test-buffer} and | ||
| 1140 | @code{ert-with-buffer-selected}. The return value is the last form in | ||
| 1141 | @var{body}. Example: | ||
| 1142 | |||
| 1143 | @lisp | ||
| 1144 | (ert-deftest whitespace-tests--global () | ||
| 1145 | (ert-with-test-buffer-selected (:name "global") | ||
| 1146 | @dots{})) | ||
| 1147 | @end lisp | ||
| 1148 | |||
| 1149 | This displays the test buffer @t{"*Test buffer | ||
| 1150 | (whitespace-tests--global): global*"}. | ||
| 1151 | @end defmac | ||
| 1152 | |||
| 1153 | @defun ert-kill-all-test-buffers () | ||
| 1154 | It kills all test buffers that are still live. | ||
| 1155 | @end defun | ||
| 1156 | |||
| 1157 | @defmac ert-with-buffer-renamed ((buffer-name-form) &body body) | ||
| 1158 | This macro protects the buffer @var{buffer-name} from side-effects and | ||
| 1159 | runs @var{body}. It renames the buffer @var{buffer-name} to a new | ||
| 1160 | temporary name, creates a new buffer named @var{buffer-name}, executes | ||
| 1161 | @var{body}, kills the new buffer, and renames the original buffer back | ||
| 1162 | to @var{buffer-name}. | ||
| 1163 | |||
| 1164 | This is useful if @var{body} has undesirable side-effects on an Emacs | ||
| 1165 | buffer with a fixed name such as @t{"*Messages*"}. Example: | ||
| 1166 | |||
| 1167 | @lisp | ||
| 1168 | (ert-with-buffer-renamed ("*Messages*") @dots{}) | ||
| 1169 | @end lisp | ||
| 1170 | @end defmac | ||
| 1171 | |||
| 1172 | @defmac ert-with-message-capture (var &rest body) | ||
| 1173 | This macro executes @var{body} while collecting messages in @var{var}. | ||
| 1174 | It captures messages issued by Lisp code and concatenates them separated | ||
| 1175 | by newlines into one string. This includes messages written by | ||
| 1176 | @code{message} as well as objects printed by @code{print}, @code{prin1} | ||
| 1177 | and @code{princ} to the echo area. Messages issued from C code using | ||
| 1178 | the above mentioned functions will not be captured. | ||
| 1179 | |||
| 1180 | This is useful for separating the issuance of messages by the code under | ||
| 1181 | test from the behavior of the @t{"*Messages*"} buffer. Example: | ||
| 1182 | |||
| 1183 | @lisp | ||
| 1184 | (ert-with-message-capture captured-messages @dots{}) | ||
| 1185 | @end lisp | ||
| 1186 | @end defmac | ||
| 1187 | |||
| 1188 | @subsection Test Directories and Files | ||
| 1189 | |||
| 1190 | @defmac ert-resource-directory () | ||
| 1191 | It returns the absolute file name of the resource (test data) directory. | ||
| 1192 | The path to the resource directory is the @file{resources} directory in | ||
| 1193 | the same directory as the test file this is called from. | ||
| 1194 | |||
| 1195 | If that directory doesn't exist, find a directory based on the test file | ||
| 1196 | name. If the file is named @file{foo-tests.el}, it returns the absolute | ||
| 1197 | file name for @file{foo-resources}. Example: | ||
| 1198 | |||
| 1199 | @lisp | ||
| 1200 | (let ((dir (ert-resource-directory))) | ||
| 1201 | @dots{}) | ||
| 1202 | @end lisp | ||
| 1203 | |||
| 1204 | In order to use a different resource directory naming scheme, the | ||
| 1205 | variable @code{ert-resource-directory-format} can be changed. Before | ||
| 1206 | formatting, the file name will be trimmed using @code{string-trim} with | ||
| 1207 | arguments @code{ert-resource-directory-trim-left-regexp} and | ||
| 1208 | @code{ert-resource-directory-trim-right-regexp}. Example: | ||
| 1209 | |||
| 1210 | @lisp | ||
| 1211 | (let* ((ert-resource-directory-format "test-resources-%s/") | ||
| 1212 | (ert-resource-directory-trim-left-regexp ".*/") | ||
| 1213 | (dir (ert-resource-directory))) | ||
| 1214 | @dots{}) | ||
| 1215 | @end lisp | ||
| 1216 | |||
| 1217 | uses the absolute file name for @file{test-resources-foo}. | ||
| 1218 | @end defmac | ||
| 1219 | |||
| 1220 | @defmac ert-resource-file (file) | ||
| 1221 | It returns the absolute file name of resource (test data) file named | ||
| 1222 | @var{file}, which should be a relative file name. A resource file is | ||
| 1223 | defined as any file placed in the resource directory as returned by | ||
| 1224 | @code{ert-resource-directory}. Example: | ||
| 1225 | |||
| 1226 | @lisp | ||
| 1227 | (let ((file (ert-resource-file "bar/baz"))) | ||
| 1228 | @dots{}) | ||
| 1229 | @end lisp | ||
| 1230 | |||
| 1231 | It returns the absolute file name for @file{foo-resources/bar/baz} when | ||
| 1232 | called in file @file{foo-tests.el}. | ||
| 1233 | @end defmac | ||
| 1234 | |||
| 1235 | @defmac ert-with-temp-file (name &rest body) | ||
| 1236 | This macro binds @var{name} to the name of a new temporary file and evaluates @var{body}. | ||
| 1237 | It deletes the temporary file after @var{body} exits normally or | ||
| 1238 | non-locally. @var{name} will be bound to the file name of the temporary | ||
| 1239 | file. | ||
| 1240 | |||
| 1241 | The following keyword arguments are supported: | ||
| 1242 | |||
| 1243 | @table @code | ||
| 1244 | @item :prefix @var{string} | ||
| 1245 | If non-nil, pass @var{string} to @code{make-temp-file} as | ||
| 1246 | the @var{prefix} argument. Otherwise, use the value of | ||
| 1247 | @code{ert-temp-file-prefix}. | ||
| 1248 | |||
| 1249 | @item :suffix @var{string} | ||
| 1250 | If non-nil, pass @var{string} to @code{make-temp-file} as the | ||
| 1251 | @var{suffix} argument. Otherwise, use the value of | ||
| 1252 | @code{ert-temp-file-suffix}; if the value of that variable is nil, | ||
| 1253 | generate a suffix based on the name of the file that | ||
| 1254 | @code{ert-with-temp-file} is called from. | ||
| 1255 | |||
| 1256 | @item :text @var{string} | ||
| 1257 | If non-nil, pass @var{string} to @code{make-temp-file} as the @var{text} argument. | ||
| 1258 | |||
| 1259 | @item :buffer @var{symbol} | ||
| 1260 | Open the temporary file using @code{find-file-noselect} and bind | ||
| 1261 | @var{symbol} to the buffer. Kill the buffer after @var{body} exits | ||
| 1262 | normally or non-locally. | ||
| 1263 | |||
| 1264 | @item :coding @var{coding} | ||
| 1265 | If non-nil, bind @code{coding-system-for-write} to @var{coding} when | ||
| 1266 | executing @var{body}. This is handy when @var{string} includes | ||
| 1267 | non-ASCII characters or the temporary file must have a specific encoding | ||
| 1268 | or end-of-line format. | ||
| 1269 | @end table | ||
| 1270 | |||
| 1271 | Example: | ||
| 1272 | |||
| 1273 | @lisp | ||
| 1274 | (ert-with-temp-file temp-file | ||
| 1275 | :prefix "foo" | ||
| 1276 | :suffix "bar" | ||
| 1277 | :text "foobar3" | ||
| 1278 | @dots{}) | ||
| 1279 | @end lisp | ||
| 1280 | @end defmac | ||
| 1281 | |||
| 1282 | @defmac ert-with-temp-directory (name &rest body) | ||
| 1283 | This macro binds @var{name} to the name of a new temporary directory and | ||
| 1284 | evaluates @var{body}. It deletes the temporary directory after | ||
| 1285 | @var{body} exits normally or non-locally. | ||
| 1286 | |||
| 1287 | @var{name} is bound to the directory name, not the directory file name. | ||
| 1288 | (In other words, it will end with the directory delimiter; on Unix-like | ||
| 1289 | systems, it will end with @t{"/"}.) | ||
| 1290 | |||
| 1291 | The same keyword arguments are supported as in | ||
| 1292 | @code{ert-with-temp-file}, except for @code{:text}. Example: | ||
| 1293 | |||
| 1294 | @lisp | ||
| 1295 | (ert-with-temp-directory temp-dir | ||
| 1296 | :prefix "foo" | ||
| 1297 | :suffix "bar" | ||
| 1298 | @dots{}) | ||
| 1299 | @end lisp | ||
| 1300 | @end defmac | ||
| 1301 | |||
| 1302 | @defvar ert-remote-temporary-file-directory | ||
| 1303 | This variable provides the name of a temporary directory for remote file | ||
| 1304 | tests. Per default, a mock-up connection method is used (this might not | ||
| 1305 | be possible when running on MS Windows). The default value is | ||
| 1306 | @t{"/mock::/tmp/"}. | ||
| 1307 | |||
| 1308 | If a real remote connection shall be used for testing, this can be | ||
| 1309 | overwritten by the environment variable | ||
| 1310 | @env{REMOTE_TEMPORARY_FILE_DIRECTORY}. Example | ||
| 1311 | |||
| 1312 | @example | ||
| 1313 | # env REMOTE_TEMPORARY_FILE_DIRECTORY=/ssh:host:/tmp make @dots{} | ||
| 1314 | @end example | ||
| 1315 | @end defvar | ||
| 1316 | |||
| 1317 | @subsection Miscellaneous Utilities | ||
| 1318 | |||
| 1319 | @defun ert-simulate-command (command) | ||
| 1320 | Simulate calling @var{command} the way the Emacs command loop would call | ||
| 1321 | it. It runs hooks like @code{pre-command-hook} and | ||
| 1322 | @code{post-command-hook}, and sets variables like @code{this-command} | ||
| 1323 | and @code{last-command}. | ||
| 1324 | |||
| 1325 | @var{command} should be a list where the @code{car} is the command | ||
| 1326 | symbol and the rest are arguments to the command. Example: | ||
| 1327 | |||
| 1328 | @lisp | ||
| 1329 | (ert-simulate-command '(find-file "project/foo.c")) | ||
| 1330 | @end lisp | ||
| 1331 | |||
| 1332 | @strong{Note}: Since the command is not called by | ||
| 1333 | @code{call-interactively}, a test for @code{(called-interactively-p 'interactive)} | ||
| 1334 | in the command will fail. | ||
| 1335 | @end defun | ||
| 1336 | |||
| 1337 | @defmac ert-simulate-keys (keys &rest body) | ||
| 1338 | This executes @var{body} with @var{keys} as pseudo-interactive input. | ||
| 1339 | @var{keys} is either a string, a list of characters, or a character | ||
| 1340 | vector. Examples: | ||
| 1341 | |||
| 1342 | @lisp | ||
| 1343 | (ert-simulate-keys '(?n ?\C-m) @dots{}) | ||
| 1344 | (ert-simulate-keys "\r\r\r\ry\r" @dots{}) | ||
| 1345 | (ert-simulate-keys (kbd "#fake C-m C-a C-k C-m") @dots{}) | ||
| 1346 | (ert-simulate-keys [?b ?2 return] @dots{}) | ||
| 1347 | @end lisp | ||
| 1348 | @end defmac | ||
| 1349 | |||
| 1350 | @defun ert-filter-string (s &rest regexps) | ||
| 1351 | This function returns a copy of string @var{s} with all matches of | ||
| 1352 | @var{regexps} removed. Elements of @var{regexps} may also be | ||
| 1353 | two-element lists @code{(@var{regexp} @var{subexp})}, where @var{subexp} | ||
| 1354 | is the number of a subexpression in @var{regexp}. In that case, only | ||
| 1355 | that subexpression will be removed rather than the entire match. | ||
| 1356 | Example: | ||
| 1357 | |||
| 1358 | @lisp | ||
| 1359 | (with-current-buffer @dots{} | ||
| 1360 | (ert-filter-string (buffer-string) | ||
| 1361 | '("Started at:\\(.*\\)$" 1) | ||
| 1362 | '("Finished at:\\(.*\\)$" 1)) | ||
| 1363 | @dots{}) | ||
| 1364 | @end lisp | ||
| 1365 | @end defun | ||
| 1366 | |||
| 1367 | @defun ert-propertized-string (&rest args) | ||
| 1368 | This function returns a string with properties as specified by @var{args}. | ||
| 1369 | |||
| 1370 | @var{args} is a list of strings and plists. The strings in @var{args} | ||
| 1371 | are concatenated to produce an output string. In the output string, | ||
| 1372 | each string from @var{args} will be have the preceding plist as its | ||
| 1373 | property list, or no properties if there is no plist before it. | ||
| 1374 | Example: | ||
| 1375 | |||
| 1376 | @lisp | ||
| 1377 | (ert-propertized-string "foo " '(face italic) "bar" " baz" nil " quux") | ||
| 1378 | @end lisp | ||
| 1379 | |||
| 1380 | This returns the string @t{"foo @i{bar baz} quux"} where the substring | ||
| 1381 | @t{"@i{bar baz}"} has a @code{face} property with the value @code{italic}. | ||
| 1382 | @end defun | ||
| 1383 | |||
| 1384 | |||
| 1085 | @node How to Debug Tests | 1385 | @node How to Debug Tests |
| 1086 | @chapter How to Debug Tests | 1386 | @chapter How to Debug Tests |
| 1087 | 1387 | ||