Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add assert_contains! macro #322

Merged
merged 5 commits into from
Feb 22, 2022
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
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));
Malax marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -34,7 +35,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 @@ -45,9 +46,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 @@ -150,13 +151,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 {
Malax marked this conversation as resolved.
Show resolved Hide resolved
($left:expr, $right:expr $(,)?) => {{
if !$left.contains($right) {
::std::panic!(
r#"assertion failed: `(left contains right)`
left (unescaped):
{}

left (escaped): `{:?}`
right: `{:?}`"#,
Malax marked this conversation as resolved.
Show resolved Hide resolved
$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)+)
)
}
}};
Malax marked this conversation as resolved.
Show resolved Hide resolved
}

#[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!");
}
}