blob: 5b533781c6c8eddeb19681b39d030cd66d832e1b [file] [log] [blame] [view]
# Running tests as components
Tests on Fuchsia can either be run as standalone executables or as components.
Standalone executables are invoked in whatever environment the test runner
happens to be in, whereas components executed in a test runner are run in a
hermetic environment.
These hermetic environments are fully separated from the host services, and the
test manifests can stipulate that new instances of services should be started in
this environment, or services from the host should be plumbed in to the test
environment.
This document aims to outline the idiomatic way for a developer to configure
their test artifacts to be run as components. This document is targeted towards
developers working inside of `fuchsia.git`, and the workflow described is
unlikely to work for SDK consumers.
An example setup of a test component is available at
`//examples/hello_world/rust`.
## Building the test
The exact GN invocations that should be used to produce a test vary between
different classes of tests and different languages. The rest of this document
assumes that test logic is being built somewhere, and that the test output is
something that can be run as a component. For C++ and Rust, this would be the
executable file the build produces.
Further documentation for building tests is [available for Rust][rust_testing].
## Packaging and component-ifying the tests
Once the build rule for building a test executable exists, a component manifest
referencing the executable and a package build rule containing the executable
and manifest must be created.
### Component manifests
The component manifest exists to inform the component framework how to run
something. In this case, it's explaining how to run the test binary. This file
typically lives in a `meta` directory next to the `BUILD.gn` file, and will be
included in the package under a top level directory also called `meta`.
The simplest possible component manifest for running a test would look like
this:
```cmx
{
"program": {
"binary": "test/hello_world_rust_bin_test"
}
}
```
This component, when run, would invoke the `test/hello_world_rust_bin_test`
binary in the package.
This example manifest may be insufficient for many use cases as the program will
have a rather limited set of capabilities, for example there will be no mutable
storage available and no services it can access. The `sandbox` portion of the
manifest can be used to expand on this. As an alternative to the prior example,
this example will give the component access to storage at `/cache` and will
allow it to talk to the service located at `/svc/fuchsia.logger.LogSink`.
```cmx
{
"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` will
be handled by a brand new instance of the service referenced by the URL.
```cmx
{
"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 a more thorough description of what is valid in a component manifest, please
see the [documentation on component manifests][component_manifest].
### Component and package build rules
With a component manifest written the GN build rule can now be added to create a
package that holds the test component.
```GN
import("//build/test/test_package.gni")
test_package("hello_world_rust_tests") {
deps = [
":bin",
]
tests = [
{
name = "hello_world_rust_bin_test"
}
]
}
```
This example will produce a new package named `hello_world_rust_tests` that
contains the artifacts necessary to run a test component. This example requires
that the `:bin` target produce a test binary named `hello_world_rust_bin_test`.
The `test_package` template requires that `meta/${TEST_NAME}.cmx` exist and that
the destination of the test binary match the target name. In this example, this
means that `meta/hello_world_rust_bin_test.cmx` must exist. This template
produces a package in the same way that the `package` template does, but it has
extra checks in place to ensure that the test is set up properly. For more
information, please see the [documentation on `test_package`][test_package].
## Running tests
Note: If you encounter any bugs or use cases not supported by `fx test`, file a
bug with `fx`.
To test the package, use the `fx test` command with the name of the package:
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>TEST_NAME</var></code>
</pre>
If the package you specified is a test component, the command makes your Fuchsia
device load and run said component. However, if the package you specified is a
host test, the command directly invokes that test binary. Note that this can lead
to the execution of multiple components.
### Customize `fx test` invocations
In most cases, you should run the entire subset of test that verify the code
that you are editing. You can run `fx test` with arguments to run specific tests
or test suites, and flags to filter down to just host or device tests. To
customize `fx test`:
<pre class="prettyprint">
<code class="devsite-terminal">fx test [<var>FLAGS</var>] [<var>TEST_NAME</var> [<var>TEST_NAME</var> [...]]]</code>
</pre>
### Multiple ways to specify a test
`fx test` supports multiple ways to reference a specific test.
- Full or partial paths:
Provide a partial path to match against all test binaries in children
directories.
<pre class="prettyprint">
<code class="devsite-terminal">fx test //host_x64/gen/sdk</code>
</pre>
Provide a full path to match against that exact binary.
<pre class="prettyprint">
<code class="devsite-terminal">fx test //host_x64/pm_cmd_pm_genkey_test</code>
</pre>
Note: `//` stands for the root of a Fuchsia tree checkout.
- Full or partial [Fuchsia Package URLs][fuchsia_package_url]:
Provide a partial URL to match against all test components whose Package
URLs start with the supplied value.
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>fuchsia-pkg://fuchsia.com/my_test_pkg</var></code>
</pre>
Provide a full URL to match against that exact test component.
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>fuchsia-pkg://fuchsia.com/my_test_pkg#meta/my_test.cmx</var></code>
</pre>
- Package name:
Provide a
[package name](/docs/concepts/packages/package_url.md#package-name) to
run all test components in that package:
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>my_test_pkg</var></code>
</pre>
- Component name:
Provide a
[resource-path](/docs/concepts/packages/package_url.md#resource-paths) to
test a single component in a package:
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>my_test</var></code>
</pre>
### Running multiple tests
If you want to run multiple sets of Fuchsia tests, configure your Fuchsia build
to include several of the primary testing bundles, build Fuchsia, and then run
all tests in the build:
```bash
fx set core.x64 --with //bundles:tools,//bundles:tests,//garnet/packages/tests:all
fx build
fx test
```
You can also provide multiple targets in a single invocation:
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>package_1 package_2 component_1 component_2</var></code>
</pre>
### Converting from `run-test` or `run-host-tests`
Note: Please file a bug with `fx` if you find any test invocations that cannot
be converted.
#### `run-test`
For `run-test`, you should always be able to change `fx run-test` to `fx test`,
for example:
<pre class="prettyprint">
<code class="devsite-terminal">fx run-test <var>TEST_PACKAGE_NAME</var></code>
</pre>
Now becomes:
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>TEST_PACKAGE_NAME</var></code>
</pre>
#### `run-host-tests`
For `run-host-tests`, you should always be able to change `fx run-host-tests` to
`fx test`, for example:
<pre class="prettyprint">
<code class="devsite-terminal">fx run-host-tests <var>PATH_TO_HOST_TEST</var></code>
</pre>
Now becomes:
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>PATH_TO_HOST_TEST</var></code>
</pre>
#### the `-t` flag
Unlike `fx run-test` (which operated on *packages*), `fx test` matches against tests
in many different ways. This means that you can easily target tests either by their
package name or directly by a component's name. One common workflow with `run-test`
was to use the `-t` flag to specify a single component:
<pre class="prettyprint">
<code class="devsite-terminal">fx run-test <var>PACKAGE_NAME</var> -t <var>NESTED_COMPONENT_NAME</var></code>
</pre>
Now, with `fx test`, that simply becomes:
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>NESTED_COMPONENT_NAME</var></code>
</pre>
#### Passing arguments to individual tests
Note: `fx test` passes extra arguments to all selected tests. If you are
targeting many test components in a single pass, this option may not be ideal.
Use the `--` flag to provide additional arguments which are ignored by `fx test`
and passed to test components.
For example, to pass a timeout flag to a test that accepts it, execute:
<pre class="prettyprint">
<code class="devsite-terminal">fx test <var>TEST_NAME</var> -- --timeout=5</code>
</pre>
Internally, this command runs the following:
<pre class="prettyprint">
<code class="devsite-terminal">fx shell run-test-component <var>TEST_NAME</var> --timeout=5</code>
</pre>
#### Implementation
When `fx test` runs your test component, `fx test` calls `run-test-component`
on the target device with the test url to run the test.
## Running tests (Legacy)
Tests can be exercised with the `fx run-test` command by providing the name of
the package containing the tests.
<pre class="prettyprint">
<code class="devsite-terminal">fx run-test <var>TEST_PACKAGE_NAME</var></code>
</pre>
This command will rebuild any modified files, push the named package to the
device, and run it.
Tests can also be run directly from the shell on a Fuchsia device with the
`run-test-component` command, which can take either a fuchsia-pkg URL or a
prefix to search pkgfs for.
If using a fuchsia-pkg URL the test will be automatically updated on the device,
but not rebuilt like if `fx run-test` was used. The test will be neither rebuilt
nor updated if a prefix is provided.
In light of the above facts, the recommended way to run tests from a Fuchsia
shell is:
<pre class="prettyprint">
<code class="devsite-terminal">fx shell run-test-component `locate <var>TEST_PACKAGE_NAME</var>`</code>
</pre>
The `locate` tool will search for and return fuchsia-pkg URLs based on a given
search query. If there are multiple matches for the query the above command will
fail, so `locate` should be invoked directly to discover the URL that should be
provided to `run-test-component`.
`run-test-component` will create transient isolated storage for the test. See
[isolated-storage][isolated-storage] for more info.
[component_manifest]: /docs/concepts/storage/component_manifest.md
[rust_testing]: ../languages/rust/testing.md
[test_package]: /docs/concepts/testing/test_component.md
[isolated-storage]: /docs/concepts/testing/test_component.md#isolated_storage
[fuchsia_package_url]: /docs/concepts/packages/package_url.md