May 08, 2024

Announcing Spin Test

Melissa Klein Melissa Klein

spin test plugin

Announcing Spin Test

Today we’re happy to announce the very first alpha release of spin-test , a plugin for Spin that runs tests written in WebAssembly against a Spin application where all Spin and WASI APIs are configurable mocks.

With spin-test, you can write test scenarios for your app in any language with WebAssembly component support and mock out all interactions your app has with the outside world without requiring any code changes to the app itself. That means the code you test in development is the exact same code that runs in production.

Note: spin-test is still under active development and so the details here may have changed since this post was first published. Check the spin-test repo for the latest information on installation and usage.

Installing the Plugin

To run spin-test , you’ll first need to install the canary release of the plugin. As spin-test matures, we’ll be making stable releases.

The following command installs the plugin to work on Linux. If you are using another OS/architecture, please visit the canary release page and choose the appropriate Asset to suit your needs:

spin plugin install -u https://github.com/fermyon/spin-test/releases/download/canary/spin-test.json

This will install the plugin which can be invoked with spin test.

Writing a test

Next you’ll need a test that spin-test can run compiled to a WebAssembly component.

There is currently first class support for Rust through the spin-test Rust SDK, but any language with support for writing WebAssembly components can be used as long as the fermyon:spin-test/test world is targeted. You can find the definition of this world here.

Here’s an example of a test written in Rust using the spin-test Rust SDK that tests that the Spin app responds properly when the key-value store has a certain key already set:

use spin_test_sdk::{
    bindings::{fermyon::spin_test_virt, wasi},
    spin_test,
};

#[spin_test]
fn cache_hit() {
    let user_json = r#"{"id":123,"name":"Ryan"}"#;

    // Configure the app's 'cache' key-value store
    let key_value = spin_test_virt::key_value::Store::open("cache");
    // Set a specific key with a specific value
    key_value.set("123", user_json.as_bytes());

    // Make the request against the Spin app
    let request = wasi::http::types::OutgoingRequest::new(wasi::http::types::Headers::new());
    request.set_path_with_query(Some("/?user_id=123")).unwrap();
    let response = spin_test_sdk::perform_request(request);

    // Assert the response status and body
    assert_eq!(response.status(), 200);
    let body = response.body_as_string().unwrap();
    assert_eq!(body, user_json);

    // Assert the key-value store was queried
    assert_eq!(
        key_value.calls(),
        vec![spin_test_virt::key_value::Call::Get("123".to_owned())]
    );
}

The test above will run inside of WebAssembly. The calls to the key value store and the Spin app itself never leave the WebAssembly sandbox. This means your tests are quick and reproducible as you don’t need to rely on running an actual web server, and you don’t need to ensure any of your app’s dependencies are actually running. Everything your app interacts with is mocked for you.

Configure spin-test

Before we can run the test, we’ll need to tell spin-test where our test lives and how to build it. We do this from inside our app’s spin.toml manifest. Let’s imagine our app has a component named “my-component” that we want to test. In the spin.toml manifest we can add the following configuration:

[component.my-component.tool.spin-test]
# A relative path to where the built test component binary will live.
source = "my-test/target/wasm32-wasi/release/test.wasm"
# A command for building the target component.
build = "cargo component build --release"
# The directory where the `build` command should be run.
dir = "my-test"

Running the test

Finally, we’re ready for our test to be run. We can do this simply by invoking spin-test from the directory where our Spin application lives:

$ spin-test

running 1 test
test cache-hit ... ok

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

Next Steps

Looking for another example? The Fermyon Developer Home has an end-to-end spin-test example that performs an outgoing HTTP request and asserts the response status.

spin-test is still in the early days of development, so you’re likely to run into things that don’t quite work yet. We’d love to hear about your experience so we can prioritize which features and bugs to fix first. We’re excited about the future of testing powered by WebAssembly components, and we look forward to hearing about your experiences as we continue the development of spin-test.

 

 

 


🔥 Recommended Posts


Quickstart Your Serveless Apps with Spin

Get Started