blob: ca642025daa9b1dd3bb6975082277d764fd04bb0 [file] [log] [blame] [view]
# Tests as components
Caution: This document describes manifests for [components v1][components-v1].
The old architecture (components v1) implemented by `appmgr` is still in use,
but will be removed once the transition to the new architecture is complete.
This document outlines the way for developers to configure their tests to run as
Fuchsia components. This document is for developers working inside the Fuchsia
source tree (`fuchsia.git`). The workflow described in this document is not
suitable for the Fuchsia SDK-based developers.
The exact GN invocations used to produce a test may vary between different
classes of tests and different languages. This document assumes that test logic
is being built somewhere and the test binary is to be built to run as a Fuchsia
component. For C++ and Rust, this would be the executable file that the build
produces. (For information on writing tests in Rust, see
[Testing Rust code][rust-testing].)
For an example setup of a test component, see
<code>[//examples/hello_world/rust][hello-world-rust]</code>.
## Fuchsia test environments
Tests on Fuchsia can run either as standalone executables (for example,
[host tests][run-fuchsia-test]) or as components. Standalone executables are
invoked within the environment the test runner is in, whereas components
executed in a test runner run in a hermetic environment. These hermetic
environments are fully separated from the host services. Test manifests
determine whether new instances of services should be started in this
environment, or services from the host should be plumbed in to the test
environment.
## Packaging a test as a component
To package a test as a component, you need to create the following:
* [Component manifest](#component-manifest-for-a-test).
* [Package build rules](#package-build-rules-for-a-test-component) for the
test executable and manifest.
Note: When writing simple unit tests that do not depend on any facets, features,
or services in Fuchsia, you can create a test package using the
<code>[fuchsia_unittest_package][fuchsia-unittest-package-gni]</code> template.
This template lets the build system automatically generate a component manifest
for these tests.
### Component manifest for a test {#component-manifest-for-a-test}
A component manifest informs the component framework how to run a component. In
this case, it explains how to run the test binary. A component manifest file
(`.cmx`) is typically located in a `meta` directory next to the `BUILD.gn` file:
```none
<your_test_directory>
├── BUILD.gn
├── meta
│ └── <component_manifest_file>
...
```
When a package is built, it includes the component manifest file under a top
level directory, which is also called `meta`.
The simplest possible component manifest for running a test may look like the
following:
```none
{
"program": {
"binary": "test/hello_world_rust_bin_test"
}
}
```
When you run the component above, it invokes the
`test/hello_world_rust_bin_test` binary in the package.
However, the example manifest above may be inadequate for many use cases because
the program running under this manifest has a very limited set of capabilities.
For instance, there is no mutable storage available for this program and it
cannot access any services in Fuchsia.
#### Sandbox
The `sandbox` portion of the manifest can be used to expand on this. As an
alternative to the prior example, the following example provides the component
access to storage at `/cache` and allows the component to talk to the service
located at `/svc/fuchsia.logger.LogSink`:
```none
{
"program": {
"binary": "test/hello_world_rust_bin_test"
},
"sandbox": {
"features": [ "isolated-cache-storage" ],
"services": [ "fuchsia.logger.LogSink" ]
}
}
```
Test components can also have new instances of services created inside their
test environment, thus isolating the impact of the test from the host. In the
following example, the service available at `/svc/fuchsia.example.Service` is be
handled by a brand new instance of the service referenced by the URL:
```none
{
"program": {
"binary": "test/hello_world_rust_bin_test"
},
"facets": {
"fuchsia.test": {
"injected-services": {
"fuchsia.example.Service": "fuchsia-pkg://fuchsia.com/example#meta/example_service.cmx"
}
}
},
"sandbox": {
"services": [
"fuchsia.example.Service"
]
}
}
```
For more information on component manifests, see
[Component manifests][component-manifest].
### Package build rules for a test component {#package-build-rules-for-a-test-component}
Once you have a component manifest, you can now add GN build rules in `BUILD.gn`
to create a package for the test component.
The following example produces a new package named `hello-world-rust-tests` that
contains the artifacts necessary to run a test component:
Note: The legacy GN templates for packages (`package.gni` and `test_package.gni`)
are being deprecated. See
[New GN templates for components v1](#new-gn-templates-for-components-v1)
for details.
```none
import("//src/sys/build/fuchsia_unittest_package.gni")
fuchsia_unittest_component("hello-world-rust-test-component") {
executable_path = "test/hello_world_rust_bin_test"
component_name = "hello-world-rust-test"
deps = [ ":bin" ]
}
fuchsia_test_package("hello-world-rust-tests") {
test_components = [
":hello-world-rust-test-component",
]
}
```
The example above requires that the `:bin` target produces a test binary named
`hello_world_rust_bin_test`. The
<code>[fuchsia_unittest_package][fuchsia-unittest-package-gni]</code>
template requires that `meta/${TEST_NAME}.cmx` exists and that the destination
of the test binary matches the target name. In the example, this means that
`meta/hello_world_rust_bin_test.cmx` must exist.
This template produces a package in the same way that the
<code>[fuchsia_package][fuchsia-package-gni]</code> template does, but it
has extra checks in place to ensure that the test is set up properly. For
more information, see [Test packages][test-packages].
## New GN templates for components v1 {#new-gn-templates-for-components-v1}
The legacy GN templates for packages
(<code>[test_package.gni][test-package-gni]</code> and
<code>[package.gni][package-gni]</code>) are being deprecated in favor
of the following new templates:
* <code>[fuchsia_package.gni][fuchsia-package-gni]</code>
* <code>[fuchsia_test_package.gni][fuchsia-test-package-gni]</code>
* <code>[fuchsia_unittest_package.gni][fuchsia-unittest-package-gni]</code>
For instance, the examples below demonstrate how you can rewrite
the `test_package` template's build rules using the
`fuchsia_unittest_package` template:
* {`test_package`}
```none
import("//build/test/test_package.gni")
test_package("hello-world-rust-tests") {
deps = [
":bin",
]
tests = [
{
name = "hello_world_rust_bin_test"
}
]
}
```
* {`fuchisa_unittest_package`}
```none
import("//src/sys/build/fuchsia_unittest_package.gni")
fuchsia_unittest_component("hello-world-rust-test-component") {
executable_path = "test/hello_world_rust_bin_test"
component_name = "hello-world-rust-test"
deps = [ ":bin" ]
}
fuchsia_test_package("hello-world-rust-tests") {
test_components = [
":hello-world-rust-test-component",
]
}
```
For more examples on these templates, see [Test component][test-component].
<!-- Reference links -->
[components-v1]: /docs/glossary.md#components-v1
[hello-world-rust]: /examples/hello_world/rust
[run-fuchsia-test]: /docs/development/testing/run_fuchsia_tests.md
[component-manifest]: /docs/concepts/components/v1/component_manifests.md
[rust-testing]: /docs/development/languages/rust/testing.md
[test-package-gni]: /build/test/test_package.gni
[package-gni]: /build/package.gni
[test-packages]: /docs/development/components/build.md#test-packages
[fuchsia-package-gni]: /src/sys/build/fuchsia_package.gni
[fuchsia-test-package-gni]: /src/sys/build/fuchsia_test_package.gni
[fuchsia-unittest-package-gni]: /src/sys/build/fuchsia_unittest_package.gni
[test-component]: /docs/concepts/testing/test_component.md