iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0

整合測試

考慮到我們的 Web Server 有多個功能,例如產生 QR Code、驗證顏色碼、從地址獲取經緯度等,整合測試將確保所有這些部分能夠正確地一起工作。

測試 index 和 generate_svg 函數

我們的 index()generate_svg() 分別負責處理 HTTP GET 和 POST 請求。這些函式調用了多個其他函式,如 get_code_data()get_coordinates(),因此它們是整合測試的理想目標。

我們可以使用 actix_web::test 來模擬 HTTP 請求。

#[cfg(test)]
mod integration_tests {
    use super::*;
    use actix_web::http::StatusCode;
    use actix_web::{test, App};
    use serde_json::json;

    #[actix_rt::test]
    async fn test_index() {
        let mut app = test::init_service(
            App::new().service(index),
        )
        .await;

        let req = test::TestRequest::get()
            .uri("/generate_qr?email=bucky0112@gmail.com")
            .to_request();

        let resp = test::call_service(&mut app, req).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn test_generate_svg_function() {
        let mut app = test::init_service(
            App::new().service(generate_svg),
        )
        .await;

        let payload = json!({
            "url": "https://example.com",
        });

        let req = test::TestRequest::post()
            .uri("/generate_qr_svg")
            .set_json(&payload)
            .to_request();

        let resp = test::call_service(&mut app, req).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }
}

然後還需要在 models/mod.rs 加上:

#[derive(serde::Deserialize, serde::Serialize)]
pub struct Info {
    pub url: Option<String>,
    pub phone: Option<String>,
    pub email: Option<String>,
    pub address: Option<String>,
    pub foreground: Option<String>,
    pub background: Option<String>,
    pub dimension: Option<u32>,
}

接著跑測試 cargo test

出來的結果是:

❯ cargo test
   Compiling qrcode-actix v0.1.0 (/Users/buckychu/sideProjects/qrcode-actix)
    Finished test [unoptimized + debuginfo] target(s) in 2.79s
     Running unittests src/main.rs (target/debug/deps/qrcode_actix-f5c31d729f1fd710)

running 5 tests
test api::tests::test_get_coordinates ... ok
test api::tests::test_get_code_data ... ok
test api::tests::test_is_valid_color ... ok
test api::integration_tests::test_index ... FAILED
test api::integration_tests::test_generate_svg_function ... ok

failures:

---- api::integration_tests::test_index stdout ----
thread 'api::integration_tests::test_index' panicked at 'assertion failed: `(left == right)`
  left: `400`,
 right: `200`', src/api/mod.rs:267:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    api::integration_tests::test_index

test result: FAILED. 4 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s

根據測試結果,test_index 測試失敗了,因為它期望得到的 HTTP 狀態碼是 200 OK,但實際得到的是 400 Bad Request。看起來我們要測試 email 但是失敗了,因為我們之前似乎都忘了在 index() 加入新的參數。

所以我們先更改一下測試:

#[cfg(test)]
mod integration_tests {
    use super::*;
    use actix_web::http::StatusCode;
    use actix_web::{test, App};
    use serde_json::json;

    #[actix_rt::test]
    async fn test_index() {
        let mut app = test::init_service(App::new().service(index)).await;

        let req = test::TestRequest::get()
            .uri("/generate_qr?url=https://example.com")
            .to_request();

        let resp = test::call_service(&mut app, req).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }
}

這樣測試結果沒問題,全部的測試都通過。🎉

❯ cargo test
   Compiling qrcode-actix v0.1.0 (/Users/buckychu/sideProjects/qrcode-actix)
    Finished test [unoptimized + debuginfo] target(s) in 2.70s
     Running unittests src/main.rs (target/debug/deps/qrcode_actix-f5c31d729f1fd710)

running 5 tests
test api::tests::test_get_code_data ... ok
test api::tests::test_get_coordinates ... ok
test api::tests::test_is_valid_color ... ok
test api::integration_tests::test_generate_svg_function ... ok
test api::integration_tests::test_index ... ok

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

然後原本的 index() 也做一下修正,可以加入其他的參數,例如 email

#[get("/generate_qr")]
async fn index(data: web::Query<Info>) -> HttpResponse {
    let code_data = match get_code_data(&data).await {
        Some(data) => data,
        None => return HttpResponse::BadRequest().body("缺少有效數據"),
    };

    let code = match QrCode::new(code_data) {
        Ok(c) => c,
        Err(_) => return HttpResponse::BadRequest().body("你輸入的字串無法處理"),
    };

    let image = code.render::<Luma<u8>>().build();

    let mut buffer = Vec::new();
    match DynamicImage::ImageLuma8(image).write_to(&mut buffer, image::ImageOutputFormat::Png) {
        Ok(_) => (),
        Err(_) => return HttpResponse::InternalServerError().body("無法生成圖像"),
    }

    HttpResponse::Ok().content_type("image/png").body(buffer)
}

現在 index() 也可以產生其他的 QR code 了,明天我們持續做好測試的部分。

https://ithelp.ithome.com.tw/upload/images/20230926/20120293hcsc658QcI.png


上一篇
Day 10 - 為 Rust 單元測試
下一篇
Day 12 - 如何利用 GitHub Action 自動化測試
系列文
30 天用 Rust 打造 QR Code 製造機30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言