{"id":28498324,"url":"https://github.com/yanganto/test-with","last_synced_at":"2025-07-03T13:30:36.856Z","repository":{"id":38384602,"uuid":"443310615","full_name":"yanganto/test-with","owner":"yanganto","description":"A lib help you run test with condition","archived":false,"fork":false,"pushed_at":"2025-06-16T14:08:26.000Z","size":227,"stargazers_count":43,"open_issues_count":4,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-16T15:26:31.200Z","etag":null,"topics":["condition","ignore","integration","rust","testing","toggle"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yanganto.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,"zenodo":null}},"created_at":"2021-12-31T09:41:38.000Z","updated_at":"2025-06-16T14:08:43.000Z","dependencies_parsed_at":"2023-02-01T01:40:17.407Z","dependency_job_id":"e633911d-d332-4fd3-8023-684ee4411172","html_url":"https://github.com/yanganto/test-with","commit_stats":{"total_commits":81,"total_committers":6,"mean_commits":13.5,"dds":"0.14814814814814814","last_synced_commit":"ab2fdef1ef6eb58934d27aa49e78cfcfbc1cc1c9"},"previous_names":[],"tags_count":64,"template":false,"template_full_name":null,"purl":"pkg:github/yanganto/test-with","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yanganto%2Ftest-with","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yanganto%2Ftest-with/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yanganto%2Ftest-with/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yanganto%2Ftest-with/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yanganto","download_url":"https://codeload.github.com/yanganto/test-with/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yanganto%2Ftest-with/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263335280,"owners_count":23450809,"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":["condition","ignore","integration","rust","testing","toggle"],"created_at":"2025-06-08T13:37:12.339Z","updated_at":"2025-07-03T13:30:36.570Z","avatar_url":"https://github.com/yanganto.png","language":"Rust","readme":"# test-with\n[![Crates.io][crates-badge]][crate-url]\n[![MIT licensed][mit-badge]][mit-url]\n[![Docs][doc-badge]][doc-url]\n\nA lib help you run test with conditions, else the test will be ignored with clear message.\nAlso, you can easiler run test with customed test environment or mock service.\n\n## Introduction\nIt is good to use this crate in dev dependency as following\n```toml\n[dev-dependencies]\ntest-with = \"*\"\n```\n\nIf you want the dependency smaller with a shorter compiling time, you can disable default features and use specific one.\nFor example, if you only checking a remote web server, you can use the `net` or `http` feature as the following.\n```toml\n[dev-dependencies]\ntest-with = { version = \"*\", default-features = false, features = [\"http\"] }\n```\nThe features you can use are `net`(`http`, `icmp`), `resource`, `user`, `executable`.\n\nCurrently, the condition is checked on build-time not runtime, because of this [issue][original-issue] of rust-lang.\nIt is not perfect but good enough for most develop scenario.\nHere are [slides@COSCUP][coscup-slides] and [slides@COSCON][coscon-slides] to help you know more about it.\nIf you really want to check the condition in runtime, please check [runtime section](https://github.com/yanganto/test-with#runtime).\nThe `runtime` feature and runtime macros (`test_with::runner!`,`test_with::tokio_runner!`, `#[test_with::module]`, `#[test_with::runtime_*()]`) can help you run the test and check the conditions in runtime.\nAlso, the customed test environment or mock service can set with the modules with `runtime` feature.\n\nIf you forget to add `#[test]` flag on the test case, `#[test_with]` macro will add it for you.\n\nRust version `1.61` of stable channel or `2022-03-30` of nightly channel will show the ignore message.\nIf the ignore message does not show in the previous Rust version you used, the feature `ign-msg` can be used to work around.\nand the name of ignored test case will be rewritten, such that you can easier to know why the test is ignored.\n\nThe order of test macros(`#[test]`, `#[tokio::test]`, `#[serial_test::serial]`, `#[rstest]`...) is important, please check out examples.\n\n## Environment Variable\nRun test case when the environment variable is set.\n\n```rust\n// PWD environment variable exists\n#[test_with::env(PWD)]\n#[test]\nfn test_works() {\n    assert!(true);\n}\n\n// NOTHING environment variable does not exist\n#[test_with::env(NOTHING)]\n#[test]\nfn test_ignored() {\n    panic!(\"should be ignored\")\n}\n```\n\nResult of `cargo test`\n```text\nrunning 2 tests\ntest tests::test_ignored ... ignored, because following variable not found: NOTHING\ntest tests::test_works ... ok\n\ntest result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s\n```\n\nOr run all test cases for test module when the environment variable is set.\n```rust\n#[test_with::env(PWD)]\n#[cfg(test)]\nmod tests {\n\n    #[test]\n    fn test_works() {\n        assert!(true);\n    }\n}\n```\n\nIf the test depends on more than one environment variables,\nyou can write it with multiple variables, `#[test_with::env(VAR1, VAR2)]`.\n\nAlso, the test case can be ignored with the specific environment variable.\n\n```rust\n// The test will be ignored in Github actions.\n#[test_with::no_env(GITHUB_ACTIONS)]\n#[test]\nfn test_ignore_in_github_action() {\n    println!(\"Should be ignored in GITHUB_ACTION\");\n}\n```\n\n## File/Folder\nRun test case when the file or folder exist.  This is good for testing with database config.\nIf you want to check the folder exist or not, please use `path`.\n\n```rust\n// hostname exists\n#[test_with::file(/etc/hostname)]\n#[test]\nfn test_works() {\n    assert!(true);\n}\n\n// nothing file does not exist\n#[test_with::file(/etc/nothing)]\n#[test]\nfn test_ignored() {\n    panic!(\"should be ignored\")\n}\n\n// etc exists\n#[test_with::path(/etc)]\n#[test]\nfn test_works_for_path() {\n    assert!(true);\n}\n```\n\nIf the test depends on more than one file or path,\nyou can write it with multiple file/path,\n`#[test_with::file(/file1, /file2)]` or `#[test_with::path(/folder, /file)]`.\n\n## Http/Https Service\nRun test case when the http/https service available.  This is good for integration testing.\nRequire `http` feature, if default features are disabled.\n\n```rust\n// https service exists\n#[test_with::https(www.rust-lang.org)]\n#[test]\nfn test_works() {\n    assert!(true);\n}\n\n// There is no not.exist.com\n#[test_with::https(not.exist.com)]\n#[test]\nfn test_ignored() {\n    panic!(\"should be ignored\")\n}\n```\n\nIf the test depends on more than one service,\nyou can write it with multiple service,\n`#[test_with::http(service1, service2)]` or `#[test_with::http2(service1, service2)]`.\n\n## TCP socket\nRun integration test case when the remote tcp socket is listening.\n\n```rust\n#[test_with::tcp(8.8.8.8:53)]\n#[test]\nfn test_works() {\n    assert!(true);\n}\n\n#[test_with::tcp(193.194.195.196)]\n#[test]\nfn test_ignored() {\n    panic!(\"should be ignored\")\n}\n```\n\n## Remote Server Online Status\nRun integration test case when the remote server online.\n**Please note the user running test case should have capability to open socket**.\nRequire `icmp` feature, if default features are disabled.\n\n```rust\n// localhost is online\n#[test_with::icmp(127.0.0.1)]\n#[test]\nfn test_works() {\n    assert!(true);\n}\n\n// 193.194.195.196 is offline\n#[test_with::icmp(193.194.195.196)]\n#[test]\nfn test_ignored() {\n    panic!(\"should be ignored\")\n}\n```\n\n## User/Group condition\nRun integration test case when the user is specific user or in specific group\nRequire `user` feature, if default features are disabled.\n```rust\n#[test_with::root()]\n#[test]\nfn test_ignored() {\n    panic!(\"should be ignored\")\n}\n\n#[test_with::group(avengers)]\n#[test]\nfn test_ignored2() {\n    panic!(\"should be ignored\")\n}\n\n#[test_with::user(spider)]\n#[test]\nfn test_ignored3() {\n    panic!(\"should be ignored\")\n}\n```\n\n## CPU/Memory/Swap condition\nRun integration test case when the memory/swap is enough\nRequire `resource` feature, if default features are disabled.\n```rust\n#[test_with::cpu_core(32)]\n#[test]\nfn test_ignored_by_cpu_core() {\n    panic!(\"should be ignored\")\n}\n\n\n#[test_with::phy_core(32)]\n#[test]\nfn test_ignored_by_physical_cpu_core() {\n    panic!(\"should be ignored\")\n}\n\n#[test_with::mem(999GB)]\n#[test]\nfn test_ignored_by_mem() {\n    panic!(\"should be ignored\")\n}\n\n#[test_with::swap(999GB)]\n#[test]\nfn test_ignored_by_swap() {\n    panic!(\"should be ignored\")\n}\n```\n\n## Executable condition\nRun integration test case when the executables can be accessed\nRequire `executable` feature, if default features are disabled.\n```rust\n    // `pwd` executable command exists\n    #[test_with::executable(pwd)]\n    #[test]\n    fn test_executable() {\n        assert!(true);\n    }\n\n    // `/bin/sh` executable exists\n    #[test_with::executable(/bin/sh)]\n    #[test]\n    fn test_executable_with_path() {\n        assert!(true);\n    }\n\n    // `non` does not exist\n    #[test_with::executable(non)]\n    #[test]\n    fn test_non_existing_executable() {\n        panic!(\"should be ignored\")\n    }\n\n    // `pwd` and `ls` exist\n    #[test_with::executable(pwd, ls)]\n    #[test]\n    fn test_executables_too() {\n        assert!(true);\n    }\n```\n\n## Runtime\nWe can let an example to do thing that cargo test runner do, `cargo run --example=\u003cexample_name\u003e`, and ignore testcase in runtime.\nThe testcase of in the example will not in `#[cfg(test)]` or `#[test]` anymore, and use `#[test_with::runtime_*]`,\nthe test runner will treat it as the test in Rust and also provide the same summary as `cargo test`.\n\nThe `runtime` feature should be enabled and include as normal dependency, and also include the `libtest-with` with corresponding features in `Cargo.toml`.\n```toml\ntest-with = { version = \"0.15.0\", features = [\"runtime\"] }\nlibtest-with = { version = \"0.8.1-8\", features = [\"net\", \"resource\", \"user\", \"executable\"] }\n```\n\nCreate an example with the following runtime macros (`test_with::runner!`, `#[test_with::module]`, `#[test_with::runtime_env()]`).\n```rust\ntest_with::runner!(module_name);\n\n#[test_with::module]\nmod module_name {\n    #[test_with::runtime_env(PWD)]\n    fn test_works() {\n    }\n}\n```\n\nor you can customized your condition function with `runtime_ignore_if`\n```rust\ntest_with::runner!(custom_mod);\n\nfn something_happened() -\u003e Option\u003cString\u003e {\n    Some(\"because something happened\".to_string())\n}\n\n#[test_with::module]\nmod custom_mod {\n    #[test_with::runtime_ignore_if(something_happened)]\n    fn test_ignored() {\n        assert!(false);\n    }\n}\n```\n\nThere are two ways to setup mock service in the test runner, one is by `struct` and the other is by `type`.\n```rust\ntest_with::runner!(test_with_mock);\n\n#[test_with::module]\nmod test_with_mock {\n    pub struct TestEnv {}\n\n    impl Default for TestEnv {\n        fn default() -\u003e TestEnv {\n            // Set up mock here\n            TestEnv {}\n        }\n    }\n\n    impl Drop for TestEnv {\n        fn drop(\u0026mut self) {\n            // Tear down mock here\n        }\n    }\n}\n```\nor\n```rust\ntest_with::runner!(test_with_mock);\n\npub struct Moc {}\n\nimpl Default for Moc {\n    fn default() -\u003e Moc {\n        // Set up mock here\n        Moc {}\n    }\n}\n\nimpl Drop for Moc {\n    fn drop(\u0026mut self) {\n        // Tear down mock here\n    }\n}\n\n#[test_with::module]\nmod test_with_mock {\n    pub type TestEnv = super::Moc;\n}\n```\n\nWe can let an example run with async test case with the following runtime macros (`test_with::tokio_runner!`, `#[test_with::module]`, `#[test_with::runtime_env()]`).\nAlso, it is possible to have async test cases and sync test cases at the same time with `test_with::tokio_runner!`.\n\nPlease check out examples under the [example/runner](https://github.com/yanganto/test-with/tree/main/examples/runner) project.\n\n## Lock\n`#[test_with::lock(LOCK_NAME)]` is a way to run your test casess one by one with file locks.\nThe first parameter is the name of the file lock, the second optional parameter is the waiting time in seconds,\ndefault will be 60 seconds.\n\n```rust\n  // `LOCK` is file based lock to prevent test1 an test2 run at the same time\n  #[test_with::lock(LOCK)]\n  fn test_1() {\n      assert!(true);\n  }\n\n  // `LOCK` is file based lock to prevent test1 an test2 run at the same time\n  #[test_with::lock(LOCK)]\n  fn test_2() {\n      assert!(true);\n  }\n\n  // `ANOTHER_LOCK` is file based lock to prevent test3 an test4 run at the same time with 3 sec\n  // waiting time.\n  #[test_with::lock(ANOTHER_LOCK, 3)]\n  fn test_3() {\n      assert!(true);\n  }\n\n  // `ANOTHER_LOCK` is file based lock to prevent test3 an test4 run at the same time with 3 sec\n  // waiting time.\n  #[test_with::lock(ANOTHER_LOCK, 3)]\n  fn test_4() {\n      assert!(true);\n  }\n```\n## Timezone\nRun test case when the machine in specific timezone\n\n```rust\n// 0 is for UTC\n#[test_with::timezone(0)]\n#[test]\nfn test_works() {\n    assert!(true);\n}\n\n// 8 for GMT+8, this test only run in the timezone\n#[test_with::timezone(+8)]\n#[test]\nfn test_run_in_TW() {\n    assert!(true)\n}\n```\n\n## Relating issues\n* [Solve this in runtime][original-issue]\n\n[crates-badge]: https://img.shields.io/crates/v/test-with.svg\n[crate-url]: https://crates.io/crates/test-with\n[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg\n[mit-url]: https://github.com/yanganto/test-with/blob/readme/LICENSE\n[doc-badge]: https://img.shields.io/badge/docs-rs-orange.svg\n[doc-url]: https://docs.rs/test-with/latest/test_with/\n[original-issue]: https://github.com/rust-lang/rust/issues/68007\n[rust-pre-rfc]: https://internals.rust-lang.org/t/pre-rfc-provide-ignore-message-when-the-test-ignored/15904\n[known-issue]: https://github.com/yanganto/test-with/issues/18\n[coscup-slides]: http://slides.com/yanganto/rust-ignore\n[coscon-slides]: https://docs.google.com/presentation/d/1SjKdwWk0_YyhrRxV0bcay8PTO5htDRjBu99-tPRkMto/edit?usp=sharing\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyanganto%2Ftest-with","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyanganto%2Ftest-with","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyanganto%2Ftest-with/lists"}