#fork #process

test-fork

A library for running tests in separate processes

4 releases

0.1.3 Feb 26, 2025
0.1.2 Feb 20, 2025
0.1.1 Feb 16, 2025
0.1.0 Feb 8, 2025

#149 in Testing

Download history 1102/week @ 2025-02-07 932/week @ 2025-02-14 2957/week @ 2025-02-21 1135/week @ 2025-02-28

6,126 downloads per month
Used in cargo-http-registry

Apache-2.0 OR MIT

47KB
685 lines

pipeline crates.io Docs

test-fork

Custom attributes making sure a test is run in a separate process. Process separation can be useful in many contexts, including when testing interactions with necessarily process-global state (e.g., when working environment variables, when testing code that requires temporary user ID switching, or when adjusting the working directory).

Usage

This crate provides the #[test_fork::test] attribute that can be used for annotating tests to run in separate processes, as opposed to sharing the address space with other concurrently running tests:

use test_fork::test;

#[test]
fn test1() {
  assert_eq!(2 + 2, 4);
}

Also provided is the #[fork] attribute, which does not in itself make a function a test, so it will always have to be combined with an additional #[test] attribute. However, it can be more convenient for annotating only a sub-set of tests for running in separate processes, especially when non-standard #[test] attributes are involved:

use test_fork::fork;

#[fork]
#[test]
fn test2() {
  assert_eq!(2 + 3, 5);
}

Async Tests

Both #[test] and #[fork] support async tests. However, they currently rely on a somewhat counter-intuitive ordering of attributes, with #[test_fork::fork] (or #[test_fork::test]) being the inner-most one, like so:

#[tokio::test]
#[test_fork::fork]
async fn test3() {
  assert_eq!(2 + 4, 6);
}

Benchmarks

The crate also supports running libtest style benchmarks in a separate process. This functionality is available only when both the unstable and unsound features are enabled. The functionality is unstable because libtest benchmarks are unstable and only available on nightly. It is potentially unsound because the implementation necessarily needs to transfer Bencher objects across process boundaries, but said objects don't offer a stable ABI.

use test_fork::bench;

#[bench]
fn bench1(b: &mut Bencher) {
  b.iter(|| sleep(Duration::from_millis(1)));
}

The #[fork] attribute is also able to deal with benchmarks.

Dependencies

~195–630KB
~15K SLoC