How to write rust tests && How to make the general rust file structure

1. For the test part 

Just create a folder called tests, and put a file called general_test.rs into it.
It may look like this:

❯ tree -L 3
.
├── Cargo.toml
├── src
│   ├── environment_module
│   │   ├── basic.rs
│   │   └── mod.rs
│   ├── internal_api_service
│   │   ├── internal_api_service_implementation.rs
│   │   ├── mod.rs
│   │   └── postgre_sql_database_handler.rs
│   ├── lib.rs
│   ├── main.rs
└── tests
    ├── general_test.rs
    └── postgre_sql_test.rs

For the test file itself, it may look like this:

#[cfg(test)]
mod tests {
    use tokio::time::{sleep, Duration};

    #[test]
    fn test_equality() {
        assert_eq!(5, 5);
    }

    #[test]
    #[should_panic]
    fn test_any_panic() {
        panic!("should panic");
    }

    #[test]
    #[should_panic(expected = "error message 1")]
    fn test_specific_panic() {
        panic!("error message 1");
    }

    #[tokio::test]
    async fn test_something_async() {
        sleep(Duration::from_millis(1000)).await;
        println!("1000 ms have elapsed");
    }
}

Then run cargo test to do the test.

For the general rust file structure

Inside of Cargo.toml, it has a name, that’s the root package name, you’ll call other modules based on it, for example, if I have the name == "rust_service", then I can import a sub module by using: use rust_service::environment_module::basic::EnvironmentVariables;

Sometimes, we also use crate to refer the root, for example, we can import the same module by using: use crate::environment_module::basic::EnvironmentVariables;

Then, you need to know the lib.rs is the center for a package. You have to specify all those modules inside of this file, here is what I did for this case:

// lib.rs
pub mod internal_api_service;
pub mod environment_module;

Then, for a folder, the folder name itself is also the module name. You can specify sub-modules by declare them inside of mod.rs file. Here is what I did:

// ./environment_module/mod.rs
pub mod basic;

Finally, for all those functions or structures, you have to put pub before them to let them be public and called for other modules. Here is what I did:

// ./environment_module/basic.rs
use std::env;

#[derive(Debug, Clone)]
pub struct EnvironmentVariables {
    // - postgre_db_network_name=db
    pub postgre_db_network_name: String,
    pub postgres_user: String,
    pub postgres_password: String,
}

pub fn get_environment_variables() -> EnvironmentVariables {
    let mut environment_variables: EnvironmentVariables = EnvironmentVariables {
        postgre_db_network_name: String::from("http://127.0.0.1:5432/"),
        postgres_user: String::from("yingshaoxo"),
        postgres_password: String::from("yingshaoxo"),
    };

    match env::var_os("postgre_db_network_name") {
        Some(v) => {
            environment_variables.postgre_db_network_name =
                String::from("http://") + v.to_str().unwrap() + ":5432/";
        }
        None => println!("environment_variable 'postgre_db_network_name' is not set"),
    };

    match env::var_os("postgres_user") {
        Some(v) => {
            environment_variables.postgres_user = v.to_str().unwrap().to_string();
        }
        None => println!("environment_variable 'postgres_user' is not set"),
    };

    match env::var_os("postgres_password") {
        Some(v) => {
            environment_variables.postgres_password = v.to_str().unwrap().to_string();
        }
        None => println!("environment_variable 'postgres_password' is not set"),
    };

    return environment_variables;
}