An open API service indexing awesome lists of open source software.

https://github.com/psfried/testing-rust

Examples of how to use a range of testing features with the Rust programming language
https://github.com/psfried/testing-rust

Last synced: over 1 year ago
JSON representation

Examples of how to use a range of testing features with the Rust programming language

Awesome Lists containing this project

README

          

# Testing Rust Code

This repo contains examples of many common features and approaches for testing [Rust](https://www.rust-lang.org/) code. Some of the features come out of the box, and others from libraries. I tried to pick the most popular tools for each purpose, since they work well for most common use cases and you're likely to encounter these libraries in real world projects.

Our example project is just one trivially simple function (`factorial`) that's built both as a library and a command line application. That way we can demonstrate the testing of both libraries and executables.

## Links to Examples

- [Basic unit tests](src/lib.rs#L30) are the simplest thing to get started with. Rust supports these out of the box, without any libraries.
- [Doc tests](src/lib.rs#L8) are a really cool Rust feature that executes code that's included in the doc comments. This can be used to check for correctness for very simple functions, but oftentimes you'll want to have regular unit tests for more complex functions. They also ensure that the examples included in your comments are actually correct! Doc tests can be attached to just about anything, not just functions. More info on doc tests can be found [here](https://doc.rust-lang.org/rustdoc/documentation-tests.html)
- [Property based testing](src/lib.rs#L40) is an excellent approach for testing certian types of functions. This approach to testing was popularized by a Haskell library called QuickCheck, but now just about every language has some similar library available. For this example, we're using the Rust [quickcheck crate](https://github.com/BurntSushi/quickcheck). The nice thing about property-based testing is that it can quickly find boundary conditions.
- [Library integration tests](tests/lib_tests.rs) allow you to write integration tests that use your library just like a normal dependency. This forces you to use only the public API that's exposed by your library. Integration tests are supported out of the box, without any additional libraries.
- [Application integration tests](tests/cli_test.rs) allow you to test the public api of an executable. Rust is particularly great for creating command line interfaces, so this example shows off the excellent [assert\_cmd](https://github.com/assert-rs/assert_cmd) crate.
- [Benchmarks](benches/factorial_benchmark.rs) are often overlooked form of testing, but they can be extremely important in some cases. Rust does have some built-in support for benchmarks, but the [Criterion crate](https://github.com/bheisler/criterion.rs) is really the standard for benchmarking in Rust, and it's not hard to see why. Criterion has just about every feature you could need, including the ability to compare benchmarks across different builds, and even generate reports with fancy graphs.
- [Fuzz testing](fuzz/fuzz_targets/fuzz_factorial_interface.rs) is a really great approach for finding panics and memory-safety issues. Here we use [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz) to help setup and execute the fuzz tests. The actual fuzz tests are run by [libFuzzer](https://llvm.org/docs/LibFuzzer.html), though cargo-fuzz also supports AFL. Fuzz testing requires a bit more in the way of setup than the other techniques, but cargo-fuzz makes it all pretty painless. To start with, you'll need to have the nightly rust toolchain installed. Run `rustup update nightly` if you don't have that already. To run the example fuzz tests, execute `cargo +nightly fuzz run fuzz_factorial_interface -- -max_total_time=60`. This will run the fuzzer for 60 seconds. If you leave off the `max_total_time`, then the fuzzer will just run until you stop it with ctrl+c. Take a look at the [libFuzzer docs](http://llvm.org/docs/LibFuzzer.html#output) on how to interpret the output. If you hit a panic or a segfault, it'll be obvious.