Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Using assert_fs, predicates, and assert_cmd to integration test bins …
…that spawn subcommands How to integration test a cargo binary that calls out to `EDITOR` for modifications and asks the user for input. First we'll create a fake editor script to use instead of vim, etc. `tests/fake_editor.sh` is a one-liner. ```shell echo "testing" >> $1; ``` Then we'll write our test using `assert_cmd` to build up a `Command` that points to the `garden` binary in out `Cargo.toml`. We grab the fake editor path script using `std::env::current_dir()`, make sure the file exists (which means we've grabbed the right path), and spawn a new `Command` with the `EDITOR` variable set to the fake editor script. The equivalent call to our bin is ```shell EDITOR=path/to/fake-editor.sh garden write -t atitle ``` And the rust code to execute. ```rust fn test_write_with_title() { let mut cmd = Command::cargo_bin("garden").unwrap(); let fake_editor_path = std::env::current_dir() .expect("expect to be in a dir") .join("tests") .join("fake-editor.sh"); if !fake_editor_path.exists() { panic!( "fake editor shell script could not be found" ) } let assert = cmd .env("EDITOR", fake_editor_path.into_os_string()) .arg("write") .arg("-t") .arg("atitle") .write_stdin("N\n".as_bytes()) .assert(); assert.success(); } ``` Note that we're asserting that the command exited sucessfully, and that we're inputing `N\n` to the bin's stdin, which responds to a request for user input after the editor closes. Note that this doesn't actually test for the resulting file existence, and also that we're writing our files out directly into our default digital garden! We can solve this with `assert_fs` and `predicates`. We'll bring in both preludes (a prelude is a bunch of stuff the library author thinks will be useful to have around all the time) and create a new temporary directory. We'll use the `GARDEN_PATH` environment variable to pass the temporary directory in to the `garden` bin and that's it, we've added a temporary directory to our test. No more polluting the default garden! ```rust use assert_fs::prelude::*; use predicates::prelude::*; fn test_write_with_title() { let temp_dir = assert_fs::TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("garden").unwrap(); let fake_editor_path = std::env::current_dir() .expect("expect to be in a dir") .join("tests") .join("fake-editor.sh"); if !fake_editor_path.exists() { panic!( "fake editor shell script could not be found" ) } let assert = cmd .env("EDITOR", fake_editor_path.into_os_string()) .env("GARDEN_PATH", temp_dir.path()) .arg("write") .arg("-t") .arg("atitle") .write_stdin("N\n".as_bytes()) .assert(); assert.success(); temp_dir .child("atitle.md") .assert(predicate::path::exists()); } ``` Now that's enough, but we can also check to make sure the file we expect to exist actually exists. `temp_dir.child` gives us the possible file, and we can assert on that file with a test from `predicates` that tests to make sure the file exists. ```rust temp_dir .child("atitle.md") .assert(predicate::path::exists()); ```
- Loading branch information