Necessist

Run tests with statements and method calls removed to help identify broken tests

Install from [crates.io]:

cargo install necessist --version=^0.1.0-beta

If you require [Foundry] support, install from [github.com]:

cargo install --git https://github.com/trailofbits/necessist --branch release

Overview

The following hypothetical test verifies that a login mechanism works. Suppose the test would pass if session.send_password(...) were removed. This could indicate that the wrong condition is checked thereafter. Or worse, it could indicate a bug in the login mechanism.

```rust

[test]

fn loginworks() { let session = Session::new(URL); session.sendusername(USERNAME).unwrap(); session.send_password(PASSWORD).unwrap(); // <-- Test passes without this assert!(session.read().unwrap().contains(WELCOME)); } ```

Necessist iteratively removes statements and method calls from tests and then runs them to help identify such cases.

Generally speaking, Necessist will not attempt to remove a statement if it is one the following:

Also, for some frameworks, certain statements and methods are ignored (see below).

Usage

``` Usage: necessist [OPTIONS] [TEST_FILES]...

Arguments: [TEST_FILES]... Test files to mutilate (optional)

Options: --allow Silence ; --allow all silences all warnings --default-config Create a default necessist.toml file in the project's root directory (experimental) --deny Treat as an error; --deny all treats all warnings as errors --dump Dump sqlite database contents to the console --framework Assume testing framework is [possible values: auto, foundry, hardhat-ts, rust] --no-dry-run Do not perform dry runs --no-sqlite Do not output to an sqlite database --quiet Do not output to the console --reset Discard sqlite database contents --resume Resume from the sqlite database --root Root directory of the project under test --timeout Maximum number of seconds to run any test; 60 is the default, 0 means no timeout --verbose Show test outcomes besides passed -h, --help Print help information -V, --version Print version information ```

By default, Necessist outputs to both the console and to an sqlite database. For the latter, a tool like sqlitebrowser can be used to filter/sort the results.

Output

By default, Necessist outputs only when tests pass. Passing --verbose causes Necessist to instead output all of the removal outcomes below.

| Outcome | Meaning (With the statement/method call removed...) | | -------------------------------------------- | --------------------------------------------------- | | passed | The test(s) built and passed. | | timed-out | The test(s) built but timed-out. | | failed | The test(s) built but failed. | | nonbuildable | The test(s) did not build. |

Supported frameworks

Supported framework specifics

Foundry

In addition to the below, the Foundry framework ignores:

Ignored functions

Ignored methods

Hardhat TS

Ignored functions

Ignored methods

Rust

Ignored macros

Ignored methods*

* This list is essentially the watched trait and inherent methods of Dylint's [unnecessary_conversion_for_trait] lint, with the following additions:

Configuration files (experimental)

Configuration files are experimental and their behavior could change at any time.

A configuration file allows one to tailor Necessist's behavior with respect to a project. The file must be named necessist.toml, appear in the project's root directory, and be [toml] encoded. The file may contain one more of the options listed below.

Hardhat TS configuration options

Rust configuration options

Goals

References