Skip to content

Commit d64a758

Browse files
committed
Rewrite example and test case to make it fit better with the rest of the
book
1 parent 0a57d5d commit d64a758

File tree

2 files changed

+95
-35
lines changed

2 files changed

+95
-35
lines changed

src/tutorial/testing.md

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -483,30 +483,90 @@ Adjust the program as needed.
483483

484484
</aside>
485485

486-
## Executing tests in a temporary directory
487-
488-
To fully control the behavior of your CLI app, you can use
489-
`assert_fs::TempDir::new()` to create a temporary directory.
490-
This is useful when you need to read and write
491-
multiple directories or files. You can also use it as the
492-
current working directory (CWD) when executing your CLI app,
493-
ensuring test results are consistent and don't interfere with
494-
other, unrelated files.
495-
496-
Temporary directories allow you to create multiple child
497-
directories and files within them, enabling more advanced
498-
test cases. Just like for single temporary files,
499-
all nested files and directories within temporary directories
500-
are also cleaned up after the test is completed.
486+
## Executing tests in temporary directories
487+
488+
In the last test, we created a temporary file and passed it as an
489+
_absolute file path_ to our program. While this is enough to verify
490+
our core functionality, how could we write a test to ensure our program
491+
also accepts _relative file paths_ like `sample.txt` as input?
492+
493+
The relative file path should be resolved based on the current working
494+
directory (CWD) where we execute our program, and this usually works fine
495+
in regular directories. However, when writing a test with temporary files,
496+
how do we know which directory where our test file was created?
497+
498+
One way to implement this test is by creating a temporary directory, and
499+
then setting it as the current working directory when executing our program.
500+
501+
Just like we created temporary files, we can use `assert_fs` to create
502+
temporary directories that are automatically deleted after the test is
503+
finished. To clearly show the effect of setting the current directory,
504+
and that our relative path `sample.txt` only can be resolved when we execute
505+
the program in the same directory as the file, we will create two nested
506+
temporary directories and a temporary file with the following structure:
507+
508+
```txt
509+
tmp_dir/
510+
child_dir/
511+
sample.txt
512+
```
513+
514+
We can describe the test for our program with the following assertions:
515+
516+
1. It **fails** to resolve the relative path `sample.txt` when executed
517+
with `tmp_dir` as the current working directory.
518+
2. It **succeeds** to resolve the relative path `sample.txt` when executed
519+
with `child_dir` as the current working directory.
520+
521+
To create the temporary directory and file structure we need for our test,
522+
we start by creating a temporary directory `tmp_dir` by calling
523+
[`assert_fs::TempDir::new()`][TempDir]. Then we create a child directory within it
524+
called `child_dir`, in which we finally create the `sample.txt` file.
525+
526+
[TempDir]: https://docs.rs/assert_fs/latest/assert_fs/struct.TempDir.html#method.new
527+
528+
```rust,ignore
529+
{{#include testing/tests/cli.rs:32:37}}
530+
{{#include testing/tests/cli.rs:54:56}}
531+
```
532+
533+
For our first, failing assertion, we set the current working directory to
534+
`tmp_dir` by calling [`current_dir(&tmp_dir)`][current_dir]. This way, `sample.txt` resolves
535+
to `tmp_dir/sample.txt` which does not exist, making the program exit with an error.
536+
537+
[current_dir]: https://docs.rs/assert_cmd/latest/assert_cmd/cmd/struct.Command.html#method.current_dir
538+
539+
```rust,ignore
540+
{{#include testing/tests/cli.rs:32:33}}
541+
// ...
542+
543+
{{#include testing/tests/cli.rs:39:45}}
544+
{{#include testing/tests/cli.rs:54:56}}
545+
```
546+
547+
For our second, successful assertion, we instead call `current_dir(&child_dir)`.
548+
This makes the program successfully resolve `sample.txt` to
549+
`tmp_dir/child_dir/sample.txt` and print the expected result.
550+
551+
```rust,ignore
552+
{{#include testing/tests/cli.rs:32:33}}
553+
// ...
554+
555+
{{#include testing/tests/cli.rs:47:53}}
556+
{{#include testing/tests/cli.rs:54:56}}
557+
```
558+
559+
Putting it all together, the complete test case looks like this:
501560

502561
```rust,ignore
503562
{{#include testing/tests/cli.rs:32:56}}
504563
```
505564

506-
You now know the core features of the crates `assert_cmd`,
507-
`assert_fs` and `predicates` and are ready to start testing
508-
your own CLI apps. Feel free to check out their documentation
509-
to find more useful features.
565+
You now know the core features of the crates `assert_cmd`, `assert_fs` and
566+
`predicates` and are ready to test your own CLI apps in ways that ensure
567+
consistent test results and without interfering with other, unrelated files.
568+
You can learn about more useful features in these crates by exploring
569+
their documentation.
510570

511571
## What to test?
512572

src/tutorial/testing/tests/cli.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,27 @@ fn find_content_in_file() -> Result<(), Box<dyn std::error::Error>> {
3030
}
3131

3232
#[test]
33-
fn find_content_in_file_of_tmp_dir() -> Result<(), Box<dyn std::error::Error>> {
34-
let cwd = assert_fs::TempDir::new()?;
35-
36-
let child_dir = cwd.child("nested/child_dir");
37-
let child_file = child_dir.child("sample.txt");
38-
39-
child_file.write_str("The first\ntest file.\nLast line of first file.")?;
33+
fn find_content_with_cwd_in_tmp_dir() -> Result<(), Box<dyn std::error::Error>> {
34+
let tmp_dir = assert_fs::TempDir::new()?;
35+
let child_dir = tmp_dir.child("child_dir");
36+
let file = child_dir.child("sample.txt");
37+
file.write_str("A test\nActual content\nMore content\nAnother test")?;
4038

41-
// Files can be nested several levels within the temporary directory
42-
assert!(child_file.path().ends_with("nested/child_dir/sample.txt"));
39+
cargo_bin_cmd!("grrs")
40+
.current_dir(&tmp_dir)
41+
.arg("test")
42+
.arg("sample.txt")
43+
.assert()
44+
.failure()
45+
.stderr(predicate::str::contains("could not read file"));
4346

4447
cargo_bin_cmd!("grrs")
45-
// Execute in the temporary directory
46-
.current_dir(cwd.path())
47-
.arg("first")
48-
.arg(child_file.path())
48+
.current_dir(&child_dir)
49+
.arg("test")
50+
.arg("sample.txt")
4951
.assert()
5052
.success()
51-
.stdout(predicate::str::contains(
52-
"The first\nLast line of first file.",
53-
));
53+
.stdout(predicate::str::contains("A test\nAnother test"));
5454

5555
Ok(())
5656
}

0 commit comments

Comments
 (0)