diff --git a/file.c b/file.c
index cfcb4954b1..e5bca9c809 100644
--- a/file.c
+++ b/file.c
@@ -5329,60 +5329,83 @@ test_check(int n, int argc, VALUE *argv)
#define CHECK(n) test_check((n), argc, argv)
/*
+ * :markup: markdown
+ *
* call-seq:
- * test(cmd, file1 [, file2] ) -> obj
+ * test(char, path0, path1 = nil) -> object
*
- * Uses the character +cmd+ to perform various tests on +file1+ (first
- * table below) or on +file1+ and +file2+ (second table).
+ * Performs a test on one or both of the filesystem entities at the given paths
+ * `path0` and `path1`:
*
- * File tests on a single file:
+ * - Each path `path0` or `path1` points to a file, directory, device, pipe, etc.
+ * - Character `char` selects a specific test.
*
- * Cmd Returns Meaning
- * "A" | Time | Last access time for file1
- * "b" | boolean | True if file1 is a block device
- * "c" | boolean | True if file1 is a character device
- * "C" | Time | Last change time for file1
- * "d" | boolean | True if file1 exists and is a directory
- * "e" | boolean | True if file1 exists
- * "f" | boolean | True if file1 exists and is a regular file
- * "g" | boolean | True if file1 has the setgid bit set
- * "G" | boolean | True if file1 exists and has a group
- * | | ownership equal to the caller's group
- * "k" | boolean | True if file1 exists and has the sticky bit set
- * "l" | boolean | True if file1 exists and is a symbolic link
- * "M" | Time | Last modification time for file1
- * "o" | boolean | True if file1 exists and is owned by
- * | | the caller's effective uid
- * "O" | boolean | True if file1 exists and is owned by
- * | | the caller's real uid
- * "p" | boolean | True if file1 exists and is a fifo
- * "r" | boolean | True if file1 is readable by the effective
- * | | uid/gid of the caller
- * "R" | boolean | True if file is readable by the real
- * | | uid/gid of the caller
- * "s" | int/nil | If file1 has nonzero size, return the size,
- * | | otherwise return nil
- * "S" | boolean | True if file1 exists and is a socket
- * "u" | boolean | True if file1 has the setuid bit set
- * "w" | boolean | True if file1 exists and is writable by
- * | | the effective uid/gid
- * "W" | boolean | True if file1 exists and is writable by
- * | | the real uid/gid
- * "x" | boolean | True if file1 exists and is executable by
- * | | the effective uid/gid
- * "X" | boolean | True if file1 exists and is executable by
- * | | the real uid/gid
- * "z" | boolean | True if file1 exists and has a zero length
+ * The tests:
*
- * Tests that take two files:
+ * - Each of these tests operates only on the entity at `path0`,
+ * and returns `true` or `false`;
+ * for a non-existent entity, returns `false` (does not raise exception):
+ *
+ * | Character | Test |
+ * |:------------:|:--------------------------------------------------------------------------|
+ * | 'b' | Whether the entity is a block device. |
+ * | 'c' | Whether the entity is a character device. |
+ * | 'd' | Whether the entity is a directory. |
+ * | 'e' | Whether the entity is an existing entity. |
+ * | 'f' | Whether the entity is an existing regular file. |
+ * | 'g' | Whether the entity's setgid bit is set. |
+ * | 'G' | Whether the entity's group ownership is equal to the caller's. |
+ * | 'k' | Whether the entity's sticky bit is set. |
+ * | 'l' | Whether the entity is a symbolic link. |
+ * | 'o' | Whether the entity is owned by the caller's effective uid. |
+ * | 'O' | Like 'o', but uses the real uid (not the effective uid). |
+ * | 'p' | Whether the entity is a FIFO device (named pipe). |
+ * | 'r' | Whether the entity is readable by the caller's effecive uid/gid. |
+ * | 'R' | Like 'r', but uses the real uid/gid (not the effective uid/gid). |
+ * | 'S' | Whether the entity is a socket. |
+ * | 'u' | Whether the entity's setuid bit is set. |
+ * | 'w' | Whether the entity is writable by the caller's effective uid/gid. |
+ * | 'W' | Like 'w', but uses the real uid/gid (not the effective uid/gid). |
+ * | 'x' | Whether the entity is executable by the caller's effective uid/gid. |
+ * | 'X' | Like 'x', but uses the real uid/gid (not the effecive uid/git). |
+ * | 'z' | Whether the entity exists and is of length zero. |
+ *
+ * - This test operates only on the entity at `path0`,
+ * and returns an integer size or +nil+:
+ *
+ * | Character | Test |
+ * |:------------:|:---------------------------------------------------------------------------------------------|
+ * | 's' | Returns positive integer size if the entity exists and has non-zero length, +nil+ otherwise. |
+ *
+ * - Each of these tests operates only on the entity at `path0`,
+ * and returns a Time object;
+ * raises an exception if the entity does not exist:
+ *
+ * | Character | Test |
+ * |:------------:|:---------------------------------------|
+ * | 'A' | Last access time for the entity. |
+ * | 'C' | Last change time for the entity. |
+ * | 'M' | Last modification time for the entity. |
+ *
+ * - Each of these tests operates on the modification time (`mtime`)
+ * of each of the entities at `path0` and `path1`,
+ * and returns a `true` or `false`;
+ * returns `false` if either entity does not exist:
+ *
+ * | Character | Test |
+ * |:------------:|:----------------------------------------------------------------|
+ * | '<' | Whether the `mtime` at `path0` is less than that at `path1`. |
+ * | '=' | Whether the `mtime` at `path0` is equal to that at `path1`. |
+ * | '>' | Whether the `mtime` at `path0` is greater than that at `path1`. |
+ *
+ * - This test operates on the content of each of the entities at `path0` and `path1`,
+ * and returns a `true` or `false`;
+ * returns `false` if either entity does not exist:
+ *
+ * | Character | Test |
+ * |:------------:|:----------------------------------------------|
+ * | '-' | Whether the entities exist and are identical. |
*
- * "-" | boolean | True if file1 and file2 are identical
- * "=" | boolean | True if the modification times of file1
- * | | and file2 are equal
- * "<" | boolean | True if the modification time of file1
- * | | is prior to that of file2
- * ">" | boolean | True if the modification time of file1
- * | | is after that of file2
*/
static VALUE