Open rylev opened 11 months ago
I wonder if the test definition manifest could be optional if a directory contains both a spin.toml
and a e.g. test.wasm
.
@rylev is there any further work related to this issue that needs to be done? Or are we considering this implemented?
@vdice this is still an active area of investigation. Please leave this issue open.
The following is an exploration pre-SIP on testing Spin applications.
High-Level Needs
At a high-level any testing mechanism for Spin needs the following:
HostComponent
mock configuration: customizing the behavior ofHostComponent
mocks so that they return customized values when invoked.HostComponent
s match expected values and that the return value from the trigger matches expected values.Request
value that gets fed into the trigger rather than having Spin start up an actual web server and the trigger being invoked through an actual HTTP request that flows through the entire network stack.HostComponent
Mocks: Instead of requiring that theHostComponent
implementations interact with real external resources (e.g., theOutboundRedisComponent
communicating with an actual Redis instance), we would provide some ability to mock that functionality. This would likely need to be optional as some users may wish for their tests to interact with actual external resources.Nice to Haves
In addition to the high-level needs above, the test trigger would preferably have the following functionality:
HostComponent
mocks: i.e., if the user wants to do something really different they can provide their ownHostComponent
mock component instead of relying on the customization knobs and levers we provide.Possible Implementation Idea
The following is a straw-man proposal for how we might be able to support testing. This implementation is an attempt to give the user the ability to write test suites orchestrators as Wasm components.
Test definition component
Users write each test definition as a component that has the following shape:
Each test suite is run against a given Spin application.
This provides the user with the ability to:
We could also provide language SDKs for writing tests that handles some of this boilerplate for you, but as with Spin components, the SDK would be optional.
Test Isolation
For each
test-suite
the Spin app under test and the test definition component only need to be compiled once. On each test invocation, a new store and instance will be used for the Spin app invocation ensuring isolation between tests.Wasi
The
test-suite
has no access to the host system throughwasi
. As usecases for interacting with the host system become more clear, we may want to reconsider this restriction.Test definition manifest
The test definition component is not sufficient to fully define a test. A test definition manifest must also be provided. We leave the exact schema of the manifest up for future bike-shedding, but it would include the following information:
Optional customization of
HostComponent
mocks. This happens in one of two ways:Static customization through the manifest. For example, a possible customization of the key-value interface could be:
A paths to
HostComponent
component implementations - more on this below.Custom Component
HostComponent
sAs stated above, the user may optionally provide paths to Wasm components that act as completely custom
HostComponent
implementations. These components export the interfaces they are mocking and are used by the test runner as the host implementation for the given mocked Spin interface.The wit for such a component would look like this:
The
configuration
export allows the component to be configured based on data from the test definition manifest. The shape of this configuration is specified by thehost-component
component. This functionality users can provide generic mocks that can be shared with the entire Spin community which should hopefully make test writting even easier.Built-in
HostComponent
mocks can be built in exactly the same way as these custom ones.Test Runner
The test runner could simply be a
spin test
command that would look for a directory of test definition manifests and run them. The test runner would read the test definition manifest and load the test component, the Spin application and configure the Spin runtime to use theHostComponent
s as defined in the manifest file.If the test component returns
ok
and none of theHostComponent
s invoke thefail
import, the test passes. Otherwise, the failure message is displayed to the user.In the future, we may want that the test runner itself can use a component for handling test suite results. For example, the test runner can invoke the stdout test runner output component for printing results to stdout, or it can invoke the JUnit test runner output component for logging results to JUnit compatible files. The community may wish to provide different implementations for their needs.
Other Thoughts
HostComponent
for a long time since many find this term confusing. Since we will now need for the user to think about the concept of "functionality that the Spin host provides" so that they can create assertions and configure mocks, we may wish to find a term that will be clearer and more immeadiately understandable.fail
import function signature to take more than just a message but potentially also asource-location
value that desciribes the source location where the assertion failure happened.HostComponent
s. This is essentially the inverse of what this document examines: testing the runtime vs. testing a component. We're likely able to share a lot between these two types of tests so we should always keep in mind that conformance testing is also something we want to be able to do in the future.