assay - A super powered testing macro for Rust

Related tags

Testing assay
Overview

assay - A super powered testing macro for Rust

as·say /ˈaˌsā,aˈsā/ noun - the testing of a metal or ore to determine its ingredients and quality.

Rust is great, but the testing leaves much to be desired sometimes. With custom test frameworks being unstable and only an eRFC since 2018 there's not much we can do to expand the abilities of our tests right? Well that's where assay enters the picture. It seeks to solve a few problems when testing in rust:

  • Tests all run in the same process which means setting env vars or changing the working dir affects all of the tests meaning you have to resort to things like cargo test -- --test-threads=1 or using some kind of mutex whereby you lose the parallelization of running the test suite
  • Setting up a temporary file system to run things in for a test and having the test run inside it is a pain to setup and being relative to it by using std::env::set_working_dir is prone to the above issues
  • Including fixtures in a test, let alone multiple, can get a bit verbose
  • Setting up and tearing down the same thing for each test can be a lot
  • Want to run async tests? There's no runtime and you have to do setup just to run it.
  • Using ? in your test means putting -> Result<(), Box > on every test and it can be tedious
  • assert_eq/assert_ne output can be hard to grok and see why something is equal/not equal

assay fixes these issues by:

  • Running each test as it's own process for you automatically. Mutate per process state as much as you want without affecting other tests and always have your tests run in parallel
  • Setting per process env vars
  • Setting up a temporary directory that the test runs in (sort of like chroot without the jail aspect and no need for sudo privileges)
  • Including files you want into the temp directory by specifying them
  • Letting you run async tests by simply adding async to the test function
  • Making all of your tests act as if they returned Result<(), Box > . Use the ? to your hearts content and no need to add the Eye of Sauron (Ok(())) to each test
  • Automatically importing the pretty_assertions crate so that you can have pretty output for assert_eq and assert_ne
  • Allowing you to define setup and teardown functions to call for the test

assay was born out of personal frustration with the way things are and wanting to handle the boilerplate without needing to write a whole test framework, while also pushing the bounds of what we could have today on stable Rust.

How to use assay

MSRV Policy

We do not have a Minimum Supported Rust Version and only track stable. Given this crate uses 2021 edition rustc >= 1.56 for now, but that's not always guaranteed to be the case and later versions might require a greater version than 1.56.

License

All files within this project are distributed under the Mozilla Public License version 2.0. You can read the terms of the license in LICENSE.txt.

Comments
  • Import pretty_assertions_sorted as well as pretty_assertions

    Import pretty_assertions_sorted as well as pretty_assertions

    See https://github.com/colin-kiegel/rust-pretty-assertions/issues/85

    Needing to assert on the results of HashMaps / HashSets is something I've needed to do quite often, so proposing this for inclusion in the crate.

    This crate provides assert_eq_sorted!(), so won't conflict with the default pretty_assertions crate's override.

    opened by gibfahn 7
  • calls `set_current_dir` in a proc macro?

    calls `set_current_dir` in a proc macro?

    I've been working on some related code today (see e.g. https://github.com/ostreedev/ostree-rs-ext/pull/244 which is changing our test code there to use more cap-std bits and also trying to more carefully move the processes we fork off into per-test tempdirs).

    And just glancing at your code, at least this call to set_current_dir() looks suspicious to me, because it looks like we're changing process global state in a proc macro.

    opened by cgwalters 3
  • Make tokio an optional dependency (+ maybe enabled by default)?

    Make tokio an optional dependency (+ maybe enabled by default)?

    What do you think of making tokio an optional dependency, enabled by default? I'd love to use assay for some tests that have nothing to do with tokio :)

    opened by sunshowers 2
  • Add support for async-std and make async optional

    Add support for async-std and make async optional

    This commit adds the ability to turn off async functionality by setting no-default-features = true in your Cargo.toml for assay. This means if you don't need the async functionality it won't bring in tokio by default reducing compile times. We also add support for async-std by setting no-default-features = true, features = ["async-std-runtime"] in your Cargo.toml for assay. Functionally this doesn't change how assay works and lets you choose another runtime for your code. Useful if you depend on functionality of a specific runtime. It has been orchestrated to make it easier to choose one of the two with feature flags while not breaking existing functionality.

    Closes #8

    opened by mgattozzi 0
  • Use NEXTEST_EXECUTION_MODE rather than NEXTEST to detect process-per-test mode

    Use NEXTEST_EXECUTION_MODE rather than NEXTEST to detect process-per-test mode

    opened by sunshowers 0
  • Struggling with test output

    Struggling with test output

    I have a test that roughly boils down to

    #[assay]
    async fn successfully_trigger_for_ci_job() {
        // Arrange
        let context = TestContext::start().await;
    
       ... a bunch of things...
    
        let status = response.status();
        let body = response
            .text()
            .await
            .unwrap();
    
        assay::assert_eq!(BodyAndStatus { body, status}, BodyAndStatus { body: "".to_string(), status: StatusCode::OK })
    }
    

    If I "break" the test by replacing the expected body, then the test output is just

    Screenshot 2022-06-10 at 09 38 59

    where I'd expect to get a nice error based on pretty_assertions.

    I don't see any feature flags or anything that I may have forgotten? Are there any constraints on how to use assay to get the pretty errors?

    opened by felipesere 0
  • Support ignored tests

    Support ignored tests

    This PR adds a new argument ignore to the attribute macro, which expands into an #[ignore] attribute on the generated test function. A minimal test for this functionality is included, but no tests for the interaction with other arguments or features yet.

    Additionally, this PR includes attributes specified on the input function in the generated test function. If you'd like, I can break this functionality out into its own PR.

    With the second change, it should also be possible to remove the first change and deprecate the should_panic argument in favor of specifying #[ignore] or #[should_panic] directly.

    Fixes #12

    opened by korrat 1
  • Macro Parsing Errors

    Macro Parsing Errors

    Assay currently parses things but any errors are a bit, well, lacking with information. It'd be nice if we could output diagnostics to the users so they can fix the issues rather than having a mostly subpar experience trying to get the syntax right OR signal an error in what they've done.

    opened by mgattozzi 0
  • Macro does not respect `#[ignore]` attribute

    Macro does not respect `#[ignore]` attribute

    With the following code, I get an error when running tests with cargo test:

    #[assay]
    #[ignore]
    fn fail() {
        panic!();
    }
    

    The output is:

    $ cargo test
    [...]
    running 1 test
    test fail ... FAILED
    

    I expected the test to be ignored.

    The equivalent code using #[test] does not cause a test failure.

    #[test]
    #[ignore]
    fn fail() {
        panic!();
    }
    

    Cargo output:

    $ cargo test
    [...]
    running 1 test
    test fail ... ignored
    

    Context

    I was trying to run proptest tests under assay. Since they take a few seconds to run each, I was trying to ignore them, which is how I discovered the problem.

    opened by korrat 3
  • File inclusion with an explicit destination path

    File inclusion with an explicit destination path

    As discussed in #9, this PR changes the behaviour of the include attribute:

    • #[assay(include = ["folder/my_file.rs"]) will copy the file into the root folder of the test working directory (i.e. file.rs);
    • #[assay(include = [("folder/my_file.rs", "folder/my_renamed_file.rs"]) will instead use the specified destination path.

    I have a few questions on the implementation that I've left as TODO comment in the code. I'd appreciate your input there.

    Closes #9

    opened by LukeMathWalker 1
  • Specify a target filepath for included files

    Specify a target filepath for included files

    I've been playing around with assay today for a side project and it has been 🔥

    The only thing I am struggling with, right now, is including files. My project folder layout follows this structure:

    src
      lib.rs
      module_with_tests.rs
      ...
      test_files
        test_name_1
          file_to_include_1
          ...
    

    test_name_1 is a test that lives in module_with_tests.rs and I'd like to mount all files under test_files/test_name_1 in the temporary directory created for test_name_1. This doesn't seem possible at the moment based on my understanding of the docs. I can do:

        #[assay]
        #[assay(include = ["src/test_files/test_name_1/a_file_in_there.txt"])]
        fn test_name_1() {
            // [...]
        }
    

    while what I want is

        #[assay]
        #[assay(include = [("src/test_files/test_name_1/a_file_in_there.txt", "a_file_in_there.txt"])]
        fn test_name_1() {
            // [...]
        }
    

    Is there an easy layout that I could use to keep the files related to different tests separated? Would you be interested to support this functionality/review a PR for adding it?

    Along the same lines, some kind of globbing would be quite handy - i.e. "mount all the files in this directory at the root of the temporary filesystem for the test".

    opened by LukeMathWalker 1
Owner
Michael Gattozzi
Rustacean 🦀"a bad programmer" according to the Orange Site, he/him
Michael Gattozzi
Testing Framework for Rust

Polish Polish is Test-Driven Development done right Getting Started Installing the Package The crates.io package is kept up-to-date with all the major

Fadi Hanna Al-Kass 49 Dec 18, 2022
ArchTest is a rule based architecture testing tool for rust

ArchTest is a rule based architecture testing tool. It applies static analyses on the specified rust project to extract use relationships.

Tom Dymel 7 Sep 26, 2021
Automated property based testing for Rust (with shrinking).

quickcheck QuickCheck is a way to do property based testing using randomly generated input. This crate comes with the ability to randomly generate and

Andrew Gallant 2k Jan 2, 2023
Hypothesis-like property testing for Rust

Proptest Introduction Proptest is a property testing framework (i.e., the QuickCheck family) inspired by the Hypothesis framework for Python. It allow

Jason Lingle 1.1k Jan 1, 2023
Simple goldenfile testing in Rust.

?? Rust Goldenfile Simple goldenfile testing in Rust. Goldenfile tests generate one or more output files as they run. At the end of the test, the gene

Calder Coalson 24 Nov 26, 2022
Cucumber testing framework for Rust. Fully native, no external test runners or dependencies.

An implementation of the Cucumber testing framework for Rust. Fully native, no external test runners or dependencies.

Brendan Molloy 394 Jan 1, 2023
Loom is a concurrency permutation testing tool for Rust.

Loom is a testing tool for concurrent Rust code

Tokio 1.4k Jan 9, 2023
Drill is an HTTP load testing application written in Rust inspired by Ansible syntax

Drill is an HTTP load testing application written in Rust inspired by Ansible syntax

Ferran Basora 1.5k Jan 1, 2023
Rust testing library

K9 - Rust Testing Library Snapshot testing + better assertions Available test macros snapshot assert_equal assert_greater_than assert_greater_than_or_

Aaron Abramov 269 Dec 10, 2022
Testing Framework for Rust

Polish Polish is Test-Driven Development done right Getting Started Installing the Package The crates.io package is kept up-to-date with all the major

Fadi Hanna Al-Kass 49 Dec 18, 2022
Rustress - stress testing library in Rust. For fun

rustress Simple network stress testing library. To get familiar with Rust Planned features (Subject to change) Multithreaded client/server Throughput

Hakan Sönmez 7 Sep 22, 2022
insta: a snapshot testing library for Rust

insta: a snapshot testing library for Rust Introduction Snapshots tests (also sometimes called approval tests) are tests that assert values against a

Armin Ronacher 1.4k Jan 1, 2023
Rnp - A simple cloud-friendly tool for testing network reachability.

Rnp - A simple cloud-friendly tool for testing network reachability. Release Status Crates.io Github release Nuget packages NOTE: This project is in e

Riff 50 Dec 13, 2022
Simple assertion library for unit testing in python with a fluent API

Simple assertions library for unit testing in Python with a nice fluent API. Supports both Python 2 and 3.

snakedye 19 Sep 10, 2022
Viceroy provides local testing for developers working with Compute@Edge.

Viceroy provides local testing for developers working with Compute@Edge. It allows you to run services written against the Compute@Edge APIs on your local development machine, and allows you to configure testing backends for your service to communicate with.

Fastly 99 Jan 7, 2023
Declarative Testing Framework

Demonstrate allows tests to be written without as a much repetitive code within the demonstrate! macro, which will generate the corresponding full tests.

Austin Baugh 41 Aug 17, 2022
🧵 Generate self-describing strings of a given length to help aid software testing

rust-counter-strings Counter strings generator written in rust to help aid software testing What is a counterstring? "A counterstring is a graduated s

Thomas Chaplin 23 Jun 24, 2022
🔥 Unit testing framework for Subgraph development on The Graph protocol. ⚙️

?? Welcome to Matchstick - a unit testing framework for The Graph protocol. Try out your mapping logic in a sandboxed environment and ensure your hand

null 157 Dec 20, 2022
This is a tiny (but delightful!) utility library for exhaustive testing.

Exhaustigen This is a tiny (but delightful!) utility library for exhaustive testing. It is based (directly) on the idea and code in the following blog

Graydon Hoare 34 Dec 14, 2022