From 57245dafe0c0b5ce2dc2d7d1aa1648c51788e351 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 11 Sep 2017 20:40:59 -0600 Subject: [PATCH 1/4] Support more than one output assertion BREAKING CHANGE: Setting a new output assertion will not overwrite the previous one. --- src/assert.rs | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/assert.rs b/src/assert.rs index 4a70290..0a78f5c 100644 --- a/src/assert.rs +++ b/src/assert.rs @@ -1,6 +1,7 @@ use std::default; use std::process::Command; use std::path::PathBuf; +use std::vec::Vec; use errors::*; use output::{OutputAssertion, StdErr, StdOut}; @@ -12,8 +13,8 @@ pub struct Assert { current_dir: Option, expect_success: Option, expect_exit_code: Option, - expect_stdout: Option>, - expect_stderr: Option>, + expect_stdout: Vec>, + expect_stderr: Vec>, } impl default::Default for Assert { @@ -27,8 +28,8 @@ impl default::Default for Assert { current_dir: None, expect_success: Some(true), expect_exit_code: None, - expect_stdout: None, - expect_stderr: None, + expect_stdout: vec![], + expect_stderr: vec![], } } } @@ -189,7 +190,7 @@ impl Assert { /// .unwrap(); /// ``` pub fn prints>(mut self, output: O) -> Self { - self.expect_stdout = Some(OutputAssertion { + self.expect_stdout.push(OutputAssertion { expect: output.into(), fuzzy: true, expected_result: true, @@ -210,7 +211,7 @@ impl Assert { /// .unwrap(); /// ``` pub fn prints_exactly>(mut self, output: O) -> Self { - self.expect_stdout = Some(OutputAssertion { + self.expect_stdout.push(OutputAssertion { expect: output.into(), fuzzy: false, expected_result: true, @@ -233,7 +234,7 @@ impl Assert { /// .unwrap(); /// ``` pub fn prints_error>(mut self, output: O) -> Self { - self.expect_stderr = Some(OutputAssertion { + self.expect_stderr.push(OutputAssertion { expect: output.into(), fuzzy: true, expected_result: true, @@ -256,7 +257,7 @@ impl Assert { /// .unwrap(); /// ``` pub fn prints_error_exactly>(mut self, output: O) -> Self { - self.expect_stderr = Some(OutputAssertion { + self.expect_stderr.push(OutputAssertion { expect: output.into(), fuzzy: false, expected_result: true, @@ -278,7 +279,7 @@ impl Assert { /// .unwrap(); /// ``` pub fn doesnt_print>(mut self, output: O) -> Self { - self.expect_stdout = Some(OutputAssertion { + self.expect_stdout.push(OutputAssertion { expect: output.into(), fuzzy: true, expected_result: false, @@ -300,7 +301,7 @@ impl Assert { /// .unwrap(); /// ``` pub fn doesnt_print_exactly>(mut self, output: O) -> Self { - self.expect_stdout = Some(OutputAssertion { + self.expect_stdout.push(OutputAssertion { expect: output.into(), fuzzy: false, expected_result: false, @@ -324,7 +325,7 @@ impl Assert { /// .unwrap(); /// ``` pub fn doesnt_print_error>(mut self, output: O) -> Self { - self.expect_stderr = Some(OutputAssertion { + self.expect_stderr.push(OutputAssertion { expect: output.into(), fuzzy: true, expected_result: false, @@ -348,7 +349,7 @@ impl Assert { /// .unwrap(); /// ``` pub fn doesnt_print_error_exactly>(mut self, output: O) -> Self { - self.expect_stderr = Some(OutputAssertion { + self.expect_stderr.push(OutputAssertion { expect: output.into(), fuzzy: false, expected_result: false, @@ -380,7 +381,6 @@ impl Assert { }; let output = command.output()?; - if let Some(expect_success) = self.expect_success { if expect_success != output.status.success() { bail!(ErrorKind::StatusMismatch( @@ -399,15 +399,14 @@ impl Assert { )); } - if let Some(ref ouput_assertion) = self.expect_stdout { - ouput_assertion.execute(&output) - .map_err(|e| ErrorKind::StdoutMismatch(self.cmd.clone(), e))?; - } - - if let Some(ref ouput_assertion) = self.expect_stderr { - ouput_assertion.execute(&output) - .map_err(|e| ErrorKind::StderrMismatch(self.cmd.clone(), e))?; - } + self.expect_stdout + .iter() + .map(|a| a.execute(&output).map_err(|e| ErrorKind::StdoutMismatch(self.cmd.clone(), e).into())) + .collect::>>()?; + self.expect_stderr + .iter() + .map(|a| a.execute(&output).map_err(|e| ErrorKind::StderrMismatch(self.cmd.clone(), e).into())) + .collect::>>()?; Ok(()) } From c25b46b4651be2b879774cce625ab9cda60832b7 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 11 Sep 2017 21:15:47 -0600 Subject: [PATCH 2/4] Refactor Output Traits into Enum This simplifies the logic for generically adding new assertions at the cost of an match statement for each output assertion executed. --- src/assert.rs | 48 +++++++++++++++++++------------------------ src/output.rs | 57 +++++++++++++++++++-------------------------------- 2 files changed, 42 insertions(+), 63 deletions(-) diff --git a/src/assert.rs b/src/assert.rs index 0a78f5c..e4a43f4 100644 --- a/src/assert.rs +++ b/src/assert.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use std::vec::Vec; use errors::*; -use output::{OutputAssertion, StdErr, StdOut}; +use output::{OutputAssertion, OutputKind}; /// Assertions for a specific command. #[derive(Debug)] @@ -13,8 +13,7 @@ pub struct Assert { current_dir: Option, expect_success: Option, expect_exit_code: Option, - expect_stdout: Vec>, - expect_stderr: Vec>, + expect_output: Vec, } impl default::Default for Assert { @@ -28,8 +27,7 @@ impl default::Default for Assert { current_dir: None, expect_success: Some(true), expect_exit_code: None, - expect_stdout: vec![], - expect_stderr: vec![], + expect_output: vec![], } } } @@ -190,11 +188,11 @@ impl Assert { /// .unwrap(); /// ``` pub fn prints>(mut self, output: O) -> Self { - self.expect_stdout.push(OutputAssertion { + self.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: true, expected_result: true, - kind: StdOut, + kind: OutputKind::StdOut, }); self } @@ -211,11 +209,11 @@ impl Assert { /// .unwrap(); /// ``` pub fn prints_exactly>(mut self, output: O) -> Self { - self.expect_stdout.push(OutputAssertion { + self.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: false, expected_result: true, - kind: StdOut, + kind: OutputKind::StdOut, }); self } @@ -234,11 +232,11 @@ impl Assert { /// .unwrap(); /// ``` pub fn prints_error>(mut self, output: O) -> Self { - self.expect_stderr.push(OutputAssertion { + self.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: true, expected_result: true, - kind: StdErr, + kind: OutputKind::StdErr, }); self } @@ -257,11 +255,11 @@ impl Assert { /// .unwrap(); /// ``` pub fn prints_error_exactly>(mut self, output: O) -> Self { - self.expect_stderr.push(OutputAssertion { + self.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: false, expected_result: true, - kind: StdErr, + kind: OutputKind::StdErr, }); self } @@ -279,11 +277,11 @@ impl Assert { /// .unwrap(); /// ``` pub fn doesnt_print>(mut self, output: O) -> Self { - self.expect_stdout.push(OutputAssertion { + self.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: true, expected_result: false, - kind: StdOut, + kind: OutputKind::StdOut, }); self } @@ -301,11 +299,11 @@ impl Assert { /// .unwrap(); /// ``` pub fn doesnt_print_exactly>(mut self, output: O) -> Self { - self.expect_stdout.push(OutputAssertion { + self.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: false, expected_result: false, - kind: StdOut, + kind: OutputKind::StdOut, }); self } @@ -325,11 +323,11 @@ impl Assert { /// .unwrap(); /// ``` pub fn doesnt_print_error>(mut self, output: O) -> Self { - self.expect_stderr.push(OutputAssertion { + self.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: true, expected_result: false, - kind: StdErr, + kind: OutputKind::StdErr, }); self } @@ -349,11 +347,11 @@ impl Assert { /// .unwrap(); /// ``` pub fn doesnt_print_error_exactly>(mut self, output: O) -> Self { - self.expect_stderr.push(OutputAssertion { + self.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: false, expected_result: false, - kind: StdErr, + kind: OutputKind::StdErr, }); self } @@ -399,13 +397,9 @@ impl Assert { )); } - self.expect_stdout + self.expect_output .iter() - .map(|a| a.execute(&output).map_err(|e| ErrorKind::StdoutMismatch(self.cmd.clone(), e).into())) - .collect::>>()?; - self.expect_stderr - .iter() - .map(|a| a.execute(&output).map_err(|e| ErrorKind::StderrMismatch(self.cmd.clone(), e).into())) + .map(|a| a.execute(&output, &self.cmd)) .collect::>>()?; Ok(()) diff --git a/src/output.rs b/src/output.rs index b95fee2..3376226 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,4 +1,3 @@ -use std::fmt; use std::process::Output; use difference::Changeset; @@ -8,14 +7,14 @@ pub use self::errors::{Error, ErrorKind}; use diff; #[derive(Debug, Clone)] -pub struct OutputAssertion { +pub struct OutputAssertion { pub expect: String, pub fuzzy: bool, pub expected_result: bool, - pub kind: T, + pub kind: OutputKind, } -impl OutputAssertion { +impl OutputAssertion { fn matches_fuzzy(&self, got: &str) -> Result<()> { let result = got.contains(&self.expect); if result != self.expected_result { @@ -45,51 +44,37 @@ impl OutputAssertion { Ok(()) } - pub fn execute(&self, output: &Output) -> Result<()> { + pub fn execute(&self, output: &Output, cmd: &[String]) -> super::errors::Result<()> { let observed = String::from_utf8_lossy(self.kind.select(output)); - if self.fuzzy { + let result = if self.fuzzy { self.matches_fuzzy(&observed) } else { self.matches_exact(&observed) - } + }; + result.map_err(|e| self.kind.map_err(e, cmd)) } } - -pub trait OutputType: fmt::Display { - fn select<'a>(&self, o: &'a Output) -> &'a [u8]; -} - - #[derive(Debug, Clone, Copy)] -pub struct StdOut; - -impl fmt::Display for StdOut { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "stdout") - } -} - -impl OutputType for StdOut { - fn select<'a>(&self, o: &'a Output) -> &'a [u8] { - &o.stdout - } +pub enum OutputKind { + StdOut, + StdErr, } - -#[derive(Debug, Clone, Copy)] -pub struct StdErr; - -impl fmt::Display for StdErr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "stderr") +impl OutputKind { + pub fn select<'a>(self, o: &'a Output) -> &'a [u8] { + match self { + OutputKind::StdOut => &o.stdout, + OutputKind::StdErr => &o.stderr, + } } -} -impl OutputType for StdErr { - fn select<'a>(&self, o: &'a Output) -> &'a [u8] { - &o.stderr + pub fn map_err(self, e: Error, cmd: &[String]) -> super::errors::Error { + match self { + OutputKind::StdOut => super::errors::ErrorKind::StdoutMismatch(cmd.to_vec(), e).into(), + OutputKind::StdErr => super::errors::ErrorKind::StderrMismatch(cmd.to_vec(), e).into(), + } } } From 1f042baec10060f46c4222860929235bc206c68e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 13 Sep 2017 11:33:01 -0600 Subject: [PATCH 3/4] Change stdout/sterr asseertion API BREAKING CHANGE: - `.prints` -> `.stdout().contains` - `.prints_exactly` -> `.stdout().is` - `.prints_error` -> `.stderr().contains` - `.prints_error_exactly` -> `.stderr().is` --- README.md | 10 +- src/assert.rs | 259 +++++++++++++++++++++----------------------------- src/lib.rs | 12 +-- src/macros.rs | 2 +- 4 files changed, 120 insertions(+), 163 deletions(-) diff --git a/README.md b/README.md index ae97974..796d975 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Here's a trivial example: extern crate assert_cli; fn main() { - assert_cli::Assert::command(&["echo", "42"]).prints("42").unwrap(); + assert_cli::Assert::command(&["echo", "42"]).stdout().contains("42").unwrap(); } ``` @@ -31,7 +31,7 @@ Or if you'd rather use the macro, to save you some writing: #[macro_use] extern crate assert_cli; fn main() { - assert_cmd!(echo "42").prints("42").unwrap(); + assert_cmd!(echo "42").stdout().contains("42").unwrap(); } ``` @@ -45,21 +45,21 @@ fn main() { let test = assert_cmd!(ls "foo-bar-foo") .fails() .and() - .prints_error("foo-bar-foo") + .stderr().contains("foo-bar-foo") .execute(); assert!(test.is_ok()); } ``` If you want to match the program's output _exactly_, you can use -`prints_exactly`: +`stdout().is`: ```rust,should_panic #[macro_use] extern crate assert_cli; fn main() { assert_cmd!(wc "README.md") - .prints_exactly("1337 README.md") + .stdout().is("1337 README.md") .unwrap(); } ``` diff --git a/src/assert.rs b/src/assert.rs index e4a43f4..ca03e26 100644 --- a/src/assert.rs +++ b/src/assert.rs @@ -79,7 +79,7 @@ impl Assert { /// /// assert_cli::Assert::command(&["echo"]) /// .with_args(&["42"]) - /// .prints("42") + /// .stdout().contains("42") /// .unwrap(); /// ``` pub fn with_args(mut self, args: &[&str]) -> Self { @@ -96,7 +96,7 @@ impl Assert { /// /// assert_cli::Assert::command(&["wc", "lib.rs"]) /// .current_dir(std::path::Path::new("src")) - /// .prints("lib.rs") + /// .stdout().contains("lib.rs") /// .execute() /// .unwrap(); /// ``` @@ -113,7 +113,7 @@ impl Assert { /// extern crate assert_cli; /// /// assert_cli::Assert::command(&["echo", "42"]) - /// .prints("42") + /// .stdout().contains("42") /// .unwrap(); /// ``` pub fn and(self) -> Self { @@ -149,7 +149,7 @@ impl Assert { /// assert_cli::Assert::command(&["cat", "non-existing-file"]) /// .fails() /// .and() - /// .prints_error("non-existing-file") + /// .stderr().contains("non-existing-file") /// .unwrap(); /// ``` pub fn fails(mut self) -> Self { @@ -167,7 +167,7 @@ impl Assert { /// assert_cli::Assert::command(&["cat", "non-existing-file"]) /// .fails_with(1) /// .and() - /// .prints_error_exactly("cat: non-existing-file: No such file or directory") + /// .stderr().is("cat: non-existing-file: No such file or directory") /// .unwrap(); /// ``` pub fn fails_with(mut self, expect_exit_code: i32) -> Self { @@ -176,7 +176,7 @@ impl Assert { self } - /// Expect the command's output to **contain** `output`. + /// Create an assertion for stdout's contents /// /// # Examples /// @@ -184,41 +184,18 @@ impl Assert { /// extern crate assert_cli; /// /// assert_cli::Assert::command(&["echo", "42"]) - /// .prints("42") + /// .stdout().contains("42") /// .unwrap(); /// ``` - pub fn prints>(mut self, output: O) -> Self { - self.expect_output.push(OutputAssertion { - expect: output.into(), - fuzzy: true, - expected_result: true, + pub fn stdout(self) -> OutputAssertionBuilder { + OutputAssertionBuilder { + assertion: self, kind: OutputKind::StdOut, - }); - self - } - - /// Expect the command to output **exactly** this `output`. - /// - /// # Examples - /// - /// ```rust - /// extern crate assert_cli; - /// - /// assert_cli::Assert::command(&["echo", "42"]) - /// .prints_exactly("42") - /// .unwrap(); - /// ``` - pub fn prints_exactly>(mut self, output: O) -> Self { - self.expect_output.push(OutputAssertion { - expect: output.into(), - fuzzy: false, expected_result: true, - kind: OutputKind::StdOut, - }); - self + } } - /// Expect the command's stderr output to **contain** `output`. + /// Create an assertion for stdout's contents /// /// # Examples /// @@ -226,67 +203,95 @@ impl Assert { /// extern crate assert_cli; /// /// assert_cli::Assert::command(&["cat", "non-existing-file"]) - /// .fails() + /// .fails_with(1) /// .and() - /// .prints_error("non-existing-file") + /// .stderr().is("cat: non-existing-file: No such file or directory") /// .unwrap(); /// ``` - pub fn prints_error>(mut self, output: O) -> Self { - self.expect_output.push(OutputAssertion { - expect: output.into(), - fuzzy: true, - expected_result: true, + pub fn stderr(self) -> OutputAssertionBuilder { + OutputAssertionBuilder { + assertion: self, kind: OutputKind::StdErr, - }); - self + expected_result: true, + } } - /// Expect the command to output **exactly** this `output` to stderr. + /// Execute the command and check the assertions. /// /// # Examples /// /// ```rust /// extern crate assert_cli; /// - /// assert_cli::Assert::command(&["cat", "non-existing-file"]) - /// .fails_with(1) - /// .and() - /// .prints_error_exactly("cat: non-existing-file: No such file or directory") - /// .unwrap(); + /// let test = assert_cli::Assert::command(&["echo", "42"]) + /// .stdout().contains("42") + /// .execute(); + /// assert!(test.is_ok()); /// ``` - pub fn prints_error_exactly>(mut self, output: O) -> Self { - self.expect_output.push(OutputAssertion { - expect: output.into(), - fuzzy: false, - expected_result: true, - kind: OutputKind::StdErr, - }); - self + pub fn execute(self) -> Result<()> { + let cmd = &self.cmd[0]; + let args: Vec<_> = self.cmd.iter().skip(1).collect(); + let mut command = Command::new(cmd); + let command = command.args(&args); + let command = match self.current_dir { + Some(ref dir) => command.current_dir(dir), + None => command, + }; + let output = command.output()?; + + if let Some(expect_success) = self.expect_success { + if expect_success != output.status.success() { + bail!(ErrorKind::StatusMismatch( + self.cmd.clone(), + expect_success, + )); + } + } + + if self.expect_exit_code.is_some() && + self.expect_exit_code != output.status.code() { + bail!(ErrorKind::ExitCodeMismatch( + self.cmd.clone(), + self.expect_exit_code, + output.status.code(), + )); + } + + self.expect_output + .iter() + .map(|a| a.execute(&output, &self.cmd)) + .collect::>>()?; + + Ok(()) } - /// Expect the command's output to not **contain** `output`. + /// Execute the command, check the assertions, and panic when they fail. /// /// # Examples /// - /// ```rust + /// ```rust,should_panic="Assert CLI failure" /// extern crate assert_cli; /// /// assert_cli::Assert::command(&["echo", "42"]) - /// .doesnt_print("73") - /// .execute() - /// .unwrap(); + /// .fails() + /// .unwrap(); // panics /// ``` - pub fn doesnt_print>(mut self, output: O) -> Self { - self.expect_output.push(OutputAssertion { - expect: output.into(), - fuzzy: true, - expected_result: false, - kind: OutputKind::StdOut, - }); - self + pub fn unwrap(self) { + if let Err(err) = self.execute() { + panic!("{}", err); + } } +} - /// Expect the command to output to not be **exactly** this `output`. +#[derive(Debug)] +pub struct OutputAssertionBuilder { + pub assertion: Assert, + pub kind: OutputKind, + pub expected_result: bool, +} + +impl OutputAssertionBuilder { + /// Negate the assertion predicate /// /// # Examples /// @@ -294,131 +299,83 @@ impl Assert { /// extern crate assert_cli; /// /// assert_cli::Assert::command(&["echo", "42"]) - /// .doesnt_print_exactly("73") - /// .execute() + /// .stdout().not().contains("73") /// .unwrap(); /// ``` - pub fn doesnt_print_exactly>(mut self, output: O) -> Self { - self.expect_output.push(OutputAssertion { - expect: output.into(), - fuzzy: false, - expected_result: false, - kind: OutputKind::StdOut, - }); + pub fn not(mut self) -> Self { + self.expected_result = ! self.expected_result; self } - /// Expect the command's stderr output to not **contain** `output`. + /// Expect the command's output to **contain** `output`. /// /// # Examples /// /// ```rust /// extern crate assert_cli; /// - /// assert_cli::Assert::command(&["cat", "non-existing-file"]) - /// .fails() - /// .and() - /// .doesnt_print_error("content") - /// .execute() + /// assert_cli::Assert::command(&["echo", "42"]) + /// .stdout().contains("42") /// .unwrap(); /// ``` - pub fn doesnt_print_error>(mut self, output: O) -> Self { - self.expect_output.push(OutputAssertion { + pub fn contains>(mut self, output: O) -> Assert { + self.assertion.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: true, - expected_result: false, - kind: OutputKind::StdErr, + expected_result: self.expected_result, + kind: self.kind, }); - self + self.assertion } - /// Expect the command to output to not be **exactly** this `output` to stderr. + /// Expect the command to output **exactly** this `output`. /// /// # Examples /// /// ```rust /// extern crate assert_cli; /// - /// assert_cli::Assert::command(&["cat", "non-existing-file"]) - /// .fails_with(1) - /// .and() - /// .doesnt_print_error_exactly("content") - /// .execute() + /// assert_cli::Assert::command(&["echo", "42"]) + /// .stdout().is("42") /// .unwrap(); /// ``` - pub fn doesnt_print_error_exactly>(mut self, output: O) -> Self { - self.expect_output.push(OutputAssertion { + pub fn is>(mut self, output: O) -> Assert { + self.assertion.expect_output.push(OutputAssertion { expect: output.into(), fuzzy: false, - expected_result: false, - kind: OutputKind::StdErr, + expected_result: self.expected_result, + kind: self.kind, }); - self + self.assertion } - /// Execute the command and check the assertions. + /// Expect the command's output to not **contain** `output`. /// /// # Examples /// /// ```rust /// extern crate assert_cli; /// - /// let test = assert_cli::Assert::command(&["echo", "42"]) - /// .prints("42") - /// .execute(); - /// assert!(test.is_ok()); + /// assert_cli::Assert::command(&["echo", "42"]) + /// .stdout().doesnt_contain("73") + /// .unwrap(); /// ``` - pub fn execute(self) -> Result<()> { - let cmd = &self.cmd[0]; - let args: Vec<_> = self.cmd.iter().skip(1).collect(); - let mut command = Command::new(cmd); - let command = command.args(&args); - let command = match self.current_dir { - Some(ref dir) => command.current_dir(dir), - None => command, - }; - let output = command.output()?; - - if let Some(expect_success) = self.expect_success { - if expect_success != output.status.success() { - bail!(ErrorKind::StatusMismatch( - self.cmd.clone(), - expect_success, - )); - } - } - - if self.expect_exit_code.is_some() && - self.expect_exit_code != output.status.code() { - bail!(ErrorKind::ExitCodeMismatch( - self.cmd.clone(), - self.expect_exit_code, - output.status.code(), - )); - } - - self.expect_output - .iter() - .map(|a| a.execute(&output, &self.cmd)) - .collect::>>()?; - - Ok(()) + pub fn doesnt_contain>(self, output: O) -> Assert { + self.not().contains(output) } - /// Execute the command, check the assertions, and panic when they fail. + /// Expect the command to output to not be **exactly** this `output`. /// /// # Examples /// - /// ```rust,should_panic="Assert CLI failure" + /// ```rust /// extern crate assert_cli; /// /// assert_cli::Assert::command(&["echo", "42"]) - /// .fails() - /// .unwrap(); // panics + /// .stdout().isnt("73") + /// .unwrap(); /// ``` - pub fn unwrap(self) { - if let Err(err) = self.execute() { - panic!("{}", err); - } + pub fn isnt>(self, output: O) -> Assert { + self.not().is(output) } } diff --git a/src/lib.rs b/src/lib.rs index 425ceae..f36cbc7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ //! //! ```rust //! assert_cli::Assert::command(&["echo", "42"]) -//! .prints("42") +//! .stdout().contains("42") //! .unwrap(); //! ``` //! @@ -26,7 +26,7 @@ //! //! ```rust,should_panic //! assert_cli::Assert::command(&["echo", "42"]) -//! .prints_exactly("1337") +//! .stdout().is("1337") //! .unwrap(); //! ``` //! @@ -45,7 +45,7 @@ //! ```rust //! # #[macro_use] extern crate assert_cli; //! # fn main() { -//! assert_cmd!(echo "42").prints("42").unwrap(); +//! assert_cmd!(echo "42").stdout().contains("42").unwrap(); //! # } //! ``` //! @@ -68,7 +68,7 @@ //! assert_cmd!(cat "non-existing-file") //! .fails() //! .and() -//! .prints_error("non-existing-file") +//! .stderr().contains("non-existing-file") //! .unwrap(); //! # } //! ``` @@ -78,7 +78,7 @@ //! - Use `fails_with` to assert a specific exit status. //! - There is also a `succeeds` method, but this is already the implicit default //! and can usually be omitted. -//! - We can inspect the output of **stderr** with `prints_error` and `prints_error_exactly`. +//! - We can inspect the output of **stderr** with `stderr().contains` and `stderr().is`. //! - The `and` method has no effect, other than to make everything more readable. //! Feel free to use it. :-) //! @@ -97,7 +97,7 @@ //! ```rust //! # #[macro_use] extern crate assert_cli; //! # fn main() { -//! let x = assert_cmd!(echo "1337").prints_exactly("42").execute(); +//! let x = assert_cmd!(echo "1337").stdout().is("42").execute(); //! assert!(x.is_err()); //! # } //! ``` diff --git a/src/macros.rs b/src/macros.rs index 1c92529..1078032 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,7 +22,7 @@ use serde_json; /// # fn main() { /// assert_cmd!(echo "Launch sequence initiated.\nNo errors whatsoever!\n") /// .succeeds() -/// .prints("No errors whatsoever") +/// .stdout().contains("No errors whatsoever") /// .unwrap(); /// # } /// ``` From 64c766b18b7551f9c96ccb8c7f0464630a2da105 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 21 Sep 2017 21:02:31 -0600 Subject: [PATCH 4/4] Document new output assertions --- src/assert.rs | 7 ++++--- src/lib.rs | 20 +++++++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/assert.rs b/src/assert.rs index ca03e26..0732c35 100644 --- a/src/assert.rs +++ b/src/assert.rs @@ -283,11 +283,12 @@ impl Assert { } } +/// Assertions for command output. #[derive(Debug)] pub struct OutputAssertionBuilder { - pub assertion: Assert, - pub kind: OutputKind, - pub expected_result: bool, + assertion: Assert, + kind: OutputKind, + expected_result: bool, } impl OutputAssertionBuilder { diff --git a/src/lib.rs b/src/lib.rs index f36cbc7..5d103da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,8 +67,6 @@ //! # fn main() { //! assert_cmd!(cat "non-existing-file") //! .fails() -//! .and() -//! .stderr().contains("non-existing-file") //! .unwrap(); //! # } //! ``` @@ -78,10 +76,25 @@ //! - Use `fails_with` to assert a specific exit status. //! - There is also a `succeeds` method, but this is already the implicit default //! and can usually be omitted. -//! - We can inspect the output of **stderr** with `stderr().contains` and `stderr().is`. //! - The `and` method has no effect, other than to make everything more readable. //! Feel free to use it. :-) //! +//! ## stdout / stderr +//! +//! You can add assertions on the content of **stdout** and **stderr**. They +//! can be mixed together or even multiple of one stream can be used. +//! +//! ```rust +//! # #[macro_use] extern crate assert_cli; +//! # fn main() { +//! assert_cmd!(echo "Hello world! The ansswer is 42.") +//! .stdout().contains("Hello world") +//! .stdout().contains("42") +//! .stderr().is("") +//! .unwrap(); +//! # } +//! ``` +//! //! ## Assert CLI Crates //! //! If you are testing a Rust binary crate, you can start with @@ -119,3 +132,4 @@ mod diff; mod assert; pub use assert::Assert; +pub use assert::OutputAssertionBuilder;