Env::set_current_dir in integration tests for command line app

I have a command line application and approx. 50 test cases in tests/integration.rs

For one particular test case I need to change the directory and after having run that test I switch back to the directory above tests/.

The problem is that other tests are affected by the env::set_current_dir as the tests run in many threads.

How could I organize my tests so that env::set_current_dir does not affect the other test cases?

You can use cargo test -- --test-threads=1 to run them sequentially. See the rust book.

Alternatively you could spawn a process for that task from the test and do it there?

Thanks, yes --test-threads=1 does it.

I also found that I could have another source, say integration_chdir.rs and run: cargo test --tests Unfortunately, I did not find a way to specify --tests as a default option in, for example, Cargo.toml.

--test-threads=1 is an anti-patttern and IMHO should not be used as a solution to any concurrency problems.

The current directory is a global mutable state, and like all global mutable state, it can be guarded with a mutex.

  1. Make a helper function such as with_directory(path, || { closure }) and make it run set_current_dir and the closure under a Mutex, so that only one of them runs at a time.

  2. Use only that function to set the current directory, so that there aren't any "non thread-safe" uses of set_current_dir. Existence of a global mutable current dir is a design flaw in the underlying OS model, so you can't have a 100% guarantee that nothing will change cwd unexpectedly, but you can try.

1 Like

On top of what others have said, if you want full integration testing, consider assert_cmd.

I have to admit that I didn't like --test-threads=1 very much. So I was happy to find that I could have more than one source in tests/ directory.

I already use assert_cmd but simply wasn't aware that there is current_dir which does things nicely.