# Section IV - module

> [hello\_world.rs](https://github.com/dsietz/rust-daas/blob/master/src/hello_world.rs)

To create the module, create a new file named ***hello\_world.rs*** in the **/src** directory.

To begin, we will follow some basic TDD practices and build our tests first.

> NOTE: This is not a TDD workshop, so we will ignore the complete practices and simply illustrate how it would be done.

At the bottom of the file, create an empty nested *testing* module. This will be where we write our unit test for the hello\_world module. The use `super::*;` line imports all the functionality and variables form the parent hello\_world module.

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

Our first test will be to return the service root. Add the following test in tests module below the `use super::;` line so it looks like the following.

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

    #[test]
    fn test_get_service_root() {
        assert_eq!(get_service_root(), format!("/hello/{}", VER));
    }
}
```

Following TDD practices, we now run our test and confirm that it will fail.

```
[user@localhost rust-daas]$ cargo test
   Compiling rust-daas v0.1.0 (C:\tmp\rust-daas)
error[E0425]: cannot find function `get_service_root` in this scope
  --> src\hello_world.rs:10:20
   |
10 |         assert_eq!(get_service_root(), format!("/hello/{}", VER));
   |                    ^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `test_get_service_root`

warning: unused imports: `App`, `HttpRequest`, `Responder`
 --> src\hello_world.rs:2:17
  |
2 | use actix_web::{App, HttpRequest, Responder};
  |                 ^^^  ^^^^^^^^^^^  ^^^^^^^^^
  |
  = note: #[warn(unused_imports)] on by default

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.
error: Could not compile `rust-daas`.

To learn more, run the command again with --verbose.
```

To make the test pass, we will add the `get_service_root()` function to the module.

```
use super::*;

pub fn get_service_root() -> String {
    format!("/hello/{}", VER)
}

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

    #[test]
    fn test_get_service_root() {
        assert_eq!(get_service_root(), format!("/hello/{}", VER));
    }
}
```

If we rerun our test, it will now pass.

```
[user@localhost rust-daas]$ cargo test
   Compiling rust-daas v0.1.0 (C:\tmp\rust-daas)
    Finished dev [unoptimized + debuginfo] target(s) in 1.60s
     Running target\debug\deps\daas-dafe2c98359dbcd2.exe

running 1 test
test hello_world::tests::test_get_service_root ... ok

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

     Running target\debug\deps\hello_world-f32c48dd7c679e2e.exe

running 0 tests

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

   Doc-tests daas

running 0 tests

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

We will do the same for the `get_service_path()` function.

```
use super::*;

pub fn get_service_root() -> String {
    format!("/hello/{}", VER)
}

pub fn get_service_path() -> String {
    get_service_root() + "/"
}

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

    #[test]
    fn test_get_service_root() {
        assert_eq!(get_service_root(), format!("/hello/{}", VER));
    }

    #[test]
    fn test_get_service_path() {
        assert_eq!(get_service_path(), format!("/hello/{}/", VER));
    }
}
```

Now that we have an understanding of how to write our tests, and then add the funcitonality to make them pass, we will move on to provide our service call.

Our test will be the following.

```
mod tests {
   use super::*;
   use actix_web::{http, test};

   #[test]
    fn test_get_service_root() {
        assert_eq!(get_service_root(), format!("/hello/{}", VER));
    }

    #[test]
    fn test_get_service_path() {
        assert_eq!(get_service_path(), format!("/hello/{}/", VER));
    }

   #[test]
    fn hello_response() {
        let resp = test::TestRequest::with_header("content-type", "text/plain")
            .run(&index)
            .unwrap();
        assert_eq!(resp.status(), http::StatusCode::OK);
    }
}
```

In order to make it pass, we will need to import the web service modules, and provide a `index()` function.

```
use actix_web::{App, HttpRequest, Responder};

pub fn index(_req: &HttpRequest) -> impl Responder {
    "Hello World!".to_string()
}
```

The final file should look like the following.

```
use super::*;
use actix_web::{App, HttpRequest, Responder};

pub fn get_service_root() -> String {
    format!("/hello/{}", VER)
}

pub fn get_service_path() -> String {
    get_service_root() + "/"
}

pub fn index(_req: &HttpRequest) -> impl Responder {
    "Hello World!".to_string()
}

mod tests {
   use super::*;
   use actix_web::{http, test};

   #[test]
    fn test_get_service_root() {
        assert_eq!(get_service_root(), format!("/hello/{}", VER));
    }

    #[test]
    fn test_get_service_path() {
        assert_eq!(get_service_path(), format!("/hello/{}/", VER));
    }

   #[test]
    fn hello_response() {
        let resp = test::TestRequest::with_header("content-type", "text/plain")
            .run(&index)
            .unwrap();
        assert_eq!(resp.status(), http::StatusCode::OK);
    }
}
```

Rerun the tests to make sure it all passes.

We now have one last step, which is to add a function that will provide the service object. This is will nor be covered by unit testing and is instead covered by integrated testing.

To create integrated tests, first create a new file named ***web-service-tests.rs*** in a new directory named ***tests*** in the root path (same level as the **src** directory). Cargo will automatically parse the ***tests*** directory and run any tests that are located in any files located here.

```
.
|-- .git
|-- .gitignore
|-- src
     |-- bin
          |-- hello-world.rs
     |-- hello_world.rs
     |-- lib.rs
|-- tests
     | -- web-service-tests.rs
|-- Cargo.toml
```

In order to execute our service test, we will first need to include the `bytes` library to our project. We do this by adding the line `bytes = "0.4"` in the `[dependencies]` section of the ***Cargo.toml*** file.

```
[dependencies]
hyper = "0.11.0"
actix-web = "0.7"
bytes = "0.4"
```

Once the library has been included in the Manifest, we define which libraries are required in the ***web-service-tests*** module by adding the following lines at the top of the ***web-service-tests.rs*** file.

```
extern crate actix_web;
extern crate bytes;
```

The `extern` declarations specify the dependent crates (or libraries) that will be used in the ***web-service-tests*** module.

We then declare the bindings (or shortcuts) to a resources that will be used in the ***web-service-tests*** module. This is done by adding the following lines below the `extern` crate declarations.

```
use daas::hello_world;
use actix_web::*;
use http::header;
use bytes::Bytes;
```

Now we can add the code for our Hello World service test, which is added below the `use` declarations.

```
#[test]
fn test_hello_world_ok() {
    let mut srv =actix_web::test::TestServer::new(|app| app.handler(hello_world::index));
    let request = srv.get().uri(srv.url("/").as_str()).finish().unwrap();
    let response = srv.execute(request.send()).unwrap();

    assert!(response.status().is_success());

    // read response
    let bytes = srv.execute(response.body()).unwrap();
    assert_eq!(bytes, Bytes::from_static("Hello World!".as_ref()));
}
```

At this point the ***web-service-tests.rs*** file should look like this:

```
extern crate actix_web;
extern crate bytes;

use daas::hello_world;
use actix_web::*;
use http::header;
use bytes::Bytes;

#[test]
fn test_hello_world_ok() {
    let mut srv =actix_web::test::TestServer::new(|app| app.handler(hello_world::index));
    let request = srv.get().uri(srv.url("/").as_str()).finish().unwrap();
    let response = srv.execute(request.send()).unwrap();

    assert!(response.status().is_success());

    // read response
    let bytes = srv.execute(response.body()).unwrap();
    assert_eq!(bytes, Bytes::from_static("Hello World!".as_ref()));
}
```

Try running your test with the `cargo test` command. There should now be a line in the results referencing that the `web_service_tests` has run.

```
     Running target\debug\deps\web_service_tests-664800ae8a37eeb0.exe

running 1 test
test test_hello_world_ok ... ok
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://davidsietz.gitbook.io/workspace/module-02/02-section-04/02-section-04-3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
