|
1 | | -//! A module for getting the crate binary in an integration test. |
2 | | -//! |
3 | | -//! If you are writing a command-line interface app then it is useful to write |
4 | | -//! an integration test that uses the binary. You most likely want to launch the |
5 | | -//! binary and inspect the output. This module lets you get the binary so it can |
6 | | -//! be tested. |
7 | | -//! |
8 | | -//! # Examples |
9 | | -//! |
10 | | -//! basic usage: |
11 | | -//! |
12 | | -//! ```no_run |
13 | | -//! let output = test_bin::get_test_bin("my_cli_app") |
14 | | -//! .output() |
15 | | -//! .expect("Failed to start my_binary"); |
16 | | -//! assert_eq!( |
17 | | -//! String::from_utf8_lossy(&output.stdout), |
18 | | -//! "Output from my CLI app!\n" |
19 | | -//! ); |
20 | | -//! ``` |
21 | | -//! |
22 | | -//! Refer to the [`std::process::Command` documentation](https://doc.rust-lang.org/std/process/struct.Command.html) |
23 | | -//! for how to pass arguments, check exit status and more. |
24 | | -
|
25 | | -/// Returns the crate's binary as a `Command` that can be used for integration |
26 | | -/// tests. |
27 | | -/// |
28 | | -/// # Arguments |
29 | | -/// |
30 | | -/// * `bin_name` - The name of the binary you want to test. |
31 | | -/// |
32 | | -/// # Remarks |
33 | | -/// |
34 | | -/// It panics on error. This is by design so the test that uses it fails. |
35 | | -pub fn get_test_bin(bin_name: &str) -> std::process::Command { |
36 | | - // Create full path to binary |
37 | | - let mut path = get_test_bin_dir(); |
38 | | - path.push(bin_name); |
39 | | - path.set_extension(std::env::consts::EXE_EXTENSION); |
40 | | - |
41 | | - assert!(path.exists()); |
42 | | - |
43 | | - // Create command |
44 | | - std::process::Command::new(path.into_os_string()) |
45 | | -} |
46 | | - |
47 | | -/// Returns the directory of the crate's binary. |
48 | | -/// |
49 | | -/// # Remarks |
50 | | -/// |
51 | | -/// It panics on error. This is by design so the test that uses it fails. |
52 | | -fn get_test_bin_dir() -> std::path::PathBuf { |
53 | | - // Cargo puts the integration test binary in target/debug/deps |
54 | | - let current_exe = |
55 | | - std::env::current_exe().expect("Failed to get the path of the integration test binary"); |
56 | | - let current_dir = current_exe |
57 | | - .parent() |
58 | | - .expect("Failed to get the directory of the integration test binary"); |
59 | | - |
60 | | - let test_bin_dir = current_dir |
61 | | - .parent() |
62 | | - .expect("Failed to get the binary folder"); |
63 | | - test_bin_dir.to_owned() |
64 | | -} |
| 1 | +//! A module for getting the crate binary in an integration test. |
| 2 | +//! |
| 3 | +//! If you are writing a command-line interface app then it is useful to write |
| 4 | +//! an integration test that uses the binary. You most likely want to launch the |
| 5 | +//! binary and inspect the output. This module lets you get the binary so it can |
| 6 | +//! be tested. |
| 7 | +//! |
| 8 | +//! # Examples |
| 9 | +//! |
| 10 | +//! basic usage: |
| 11 | +//! |
| 12 | +//! ```no_run |
| 13 | +//! let output = test_bin::get_test_bin!("my_cli_app") |
| 14 | +//! .output() |
| 15 | +//! .expect("Failed to start my_binary"); |
| 16 | +//! assert_eq!( |
| 17 | +//! String::from_utf8_lossy(&output.stdout), |
| 18 | +//! "Output from my CLI app!\n" |
| 19 | +//! ); |
| 20 | +//! ``` |
| 21 | +//! |
| 22 | +//! Refer to the [`std::process::Command` documentation](https://doc.rust-lang.org/std/process/struct.Command.html) |
| 23 | +//! for how to pass arguments, check exit status and more. |
| 24 | +//! |
| 25 | +//! NOTE: There is also the older non-macro `get_test_bin` which has been |
| 26 | +//! deprecated. I has been deprecated because there is work to allow cargo to |
| 27 | +//! write its output to new paths. See [Cargo issue 14125](https://github.com/rust-lang/cargo/issues/14125). |
| 28 | +//! |
| 29 | +//! The `get_test_bin` macro uses the `CARGO_BIN_EXE_<name>` environment |
| 30 | +//! variable which was introduced in [Rust 1.43 released on 23 April 2020](https://releases.rs/docs/1.43.0/). |
| 31 | +//! |
| 32 | +
|
| 33 | +// Returns the crate's binary as a `Command` that can be used for integration |
| 34 | +/// tests. |
| 35 | +/// |
| 36 | +/// # Arguments |
| 37 | +/// |
| 38 | +/// * `bin_name` - The name of the binary you want to test. |
| 39 | +/// |
| 40 | +/// # Remarks |
| 41 | +/// |
| 42 | +/// It will fail to compile if the `bin_name` is incorrect. The `bin_name` is |
| 43 | +/// used for creating an environment variable. |
| 44 | +#[macro_export] |
| 45 | +macro_rules! get_test_bin { |
| 46 | + ($x:expr) => { |
| 47 | + { |
| 48 | + // Get path string. See the CARGO_BIN_EXE_<name> documentation: |
| 49 | + // https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates |
| 50 | + let path_str = env!(concat!("CARGO_BIN_EXE_", $x)); |
| 51 | + // Create command |
| 52 | + std::process::Command::new(path_str) |
| 53 | + } |
| 54 | + }; |
| 55 | +} |
| 56 | + |
| 57 | +/// Returns the crate's binary as a `Command` that can be used for integration |
| 58 | +/// tests. |
| 59 | +/// |
| 60 | +/// # Arguments |
| 61 | +/// |
| 62 | +/// * `bin_name` - The name of the binary you want to test. |
| 63 | +/// |
| 64 | +/// # Remarks |
| 65 | +/// |
| 66 | +/// It panics on error. This is by design so the test that uses it fails. |
| 67 | +#[deprecated(since = "0.5.0", note = "please use `get_test_bin!` macro instead")] |
| 68 | +pub fn get_test_bin(bin_name: &str) -> std::process::Command { |
| 69 | + // Create full path to binary |
| 70 | + let mut path = get_test_bin_dir(); |
| 71 | + path.push(bin_name); |
| 72 | + path.set_extension(std::env::consts::EXE_EXTENSION); |
| 73 | + |
| 74 | + if !path.exists() { |
| 75 | + // Print all environment variables. |
| 76 | + for (key, value) in std::env::vars() { |
| 77 | + println!("{key}: {value}"); |
| 78 | + } |
| 79 | + let path: &'static str = env!("PATH"); |
| 80 | + println!("the $PATH variable at the time of compiling was: {path}"); |
| 81 | + let build_dir = std::env::var("CARGO_BIN_EXE_test_bin").unwrap(); |
| 82 | + panic!("Environment variable is {}", build_dir); |
| 83 | + } |
| 84 | + |
| 85 | + assert!(path.exists()); |
| 86 | + |
| 87 | + // Create command |
| 88 | + std::process::Command::new(path.into_os_string()) |
| 89 | +} |
| 90 | + |
| 91 | +/// Returns the directory of the crate's binary. |
| 92 | +/// |
| 93 | +/// # Remarks |
| 94 | +/// |
| 95 | +/// It panics on error. This is by design so the test that uses it fails. |
| 96 | +fn get_test_bin_dir() -> std::path::PathBuf { |
| 97 | + // Cargo puts the integration test binary in target/debug/deps |
| 98 | + let current_exe = |
| 99 | + std::env::current_exe().expect("Failed to get the path of the integration test binary"); |
| 100 | + let current_dir = current_exe |
| 101 | + .parent() |
| 102 | + .expect("Failed to get the directory of the integration test binary"); |
| 103 | + |
| 104 | + let test_bin_dir = current_dir |
| 105 | + .parent() |
| 106 | + .expect("Failed to get the binary folder"); |
| 107 | + test_bin_dir.to_owned() |
| 108 | +} |
0 commit comments