| # 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 |