Skip to content

Commit

Permalink
Add assert_contains! macro (#322)
Browse files Browse the repository at this point in the history
* Add assert_contains macro

* Update CHANGELOG

* Add unit tests for assert_contains

* Use assert_contains in docs instead of assert

* Replace assert! with assert_contains!
  • Loading branch information
Malax authored Feb 22, 2022
1 parent 37ca5f6 commit 87b4376
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 19 deletions.
15 changes: 8 additions & 7 deletions examples/ruby-sample/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// https://rust-lang.github.io/rust-clippy/stable/index.html
#![warn(clippy::pedantic)]

use libcnb_test::assert_contains;
use libcnb_test::IntegrationTest;
use std::io;
use std::io::{Read, Write};
Expand All @@ -19,9 +20,9 @@ use std::time::Duration;
fn basic() {
IntegrationTest::new("heroku/buildpacks:20", "test-fixtures/simple-ruby-app").run_test(
|context| {
assert!(context.pack_stdout.contains("---> Ruby Buildpack"));
assert!(context.pack_stdout.contains("---> Installing bundler"));
assert!(context.pack_stdout.contains("---> Installing gems"));
assert_contains!(context.pack_stdout, "---> Ruby Buildpack");
assert_contains!(context.pack_stdout, "---> Installing bundler");
assert_contains!(context.pack_stdout, "---> Installing gems");

context.start_container(&[12345], |container| {
std::thread::sleep(Duration::from_secs(1));
Expand All @@ -35,10 +36,10 @@ fn basic() {
"!dlroW olleH"
);

assert!(container
.shell_exec("ruby --version")
.stdout
.contains("ruby 2.7.0p0"));
assert_contains!(
container.shell_exec("ruby --version").stdout,
"ruby 2.7.0p0"
);
});
},
);
Expand Down
1 change: 1 addition & 0 deletions libcnb-test/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- `libcnb-test` now cross-compiles and packages all binary targets of the buildpack for an integration test. The main buildpack binary is either the only binary target or the target with the same name as the crate. This feature allows the usage of additional binaries for i.e. execd. ([#314](https://github.com/Malax/libcnb.rs/pull/314))
- Increase minimum supported Rust version from 1.56 to 1.58 ([#318](https://github.com/Malax/libcnb.rs/pull/318)).
- Add `assert_contains!` macro for easier matching of `pack` output in integration tests. ([#322](https://github.com/Malax/libcnb.rs/pull/322))

## [0.1.1] 2022-02-04

Expand Down
8 changes: 4 additions & 4 deletions libcnb-test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Please use the same tag for feature requests.

```rust,no_run
// In $CRATE_ROOT/test/integration_test.rs
use libcnb_test::{IntegrationTest, BuildpackReference};
use libcnb_test::{IntegrationTest, BuildpackReference, assert_contains};
#[test]
fn test() {
Expand All @@ -25,9 +25,9 @@ fn test() {
BuildpackReference::Crate,
])
.run_test(|context| {
assert!(context.pack_stdout.contains("---> Maven Buildpack"));
assert!(context.pack_stdout.contains("---> Installing Maven"));
assert!(context.pack_stdout.contains("---> Running mvn package"));
assert_contains!(context.pack_stdout, "---> Maven Buildpack");
assert_contains!(context.pack_stdout, "---> Installing Maven");
assert_contains!(context.pack_stdout, "---> Running mvn package");
context.start_container(&[12345], |container| {
assert_eq!(
Expand Down
17 changes: 9 additions & 8 deletions libcnb-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod app;
mod build;
mod container_context;
mod container_port_mapping;
mod macros;
mod pack;
mod util;

Expand All @@ -32,7 +33,7 @@ use std::process::{Command, Stdio};
///
/// # Example
/// ```no_run
/// use libcnb_test::{IntegrationTest, BuildpackReference};
/// use libcnb_test::{IntegrationTest, BuildpackReference, assert_contains};
///
/// # fn call_test_fixture_service(addr: std::net::SocketAddr, payload: &str) -> Result<String, ()> {
/// # unimplemented!()
Expand All @@ -43,9 +44,9 @@ use std::process::{Command, Stdio};
/// BuildpackReference::Crate,
/// ])
/// .run_test(|context| {
/// assert!(context.pack_stdout.contains("---> Maven Buildpack"));
/// assert!(context.pack_stdout.contains("---> Installing Maven"));
/// assert!(context.pack_stdout.contains("---> Running mvn package"));
/// assert_contains!(context.pack_stdout, "---> Maven Buildpack");
/// assert_contains!(context.pack_stdout, "---> Installing Maven");
/// assert_contains!(context.pack_stdout, "---> Running mvn package");
///
/// context.start_container(&[12345], |container| {
/// assert_eq!(
Expand Down Expand Up @@ -148,13 +149,13 @@ impl IntegrationTest {
///
/// # Example
/// ```no_run
/// use libcnb_test::IntegrationTest;
/// use libcnb_test::{IntegrationTest, assert_contains};
///
/// IntegrationTest::new("heroku/buildpacks:20", "test-fixtures/app")
/// .run_test(|context| {
/// assert!(context.pack_stdout.contains("---> Ruby Buildpack"));
/// assert!(context.pack_stdout.contains("---> Installing bundler"));
/// assert!(context.pack_stdout.contains("---> Installing gems"));
/// assert_contains!(context.pack_stdout, "---> Ruby Buildpack");
/// assert_contains!(context.pack_stdout, "---> Installing bundler");
/// assert_contains!(context.pack_stdout, "---> Installing gems");
/// })
/// ```
pub fn run_test<F: FnOnce(IntegrationTestContext)>(&mut self, f: F) {
Expand Down
116 changes: 116 additions & 0 deletions libcnb-test/src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/// Asserts that `left` contains `right`.
///
/// Commonly used when asserting `pack` output in integration tests. Expands to a [`str::contains`]
/// call and logs `left` (in unescaped and escaped form) as well as `right` on failure.
///
/// # Example
///
/// ```
/// use libcnb_test::assert_contains;
///
/// let output = "Hello World!\nHello Integration Test!";
/// assert_contains!(output, "Integration");
/// ```
#[macro_export]
macro_rules! assert_contains {
($left:expr, $right:expr $(,)?) => {{
if !$left.contains($right) {
::std::panic!(
r#"assertion failed: `(left contains right)`
left (unescaped):
{}
left (escaped): `{:?}`
right: `{:?}`"#,
$left,
$left,
$right,
)
}
}};

($left:expr, $right:expr, $($arg:tt)+) => {{
if !$left.contains($right) {
::std::panic!(
r#"assertion failed: `(left contains right)`
left (unescaped):
{}
left (escaped): `{:?}`
right: `{:?}`: {}"#,
$left,
$left,
$right,
::core::format_args!($($arg)+)
)
}
}};
}

#[cfg(test)]
mod test {
#[test]
fn simple() {
assert_contains!("Hello World!", "World");
}

#[test]
fn simple_with_args() {
assert_contains!("Hello World!", "World", "World must be greeted!");
}

#[test]
#[should_panic(expected = "assertion failed: `(left contains right)`
left (unescaped):
foo
left (escaped): `\"foo\"`
right: `\"bar\"`")]
fn simple_failure() {
assert_contains!("foo", "bar");
}

#[test]
#[should_panic(expected = "assertion failed: `(left contains right)`
left (unescaped):
Hello Germany!
left (escaped): `\"Hello Germany!\"`
right: `\"World\"`: World must be greeted!")]
fn simple_failure_with_args() {
assert_contains!("Hello Germany!", "World", "World must be greeted!");
}

#[test]
fn multiline() {
assert_contains!("Hello World!\nFoo\nBar\nBaz", "Bar");
}

#[test]
#[should_panic(expected = "assertion failed: `(left contains right)`
left (unescaped):
Hello World!
Foo
Bar
Baz
left (escaped): `\"Hello World!\\nFoo\\nBar\\nBaz\"`
right: `\"Eggs\"`")]
fn multiline_failure() {
assert_contains!("Hello World!\nFoo\nBar\nBaz", "Eggs");
}

#[test]
#[should_panic(expected = "assertion failed: `(left contains right)`
left (unescaped):
Hello World!
Foo
Bar
Baz
left (escaped): `\"Hello World!\\nFoo\\nBar\\nBaz\"`
right: `\"Eggs\"`: We need eggs!")]
fn multiline_failure_with_args() {
assert_contains!("Hello World!\nFoo\nBar\nBaz", "Eggs", "We need eggs!");
}
}

0 comments on commit 87b4376

Please sign in to comment.