I'd like to be able to run a binary generated by cargo directly in integration tests. I know that cargo places binaries (at least ones in a main.rs) in target/(debug or release)/myapp(.exe) . Is there a cleaner way to get that location, though? Like in an environment variable or macro? I didn't see exactly what I want in Page Moved . I can use CARGO_MANIFEST_DIR , detect whether it's debug or release, then sort of guess the executable name with CARGO_PKG_NAME, but that doesn't seem very clean and a little unreliable.
Also, tangentially, is there a place where all the possible values for cfg! can be found? I didn't see anything in https://rustbyexample.com/attribute/cfg.html , cfg in std - Rust , or Conditional Compilation - The Rust Programming Language .
Thanks.
If you are scripting your ITs is it enough to know that --release compiles to target/release and without goes to target/debug?
You could also combine RUSTFLAGS and CARGO_TARGET_DIR to get the desired output.
1 Like
Thanks for the response. Unless I'm misinterpreting the docs, those two variables are passed to cargo, rather than set by cargo. Whatever the case, I tried them and they weren't found.
I ended up doing this, but it's less than pretty:
let mut program_path_buf = PathBuf::new();
program_path_buf.push(env!("CARGO_MANIFEST_DIR"));
program_path_buf.push("target");
program_path_buf.push(if cfg!(debug_assertions) { "debug" } else { "release" });
program_path_buf.push(if cfg!(windows) { concat!(env!("CARGO_PKG_NAME"), ".exe") } else { env!("CARGO_PKG_NAME") });
println!("program_path_buf: {:?}", program_path_buf);
Does anyone have a nicer way?
I know you can use std::env::current_exe()
to get the location of the currently running binary at runtime. Could you calculate the location of your other binary relative to the integration test binary being run?
1 Like
Hmm, I think I might like that better. It avoids the if/else on cfg!(debug_assertions). Also, it looks like std::env::consts can be used instead of hard-coded ".exe". So almost there . To get what I really want I might ultimately need a build script...
Just out of curiosity, do you know if cargo
adds the output directory (e.g. target/debug/
) to your PATH
when running tests? If that's the case you wouldn't have to stuff around with any of this, you can just do Command::new("my_program").output().unwrap()
in your test.
1 Like
I'll give that a try when I get home from work, that's a good suggestion.
I'm thinking something like Expect/DejaGnu might be more appropriate to what I'm trying to do, so I'm going to look into that. Maybe a 3rd-party cargo module would be interesting to work on.
I just had a google and apparently there's a rexpect crate. Looking at the README it seems to be fairly useful and actively maintained. Would that be useful for running tests?
1 Like
Cool, I think it might. When I googled "rust expect" I got nothing but pages talking about Option and Result. Thanks.
what you are trying to do is exactly the same I'm planning. Nice coincidence
I designed rexpect as a standalone crate which can execute programs where you can interact with them, send ctrl-c etc. and expect output (you're right: expect
is already a reserved keyword in rust, that is one of a drawback of such a crate..).
That said, I just created shell_doctest (unfortunately it's only a stub and not usable at all yet) to be able to add doctests to executables (and so create a kind of integration test which starts the executable and does some input/output tests):
$ my_program
expected_output
Ultimately it would need the same things as you say, find out if the current target is debug or release, but I'm planning to put that into a build script so I'm sure that available is available at build/test time. I would be happy if we could cooperate on that quest..!