출시·고도화 중
Tauri 안내서 · 5/6
Tauri 앱은 Rust 코어와 웹 프런트엔드가 함께 움직이므로 테스트도 층을 나눠 생각하는 것이 좋습니다. 이 장에서는 Rust 단위 테스트, IPC를 흉내 낸 프런트엔드 테스트, 실제 앱 창을 조작하는 WebDriver 기반 E2E 테스트를 차례로 다룹니다.
| 층 | 도구 | 확인하는 것 |
|---|---|---|
| Rust 단위 테스트 | cargo test | 명령과 비즈니스 로직 |
| 프런트엔드 테스트 | Vitest + @tauri-apps/api/mocks | 화면 로직, invoke 호출 |
| E2E 테스트 | WebdriverIO 또는 Selenium + WebDriver | 빌드된 앱 전체의 동작 |
#[tauri::command]가 붙은 함수도 평범한 Rust 함수이므로 테스트에서 바로 부를 수 있습니다. 다만 명령 안에 로직을 많이 넣기보다, 순수 함수로 떼어 두고 명령은 그 함수를 부르는 얇은 층으로 두면 테스트가 훨씬 쉬워집니다.
// src-tauri/src/lib.rs
fn normalize_title(title: &str) -> String {
title.trim().to_string()
}
#[tauri::command]
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
return Err("0으로 나눌 수 없습니다".into());
}
Ok(a / b)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn trims_title() {
assert_eq!(normalize_title(" 장보기 "), "장보기");
}
#[test]
fn divide_by_zero_is_error() {
assert!(divide(1.0, 0.0).is_err());
assert_eq!(divide(9.0, 3.0), Ok(3.0));
}
}테스트는 src-tauri 폴더에서 실행합니다. 저장소 루트에서 돌리려면 매니페스트 경로를 넘깁니다.
cd src-tauri && cargo test
# 또는 저장소 루트에서
cargo test --manifest-path src-tauri/Cargo.tomlState나 AppHandle을 받는 명령까지 IPC 경로 그대로 확인하고 싶다면, tauri 크레이트의 test 기능을 켜고 tauri::test 모듈의 모의 런타임(mock_builder, mock_context, noop_assets)으로 창 없이 앱을 만들어 시험할 수 있습니다.
일반 브라우저나 jsdom에는 Tauri 코어가 없으므로 invoke가 그대로는 동작하지 않습니다. @tauri-apps/api/mocks의 mockIPC로 명령 응답을 흉내 내면, 화면 코드를 Vitest나 Jest로 시험할 수 있습니다. Vitest 설정에서 environment를 "jsdom"으로 둡니다.
// src/greet.test.ts
import { afterEach, beforeAll, expect, test } from "vitest";
import { randomFillSync } from "node:crypto";
import { clearMocks, mockIPC } from "@tauri-apps/api/mocks";
import { invoke } from "@tauri-apps/api/core";
beforeAll(() => {
// jsdom에는 WebCrypto 구현이 없어 채워 줍니다
Object.defineProperty(window, "crypto", {
value: { getRandomValues: (buffer: any) => randomFillSync(buffer) },
});
});
// 테스트마다 흉내 낸 상태를 지웁니다
afterEach(() => clearMocks());
test("greet 명령 응답을 흉내 낸다", async () => {
mockIPC((cmd, args) => {
if (cmd === "greet") return `안녕하세요, ${(args as { name: string }).name}님!`;
});
await expect(invoke("greet", { name: "Tauri" })).resolves.toBe("안녕하세요, Tauri님!");
});같은 모듈의 mockWindows로 창 라벨을 흉내 낼 수도 있습니다. 화면이 어떤 인자로 명령을 부르는지 확인하려면 mockIPC 안에서 받은 args를 기록해 두고 검사합니다.
빌드된 앱을 실제로 띄워 버튼을 누르고 결과를 확인하려면 W3C 표준인 WebDriver를 씁니다. 공식 문서가 권하는 방법은 WebdriverIO의 Tauri 서비스(@wdio/tauri-service)입니다. npm create wdio@latest ./에서 Desktop Testing과 Tauri를 고르면 설정이 만들어집니다. 기본 방식(embedded)은 앱 안에 WebDriver 서버를 넣는 tauri-plugin-wdio-webdriver 플러그인을 쓰며, Windows · Linux · macOS에서 모두 동작합니다. 이 플러그인은 테스트용 빌드에만 넣도록 구성하는 것이 좋습니다.
// wdio.conf.ts
export const config: WebdriverIO.Config = {
specs: ["./e2e/**/*.e2e.ts"],
framework: "mocha",
services: [
["tauri", {
appBinaryPath: "./src-tauri/target/release/tauri-app",
driverProvider: "embedded",
}],
],
};// e2e/greet.e2e.ts
describe("인사 화면", () => {
it("이름을 넣으면 인사말을 보여 준다", async () => {
await $("#greet-input").setValue("Tauri");
await $("button[type='submit']").click();
await expect($("#greet-msg")).toHaveText(/Tauri/);
});
});전통적인 방법은 tauri-driver입니다. cargo install tauri-driver --locked로 설치하면 운영체제의 네이티브 WebDriver를 감싸 줍니다. Windows에서는 설치된 Edge와 버전이 맞는 msedgedriver.exe가 PATH에 있어야 하고(버전이 다르면 연결 단계에서 멈출 수 있습니다), Linux에서는 WebKitWebDriver(Debian 계열 패키지 webkit2gtk-driver)가 필요합니다. macOS에는 WKWebView용 WebDriver 도구가 없어 이 방법을 쓸 수 없습니다. Node.js를 쓰지 않는다면 Selenium 같은 다른 WebDriver 클라이언트와 함께 쓸 수 있습니다.
CI의 Linux 환경에는 화면이 없으므로 xvfb-run 같은 가상 디스플레이 아래에서 E2E 테스트를 실행합니다.
cargo test로 시험하고, 명령은 얇게 유지합니다.mockIPC로 Rust 응답을 흉내 내 Vitest 등으로 시험하고, 테스트마다 clearMocks로 정리합니다.tauri-driver는 Windows와 Linux만 지원합니다.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.