How do I display only test classes where tests exist?

I am reading the rust book and follow along. This is what I thought is important in my main.rs file:

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_get_first_word() {
        let s1 = String::from("a b c");
        let s2 = String::from("élan ah");
        assert_eq!(get_first_word(&s1), "a");
        assert_eq!(get_first_word(&s2), "élan");
    }
}

it is the only place where I used mod tests #[cfg(test)]
yet I get this output, all warnings are unused warnings:

warning: `hello_cargo` (bin "hello_cargo" test) generated 5 warnings (run `cargo fix --bin "hello_cargo" --tests` to apply 1 suggestion)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.03s
     Running unittests src/lib.rs (target/debug/deps/hello_cargo-390c22ba899df2a1)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/main.rs (target/debug/deps/hello_cargo-6fd24f2278d42774)

running 1 test
test tests::test_get_first_word ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests hello_cargo

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

how can I turn the other test classes off? Thanks!

This output indicates that you have both src/lib.rs (the root file of a library crate) and src/main.rs (the root file of a binary crate). You should generally avoid this when getting started, because it is a tricky setup to comprehend and can produce highly confusing errors and warnings. I imagine you probably either did it by accident, or decided to name one of your modules lib.

In any case, unless you are trying to develop a library (which I assume you probably aren’t), you should remove the file src/lib.rs; if it has any code you want to save, put it in a file with a different name than that. That will stop the extra test output, keep your project organization clean, and possibly avoid some warnings.


If you really want to keep the current configuration and just disable those empty test targets, you can do that by adding this to your Cargo.toml:

[lib]
test = false
doctest = false

However, this should be used with care, because it means that if there are tests in the library crate, they still won't be run. Cargo doesn’t try to discover whether or not tests exist in a crate; it just tries to run them.


You can also use cargo test --quiet to get less output from both Cargo and the test harness.

1 Like

thanks! :slight_smile:

I have a follow up question: I deleted lib.rs as you said. I have two crates, main.rs and main1.rs
and a number of submodules in main.rs, this is the directory structure:

tests/
- integrationtests.rs
src/
- main.rs
- module1/
-- mod.rs
-- submodule1/
--- mod.rs
- module2/
-- mod.rs
- main1.rs
//integrationtests.rs
use main::*;

// unresolved import: 
// unresolved module or use of unimported module "main1"
use main1::*;


#[test]
fn testmain() {
    assert_eq!(main::module1::mod1string(), "mod1string");
    assert_eq!(main::module2::mod2string(), "mod2string");
    assert_eq!(main::module1::submodule1::mod1string(), "submod1string");
    assert_eq!(main1::main1test(), "main1test");
}

I followed the compiler suggestion and executed cargo add main
but this throws an error for cargp add main1: error: the crate main1 could not be found in registry index.
Could you tell me what is wrong once more? :slight_smile:

I have two crates, main.rs and main1.rs

That's not what a crate is. Right now, main1.rs is just a source file that is not compiled. It sounds like you are thinking “module” means “directory of source code”. That’s not true; every source file except the root is a module file and needs to be declared with mod.

So, the answer to your question is perhaps that you should put

mod main1;

in src/main.rs to declare the module. But I'm now further confused about what you’re trying to do and what your project setup is. Here are some questions to try to clarify things so I can help you better:

  • What are the contents of your Cargo.toml?
  • Which chapter of the book are you currently working on?
  • What are you trying to get your program to do when you run it?

The contents of Cargo.toml:

[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"

[dependencies]
main = "0.1.0"

Where I am currently at in the book: I finished chapter 11 Writing Automated Tests - The Rust Programming Language
I ran simple unit tests for main.rs and its submodules and wanted to run an integration test using different crates (which I thought where different crates). Thats why I test functions from main and main1.

From the book Packages and Crates - The Rust Programming Language

A crate can come in one of two forms: a binary crate or a library crate. Binary crates are programs you can compile to an executable that you can run, such as a command line program or a server. Each must have a function called main that defines what happens when the executable runs. All the crates we’ve created so far have been binary crates.

My aim: So I though main.rs and main1.rs both with main()would be different crates so how can I make them different crates and if the excerpt from the book is not an exhaustive definition for crates what is one?

You'll want to delete the line main = "0.1.0". It’s referring to main on crates.io, which isn't particularly harmful but is a basically empty library that doesn’t do anything you want.

If you want multiple binary crates, then you should organize them differently, like this:

src/
    bin/                  # this name is where Cargo looks for additional crates 
        mybin1/           # this is your choice of name
            main.rs       # This will be compiled as the crate root for mybin1
        mybin2/           # this is your choice of name
            main.rs       # This will be compiled as the crate root for mybin1

The point of having multiple binary crates in a package is to compile them into multiple, distinct executable programs. If you don't want to make multiple programs that share some parts, you don't need multiple binary crates.

If you want multiple library crates, you need to create an additional package (directory with Cargo.toml file). Each package may only have at most one library crate (but can have any number of binary crates in addition).

The point of having library crates is to produce libraries that other programs can use. If you don't want to share code for others to use, or share code between multiple binary crates you are working on, then you don't need any library crates.[1]

… and if the excerpt from the book is not an exhaustive definition for crates what is one?

A crate is “the thing that rustc compiles when run once”. Multiple crates mean rustc is being run more than once. The compilation can produce either a compiled library for use by further crate compilations, or a compiled binary (executable) that you can run standalone. There are a number of things in the language that care about what crate code is in, like trait coherence and paths that start with crate::.

Broadly speaking, every project should be a single crate until you have a specific reason to split it into more than one crate. Multiple crates add complexity (and can either increase or decrease total build time, depending on the choice of split).

The “integration test” feature of Cargo is intended to be used for two use cases:

  • Testing a library crate by using its public functions.
  • Testing a binary crate by running the program and seeing what it does.

Testing functions in the code of a binary crate is neither of those things — to write that kind of test, you must write the tests in the crate's own source code in src/, not in tests/. That's the only way the functions will be reachable.


  1. There are more reasons to add library crates, but they are more complex. ↩︎

2 Likes

Thank you for taking the time to write this! :slight_smile:

1 Like

Another followup, I am following the book Developing the Library’s Functionality with Test Driven Development - The Rust Programming Language and copied their source code.
My directory structure is this:

src/
- bin/
-- lib.rs
-main.rs
Cargo.toml
#Cargo.toml
[package]
name = "minigrep"
version = "0.1.0"
edition = "2024"
[dependencies]
# lib.rs
# the only place where I use #[cfg(test)] and #[test]

#...

#[cfg(test)]
mod tests {
    use crate::Config;

    #[test]
    fn test_build_config() {
        let file_path = "censoredpath/Rust/Tutorials/minigrep/searchfile";
        let minigrep_path = "censoredpath/Rust/Tutorials/minigrep/";
        let search_text = "keyword";
        let args = [String::from(minigrep_path), String::from(file_path)];
        assert_eq!(Config::build(&args), Err("Not enough arguments."));
    }
}

Again I get test output for non existing test classes, can you explain why and how to omit this?

Finished `test` profile [unoptimized + debuginfo] target(s) in 0.20s
     Running unittests src/lib.rs (target/debug/deps/minigrep-6189184d8e53aca1)

running 1 test
test tests::test_build_config ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/bin/main.rs (target/debug/deps/main-b307b7a86dbfe662)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests minigrep

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Chapter 7 does explain you the meaning of the project's structure. Including:

Here, we have a package that only contains src/main.rs , meaning it only contains a binary crate named my-project . If a package contains src/main.rs and src/lib.rs , it has two crates: a binary and a library, both with the same name as the package. A package can have multiple binary crates by placing files in the src/bin directory: each file will be a separate binary crate.

What is important from there is that you creating a package with two crates. By default it will try to test both and the documentation.

The structure they should be talking about is the simpler:

src/
    lib.rs
    main.rs

does not need any extra /bin if you have a single binary. It does have two crates though.

Ideally, you should have tests in the binary and in the library; these are two separate crates each with its own tests.

If you want to temporarily turn one off, do what was suggested:

[lib]
test = false
doctest = false

But look at what this means: turn of doc tests and tests for library crate.

Also remember to move binary crate file main.rs to the top level.

2 Likes

thanks!