{"id":16589458,"url":"https://github.com/oknozor/speculoos","last_synced_at":"2025-04-07T06:08:29.264Z","repository":{"id":42193166,"uuid":"407837480","full_name":"oknozor/speculoos","owner":"oknozor","description":"Fluent test assertions for Rust.","archived":false,"fork":false,"pushed_at":"2024-01-10T20:57:41.000Z","size":120,"stargazers_count":43,"open_issues_count":3,"forks_count":9,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-05-01T16:23:41.814Z","etag":null,"topics":["assert","assertion-library","assertions","fluent","fluentassertions","rust","rust-crate","rust-library","rust-test","rust-tests","test","testing","tests"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oknozor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-18T11:08:54.000Z","updated_at":"2024-06-20T19:07:47.850Z","dependencies_parsed_at":"2024-06-20T19:07:46.844Z","dependency_job_id":"a4b585e1-dfc1-4fc5-933e-19cdcc8befbc","html_url":"https://github.com/oknozor/speculoos","commit_stats":{"total_commits":125,"total_committers":11,"mean_commits":"11.363636363636363","dds":0.272,"last_synced_commit":"06b3432ad9efcae692e93dd1d677c0d70452027a"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oknozor%2Fspeculoos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oknozor%2Fspeculoos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oknozor%2Fspeculoos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oknozor%2Fspeculoos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oknozor","download_url":"https://codeload.github.com/oknozor/speculoos/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247601448,"owners_count":20964864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assert","assertion-library","assertions","fluent","fluentassertions","rust","rust-crate","rust-library","rust-test","rust-tests","test","testing","tests"],"created_at":"2024-10-11T23:08:55.646Z","updated_at":"2025-04-07T06:08:29.243Z","avatar_url":"https://github.com/oknozor.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"This is a fork the unmaintained crate [spectral](https://github.com/cfrancia/spectral).\nSpectral as not changed for five years and yet is still very usable, the goal of this fork\nis to add new assertion capabilities without breaking the existing API.\n\n# speculoos\n\n![Crates.io](https://img.shields.io/crates/v/speculoos?style=plastic)\n[![CI](https://github.com/oknozor/speculoos/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/oknozor/speculoos/actions/workflows/CI.yml)\n[![codecov](https://codecov.io/gh/oknozor/speculoos/branch/main/graph/badge.svg?token=MZ45HO00YE)](https://codecov.io/gh/oknozor/speculoos)\n![GitHub](https://img.shields.io/github/license/oknozor/speculoos)\n--- \nFluent test assertions for Rust.\n\nInfluenced by Google Truth and other fluent assertion frameworks.\n\n## Usage\n\nAdd this to your `Cargo.toml`:\n\n```toml\n[dependencies]\nspeculoos = \"0.12.0\"\n```\n\nTo quickly start using assertions, simply use the `prelude` module in your test module:\n\n```rust\nuse speculoos::prelude::*;\n```\n\n## Overview\n\nSpeculoos allows you to write your assertions in a fluent manner by separating out what you are testing with, what you\nare testing against and how you are asserting.\n\n### Simple asserts\n\nFor example, to test that a produced value is equal to an expected value, you would write:\n\n```rust\nassert_that( \u0026 1).is_equal_to(1);\n```\n\nOr that a Vec contains a certain number of elements:\n\n```rust\nlet test_vec = vec![1, 2, 3];\nassert_that( \u0026 test_vec).has_length(3);\n```\n\nThe methods available for asserting depend upon the type under test and what traits are implemented.\n\n### Failure messages\n\nFor failing assertions, the usual panic message follows the following format:\n\n```\n    expected: \u003c2\u003e\n     but was: \u003c1\u003e\n```\n\nTo add additional clarification to the panic message, you can also deliberately state what you are asserting by calling\nthe `asserting(...)` function rather than `assert_that(...)`:\n\n```rust\nasserting( \u0026 \"test condition\").that( \u0026 1).is_equal_to( \u0026 2);\n```\n\nWhich will produce:\n\n```\n    test condition:\n    expected: \u003c2\u003e\n     but was: \u003c1\u003e\n```\n\n### Named Subjects\n\nTo make it more obvious what your subject actually is, you can call `.named(...)` after `assert_that` (or\n`asserting(...).that(...)`), which will print out the provided `\u0026str` as the subject name if the assertion fails.\n\n```\nassert_that(\u0026thing.attributes).named(\u0026\"thing attributes\").has_length(2);\n```\n\nOn failure, this will display:\n\n```\n    for subject [thing attributes]\n    expected: vec to have length \u003c2\u003e\n     but was: \u003c1\u003e\n```\n\n### Mapping values\n\nIf you want to assert against a value contained within a struct, you can call `map(...)` with a closure, which will\ncreate a new `Spec` based upon the return value of the closure. You can then call any applicable assertions against the\nmapped value.\n\n```rust\nlet test_struct = TestStruct { value: 5 };\nassert_that( \u0026 test_struct).map( | val| \u0026 val.value).is_equal_to(5);\n```\n\n## Macros\n\nThe macros are no longer needed as the line number is correctly passed through for the assertions.\n\n## Assertions (Basic)\n\nNote: Descriptions and examples for each of the assertions are further down in this readme.\n\n### General\n\n#### is_equal_to\n\n#### is_not_equal_to\n\n#### matches\n\n### Booleans\n\n#### is_true\n\n#### is_false\n\n### Numbers\n\n#### is_less_than\n\n#### is_less_than_or_equal_to\n\n#### is_greater_than\n\n#### is_greater_than_or_equal_to\n\n### Floats (optional)\n\n#### is_close_to\n\n### Options\n\n#### is_some -\u003e (returns a new Spec with the Option value)\n\n#### is_none\n\n#### contains_value\n\n### Paths\n\n#### exists\n\n#### does_not_exist\n\n#### is_a_file\n\n#### is_a_directory\n\n#### has_file_name\n\n### Results\n\n#### is_ok -\u003e (returns a new Spec with the Ok value)\n\n#### is_err -\u003e (returns a new Spec with the Err value)\n\n#### is_ok_containing\n\n#### is_err_containing\n\n### Strings\n\n#### starts_with\n\n#### ends_with\n\n#### contains\n\n#### is_empty\n\n### Vectors\n\n#### has_length\n\n#### is_empty\n\n### HashMaps\n\n#### has_length\n\n#### is_empty\n\n#### contains_key -\u003e (returns a new Spec with the key value)\n\n#### does_not_contain_key\n\n#### contains_entry\n\n#### does_not_contain_entry\n\n### HashSets\n\n#### has_length\n\n#### is_empty\n\n#### contains (from iterator)\n\n#### does_not_contain (from iterator)\n\n#### contains_all_of (from iterator)\n\n### IntoIterator/Iterator\n\n#### contains\n\n#### does_not_contain\n\n#### contains_all_of\n\n#### mapped_contains\n\n#### equals_iterator\n\n### IntoIterator\n\n#### matching_contains\n\n## Optional Features\n\n### Num Crate\n\nThe `num` crate is used for `Float` assertions. This feature will be enabled by default, but if you don't want the\ndependency on `num`, then simply disable it.\n\n## Assertions (Detailed)\n\nAs a general note, any type under test will usually need to implement at least `Debug`. Other assertions will have\nvarying bounds attached to them.\n\n### General\n\n#### is_equal_to\n\nAsserts that the subject and the expected value are equal. The subject type must implement `PartialEq`.\n\n##### Example\n\n```rust\nassert_that( \u0026 \"hello\").is_equal_to( \u0026 \"hello\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: \u003c2\u003e\n\t but was: \u003c1\u003e\n```\n\n#### is_not_equal_to\n\nAsserts that the subject and the expected value are not equal. The subject type must implement `PartialEq`.\n\n##### Example\n\n```rust\nassert_that( \u0026 \"hello\").is_not_equal_to( \u0026 \"hello\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: \u003c1\u003e not equal to \u003c1\u003e\n\t but was: equal\n```\n\n#### matches\n\nAccepts a function accepting the subject type which returns a bool. Returning false will cause the assertion to fail.\n\nNOTE: The resultant panic message will only state the actual value. It's recommended that you write your own assertions\nrather than relying upon this.\n\n##### Example\n\n```rust\nassert_that( \u0026 \"Hello\").matches( | val| val.eq( \u0026 \"Hello\"));\n```\n\n##### Failure Message\n\n```bash\n\texpectation failed for value \u003c\"Hello\"\u003e\n```\n\n### Booleans\n\n#### is_true\n\nAsserts that the subject is true. The subject type must be `bool`.\n\n##### Example\n\n```rust\nassert_that( \u0026 true).is_true(); \n```\n\n##### Failure Message\n\n```bash\n\texpected: bool to be \u003ctrue\u003e\n\t but was: \u003cfalse\u003e\n```\n\n#### is_false\n\nAsserts that the subject is false. The subject type must be `bool`.\n\n##### Example\n\n```rust\nassert_that( \u0026 false).is_false();\n```\n\n##### Failure Message\n\n```bash\n\texpected: bool to be \u003cfalse\u003e\n\t but was: \u003ctrue\u003e\n```\n\n### Numbers\n\n#### is_less_than\n\nAsserts that the subject value is less than the expected value. The subject type must implement `PartialOrd`.\n\n##### Example\n\n```rust\nassert_that( \u0026 1).is_less_than( \u0026 2);\n```\n\n##### Failure Message\n\n```bash\n\texpected: value less than \u003c2\u003e\n\t but was: \u003c3\u003e\n```\n\n#### is_less_than_or_equal_to\n\nAsserts that the subject is less than or equal to the expected value. The subject type must implement `PartialOrd`.\n\n##### Example\n\n```rust\nassert_that( \u0026 2).is_less_than_or_equal_to( \u0026 2);\n```\n\n##### Failure Message\n\n```bash\n\texpected: value less than or equal to \u003c2\u003e\n\t but was: \u003c3\u003e\n```\n\n#### is_greater_than\n\nAsserts that the subject is greater than the expected value. The subject type must implement `PartialOrd`.\n\n##### Example\n\n```rust\nassert_that( \u0026 2).is_greater_than( \u0026 1);\n```\n\n##### Failure Message\n\n```bash\n\texpected: value greater than \u003c3\u003e\n\t but was: \u003c2\u003e\n```\n\n#### is_greater_than_or_equal_to\n\nAsserts that the subject is greater than or equal to the expected value. The subject type must implement `PartialOrd`.\n\n##### Example\n\n```rust\nassert_that( \u0026 2).is_greater_than_or_equal_to( \u0026 1); \n```\n\n##### Failure Message\n\n```bash\n\texpected: value greater than or equal to \u003c3\u003e\n\t but was: \u003c2\u003e\n```\n\n### Floats (optional)\n\n#### is_close_to\n\nAsserts that the subject is close to the expected value by the specified tolerance. The subject type must implement\n`Float` and `Debug`.\n\n##### Example\n\n```rust\nassert_that( \u0026 2.0f64).is_close_to(2.0f64, 0.01f64);\n```\n\n##### Failure Message\n\n```bash\n\texpected: float close to \u003c1\u003e (tolerance of \u003c0.01\u003e)\n\t but was: \u003c2\u003e\n```\n\n### Options\n\n#### is_some -\u003e (returns a new Spec with the Option value)\n\nAsserts that the subject is `Some`. The subject type must be an `Option`.\n\nThis will return a new `Spec` containing the unwrapped value if it is `Some`.\n\n##### Example\n\n```rust\nassert_that( \u0026 Some(1)).is_some();\n```\n\n##### Chaining\n\n```rust\nassert_that( \u0026 option).is_some().is_equal_to( \u0026 \"Hello\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: option[some]\n\t but was: option[none]\n```\n\n#### is_none\n\nAsserts that the subject is `None`. The value type must be an `Option`.\n\n##### Example\n\n```rust\nassert_that( \u0026 Option::None::\u003cString\u003e).is_none();\n```\n\n##### Failure Message\n\n```bash\n\texpected: option[none]\n\t but was: option\u003c\"Hello\"\u003e\n```\n\n#### contains_value\n\nAsserts that the subject is a `Some` containing the expected value. The subject type must be an `Option`.\n\n##### Example\n\n```rust\nassert_that( \u0026 Some(1)).contains_value( \u0026 1);\n```\n\n##### Failure Message\n\n```bash\n\texpected: option to contain \u003c\"Hi\"\u003e\n\t but was: \u003c\"Hello\"\u003e\n```\n\n### Paths\n\n#### exists\n\nAsserts that the subject `Path` or `PathBuf` refers to an existing location.\n\n##### Example\n\n```rust\nassert_that( \u0026 Path::new(\"/tmp/file\")).exists();\n```\n\n##### Failure Message\n\n```bash\n\texpected: Path of \u003c\"/tmp/file\"\u003e to exist\n\t but was: a non-existent Path\n```\n\n#### does_not_exist\n\nAsserts that the subject `Path` or `PathBuf` does not refer to an existing location.\n\n##### Example\n\n```rust\nassert_that( \u0026 Path::new(\"/tmp/file\")).does_not_exist();\n```\n\n##### Failure Message\n\n```bash\n\texpected: Path of \u003c\"/tmp/file\"\u003e to not exist\n     but was: a resolvable Path\n```\n\n#### is_a_file\n\nAsserts that the subject `Path` or `PathBuf` refers to an existing file.\n\n##### Example\n\n```rust\nassert_that( \u0026 Path::new(\"/tmp/file\")).is_a_file();\n```\n\n##### Failure Message\n\n```bash\n\texpected: Path of \u003c\"/tmp/file\"\u003e to be a file\n\t but was: not a resolvable file\n```\n\n#### is_a_directory\n\nAsserts that the subject `Path` or `PathBuf` refers to an existing directory.\n\n##### Example\n\n```rust\nassert_that( \u0026 Path::new(\"/tmp/dir/\")).is_a_directory();\n```\n\n##### Failure Message\n\n```bash\n\texpected: Path of \u003c\"/tmp/dir/\"\u003e to be a directory\n\t but was: not a resolvable directory\n```\n\n#### has_file_name\n\nAsserts that the subject `Path` or `PathBuf` has the expected file name.\n\n##### Example\n\n```rust\nassert_that( \u0026 Path::new(\"/tmp/file\")).has_file_name( \u0026 \"file\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: Path with file name of \u003cpom.xml\u003e\n\t but was: \u003cCargo.toml\u003e\n```\n\n### Results\n\n#### is_ok -\u003e (returns a new Spec with the Ok value)\n\nAsserts that the subject is `Ok`. The value type must be a `Result`.\n\nThis will return a new `Spec` containing the unwrapped value if it is `Ok`.\n\n##### Example\n\n```rust\nassert_that( \u0026 Result::Ok::\u003cusize, usize\u003e(1)).is_ok();\n```\n\n##### Chaining\n\n```rust\nlet result: Result\u003c \u0026 str, \u0026 str\u003e = Ok(\"Hello\");\nassert_that( \u0026 result).is_ok().is_equal_to( \u0026 \"Hello\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: result[ok]\n\t but was: result[error]\u003c\"Oh no\"\u003e\n```\n\n#### is_err -\u003e (returns a new Spec with the Err value)\n\nAsserts that the subject is `Err`. The value type must be a `Result`.\n\nThis will return a new `Spec` containing the unwrapped value if it is `Err`.\n\nNote: This used to be called `is_error`, but has been renamed to match standard Rust naming.\n\n##### Example\n\n```rust\nassert_that( \u0026 Result::Err::\u003cusize, usize\u003e(1)).is_err();\n```\n\n##### Chaining\n\n```rust\nlet result: Result\u003c \u0026 str, \u0026 str\u003e = Err(\"Hello\");\nassert_that( \u0026 result).is_err().is_equal_to( \u0026 \"Hello\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: result[error]\n\t but was: result[ok]\u003c\"Hello\"\u003e\n```\n\n#### is_ok_containing\n\nAsserts that the subject is an `Ok` Result containing the expected value. The subject type must be a `Result`.\n\n##### Example\n\n```rust\nassert_that( \u0026 Result::Ok::\u003cusize, usize\u003e(1)).is_ok_containing( \u0026 1);\n```\n\n##### Failure Message\n\n```bash\n\texpected: Result[ok] containing \u003c\"Hi\"\u003e\n\t but was: Result[ok] containing \u003c\"Hello\"\u003e\n```\n\n#### is_err_containing\n\nAsserts that the subject is an `Err` Result containing the expected value. The subject type must be a `Result`.\n\n##### Example\n\n```rust\nassert_that( \u0026 Result::Err::\u003cusize, usize\u003e(1)).is_err_containing( \u0026 1);\n```\n\n##### Failure Message\n\n```bash\n\texpected: Result[err] containing \u003c\"Oh no\"\u003e\n\t but was: Result[err] containing \u003c\"Whoops\"\u003e\n```\n\n### Strings\n\n#### starts_with\n\nAsserts that the subject `\u0026str` or `String` starts with the provided `\u0026str`.\n\n##### Example\n\n```rust\nassert_that( \u0026 \"Hello\").starts_with( \u0026 \"H\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: string starting with \u003c\"A\"\u003e\n\t but was: \u003c\"Hello\"\u003e\n```\n\n#### ends_with\n\nAsserts that the subject `\u0026str` or `String` ends with the provided `\u0026str`.\n\n##### Example\n\n```rust\nassert_that( \u0026 \"Hello\").ends_with( \u0026 \"o\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: string ending with \u003c\"A\"\u003e\n\t but was: \u003c\"Hello\"\u003e\n```\n\n#### contains\n\nAsserts that the subject `\u0026str` or `String` contains the provided `\u0026str`.\n\n##### Example\n\n```rust\nassert_that( \u0026 \"Hello\").contains( \u0026 \"e\");\n```\n\n#### does_not_contain\n\nAsserts that the subject `\u0026str` or `String` does not contain the provided `\u0026str`.\n\n##### Example\n\n```rust\nassert_that( \u0026 \"Hello\").does_not_contain( \u0026 \"Bonjour\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: string containing \u003c\"A\"\u003e\n\t but was: \u003c\"Hello\"\u003e\n```\n\n#### is_empty\n\nAsserts that the subject `\u0026str` or `String` represents an empty string.\n\n##### Example\n\n```rust\nassert_that( \u0026 \"\").is_empty();\n```\n\n##### Failure Message\n\n```bash\n\texpected: an empty string\n\t but was: \u003c\"Hello\"\u003e\n```\n\n### Vectors\n\n#### has_length\n\nAsserts that the length of the subject vector is equal to the provided length. The subject type must be of `Vec`.\n\n##### Example\n\n```rust\nassert_that( \u0026 vec![1, 2, 3, 4]).has_length(4);\n```\n\n##### Failure Message\n\n```bash\n\texpected: vec to have length \u003c1\u003e\n\t but was: \u003c3\u003e\n```\n\n#### is_empty\n\nAsserts that the subject vector is empty. The subject type must be of `Vec`.\n\n##### Example\n\n```rust\nlet test_vec: Vec\u003cu8\u003e = vec![];\nassert_that( \u0026 test_vec).is_empty();\n```\n\n##### Failure Message\n\n```bash\n\texpected: an empty vec\n\t but was: a vec with length \u003c1\u003e\n```\n\n### HashMaps\n\n#### has_length\n\nAsserts that the length of the subject hashmap is equal to the provided length. The subject type must be of `HashMap`.\n\n##### Example\n\n```rust\nlet mut test_map = HashMap::new();\ntest_map.insert(1, 1);\ntest_map.insert(2, 2);\n\nassert_that( \u0026 test_map).has_length(2);\n```\n\n##### Failure Message\n\n```bash\n\texpected: hashmap to have length \u003c1\u003e\n\t but was: \u003c2\u003e\n```\n\n#### is_empty\n\nAsserts that the subject hashmap is empty. The subject type must be of `HashMap`.\n\n##### Example\n\n```rust\nlet test_map: HashMap\u003cu8, u8\u003e = HashMap::new();\nassert_that( \u0026 test_map).is_empty();\n```\n\n##### Failure Message\n\n```bash\n\texpected: an empty hashmap\n\t but was: a hashmap with length \u003c1\u003e\n```\n\n#### contains_key -\u003e (returns a new Spec with the key value)\n\nAsserts that the subject hashmap contains the expected key. The subject type must be of `HashMap`.\n\nThis will return a new `Spec` containing the associated value if the key is present.\n\n##### Example\n\n```rust\nlet mut test_map = HashMap::new();\ntest_map.insert(\"hello\", \"hi\");\n\nassert_that( \u0026 test_map).contains_key( \u0026 \"hello\");\n```\n\n##### Chaining\n\n```rust\nlet mut test_map = HashMap::new();\ntest_map.insert(\"hello\", \"hi\");\n\nassert_that( \u0026 test_map).contains_key( \u0026 \"hello\").is_equal_to( \u0026 \"hi\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: hashmap to contain key \u003c\"hello\"\u003e\n\t but was: \u003c[\"hey\", \"hi\"]\u003e\n```\n\n#### does_not_contain_key\n\nAsserts that the subject hashmap does not contain the provided key. The subject type must be of `HashMap`.\n\n##### Example\n\n```rust\nlet mut test_map = HashMap::new();\ntest_map.insert(\"hello\", \"hi\");\n\nassert_that( \u0026 test_map).does_not_contain_key( \u0026 \"hey\");\n```\n\n##### Failure Message\n\n```bash\n\texpected: hashmap to not contain key \u003c\"hello\"\u003e\n\t but was: present in hashmap\n```\n\n#### contains_entry\n\nAsserts that the subject hashmap contains the expected key with the expected value. The subject type must be of\n`HashMap`.\n\n##### Example\n\n```rust\nlet mut test_map = HashMap::new();\ntest_map.insert(\"hello\", \"hi\");\n\nassert_that( \u0026 test_map).contains_entry( \u0026 \"hello\", \u0026 \"hi\");\n```\n\n##### Failure Message\n\n```bash\n    expected: hashmap containing key \u003c\"hi\"\u003e with value \u003c\"hey\"\u003e\n     but was: key \u003c\"hi\"\u003e with value \u003c\"hello\"\u003e instead\n```\n\n#### does_not_contain_entry\n\nAsserts that the subject hashmap does not contain the provided key and value. The subject type must be of `HashMap`.\n\n##### Example\n\n```rust\nlet mut test_map = HashMap::new();\ntest_map.insert(\"hello\", \"hi\");\n\nassert_that( \u0026 test_map).does_not_contain_entry( \u0026 \"hello\", \u0026 \"hey\");\n```\n\n##### Failure Message\n\n```bash\n    expected: hashmap to not contain key \u003c\"hello\"\u003e with value \u003c\"hi\"\u003e\n     but was: present in hashmap\n```\n\n### HashSets\n\n#### has_length\n\nAsserts that the length of the subject hashset is equal to the provided length. The subject type must be of `HashSet`.\n\n##### Example\n\n```rust\nlet mut test_map = HashSet::new();\ntest_map.insert(1);\ntest_map.insert(2);\n\nassert_that( \u0026 test_map).has_length(2);\n```\n\n##### Failure Message\n\n```bash\n\texpected: hashset to have length \u003c1\u003e\n\t but was: \u003c2\u003e\n```\n\n#### is_empty\n\nAsserts that the subject hashset is empty. The subject type must be of `HashSet`.\n\n##### Example\n\n```rust\nlet test_map: HashSet\u003cu8\u003e = HashSet::new();\nassert_that( \u0026 test_map).is_empty();\n```\n\n##### Failure Message\n\n```bash\n\texpected: an empty hashset\n\t but was: a hashset with length \u003c1\u003e\n```\n\n#### Iterator based asserts\n\nSince a hashset is implements Iterator, all the Iterator assertions below also apply (e.g. contains \u0026 does_not_contain)\n\n### IntoIterator/Iterator\n\n#### contains\n\nAsserts that the subject contains the provided value. The subject must implement `IntoIterator` or `Iterator`, and the\ncontained type must implement `PartialEq` and `Debug`.\n\n##### Example\n\n```rust\nlet test_vec = vec![1, 2, 3];\nassert_that( \u0026 test_vec).contains( \u0026 2);\n```\n\n##### Failure Message\n\n```bash\n\texpected: iterator to contain \u003c1\u003e\n\t but was: \u003c[5, 6]\u003e\n```\n\n#### does_not_contain\n\nAsserts that the subject does not contain the provided value. The subject must implement `IntoIterator` or `Iterator`,\nand the contained type must implement `PartialEq` and `Debug`.\n\n##### Example\n\n```rust\nlet test_vec = vec![1, 2, 3];\nassert_that( \u0026 test_vec).does_not_contain( \u0026 4);\n```\n\n##### Failure Message\n\n```bash\n\texpected: iterator to not contain \u003c1\u003e\n\t but was: \u003c[1, 2]\u003e\n```\n\n#### contains_all_of\n\nAsserts that the subject contains all of the provided values. The subject must implement `IntoIterator` or `Iterator`,\nand the contained type must implement `PartialEq` and `Debug`.\n\n##### Example\n\n```rust\nlet test_vec = vec![1, 2, 3];\nassert_that( \u0026 test_vec.iter()).contains_all_of( \u0026 vec![\u00262, \u00263]);\n```\n\n##### Failure Message\n\n```bash\n    expected: iterator to contain items \u003c[1, 6]\u003e\n     but was: \u003c[1, 2, 3]\u003e\n```\n\n#### mapped_contains\n\nMaps the values of the subject before asserting that the mapped subject contains the provided value. The subject must\nimplement IntoIterator, and the type of the mapped value must implement `PartialEq`.\n\nNOTE: The panic message will refer to the mapped values rather than the values present in the original subject.\n\n##### Example\n\n```rust\n#[derive(PartialEq, Debug)]\nstruct Simple {\n    pub val: usize,\n}\n\n...\n\nassert_that( \u0026 vec![Simple { val: 1 }, Simple { val: 2 }]).mapped_contains( | x| \u0026 x.val, \u0026 2);\n```\n\n##### Failure Message\n\n```bash\n\texpected: iterator to contain \u003c5\u003e\n\t but was: \u003c[1, 2, 3]\u003e\n```\n\n#### equals_iterator\n\nAsserts that the subject is equal to provided iterator. The subject must implement `IntoIterator` or `Iterator`, the\ncontained type must implement `PartialEq` and `Debug` and the expected value must implement Iterator and Clone.\n\n##### Example\n\n```rust\nlet expected_vec = vec![1, 2, 3];\nlet test_vec = vec![1, 2, 3];\nassert_that( \u0026 test_vec).equals_iterator( \u0026 expected_vec.iter());\n```\n\n##### Failure Message\n\n```bash\n\texpected: Iterator item of \u003c4\u003e (read \u003c[1, 2]\u003e)\n\t but was: Iterator item of \u003c3\u003e (read \u003c[1, 2]\u003e)\n```\n\n### IntoIterator\n\n#### matching_contains\n\nAsserts that the subject contains a matching item by using the provided function. The subject must implement\n`IntoIterator`, and the contained type must implement `Debug`.\n\n##### Example\n\n```rust\nlet mut test_into_iter = LinkedList::new();\ntest_into_iter.push_back(TestEnum::Bad);\ntest_into_iter.push_back(TestEnum::Good);\ntest_into_iter.push_back(TestEnum::Bad);\n\nassert_that( \u0026 test_into_iter).matching_contains( | val| {\nmatch val {\n\u0026 TestEnum::Good =\u003e true,\n_ =\u003e false\n}\n});\n```\n\n##### Failure Message\n\n```bash\nexpectation failed for iterator with values \u003c[Bad, Bad, Bad]\u003e\n```\n\n## How it works\n\nThe `Spec` struct implements a number of different bounded traits which provide assertions based upon the bound type.\n\nAs a single example, length assertions are provided by the `VecAssertions` trait:\n\n```rust\npub trait VecAssertions {\n    fn has_length(self, expected: usize);\n} \n```\n\nWhich is then implemented by Spec:\n\n```rust\nimpl\u003c's, T\u003e VecAssertions for Spec\u003c's, Vec\u003cT\u003e\u003e {\n    fn has_length(self, expected: usize) {\n        ...\n    }\n} \n```\n\nNaturally traits need to be included with a `use` before they apply, but to avoid an excessive number of `use`\nstatements there is a `prelude` module which re-exports commonly used assertion traits.\n\n## Creating your own\n\nTo create your own assertions, simply create a new trait containing your assertion methods and implement Spec against\nit.\n\nTo fail an assertion, create a new `AssertionFailure` struct using `from_spec(...)` within your assertion method and\npass in `self`.\n\n`AssertionFailure` also implements builder methods `with_expected(...)`, `with_actual(...)` and `fail(...)`, which\nprovides the necessary functionality to fail the test with the usual message format. If you need greater control of the\nfailure message, you can call `fail_with_message(...)` which will directly print the provided message.\n\nIn either case, any description provided using `asserting(...)` will always be prepended to the panic message.\n\nFor example, to create an assertion that the length of a `Vec` is at least a certain value:\n\n```rust\ntrait VecAtLeastLength {\n    fn has_at_least_length(\u0026mut self, expected: usize);\n}\n\nimpl\u003c's, T\u003e VecAtLeastLength for Spec\u003c's, Vec\u003cT\u003e\u003e {\n    fn has_at_least_length(\u0026mut self, expected: usize) {\n        let subject = self.subject;\n        if expected \u003e subject.len() {\n            AssertionFailure::from_spec(self)\n                .with_expected(format!(\"vec with length at least \u003c{}\u003e\", expected))\n                .with_actual(format!(\"\u003c{}\u003e\", subject.len()))\n                .fail();\n        }\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foknozor%2Fspeculoos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foknozor%2Fspeculoos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foknozor%2Fspeculoos/lists"}