Cannot import a module in an integration test - rust

I am trying to configure an example project in Rust to work.
My structure is:
src/potter.rs
tests/tests.rs
And my Cargo.toml
[package]
name = "potter"
version = "0.1.0"
authors = ["my name"]
[dependencies]
My potter.rs contains:
pub mod potter {
pub struct Potter {
}
impl Potter {
pub fn new() -> Potter {
return Potter {};
}
}
}
And my tests.rs contains:
use potter::Potter;
#[test]
fn it_works() {
let pot = potter::Potter::new();
assert_eq!(2 + 2, 4);
}
But I receive this error:
error[E0432]: unresolved import `potter`
--> tests/tests.rs:1:5
|
1 | use potter::Potter;
| ^^^^^^ Maybe a missing `extern crate potter;`?
error[E0433]: failed to resolve. Use of undeclared type or module `potter`
--> tests/tests.rs:6:19
|
6 | let pot = potter::Potter::new();
| ^^^^^^ Use of undeclared type or module `potter`
warning: unused import: `potter::Potter`
--> tests/tests.rs:1:5
|
1 | use potter::Potter;
| ^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
If I add extern crate potter;, it doesn't fix anything...
error[E0463]: can't find crate for `potter`
--> tests/tests.rs:1:1
|
1 | extern crate potter;
| ^^^^^^^^^^^^^^^^^^^^ can't find crate

Go back and reread The Rust Programming Language about packages, crates, modules and the filesystem.
Common pain points:
Every programming language has its own way of dealing with files — you cannot just assume that because you've used any other language that you will magically get Rust's take on it. That's why you should go back and re-read the book chapter on it.
Each file defines a module. Your lib.rs defines a module of the same name as your crate; a mod.rs defines a module of the same name as the directory it's in; every other file defines a module of the name of the file.
The root of your library crate must be lib.rs; binary crates may use main.rs.
No, you really shouldn't try to do non-idiomatic filesystem organization. There are tricks to do most anything you want; these are terrible ideas unless you are already an advanced Rust user.
Idiomatic Rust does not generally place "one type per file" like many other languages. Yes, really. You can have multiple things in one file.
Unit tests usually live in the same file as the code it's testing. Sometimes they will be split out into a file containing the submodule, but that's uncommon.
Integration tests, examples, benchmarks all have to import the crate like any other user of the crate and can only use the public API.
To fix your issue:
Move your src/potter.rs to src/lib.rs.
Remove pub mod potter from src/lib.rs. Not strictly required, but removes needless nesting of modules.
Add extern crate potter to your integration test tests/tests.rs (Only needed if you are using Rust 2015).
filesystem
├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
├── target
└── tests
└── tests.rs
src/lib.rs
pub struct Potter {}
impl Potter {
pub fn new() -> Potter {
Potter {}
}
}
tests/tests.rs
use potter::Potter;
#[test]
fn it_works() {
let pot = Potter::new();
assert_eq!(2 + 2, 4);
}

Related

How to share a file in test files? [duplicate]

This question already has answers here:
How do I import from a sibling module?
(1 answer)
What is an idiomatic way to have shared utility functions for integration tests and benchmarks?
(3 answers)
Closed 8 months ago.
I have this hierarchy in my substrate pallet:
src/
├── lib.rs
├── mock.rs
├── tests.rs
└── common.rs
Cargo.toml
My mock.rs and tests.rs need to share some constants and types, so I put those into common.rs.
in my mock.rs and tests.rs:
mod common;
use crate::common::{
TOKEN_TRANSFER_FEE, Balance,
};
in my common.rs:
pub mod common {
pub type Balance = u128;
pub const TOKEN_TRANSFER_FEE: Balance = 1_000;
}
then I got these errors:
error[E0583]: file not found for module `common`
--> pallets/bridge/src/mock.rs:48:1
|
48 | mod common;
| ^^^^^^^^^^^
|
= help: to create the module `common`, create file "pallets/bridge/src/mock/common.rs" or "pallets/bridge/src/mock/common/mod.rs"
error[E0583]: file not found for module `common`
--> pallets/bridge/src/tests.rs:36:1
|
36 | mod common;
| ^^^^^^^^^^^
|
= help: to create the module `common`, create file "pallets/bridge/src/tests/common.rs" or "pallets/bridge/src/tests/common/mod.rs"
Is there an easier way to import those constants and types from that shared common file into mock.rs and tests.rs, instead of making mock folder and tests folders?
Use only mod once and in the other files use:
lib
mod common;
mod mock;
fn entry() {
eprintln!("{}", common::common::TEST);
}
common
pub mod common {
pub const TEST: &str = "";
}
mock
use crate::common;
fn mock() {
eprintln!("{}", common::common::TEST);
}

how to include a module from another file [duplicate]

This question already has answers here:
How can I include a module from another file from the same project?
(6 answers)
Closed 1 year ago.
I created a Cargo project. My project tree looks like this:
├── src
├── main.rs
├── animal.rs
└── human.rs
animal.rs
use crate::human::Job;
pub struct Animal {
id: u8,
job: Job,
}
impl Animal {
pub fn new(i: u8, j: Job) -> Animal {
Animal {id:i, job:j}
}
}
human.rs
pub struct Human {
id: u8,
job: Job,
}
pub enum Job {
Builder,
Magician,
}
impl Human {
pub fn new(i: u8, j: Job) -> Human {
Human {id: i, job: j}
}
}
When I compile it, it complains
$ cargo run
error[E0433]: failed to resolve: could not find `human` in the crate root
--> src/animal.rs:4:17
|
4 | job: crate::human::Job,
| ^^^^^ could not find `human` in the crate root
It gets compiled if I add "mod human;" in main.rs. What is the right way to include one module from another file in the same project?
The default package structure cargo expects is described here: https://doc.rust-lang.org/cargo/guide/project-layout.html
Therefore, you would expect to have the following files:
└── src
├── main.rs
├── lib.rs
├── animal.rs
└── human.rs
And lib.rs should contain
mod animal;
mod human;
The main.rs is an executable that would use the crate as if the library was a dependency:
use <crate_name>::human::Job;
fn main() {
// do whatever with `Job`
}
crate_name here would be the name of the crate in Cargo.toml.
Although technically nothing prevents you from declaring the modules inside main.rs like so:
mod animal;
mod human;
fn main() {
// use `human::Job`
}

Unresolved import when organising Rust code in multiple directories

I am used to organising files in separate directories depending on the problem domain (for example grouping image processing stuff together, IO stuff in another directory etc). I am not sure if this way or organisation is even recommended in Rust.
I have setup my project in multiple directories:
- helloworld
- Cargo.toml
- src
- main.rs
- test
- one.rs
I am trying to use a function from one.rs in main.rs
one.rs
fn test() {
println!("Calling test...");
}
main.rs
use test::one::*;
fn main() {
println!("Hello, world!");
test();
}
This results in a compile time error:
error[E0432]: unresolved import `test::one::*`
--> src/main.rs:1:5
|
1 | use test::one::*;
| ^^^^^^^^^^^^^ Maybe a missing `extern crate test;`?
error[E0425]: cannot find function `test` in this scope
--> src/main.rs:6:5
|
6 | test();
| ^^^^ not found in this scope
Looking at some online projects, it seems like something like this should be possible.
It is possible, however you need to inform your code about additional module that is inside your code using:
mod test;
And then create additional file
// src/test/mod.rs
pub mod one;

How do I access files in the src directory from files in my tests directory?

I have a project layout that looks like the following:
src/
int_rle.rs
lib.rs
tests/
test_int_rle.rs
The project compiles with cargo build, but I am unable to run the test with cargo test. I get the error
error[E0432]: unresolved import `int_rle`. There is no `int_rle` in the crate root
--> tests/test_int_rle.rs:1:5
|
1 | use int_rle;
| ^^^^^^^
error[E0433]: failed to resolve. Use of undeclared type or module `int_rle`
--> tests/test_int_rle.rs:7:9
|
7 | int_rle::IntRle { values: vec![1, 2, 3] }
| ^^^^^^^^^^^^^^^ Use of undeclared type or module `int_rle`
error: aborting due to 2 previous errors
error: Could not compile `minimal_example_test_directories`.
My code:
// src/lib.rs
pub mod int_rle;
// src/int_rle.rs
#[derive(Debug, PartialEq)]
pub struct IntRle {
pub values: Vec<i32>,
}
// tests/test_int_rle.rs
use int_rle;
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
int_rle::IntRle { values: vec![1, 2, 3] }
}
}
// Cargo.toml
[package]
name = "minimal_example_test_directories"
version = "0.1.0"
authors = ["Johann Gambolputty de von Ausfern ... von Hautkopft of Ulm"]
[dependencies]
Related: How do I compile a multi-file crate in Rust? (how to do it if the test and source files are in the same folder.)
The files src/int_rle.rs and src/lib.rs form your library, and together are called a crate.
Your tests and examples folders are not considered part of the crate. This is good, because when someone uses your library, they don't need your tests, they just need your library.
You can fix your issue by adding the line extern crate minimal_example_test_directories; to the top of tests/test_int_rle.rs.
You can read more about Rust's crate and module structure in the book, here.
This should be a working version of your test file:
// tests/test_int_rle.rs
extern crate minimal_example_test_directories;
pub use minimal_example_test_directories::int_rle;
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
super::int_rle::IntRle { values: vec![1, 2, 3] };
}
}

How to access a symbol defined in nested module?

I am using rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)
src
├── main.rs
└── core
├── mod.rs
└── expressionType.rs
main.rs:
mod core;
use core::expressionType;
fn main() {
let t = expressionType::ExpressionType.Integer;
println!("Hello, world!")
}
expressionType.rs:
pub enum ExpressionType {
Integer,
List(Box<ExpressionType>),
Function(Box<ExpressionType>, Box<ExpressionType>)
}
mod.rs:
pub mod expressionType;
from src, when I try to do rustc main.rs, I get
main.rs:5:13: 5:43 error: unresolved name `expressionType::ExpressionType`
main.rs:5 let t = expressionType::ExpressionType.Integer;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
I also tried core::expressionType::ExpressionType and expressionType.ExpressionType
Am I missing something? Why can't I access enum from expressionType.rs
UPD1: I also tried to add
pub use self::expressionType::ExpressionType;
to mod.rs, but after that in main.rs neither core::ExpressionType, nor expressionType::ExpressionType become available.
You need to write ExpressionType::Integer rather than ExpressionType.Integer (:: instead of .). In the latter case, the compiler is looking for a value, such as a variable or constant, named ExpressionType.

Resources