json2tests

Crates.iojson2tests
lib.rsjson2tests
version0.3.1
created_at2025-10-20 13:21:41.961849+00
updated_at2025-10-28 15:54:37.075659+00
descriptionMacro to generate your Rust tests from a provided JSON file
homepagehttps://github.com/niri81/json2tests-rs/
repositoryhttps://github.com/niri81/json2tests-rs/
max_upload_size
id1891911
size304,147
(niri81)

documentation

README

json2tests — Generate Rust Tests from a Given JSON File

The macro provided in this crate allows for generating test cases from a given JSON file following the schema defined in schema.json.

The example code shows how to use the macro. Notice how you can run cargo test for this example and the tests from the JSON files are executed.

cargo test --example implementation

Requirements

Add the following to your Cargo.toml (if not already in it):

[packages]
assert-json-diff = "2.0"
json2test = { version = "0.1.0", path = "YOUR_PATH" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = "1.0"

Please note that this macro is not yet available via cargo add, you need to clone the repository and specify the local path!

Usage

Add the following to your source code:

#[cfg(test)]
mod test {
    use super::*;
    use json2tests::json2tests;

    json2tests!(file_path)
}

Generate tests from JSON takes a file path as input and will invoke a run() function for each testcase contained in the JSON. Your run function needs to be defined as follows:

fn run(action: &str, args: serde_json::Value) -> Result<serde_json::Value, impl std::error::Error>;

[!NOTE] Cargo will not detect if you change something on your test files. I therefore recommend to add a build.rs file declaring a dependency on your JSON file(s), to ensure a recompilation when you change your tests.

Example:

fn main() {
    println!("cargo:rerun-if-changed=tests.json");
}

Panics

You can specify that your code is expected to panic by setting the panic property in the JSON file. This will add the #[should_panic] attribute to the test.

{
  "testcases": {
    "test_addition": {
      "action": "add",
      "arguments": {
        "a": 2,
        "b": 3
      },
      "result": 4,
      "panic": true
    }
  }
}

When the panic property is set to a string, it will be matched against the panic message using the #[should_panic(expected = "...")] attribute.

Example

This JSON script

{
  "testcases": {
    "test_addition": {
      "action": "add",
      "arguments": {
        "a": 2,
        "b": 3
      },
      "result": 5
    }
  }
}

will generate the following code, when implemented as described in Usage:

mod test {
    use super::*;
    use json2tests::json2tests;
    extern crate test;
    #[rustc_test_marker = "test::test_addition"]
    #[doc(hidden)]
    pub const test_addition: test::TestDescAndFn = test::TestDescAndFn {
        // Snip
    };
    fn test_addition() {
        let value = serde_json::from_str("{\"a\":2,\"b\":3}").unwrap();
        let result = run("add", value);
        if !result.is_ok() {
            ::core::panicking::panic("assertion failed: result.is_ok()")
        }
        let expected_result: serde_json::Value = serde_json::from_str("5").unwrap();
        {
            {
                if let Err(error) = ::assert_json_diff::assert_json_matches_no_panic(
                    &result.unwrap(),
                    &expected_result,
                    ::assert_json_diff::Config::new(
                        ::assert_json_diff::CompareMode::Strict,
                    ),
                ) {
                    {
                        ::std::rt::panic_fmt(format_args!("\n\n{0}\n\n", error));
                    };
                }
            }
        }
    }
}

You (probably)

Meme stating "I'm a high efficiency man for a high speed age"

(This shall include all Rustaceans equally, without regard to gender :crab:).

Happy coding (and testing)! :rocket:

Commit count: 0

cargo fmt