Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest splitting a crate to lib.rs and main.rs if an integration test can't find the crate because it's a binary #7885

Open
golddranks opened this issue Feb 14, 2020 · 15 comments
Labels
A-diagnostics Area: Error and warning messages generated by Cargo itself. C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-team-input Status: Needs input from team on whether/how to proceed.

Comments

@golddranks
Copy link
Contributor

golddranks commented Feb 14, 2020

Describe the problem you are trying to solve
It might be a very frustrating experience for a newbie to read about integration tests, placing tests under tests/integration.rs, trying to import the main crate, only to find a cryptic message that the "crate is not found".

Here's an example:

error[E0463]: can't find crate for `example_binary`
 --> tests/integration.rs:1:1
  |
1 | extern crate example_binary;
  | ^^^^^^^^^^^^^^^^^^^^ can't find crate

error: aborting due to previous error

Describe the solution you'd like
In the spirit of Rust's helpful error messages, it would be good to have something in the vein of "help: actually, the crate example_binary exists, but it's a binary crate, so it can't be imported. If you want to test its functionality by calling it from Rust code, try to separate the APIs you want to test into a separate library, (a link to documentation that explains main.rs and lib.rs), with the relevant functions and types exported with pub."

Notes
Of course, even more desirable thing here would be if it Simply Worked. For example, I kind of expected that you could call functions with pub even from a binary main.rs.

@golddranks golddranks added the C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` label Feb 14, 2020
@ArekPiekarz
Copy link

ArekPiekarz commented Feb 25, 2020

I feel like your issue is similar to mine for an improvement in The Rust Book - rust-lang/book#1940. It got a few voices of support, but unfortunately was closed. It seems to me this is a problem more people get exposed to and should be addressed.

@ehuss ehuss added the A-diagnostics Area: Error and warning messages generated by Cargo itself. label Mar 4, 2020
@drewgonzales360
Copy link

I also ran into a similar issue today. I was building a crate-type = ["cdylib"] and tried to use extern crate my_package but got the same error and couldn't figure out why. Now that I know the fix, it totally makes sense, but the error messages left a little confused.

For now, I'll just comment that line out when I run integration tests.

@prodrive11
Copy link

I've just spent 4hrs reading docs and shuffling files in a project with no luck, until I've found this post...
Also building cdylib, which is technically a lib... anyways...
Thanks guys for hints.

@BenjaminRi
Copy link

The error message is extremely confusing, and the fact that binary crates cannot be tested is unintuitive and guaranteed to confuse every single person who runs across this problem. Why can't binary crates be tested at an internal API level?

@ManevilleF
Copy link

I'm exactly in that situation and I don't understand what I'm supposed to do. Have a lib.rs AND a main.rs? I don't get it.

@BenjaminRi
Copy link

I'm exactly in that situation and I don't understand what I'm supposed to do. Have a lib.rs AND a main.rs? I don't get it.

@EpiFouloux There is an alternative to splitting up your project into a lib and a binary. Just put the test into your source tree. For example, suppose you have a file called frob.rs that implements various functions you want to test. Then, at the bottom of frob.rs, append the following:

#[cfg(test)]
mod tests {
	// Test in-file as we cannot test on a binary crate level
	use super::*;

	#[test]
	fn test_frob_operation() {
		// Insert your assertions here. You may use any of the functions defined in this file.
		assert_eq!(1, 1);
	}
}

These tests will not be compiled into the release binary, but they will be compiled and run if you execute cargo test, the output looks as following:

    Finished test [unoptimized + debuginfo] target(s) in 1.45s
     Running target\debug\deps\testcrate-619e72657b7037dd.exe

running 1 test
test tests::test_frob_operation ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

I chose this option and it works well for me.

@ArekPiekarz
Copy link

ArekPiekarz commented Aug 17, 2020

@BenjaminRi What you described is a unit test, while the questions in this thread were about integration tests. Note that the code undercfg(test) is not compiled in the latter.

@ManevilleF
Copy link

What I ended up doing and that works is keeping only my main.rs, having my "tests" folder under src but adding #[cfg(tests)] above mod tests; in main.rs.
All integration tests work and the cargo build doesn't check errors and warns under that folder.

@ArekPiekarz
Copy link

@EpiFouloux That sounds like unit tests, not integration ones, because in the latter cfg(tests) is not compiled. Can you try what I described in rust-lang/book#1940?

@ManevilleF
Copy link

Yes that seems like a good solution, but what are those make_binary_testableuses?

@ArekPiekarz
Copy link

@EpiFouloux For clarity I changed them into "my_library" - it's just the name of your project you are working on, structured as a library. That library can then be used in a binary or in integration tests.

@lynnpepin
Copy link

I've just spent 4hrs reading docs and shuffling files in a project with no luck, until I've found this post... Also building cdylib, which is technically a lib... anyways... Thanks guys for hints.

This is exactly where I am too. Hours spent, only to realize I had to remove cdylib.

It's very unclear why/how this happens. Does anyone have an explanation for this? (For I am thoroughly lost myself)

@enterprisey
Copy link

I'd like to try working on this. I read through the relevant bits of rustc_resolve. I think this might be a little tricky to do. I suppose when there's an import error, rustc would check if there's a binary crate with that name? I imagine this change would need both rustc and cargo work?

@stockschlaeger
Copy link

Yes, I agree that error message could be more precise and / or better explanation in the book regarding that point.

@epage
Copy link
Contributor

epage commented Nov 3, 2023

This deals with the challenge of the split of cargo and rustc. rustc doesn't know enough to detect and suggest this but cargo just passes along the error without much information to help with this.

@epage epage added the S-needs-team-input Status: Needs input from team on whether/how to proceed. label Nov 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Error and warning messages generated by Cargo itself. C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-team-input Status: Needs input from team on whether/how to proceed.
Projects
None yet
Development

No branches or pull requests