#matcher #experimental #framework #test-framework #r-spec

bin+lib expecto

Experimental testing framework for Rust inspired by RSpec

1 unstable release

0.0.1 Dec 21, 2023

#34 in #matcher

MIT license

23KB
588 lines

Matchers

  • to_eq
  • to_panic
  • to_be_in_range
  • to_match_array or to_contain_exactly

Questionable:

  • to_have_len
  • to_be_empty

New Ideas

Use std::panic::take_hook and set_hook

Try to use take_hook and set_hook to interfere panic message in ToPanic matcher. Also consider using the hooks to create a friendly panic message.

Display the test name

In the panic message display the test name (function name).

Improve error message

Expected not to equal 4
Got 4

/home/sergey/dev/rust/expecto/src/main.rs:22

by showing the piece of the code, where a chunk of the code with expectation:

Expected not to equal 4
Got 4

expect(square(2)).not_to_eq(4);

/home/sergey/dev/rust/expecto/src/main.rs:22

This can be done by reading a source code file.

Use #[must_use]

Add #[must_use] on Subject, to ensure that subject is propoerly tested.

Failed ideas

// pub trait ToEq<R> {
//     fn to_eq(self, rhs: R);
//     fn not_to_eq(self, rhs: R);
// }
expect(2.0 + 2.0).to_eq(4.1);

Provide custom error message as second argument by (hopefully) using another trait:

// pub trait ToEqWithMsg<R> {
//     fn to_eq(self, rhs: R, msg: impl Into<String>);
//     fn not_to_eq(self, rhs: R, msg: impl Into<String>);
// }
expect(2.0 + 2.0).to_eq(4.1, "This should not happen!");

Compile error:

error[E0034]: multiple applicable items in scope
 --> src/main.rs:4:23
  |
4 |     expect(2.0 + 2.0).to_eq(4.1, "This should not happen!");
  |                       ^^^^^ multiple `to_eq` found
  |
  = note: candidate #1 is defined in an impl of the trait `expecto::prelude::ToEq` for the type `Subject<L>`
  = note: candidate #2 is defined in an impl of the trait `expecto::prelude::ToEqWithMsg` for the type `Subject<L>`

Syntax ideas

// test target (subject)
let sum = 2 + 2;

// Old Ruby should
// Cons:
//  * pollutes namespace with functions like `eq`
//  * Probably too many parenthesis

sum.should(eq(4));
sum.should_not(eq(4).msg("Not four!"));


sum.must_eq(4);
sum.must_not_eq(4);
sum.must_not_eq(4);

expect(sum).to_eq(4)
    .or(sum).to_eq(5);

Drop for all matchers

impl<T: Matcher + ?Sized> Drop for T {
    fn drop() {
        println!("Goodbye matcher");
    }
}

Fails to compile with:

   |
98 | impl<T: Matcher + ?Sized> Drop for T {
   |      ^ type parameter `T` must be used as the type parameter for some local type
   |
   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
   = note: only traits defined in the current crate can be implemented for a type parameter

error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions

Dependencies

~3–13MB
~124K SLoC