Skip to content
This repository has been archived by the owner on Dec 29, 2021. It is now read-only.

Review/feedback #16

Merged
merged 10 commits into from
Mar 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ homepage = "https://github.com/killercup/assert_cli"
documentation = "http://killercup.github.io/assert_cli/"
readme = "README.md"
categories = ["development-tools::testing"]
keywords = ["cli", "testing"]
keywords = ["cli", "testing", "assert"]
build = "build.rs"

[dependencies]
colored = "1.4"
difference = "1.0"
error-chain = "0.10.0"
rustc-serialize = "0.3"

[build-dependencies]
skeptic = "0.5"
Expand Down
40 changes: 23 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
# Assert CLI

> Test CLI Applications.
> **Test CLI Applications** - This crate checks the output of a child process is as expected.

Currently, this crate only includes basic functionality to check the output of a child process
is as expected.

[![Build Status](https://travis-ci.org/killercup/assert_cli.svg)](https://travis-ci.org/killercup/assert_cli) [![Coverage Status](https://coveralls.io/repos/killercup/assert_cli/badge.svg?branch=master&service=github)](https://coveralls.io/github/killercup/assert_cli?branch=master)

**[Documentation](http://killercup.github.io/assert_cli/)**
[![Build Status](https://travis-ci.org/killercup/assert_cli.svg)](https://travis-ci.org/killercup/assert_cli) [![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation]

## Install

Expand All @@ -30,13 +25,13 @@ fn main() {
}
```

Or if you'd rather use the macro:
Or if you'd rather use the macro, to save you some writing:

```rust
#[macro_use] extern crate assert_cli;

fn main() {
assert_cmd!(echo 42).succeeds().and().prints("42").unwrap();
assert_cmd!(echo "42").prints("42").unwrap();
}
```

Expand All @@ -47,33 +42,42 @@ And here is one that will fail (which also shows `execute` which returns a
#[macro_use] extern crate assert_cli;

fn main() {
let test = assert_cmd!(grep amet Cargo.toml)
.fails_with(1)
let test = assert_cmd!(ls "foo-bar-foo")
.fails()
.and()
.prints_error("foo-bar-foo")
.execute();
assert!(test.is_err());
assert!(test.is_ok());
}
```

If you want to check for the program's output, you can use `print` or
`print_exactly`:
If you want to match the program's output _exactly_, you can use
`prints_exactly`:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a random comment.

When first poking around with this crate I found the semantics of prints a bit surprising. I expected a strict equality assertion. Then I learned that there is prints_exactly.

It's very likely a matter of taste and I might even change my mind (I often do), but I think I would prefer the strict assertion over the fuzzy assertion. I tried hard to think of a different naming, where the strict variant would have the shorter name, but I couldn't find something nice.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried hard to think of a different naming, where the strict variant would have the shorter name, but I couldn't find something nice.

Me neither! That's one of the main reason I made the exact method's name longer.

The previous version only had exact matching, and it was difficult to get right, because you had to include every new line (Maybe with carriage return on Windows? Who knows!) and control character.

This reminds of of another thing I want to support: Multiple fuzzy checks. I'll open an issue for that in a minute.


```rust,should_panic="Assert CLI failure"
```rust,should_panic
#[macro_use] extern crate assert_cli;

fn main() {
assert_cmd!("wc" "README.md")
assert_cmd!(wc "README.md")
.prints_exactly("1337 README.md")
.unwrap();
}
```

this will show a nice, colorful diff in your terminal, like this:
... which has the benefit to show a nice, colorful diff in your terminal,
like this:

```diff
-1337
+92
```

**Tip**: Enclose arguments in the `assert_cmd!` macro in quotes `"`,
if there are special characters, which the macro doesn't accept, e.g.
`assert_cmd!(cat "foo.txt")`.

More detailed information is available in the [documentation]. :-)

## License

Licensed under either of
Expand All @@ -89,3 +93,5 @@ Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.

[Documentation]: http://killercup.github.io/assert_cli/
41 changes: 22 additions & 19 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const ERROR_PREFIX: &'static str = "CLI assertion failed";

error_chain! {
foreign_links {
Io(::std::io::Error);
Expand All @@ -7,42 +9,43 @@ error_chain! {
StatusMismatch(cmd: Vec<String>, expected: bool) {
description("Wrong status")
display(
"Command {:?} {got} but expected it to {expected}",
"{}: `(command `{}` expected to {})` (command {})",
ERROR_PREFIX,
cmd.join(" "),
got = if *expected { "failed" } else { "succeed" },
expected = if *expected { "succeed" } else { "failed" },
expected = if *expected { "succeed" } else { "fail" },
got = if *expected { "failed" } else { "succeeded" },
)
}
ExitCodeMismatch(cmd: Vec<String>, expected: Option<i32>, got: Option<i32>) {
description("Wrong exit code")
display(
"Command {:?} exited with code {:?} but expected it to be {:?}",
cmd.join(" "), got, expected,
"{}: `(exit code of `{}` expected to be `{:?}`)` (exit code was: `{:?}`)",
ERROR_PREFIX,
cmd.join(" "),
expected,
got,
)
}
OutputMismatch(expected: String, got: String) {
OutputMismatch(output_name: String, cmd: Vec<String>, expected: String, got: String) {
description("Output was not as expected")
display(
"Expected output to contain\n{}\nbut could not find it in\n{}",
"{}: `({} of `{}` expected to contain `{:?}`)` (output was: `{:?}`)",
ERROR_PREFIX,
output_name,
cmd.join(" "),
expected,
got,
)
}
ExactOutputMismatch(diff: String) {
ExactOutputMismatch(output_name: String, cmd: Vec<String>, diff: String) {
description("Output was not as expected")
display("{}", diff)
}
ErrorOutputMismatch(expected: String, got: String) {
description("Stderr output was not as expected")
display(
"Expected stderr output to contain\n{}\nbut could not find it in\n{}",
expected,
got,
"{}: `({} of `{}` was not as expected)`\n{}\n",
ERROR_PREFIX,
output_name,
cmd.join(" "),
diff.trim()
)
}
ExactErrorOutputMismatch(diff: String) {
description("Stderr output was not as expected")
display("{}", diff)
}
}
}
Loading