← Back to Lessons Lesson 18 of 28
Intermediate getting-started

Testing Wasm

Why Test Wasm?

Rust/Wasm code runs in two environments — native (your machine) and browser (Wasm). Tests should cover both to catch environment-specific bugs.

Test Setup

# Cargo.toml
[dev-dependencies]
wasm-bindgen-test = "0.3"

Unit Tests (Native)

Standard Rust tests run with cargo test:

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

    #[test]
    fn test_add() {
        assert_eq!(add(2, 3), 5);
        assert_eq!(add(-1, 1), 0);
        assert_eq!(add(0, 0), 0);
    }

    #[test]
    fn test_fibonacci() {
        assert_eq!(fibonacci(0), 0);
        assert_eq!(fibonacci(1), 1);
        assert_eq!(fibonacci(10), 55);
    }
}
cargo test

Wasm Tests (Browser)

Tests that need browser APIs use wasm-bindgen-test:

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

    wasm_bindgen_test_configure!(run_in_browser);

    #[wasm_bindgen_test]
    fn test_greet() {
        let result = greet("World");
        assert_eq!(result, "Hello, World!");
    }

    #[wasm_bindgen_test]
    fn test_dom_creation() {
        let document = web_sys::window().unwrap().document().unwrap();
        let el = document.create_element("div").unwrap();
        el.set_text_content(Some("test"));
        assert_eq!(el.text_content().unwrap(), "test");
    }
}
# Run in headless Chrome
wasm-pack test --headless --chrome

# Run in headless Firefox
wasm-pack test --headless --firefox

# Run in Node.js (no DOM available)
wasm-pack test --node

Async Tests

Test async Wasm functions:

#[wasm_bindgen_test]
async fn test_async_fetch() {
    let window = web_sys::window().unwrap();
    let resp = JsFuture::from(
        window.fetch_with_str("/test-data.json")
    ).await.unwrap();
    assert!(resp.is_object());
}

Test Organization

src/
├── lib.rs          # Your Wasm code
└── tests/          # Integration tests
    ├── native.rs   # cargo test (no browser)
    └── web.rs      # wasm-pack test (needs browser)

Testing Best Practices

Practice Why
Test pure logic natively (cargo test) Fast, no browser needed
Test DOM/browser interactions with wasm-bindgen-test Catches Wasm-specific issues
Use --headless in CI No GUI needed on CI servers
Test error cases Result::Err paths are often untested
Benchmark with console.time() Catch performance regressions

CI Configuration (GitHub Actions)

name: Test
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: cargo-bins/cargo-binstall@main
      - run: cargo binstall wasm-pack -y
      - run: cargo test
      - run: wasm-pack test --headless --chrome

Try It

Click Run to see the test assertions pass. In real projects, these would be in #[test] and #[wasm_bindgen_test] functions.

Try It

Chapter Quiz

Pass all questions to complete this lesson