blob: 2f6ad4b426da621687975b5223b18ae248318be8 [file] [log] [blame] [view] [edit]
# The Fuchsia Test Runner Framework
<<../components/_v2_banner.md>>
## Integrating testing frameworks with the Component Framework
The Fuchsia [Component Framework][cf] allows developers to create components in
a variety of languages and runtimes. Fuchsia's own code uses a diverse mix of
programming languages for components, including C/C++, Rust, Dart, and Go.
The Test Runner Framework uses Component Framework [runners][runners] as an
integration layer between various testing runtimes and a common Fuchsia protocol
for launching tests and receiving their results.
## The test suite protocol {#test-suite-protocol}
The test suite protocol, [`fuchsia.test.Suite`][fidl-test-suite], is used by the
test manager to control tests, such as to invoke test cases and to collect their
results.
Test authors typically don't need to implement this protocol. Instead, they rely
on a [test runner](#test-runners) to do this for them. For instance, you might
write a test in C++ using the GoogleTest framework, and then use
[`gtest_runner`](#gtest-runner) in your [component manifest][component-manifest]
to integrate with the Test Runner Framework.
## Test runners {#test-runners}
Test runners are reusable adapters between the Test Runner Framework and common
languages & frameworks used by developers to write tests. They implement the
[`fuchsia.test.Suite`][fidl-test-suite] protocol on behalf of the test author,
allowing developers to write idiomatic tests for their language and framework of
choice.
Component manifests for simple unit tests can be [generated][unit-tests]
by the build rules. Generated component manifests for v2 tests will include the
appropriate test runner based on their build definition. For instance a test
executable that depends on the GoogleTest library will include the
[GoogleTest runner](#gtest-runner) in its generated manifest.
### Inventory of test runners
The following test runners are currently available for general use:
#### GoogleTest runner {#gtest-runner}
A runner for tests written in C/C++ using the GoogleTest framework.
Use this for all tests written using GoogleTest.
Common GoogleTest features are supported, such as disabling tests, running
only specified tests, running the same test multiple times, etc'.
Standard output, standard error, and logs are captured from the test.
In order to use this runner, add the following to your component manifest:
```json5
{
include: [ "src/sys/test_runners/gtest/default.shard.cml" ]
}
```
By default GoogleTest test cases run serially (one test case at a time).
#### Rust runner {#rust-runner}
A runner for tests written in the Rust programming language and following Rust
testing idioms.
Use this for all idiomatic Rust tests (i.e. tests with modules that set the
attribute `[cfg(test)]`).
Common Rust testing features are supported, such as disabling tests, running
only specified tests, running the same test multiple times, etc'.
Standard output, standard error, and logs are captured from the test.
In order to use this runner, add the following to your component manifest:
```json5
{
include: [ "src/sys/test_runners/rust/default.shard.cml" ]
}
```
By default Rust test cases run in parallel, at most 10 cases at a time.
#### Go test runner {#gotest-runner}
A runner for tests written in the Go programming language and following Go
testing idioms.
Use this for all tests written in Go using `import "testing"`.
Common Go testing features are supported, such as disabling tests, running
only specified tests, running the same test multiple times, etc'.
Standard output, standard error, and logs are captured from the test.
In order to use this runner, add the following to your component manifest:
```json5
{
include: [ "src/sys/test_runners/gotests/default.shard.cml" ]
}
```
By default Go test cases run in parallel, at most 10 cases at a time.
#### ELF test runner {#elf-test-runner}
The simplest test runner - it waits for your program to terminate, then reports
that the test passed if the program returned zero or that it failed for any
non-zero return value.
Use this test runner if your test is implemented as an ELF program (for instance
an executable written in C/C++) but it does not use a common testing framework
that's supported by existing runners and you'd rather not implement a bespoke
test runner.
In order to use this runner, add the following to your component manifest:
```json5
{
include: [ "src/sys/test_runners/elf/default.shard.cml" ]
}
```
There is no notion of parallelism since tests that use this runner don't have a
notion of multiple test cases.
### Controlling parallel execution of test cases
When using `fx test` to launch tests, they may run each test case in sequence or
run multiple test cases in parallel up to a given limit. The default parallelism
behavior is determined by the test runner.
To manually set the parallelism level for test cases, run the following:
```posix-terminal
fx shell run-test-suite --parallel=5 <test_url>
```
## Temporary storage
To use temporary storage in your test, add the following to your component manifest:
```json5
{
include: [ "src/sys/test_runners/tmp_storage.shard.cml" ]
}
```
At runtime, your test will have read/write access to `/tmp`.
The contents of this directory will be empty when the test starts, and will be
deleted after the test finishes.
## Hermeticity
A test is *hermetic* if it [uses][manifests-use] or [offers][manifests-offer] no
capabilities from the [test root](#tests-as-components)'s parent. As a rule of
thumb, tests should be hermetic, but sometimes a test requires a capability that
cannot be injected in the test realm.
In the context of hermetic tests, a capability that originates from outside of
the test's realm is called a *system capability*.
## Test roles {#test-roles}
Components in the test realm may play various roles in the test, as follows:
- Test driver: The component that actually runs the test, and implements
(either directly or through a [test runner](#test-runners)) the
[`fuchsia.test.Suite`][test-suite-protocol] protocol. This role may be, but
is not necessarily, owned by the [test root](#tests-as-components).
- Capability provider: A component that provides a capability that the test
will exercise somehow. The component may either provide a "fake"
implementation of the capability for test, or a "real" implementation that
is equivalent to what production uses.
- Component under test: A component that exercises some behavior to be tested.
This may be identical to a component from production, or a component written
specifically for the test intended to model production behavior.
[cf]: /docs/concepts/components/v2/
[component-manifest]: /docs/concepts/components/v2/component_manifests.md
[fidl-test-suite]: /sdk/fidl/fuchsia.test/suite.fidl
[manifests-offer]: /docs/concepts/components/v2/component_manifests.md#offer
[manifests-use]: /docs/concepts/components/v2/component_manifests.md#use
[runners]: /docs/concepts/components/v2/capabilities/runners.md
[test-suite-protocol]: /docs/concepts/components/v2/realms.md