GithubHelp home page GithubHelp logo

nfurfaro / hunter Goto Github PK

View Code? Open in Web Editor NEW
8.0 1.0 0.0 4.12 MB

A mutation testing CLI tool built in Rust. Currently supports Noir as a target language

License: MIT License

Rust 95.95% Roff 0.73% Shell 1.13% Mermaid 2.18%

hunter's Introduction

Hunter

A Rust CLI mutation-testing tool for Noir source code.

Disclaimer

!!! Note: Hunter is currently in its alpha stage of development. While functional, it is still under active development. This means that there may be bugs and/or significant changes. It is not recommended to use this tool in a production environment or for securing code that protects valuable assets. Hunter, like many mutation testing tools, is designed to assist in writing improved tests. It is NOT a substitute for creating tests or conducting thorough code reviews.

Inspiration

Vertigo A mutation testing tool for Solidity x Truffle by Joran Honig

Guide to mutation testing bt Artem Golubev

Mutation Testing at scale by Goran Petrovi´c, Marko Ivankovi´c, Gordon Fraser, René Just

Overview

At a high level, Hunter exposes a CLI with 2 primary commands, scan and mutate. The former is like a dry-run, giving quick feedback on which eligible files were found, the number of mutation candidates, the number of tests required, etc. The mutate command takes the result of the scan, applies the mutations, runs the tests, and generates a report.

Installation

Build from source

You can easily build Hunter from source. To do so, you'll need to have Rust installed. If you don't have Rust installed, you can install it by following the instructions here.

  1. Clone the repo: git clone [email protected]:nfurfaro/hunter.git

  2. Build the project: cargo build --release

  3. Move the binary to a directory in your PATH (i.e: /usr/local/bin): mv ./target/release/hunter /usr/local/bin

You should now be able to run the program by typing hunter in your terminal!

Quickstart

The simplest way to get started with Hunter is to $ cd into the root of the project you want to test. From there, it is recommended to run the scan command: $ hunter scan. By default, this will scan the current directory and all subdirectories for Noir source files. It will then print a summary of the results to the terminal.

The next step is to run the mutate command: $ hunter mutate. This will apply the mutations to the source code, run the tests, and generate a report. If the scan command indicated that there is a high number of test runs required, you may want to refer to the filtering options section to limit the scope of the source code analysed.

Help

To see Hunter's help menu, run hunter --help.

hunter --info will give some more context on the results of the mutate command.

About Mutation Testing

At a high level, mutation testing is a way to measure the quality of a test suite. It is possible to have 100% test coverage and still have poor quality/incomplete tests. Mutation testing helps to identify these cases.

Mutation testing involves modifying the source code of a program in small ways. Specifically, it modifies the program by replacing an operator with another operator. Each modification is called a mutant. For each mutant, we run the existing test suite against the mutated code. If at least one test fails, the mutant is "killed". If all tests pass, the mutant "survives". The mutation score is the percentage of mutants that are killed by the test suite, calculated as follows:

mutation_score = (killed_mutants / total_mutants) * 100

The closer the score is to 100%, the better the test suite is at detecting changes or errors in the source code.

To learn more about mutation testing, check out this article.

Assumptions and Limitations

Hunter assumes the following:

  • the user has Nargo installed in their PATH.
  • the test suite for the project you want to mutate is currently all passing. If there are failing tests, you're not ready to perform mutation testing yet!

The larger the project and test suites are, the longer the mutation testing run will take. By default, Hunter will run your entire test suite for each mutant generated (in parallel). See the filtering options section for ways to limit the number of tests run per mutant.

Note: Hunter currently only targets in-language unit tests written in the same file as the source they test. It does not currently support tests written in separate files or in a separate directory, but this is definitely a feature that is planned for the next release!

Mutations

Hunter currently supports the following mutations:

Arithmetic operators

+, -, *, /, and %.

Bitwise operators

!, &, |, ^, <<, and >>.

Predicate/Comparison operators

==, !=, >, >=, <, and <=.

Shorthand operators

+=, -=, *=, /=, %=, &=, |=, ^=, <<=, and >>=.

Mutation rules

Hunter currently takes the approach of using deterministic rules to determine which mutations to apply. This means that the same source code will always produce the same mutations. This is in contrast to probabilistic approaches, which randomly select mutations to apply. The advantage of deterministic rules is that it's easier to reason about the mutations that will be applied and limit the number of false positives(i.e: equivalent mutations) that are generated.

To see how Hunter currently determines which mutations to apply, check out the ./src/token.rs::token_transformer() function.

Output & Reporting Options

By default, Hunter will output all reports to the terminal.

Alt text

For a larger project, it can be helpful to generate a report file. This can be achieved by passing the --output-path (-o) flag to the mutate command, and specifying a path to a file. For example, hunter mutate --output-path ./hunter_report.md. This will generate a markdown file with the report in table format mimicking the tables printed to stdout by default.

Filtering Options

Hunter currently provides an option to filter the number of mutants generated by limiting the scope of source code analyzed. This can be useful for larger projects with a large number of tests. Using the --source-path(-s) flag, you can specify a path to a directory containing the source code you want to mutate. For example, hunter mutate --source-path ./src/main.nrwill limit the scope of the source code analysed to the ./src/main.nr file. By using this targeted approach methodically, you can incrementally test your codebase and improve your test suite.

Note: This is in contrast to the approach taken by some other mutation testing tools which is to optionally set the sample size, which then (non-deterministically) limits the number of mutants generated to cut down the run time.

Excluded Directories

Hunter ignores the following directories by default:

./temp, ./target, & ./test

If you want to test source files in any of these directories, simply cd into the directory and run the scan or mutate command from there. You will be prompted to choose if you want to continue, just select yes.

hunter's People

Contributors

nfurfaro avatar

Stargazers

Lulzx avatar geoffhorwitz.eth  avatar pia avatar rati.eth avatar 0xYYY avatar Shun Kakinoki avatar Maddiaa avatar  avatar

Watchers

 avatar

hunter's Issues

CI updates

Installation script

The installation section has 2 sections with 3 steps each.

An installation script may be used to replace the need for 3 commands with a single sh ./install.sh command.

Replace command sections that use a single backtick to use codeblocks

It is easier, and more presentable imo, to use a codeblock to allow a user to quickly copy and paste a command without having to highlight a part of the sentence and copy and paste a section.

So, instead of using sections such as mv location1 location2 we can use

mv location1 location2

This can be achieved with the following format
1

Readme ToC

There is a lot of content in the readme, some of which I would group differently.
A quicker, initial, solution would be to add a table of content to allow the user to jump to a specific section.

The next step would be to split the readme into different pages, potentially using mdbook.
For example, sections such as the disclaimer, help, limitations could be grouped together while usage, filtering options etc. could also be grouped.

Imperative tone in the readme

The readme mixes explanations with suggestions which results in the user having to read the entire section and parse it every time they need to find whatever they are looking for.

Instead, it would be easier to parse content by changing the tone to tell the user what they should do to achieve a desirable outcome.

For example, the quickstart cant be re-written to:


  1. Change into the root of the project
cd /path/to/project/root
  1. Display a summary of the project (can be more specific regarding Noir)
hunter scan

(In this section I would present an image, or perhaps a gif, of the action and output so the user knows what to expect)

  1. Run the mutations on the tests and generate a report (I guess this generates a file silently instead of printing to the terminal so perhaps that ought to be mentioned)
hunter mutate

(another visual example here)

Optionally, print the results to the terminal instead

hunter mutate --verbose

This style can be used throughout to reduce cognitive load and let the user quickly jump in and out with the information they need because there is less information (additional words) to parse.

Introduce additional visual aids to the documentation

In #5 I have suggested additional images, or perhaps gifs, to be added to the quickstart.

This can be expanded to any other section of the documentation.

The use of images is good for setting an expectation and showing the user what they should expect which, at least personally, may make them more inclined to try the tool.
Moreover, unlike a gif, an image is static so it allows the user to see the full content without being frustrated by it disappearing if they have not read the content in time.

On the other hand, gifs display a sample of live usage and thus allow the user to "feel" more what the tool may be like in use.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.