{"id":33941523,"url":"https://github.com/mindsbackyard/galvanic-assert","last_synced_at":"2026-04-01T20:44:23.921Z","repository":{"id":57632944,"uuid":"82859172","full_name":"mindsbackyard/galvanic-assert","owner":"mindsbackyard","description":"A comprehensive set of matcher-based assertions for easier testing of Rust code","archived":false,"fork":false,"pushed_at":"2020-03-25T23:13:01.000Z","size":90,"stargazers_count":40,"open_issues_count":3,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-14T04:41:44.716Z","etag":null,"topics":["assertion-library","assertion-macros","assertions","fluent","matchers","rust","rust-library","testing"],"latest_commit_sha":null,"homepage":null,"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/mindsbackyard.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}},"created_at":"2017-02-22T22:32:36.000Z","updated_at":"2024-02-26T03:22:04.000Z","dependencies_parsed_at":"2022-08-31T13:20:54.533Z","dependency_job_id":null,"html_url":"https://github.com/mindsbackyard/galvanic-assert","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/mindsbackyard/galvanic-assert","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsbackyard%2Fgalvanic-assert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsbackyard%2Fgalvanic-assert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsbackyard%2Fgalvanic-assert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsbackyard%2Fgalvanic-assert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mindsbackyard","download_url":"https://codeload.github.com/mindsbackyard/galvanic-assert/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsbackyard%2Fgalvanic-assert/sbom","scorecard":{"id":647869,"data":{"date":"2025-08-11","repo":{"name":"github.com/mindsbackyard/galvanic-assert","commit":"192363160395a6b9a9250dff573c47e08d7df11e"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}}]},"last_synced_at":"2025-08-21T12:38:20.165Z","repository_id":57632944,"created_at":"2025-08-21T12:38:20.166Z","updated_at":"2025-08-21T12:38:20.166Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31291782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["assertion-library","assertion-macros","assertions","fluent","matchers","rust","rust-library","testing"],"created_at":"2025-12-12T16:26:18.412Z","updated_at":"2026-04-01T20:44:23.912Z","avatar_url":"https://github.com/mindsbackyard.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"Galvanic-assert: Matcher-based assertions and expectations for easier testing\n=============================================================================\n[![Build Status](https://travis-ci.org/mindsbackyard/galvanic-assert.svg?branch=master)](https://travis-ci.org/mindsbackyard/galvanic-assert)\n[![Documentation](https://docs.rs/galvanic-assert/badge.svg)](https://docs.rs/galvanic-assert)\n[![Crates.io](https://img.shields.io/crates/v/galvanic-assert.svg)](https://crates.io/crates/galvanic-assert)\n\nThis crate provides a new assertion macros (`assert_that!`, `expect_that!`, `get_expectation_for!`) based on **matching predicates** (matchers) to\n * make **writing** asserts easier\n * make **reading** asserts comprehendable\n * easily **extend** the assertion framework\n * provide a large list **common matchers**\n * integrate with **[galvanic-test](https://www.github.com/mindsbackyard/galvanic-test)** and **[galvanic-mock](https://www.github.com/mindsbackyard/galvanic-mock)**\n * be used with your favourite test framework\n\nThe crate is part of **galvanic**---a complete test framework for **Rust**.\nThe framework is shipped in three parts, so you can choose to use only the parts you need.\n\nThe 2-minute tutorial\n---------------------\nEach assertion has the form `assert_that!(SOME_VALUE, MATCHES_SOMETHING);`.\nTo check if some value satisfies some matching predicate, e.g., `less_than`, `contains_in_order`, `is_variant!`, ...; we can write something like the following to when operating on a single value:\n```rust\n#[macro_use]\nextern crate galvanic_assert;\nuse galvanic_assert::matchers::*;\n\n#[test]\nfn expression_should_compute_correct_value {\n    assert_that!(\u00261+2, eq(3));\n    // or more wordy ...\n    assert_that!(\u00261+2, is(eq(3)));\n}\n```\n\nor assert properties of collections ...\n```rust\nuse galvanic_assert::matchers::collection::*;\n#[test]\nfn expression_should_compute_correct_value {\n    /// check for containment\n    assert_that!(\u0026vec![5,1,3,4,2], contains_in_any_order(vec![1,2,3,4,5]));\n    // check for internal structure\n    assert_that!(\u0026vec![4,3,2,1], sorted_descending());\n}\n```\n\nor of variants ...\n```rust\nenum Variants {\n    First(i32),\n    Second { x: i32, y: i32 },\n    Third\n}\n\n#[test]\nfn should_be_the_correct_variant {\n    let var = Second { x: 1, y: 2 };\n    assert_that!(\u0026var, is_variant!(Variants::Second));\n}\n```\n\nIf you need to assert multiple fields of a struct or enum you can use a structural matcher ...\n```rust\nenum Baz {\n    Var1 { x: i32, y: f64 },\n    Var2(i32, f64)\n}\n\n#[test]\nfn expression_should_compute_correct_value {\n    let var1 = Baz::Var1 { x: 12, y: 23.4 };\n    assert_that!(\u0026var1, has_structure!(Baz::Var1 {\n        x: eq(12),\n        y: lt(25.0)\n    }));\n\n    let var2 = Baz::Var2(12, 23.4);\n    assert_that!(\u0026var2, has_structure!(Baz::Var2 [eq(12), lt(25.0)] ));\n}\n```\n\nIt is also possible to combine multiple matchers to create more expressive ones ...\n```rust\n#[test]\nfn expression_should_compute_correct_value {\n    // invert the meaning of a matcher\n    assert_that!(\u00261+2, not(greater_than(3)));\n    // join several matchers conjunctively\n    assert_that!(\u00261+2, all_of!(greater_than(0), less_than(5)));\n    // join several matchers disjunctively\n    assert_that!(\u00261+2, any_of!(greater_than(5), less_than(5)));\n}\n```\n\nIf this is not enough you can write your own matchers, either as a closure ...\n```rust\n#[test]\nfn expression_should_compute_correct_value {\n    assert_that!(\u00261+2, |x| {\n        let builder = MatchResultBuilder::for_(\"odd\");\n        if x % 2 == 1 { builder.matched() } else { builder.failed_because(\"result is not odd\") }\n    });\n}\n```\n\nor if it is easy enough, as an expression ...\n```rust\n#[test]\nfn expression_should_compute_correct_value {\n    let val = 1 + 2;\n    assert_that!(val % 2 == 1, otherwise \"result is not odd\");\n}\n```\nIf it is more complex implement the `Matcher` trait for some struct representing the state of the matcher.\n\nAsserting positive things is good, but sometimes we expect that something goes horribly wrong ...\n```rust\nfn press_big_red_button() {\n    panic!(\"shouldn't have done that ...\");\n}\n\n#[test]\nfn someting_should_go_wrong {\n    assert_that!(press_big_red_button(), panics);\n}\n```\n\n... except when it doesn't.\n```rust\nfn press_faulty_red_button() {\n    return;\n    panic!(\"shouldn't have done that ...\");\n}\n\n#[test]\nfn everything_is_fine {\n    assert_that!(press_faulty_red_button(), does not panic);\n}\n```\n\nAnother 2-minutes for learning about expectations\n-------------------------------------------------\nAn assertion is immediately check for correctness.\nThat means that any later assertion is not executed and you might lose valuable information for debugging the error.\nBasically you want as much information as possible to do that.\nTherefore the the macros `expect_that!` and `get_expectation_for!` have been introduced.\n\nBoth state an expectation instead of an assertion in exactly the same way as `assert_that!`---so anything you learned from the last section still applies.\nThe condition is still checked at the point of specification but the inspection of the result is deferred to a later point in time.\n\nThe `expect_that!` macro defers the inspection of the result until the end of the current block:\n```rust\n{\n    expect_that!(\u00261+1, equal_to(0));\n    expect_that!(\u00261+1, less_than(4)); // is executed\n}\nexpect_that!(1+1, panics); // is never executed as the first expectation panics at the end of the block\n```\n\nThe `get_expectation_for!` macro allows for more fine grained control.\nIt returns an `Expectation` object which can be verified by calling `verify` ...\n```rust\nlet e1 = get_expectation_for!(\u00261+1, equal_to(0));\nlet e2 = get_expectation_for!(\u00261+1, less_than(4)); // is executed\ne1.verify();\nlet e3 = get_expectation_for!(\u00261+1, panics); // is never executed as e1 panics\n```\n... or will be automatically verified once the object goes out of scope.\n```rust\n{\n    let e1 = get_expectation_for!(\u00261+1, equal_to(0));\n    let e2 = get_expectation_for!(\u00261+1, less_than(4)); // is executed\n}\nlet e3 = get_expectation_for!(1+1, panics); // is never executed as e1 panics\n```\n\nNot much more to say---have a look at the [documentation](https://docs.rs/galvanic-assert) and the growing list of matchers.\n\nAnd remember ...\n*only tested code is happy code!*\n\nContributions\n-------------\nContributions are very welcome! (Please read and agree with the license.)\n\nThe list of included matchers is far from complete.\nIf you encounter a useful matcher please open an issue.\nCheck before if there's already a boolean predicate on the type itself, e.g., like `Option::is_none()`.\nThose are already supported by the assertion macros and should only be included if the error message of the `Matcher` is substantially better than the default one.\nIf something is missing or broken, please open an issue and send (if you want to) a pull request.\n\nFor pull requests be sure to include test cases to avoid regressions.\nTests for `Matchers` should be added as integration tests as they test the integration with the assertion macros.\nHave a look at the existing ones!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmindsbackyard%2Fgalvanic-assert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmindsbackyard%2Fgalvanic-assert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmindsbackyard%2Fgalvanic-assert/lists"}