Declarative Testing Framework

Related tags

Testing testing
Overview

Declarative Testing Framework

github crates.io docs.rs build status

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

This testing library is highly influenced by speculate.rs and ruspec which both take inspiration from RSpec.

The following new block definitions are utilized by Demonstrate:

  • before/after — A block of source code that will be included at the start or end of each test respectively in the current and nested describe/context blocks.

  • describe/contextdescribe and context are aliases for eachother. Specifies a new scope of tests which can contain a before and/or after block, nested describe/context blocks, and it/test blocks. These translate to Rust mod blocks, but also allow for shared test properties to be defined such as tests having outer attributes, being async, and having Return<()> types.

  • it/testit and test are aliases for eachother. Represents one test that translate to a Rust unit test.


Example

Result<(), &'static str> { if is_4() == four { Ok(()) } else { Err("It isn't 4! :o") } } #[async_attributes::test] async context "asynchronous" { before { let is_4_task = async_std::task::spawn(async { is_4() }); } it "awaits" { assert_eq!(four, is_4_task.await) } } } } ">
use demonstrate::demonstrate;

fn is_4() -> u8 {
    4
}

demonstrate! {
    describe "module" {
        use super::*;

        before {
            let four = 4;
        }

        #[should_panic]
        it "can fail" {
            assert!(four != 4)
        }

        test "is returnable" -> Result<(), &'static str> {
            if is_4() == four {
                Ok(())
            } else {
                Err("It isn't 4! :o")
            }
        }

        #[async_attributes::test]
        async context "asynchronous" {
            before {
                let is_4_task = async_std::task::spawn(async {
                    is_4()
                });
            }

            it "awaits" {
                assert_eq!(four, is_4_task.await)
            }
        }
    }
}

License

Licensed under MIT license.
Comments
  • Mix of mutable/immutable usage of `before` variables cause warning

    Mix of mutable/immutable usage of `before` variables cause warning

    When a variable declared in a before block is used in both mutable and immutable way in different unit tests, it will cause a warning in the declaration.

    Example (the code is a butchered version of an existing test suite):

    demonstrate! {
      describe "CPU" {
        use super::*;
    
        before { let mut cpu = Cpu::new(); }
    
        it "initializes" {
          cpu.internal_ram.to_vec().iter().map(|&x| x as u32).sum::<u32>();
        }
    
        it "NOP (0x00)" {
            assert_cpu_execute(&mut cpu, &[0x00]);
        }
      }
    }
    

    The cpu variable needs to be mutable, however, it causes a warning "variable doesn't need to be mutable"

    I don't know if this is inevitable or not, as it also happens to ruspec.

    opened by 64kramsystem 4
  • Do setup code blocks get re-run for every test?

    Do setup code blocks get re-run for every test?

    In python, I'm used to using "fixtures" in pytest to amortize the cost of loading big blobs of test data over multiple tests.

    https://docs.pytest.org/en/stable/fixture.html

    A workaround in rust would be just to put all of my tests in one tests, but then the blob still can't be shared between modules or crates.

    Does demonstrate avoid calling the setup functions, or does it just automated calling them at the front of each test?

    Thanks!

    opened by drewm1980 2
  • Allow strings to be used by macros as names

    Allow strings to be used by macros as names

    Not sure if it's by design, anyway... :slightly_smiling_face:

    RSpec (and ruspec, by extension) allow strings to be used for block names, eg:

        it "test subject" {
          assert_eq!(subject, 10);
        }
    

    I think this is important for a declarative testing framework, as expressivity is crucial - using function names is instead very limiting.

    My 10 bitcents :grimacing:

    opened by 64kramsystem 2
  • Added given, when, then keywords

    Added given, when, then keywords

    In BDD testing, it's common to use the words "given", "when" and "then" to describe the test units. This patch adds:

    • given and when as aliases of describe
    • then as an alias to it
    opened by tomsik68 1
  • Feature request: integration tests

    Feature request: integration tests

    Hi, thank you for your hard work!

    I'd love to use this library in integration tests and there's only one thing that prevents me from doing that: #[cfg(test)]. Since integration tests are compiled in a separate crate without the test configuration, tests written using demonstrate aren't compiled.

    It'd be nice to add some way to hide #[cfg(test)]. I have a few proposals for the syntax. Personally, I like number 2 the best but feel free to go with anything that fits the library philosophy.

    Proposal 1 - let the user write it

    This might be a breaking change, but it'd be the simplest to implement.

    #[cfg(test)]
    demonstrate! {
    }
    

    Proposal 2 - separate macro

    No breaking change, easy implementation, but requires additional macro.

    /// this one stays as is - no breaking changes, generates #[cfg(test)]
    demonstrate! {
    }
    
    /// this one doesn't generate #[cfg(test)]
    demonstrate_for_integration_tests! {
    }
    

    Proposal 3 - arguments

    An optional keyword inside of the macro that says whether or not the #[cfg(test)] should be generated. Not a breaking change, no need for another macro, but needs parser tweaks.

    demonstrate! { integration_tests,
    }
    
    opened by tomsik68 1
  • Possibly unnecessary and inefficient `.clone()` calls

    Possibly unnecessary and inefficient `.clone()` calls

    I'm concerned about two .clone() calls in the src/generate.rs file: https://github.com/austinsheep/demonstrate/blob/4b832d0aa08c948bdf0e415eae73411200293140/src/generate.rs#L21 https://github.com/austinsheep/demonstrate/blob/6954fe6ecf262462f965c3516ea5cc3371ac08bd/src/generate.rs#L61

    I'm not sure if these .clone() calls are necessary and if I should consider a different approach as they are cloning each nested Describe and Test block once per generated Root and Describe scope

    opened by aubaugh 1
  • Added Inherit trait and made uses inherited

    Added Inherit trait and made uses inherited

    Still need to:

    • [x] Consider if all uses should really be inherited
    • [ ] See if it would be worth making inherited uses super::last_segment
    • [x] Update inherit.rs comments
    • [x] Update library docs
    • [x] Update Readme example (maybe change this altogether)
    • [ ] Add more examples
    opened by aubaugh 0
  • Feature request: Implement

    Feature request: Implement "before all" macro

    In some cases, it's required to share a single instance between tests.

    AFAIK, the current macro before is run before each test, so it doesn't work for the cases above.

    There is a workaround, which is very ugly though - using lazy_static with phony implementations of Send and Sync, which is... 🤯

    My request is therefore to implement the (typical) "before_all" logic, which is executed only once (per context/describe).

    opened by 64kramsystem 5
Owner
Austin Baugh
Austin Baugh
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
🔥 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
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
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
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 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
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
🧵 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
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
assay - A super powered testing macro for Rust

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

Michael Gattozzi 105 Dec 4, 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
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
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
A series of utility macros for outputting testing results.

test-results A series of utility macros for outputting testing results. Getting Started Simply add the test-results crate to your project's Cargo.toml

EYHN 1 Jan 27, 2022
hb is an endpoint focused HTTP load testing / benchmark tool.

hb hb is an endpoint focused HTTP load testing / benchmark tool. Description The goal of hb is to provide a simple, robust tool to apply load against

Mark Pritchard 2 Aug 23, 2022