Skip to content

Conversation

@tgmof
Copy link

@tgmof tgmof commented Jan 14, 2026

Hello there!

I'm learning Rust and found on some Reddit post that this repo may need contributors, and I took this issue 16 as my playground for my first Rust contribution.

Here is the design idea:

  • Reusing the assert_contains to avoid a lot of additional boilerplate / code copied around.
  • Make it still very clear to the user when "whatever he's trying to assert" does not have a contains method and offer an immediate workaround in the instructions (namely, just add a => IntoIterator suffix to the Collection/Iterator in the macro call).
  • Make sure the "fallback" (that iterates over the elements because no contains is available) works for ALL iterable (collections and iterators).

@joelparkerhenderson
Copy link
Member

joelparkerhenderson commented Jan 14, 2026

Welcome to Rust! <3 Good work with this pull request. The concept of iter -> any -> eq makes sense, and also you're doing the right kinds of things by using the existing styles, tests, and the like. Really well done.

There are a few atypical aspects to this crate because it's specifically for quality control testing and for widespread software, for you to consider.

The crate aims to have each assert concept do exactly one thing, ideally as close to existing coding naming; this means aiming away from what's broadly known as casting or polymorphism, and aiming toward explicit method names. For example, you can imagine assert_contains(rectangle1, rectangle2) which would call code rectangle1.contains(rectangle2) which would do a geometric calculation. By doing exactly one thing, it makes the surface area concise and the API more stable.

For your PR, you use casting/polymorphism which is technically fine and correct, yet which makes assert_contains do two different things. I have an idea that can gives even more capabilities by pulling your concept into a new assert kind, such as assert_any_eq, that does exactly one thing. You can look at the existing macro assert_any to see how it works. The developer would invoke iter, such as assert_any_eq(a.iter(), 1).

Notice that you also can create assert_{all,any}_{eq,lt,le,gt,ge,ne}. This would be a whole bunch of new helpful code, if you want to do it.

As an aside, take a closer look at your tests. You have one that looks as if you expect a binary heap to contain an item that's between the min and max, whereas the actual Rust std lib is doing any eq. The test code you wrote is essentially this:

    let a: BinaryHeap<String> = BinaryHeap::from(vec![String::from("1"), String::from("3")]);
    let b: String = String::from("2"); // The heap does contain this in the sense of min-max, but not elementwise.
    if a.iter().any(|x| x == &b) {
        println!("true")
    } else {
        println!("false")
    }

What do you think about updating your PR so it isn't for assert_contains, rather is for 12 new files?

  • assert_any_eq
  • assert_any_ne
  • assert_any_lt
  • assert_any_le
  • assert_any_gt
  • assert_any_ge
  • assert_all_eq
  • assert_all_ne
  • assert_all_lt
  • assert_all_le
  • assert_all_gt
  • assert_all_ge

As another aside, your PR energized me today to look more closely at the existing assert_all and assert_any, which led me to find and fix one glitch in the docs, and also to redo the code from using into_iter to iter as a reference, thus improving the speed and simplicity. So thank you very much for this too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants