Skip to content

Commit e089a32

Browse files
committed
feat(assert): Show cause of assert
While at it, fixed duplicate information being reported. Fixes #8, #1 BREAKING CHANGE: Upgraded the version of `predicates` from 0.5.0 to `predicates-core` 0.9.0.
1 parent eaea7a2 commit e089a32

File tree

3 files changed

+75
-40
lines changed

3 files changed

+75
-40
lines changed

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ keywords = ["cli", "test", "assert", "command", "duct"]
1515
name = "bin_fixture"
1616

1717
[dependencies]
18-
predicates = "0.5.1"
18+
predicates = "0.9.0"
19+
predicates-core = "0.9.0"
20+
predicates-tree = "0.9.0"
1921
escargot = "0.2"
2022
serde = { version = "1.0", features = ["derive"] }
2123

src/assert.rs

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use std::str;
88

99
use predicates;
1010
use predicates::str::PredicateStrExt;
11+
use predicates_core;
12+
use predicates_tree::CaseTreeExt;
1113

1214
use errors::dump_buffer;
1315
use errors::output_fmt;
@@ -185,23 +187,15 @@ impl Assert {
185187
/// ```
186188
pub fn failure(self) -> Self {
187189
if self.output.status.success() {
188-
panic!(
189-
"Unexpected success\nstdout=```{}```\n{}",
190-
dump_buffer(&self.output.stdout),
191-
self
192-
);
190+
panic!("Unexpected success\n{}", self);
193191
}
194192
self
195193
}
196194

197195
/// Ensure the command aborted before returning a code.
198196
pub fn interrupted(self) -> Self {
199197
if self.output.status.code().is_some() {
200-
panic!(
201-
"Unexpected completion\nstdout=```{}```\n{}",
202-
dump_buffer(&self.output.stdout),
203-
self
204-
);
198+
panic!("Unexpected completion\n{}", self);
205199
}
206200
self
207201
}
@@ -224,26 +218,21 @@ impl Assert {
224218
pub fn code<I, P>(self, pred: I) -> Self
225219
where
226220
I: IntoCodePredicate<P>,
227-
P: predicates::Predicate<i32>,
221+
P: predicates_core::Predicate<i32>,
228222
{
229223
self.code_impl(&pred.into_code())
230224
}
231225

232-
fn code_impl(self, pred: &predicates::Predicate<i32>) -> Self {
226+
fn code_impl(self, pred: &predicates_core::Predicate<i32>) -> Self {
233227
let actual_code = self.output.status.code().unwrap_or_else(|| {
234228
panic!(
235229
"Command interrupted\nstderr=```{}```\n{}",
236230
dump_buffer(&self.output.stderr),
237231
self
238232
)
239233
});
240-
if !pred.eval(&actual_code) {
241-
panic!(
242-
"Unexpected return code\nstdout=```{}```\nstderr=```{}```\n{}",
243-
dump_buffer(&self.output.stdout),
244-
dump_buffer(&self.output.stderr),
245-
self
246-
);
234+
if let Some(case) = pred.find_case(false, &actual_code) {
235+
panic!("Unexpected return code, failed {}\n{}", case.tree(), self);
247236
}
248237
self
249238
}
@@ -267,16 +256,16 @@ impl Assert {
267256
pub fn stdout<I, P>(self, pred: I) -> Self
268257
where
269258
I: IntoOutputPredicate<P>,
270-
P: predicates::Predicate<[u8]>,
259+
P: predicates_core::Predicate<[u8]>,
271260
{
272261
self.stdout_impl(&pred.into_output())
273262
}
274263

275-
fn stdout_impl(self, pred: &predicates::Predicate<[u8]>) -> Self {
264+
fn stdout_impl(self, pred: &predicates_core::Predicate<[u8]>) -> Self {
276265
{
277266
let actual = &self.output.stdout;
278-
if !pred.eval(actual) {
279-
panic!("Unexpected stdout\n{}", self);
267+
if let Some(case) = pred.find_case(false, &actual) {
268+
panic!("Unexpected stdout, failed {}\n{}", case.tree(), self);
280269
}
281270
}
282271
self
@@ -301,16 +290,16 @@ impl Assert {
301290
pub fn stderr<I, P>(self, pred: I) -> Self
302291
where
303292
I: IntoOutputPredicate<P>,
304-
P: predicates::Predicate<[u8]>,
293+
P: predicates_core::Predicate<[u8]>,
305294
{
306295
self.stderr_impl(&pred.into_output())
307296
}
308297

309-
fn stderr_impl(self, pred: &predicates::Predicate<[u8]>) -> Self {
298+
fn stderr_impl(self, pred: &predicates_core::Predicate<[u8]>) -> Self {
310299
{
311300
let actual = &self.output.stderr;
312-
if !pred.eval(actual) {
313-
panic!("Unexpected stderr\n{}", self);
301+
if let Some(case) = pred.find_case(false, &actual) {
302+
panic!("Unexpected stderr, failed {}\n\n{}", case.tree(), self);
314303
}
315304
}
316305
self
@@ -358,10 +347,10 @@ impl fmt::Debug for Assert {
358347
/// ```
359348
///
360349
/// [`Assert::code`]: struct.Assert.html#method.code
361-
/// [`Predicate<i32>`]: https://docs.rs/predicates/0.5.2/predicates/trait.Predicate.html
350+
/// [`Predicate<i32>`]: https://docs.rs/predicates-core/0.9.0/predicates_core/trait.Predicate.html
362351
pub trait IntoCodePredicate<P>
363352
where
364-
P: predicates::Predicate<i32>,
353+
P: predicates_core::Predicate<i32>,
365354
{
366355
/// The type of the predicate being returned.
367356
type Predicate;
@@ -372,7 +361,7 @@ where
372361

373362
impl<P> IntoCodePredicate<P> for P
374363
where
375-
P: predicates::Predicate<i32>,
364+
P: predicates_core::Predicate<i32>,
376365
{
377366
type Predicate = P;
378367

@@ -410,10 +399,10 @@ impl IntoCodePredicate<predicates::iter::InPredicate<i32>> for &'static [i32] {
410399
///
411400
/// [`Assert::stdout`]: struct.Assert.html#method.stdout
412401
/// [`Assert::stderr`]: struct.Assert.html#method.stderr
413-
/// [`Predicate<[u8]>`]: https://docs.rs/predicates/0.5.2/predicates/trait.Predicate.html
402+
/// [`Predicate<[u8]>`]: https://docs.rs/predicates-core/0.9.0/predicates_core/trait.Predicate.html
414403
pub trait IntoOutputPredicate<P>
415404
where
416-
P: predicates::Predicate<[u8]>,
405+
P: predicates_core::Predicate<[u8]>,
417406
{
418407
/// The type of the predicate being returned.
419408
type Predicate;
@@ -424,7 +413,7 @@ where
424413

425414
impl<P> IntoOutputPredicate<P> for P
426415
where
427-
P: predicates::Predicate<[u8]>,
416+
P: predicates_core::Predicate<[u8]>,
428417
{
429418
type Predicate = P;
430419

@@ -437,7 +426,7 @@ where
437426
/// [Predicate] used by [`IntoOutputPredicate`] for bytes.
438427
///
439428
/// [`IntoOutputPredicate`]: trait.IntoOutputPredicate.html
440-
/// [Predicate]: https://docs.rs/predicates/0.5.2/predicates/trait.Predicate.html
429+
/// [Predicate]: https://docs.rs/predicates-core/0.9.0/predicates_core/trait.Predicate.html
441430
#[derive(Debug)]
442431
pub struct BytesContentOutputPredicate(predicates::ord::EqPredicate<&'static [u8]>);
443432

@@ -448,10 +437,31 @@ impl BytesContentOutputPredicate {
448437
}
449438
}
450439

451-
impl predicates::Predicate<[u8]> for BytesContentOutputPredicate {
440+
impl predicates_core::reflection::PredicateReflection for BytesContentOutputPredicate {
441+
fn parameters<'a>(
442+
&'a self,
443+
) -> Box<Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
444+
self.0.parameters()
445+
}
446+
447+
/// Nested `Predicate`s of the current `Predicate`.
448+
fn children<'a>(&'a self) -> Box<Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
449+
self.0.children()
450+
}
451+
}
452+
453+
impl predicates_core::Predicate<[u8]> for BytesContentOutputPredicate {
452454
fn eval(&self, item: &[u8]) -> bool {
453455
self.0.eval(item)
454456
}
457+
458+
fn find_case<'a>(
459+
&'a self,
460+
expected: bool,
461+
variable: &[u8],
462+
) -> Option<predicates_core::reflection::Case<'a>> {
463+
self.0.find_case(expected, variable)
464+
}
455465
}
456466

457467
impl fmt::Display for BytesContentOutputPredicate {
@@ -472,7 +482,7 @@ impl IntoOutputPredicate<BytesContentOutputPredicate> for &'static [u8] {
472482
/// [Predicate] used by [`IntoOutputPredicate`] for [`str`].
473483
///
474484
/// [`IntoOutputPredicate`]: trait.IntoOutputPredicate.html
475-
/// [Predicate]: https://docs.rs/predicates/0.5.2/predicates/trait.Predicate.html
485+
/// [Predicate]: https://docs.rs/predicates-core/0.9.0/predicates_core/trait.Predicate.html
476486
/// [`str`]: https://doc.rust-lang.org/std/primitive.str.html
477487
#[derive(Debug, Clone)]
478488
pub struct StrContentOutputPredicate(
@@ -486,10 +496,31 @@ impl StrContentOutputPredicate {
486496
}
487497
}
488498

489-
impl predicates::Predicate<[u8]> for StrContentOutputPredicate {
499+
impl predicates_core::reflection::PredicateReflection for StrContentOutputPredicate {
500+
fn parameters<'a>(
501+
&'a self,
502+
) -> Box<Iterator<Item = predicates_core::reflection::Parameter<'a>> + 'a> {
503+
self.0.parameters()
504+
}
505+
506+
/// Nested `Predicate`s of the current `Predicate`.
507+
fn children<'a>(&'a self) -> Box<Iterator<Item = predicates_core::reflection::Child<'a>> + 'a> {
508+
self.0.children()
509+
}
510+
}
511+
512+
impl predicates_core::Predicate<[u8]> for StrContentOutputPredicate {
490513
fn eval(&self, item: &[u8]) -> bool {
491514
self.0.eval(item)
492515
}
516+
517+
fn find_case<'a>(
518+
&'a self,
519+
expected: bool,
520+
variable: &[u8],
521+
) -> Option<predicates_core::reflection::Case<'a>> {
522+
self.0.find_case(expected, variable)
523+
}
493524
}
494525

495526
impl fmt::Display for StrContentOutputPredicate {
@@ -517,7 +548,7 @@ mod test {
517548
fn convert_code<I, P>(pred: I) -> P
518549
where
519550
I: IntoCodePredicate<P>,
520-
P: predicates::Predicate<i32>,
551+
P: predicates_core::Predicate<i32>,
521552
{
522553
pred.into_code()
523554
}
@@ -551,7 +582,7 @@ mod test {
551582
fn convert_output<I, P>(pred: I) -> P
552583
where
553584
I: IntoOutputPredicate<P>,
554-
P: predicates::Predicate<[u8]>,
585+
P: predicates_core::Predicate<[u8]>,
555586
{
556587
pred.into_output()
557588
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454

5555
extern crate escargot;
5656
extern crate predicates;
57+
extern crate predicates_core;
58+
extern crate predicates_tree;
5759
#[macro_use]
5860
extern crate serde;
5961

0 commit comments

Comments
 (0)