blob: 2b264f478a098861dafd788be190673bd2be89d1 [file] [log] [blame] [view] [edit]
# Migrate test components
To migrate your test components, follow these steps:
1. [Migrate the test manifest](#create-test-manifest)
1. [Update test dependencies](#update-dependencies)
1. [Migrate component features](#features)
1. [Verify the migrated tests](#verify-tests)
## Migrate the test manifest {#create-test-manifest}
Find the GN build rules for the tests that exercise your component.
Typically this is a [`fuchsia_test_package()`](#test-package) or
[`fuchsia_unittest_package()`](#unittest-package).
### Unit test packages {#unittest-package}
The preferred practice for tests declared with a `fuchsia_unittest_package()`
build rule is to use the [generated manifest][unit-test-manifests] provided by
the Fuchsia build system.
To allow the GN target to generate your manifest, remove the `manifest`
attribute from the `fuchsia_unittest_package()`:
```gn
fuchsia_unittest_package("my_component_tests") {
{{ '<strike>' }}manifest = "meta/my_component_test.cmx"{{ '</strike>' }}
deps = [ ":my_component_test" ]
}
```
Your test package is now able to execute using Components v2 and the
Test Runner Framework.
### Test packages {#test-package}
Consider the following example test component manifest:
```json
// my_component_test.cmx
{
"include": [
"syslog/client.shard.cmx"
],
"program": {
"binary": "bin/my_component_test"
}
}
```
To migrate this test to the Test Runner Framework, do the following:
1. Create a CML file that points to the test binary that includes the
appropriate [test runner][trf-test-runners]:
Note: See the [available test runners][trf-provided-test-runners] provided
by the framework.
```json5
// my_component_test.cml
{
include: [
// Select the appropriate test runner shard here:
// rust, gtest, go, etc.
"//src/sys/test_runners/rust/default.shard.cml",
// Enable system logging
"syslog/client.shard.cml",
],
program: {
binary: "bin/my_component_test",
}
}
```
1. Locate the GN build rule for your test component referenced by the
`fuchsia_test_package()`:
```gn
fuchsia_component("my_component_test") {
testonly = true
manifest = "meta/my_component_test.cmx"
deps = [ ":bin_test" ]
}
fuchsia_test_package("my_component_tests") {
deps = [ ":my_component_test" ]
}
```
1. Update your test component's build rule to reference the new CML file:
```gn
fuchsia_component("my_component_test") {
testonly = true
{{ '<strong>' }}manifest = "meta/my_component_test.cml"{{ '</strong>' }}
deps = [ ":bin_test" ]
}
fuchsia_test_package("my_component_tests") {
deps = [ ":my_component_test" ]
}
```
## Update test dependencies {#update-dependencies}
A test may include or depend on components that are separate from the test
component. Here are some things to look for:
- Does your test have a CMX with [`fuchsia.test facets`][fuchsia-test-facets],
such as `injected-services` or `system-services`?
- Does your test create environments in-process? If so, does it create a
separate environment for each test case?
Note: The Test Runner Framework executes tests within a realm that enforces
hermetic component resolution, which means that test components must resolve
dependencies from within their own package.
For more details, see [hermetic component resolution][hermetic-resolution].
The migration procedure varies depending on the testing framework features in
your v1 component:
- [Test depends on system services](#system-services): The test has a CMX that
contains [`system-services`][system-services] test facets.
- [Test depend on injected services](#injected-services): The test has a CMX that
contains [`injected-services`][fuchsia-test-facets] test facets.
Note: For more details on the services and capabilities provided to components
by the Test Runner Framework, see the
[test manager documentation][trf-test-manager].
### System service dependencies {#system-services}
For tests that use [`system-services`][system-services] test facets, consider if
they can be converted to [injected services](#injected-services) instead.
Injecting services is the preferred method because it promotes hermetic test
behavior.
For certain non-hermetic tests, the Test Runner Framework provides the test
realm with the following services:
| Service | Description |
| ----------------------------------- | ------------------------------------- |
| `fuchsia.scheduler.ProfileProvider` | Profile provider for scheduler |
| `fuchsia.sysmem.Allocator` | Allocates system memory buffers |
| `fuchsia.tracing.provider.Registry` | Register to trace provider |
| `fuchsia.vulkan.loader.Loader` | Vulkan library provider |
| `fuchsia.sys.Loader` | CFv1 loader service to help with |
: : migration. :
| `fuchsia.sys.Environment` | CFv1 environment service to help with |
: : migration. :
Consider the following example test component that uses a single system service,
`fuchsia.sysmem.Allocator`:
```json
// my_component_test.cmx
{
"facets": {
"fuchsia.test": {
"system-services": [
"fuchsia.sysmem.Allocator"
]
}
},
"program": {
"binary": "bin/my_component_test"
},
"sandbox": {
"services": [
"fuchsia.sysmem.Allocator"
]
}
}
```
To migrate this test to the Test Runner Framework, declare each available system
service with the other [required services](#required-services) in your test
component manifest. Since this test uses the `fuchsia.sysmem.Allocator`
system capability, it also needs to be marked as `hermetic: "false"` as shown
below.
```json5
// my_component_test.cml
{
include: [
// Select the appropriate test runner shard here:
// rust, gtest, go, etc.
"//src/sys/test_runners/rust/default.shard.cml",
],
program: {
binary: "bin/my_component_test",
},
{{ '<strong>' }}facets: {
"fuchsia.test": {
type: "system"
},
},
use: [
{
protocol: [ "fuchsia.sysmem.Allocator" ],
},
],{{ '</strong>' }}
}
```
### Injected service dependencies {#injected-services}
For tests that use other [fuchsia.test facets][fuchsia-test-facets], such as
`injected-services`, your test component manifest must declare each dependent
component and route the provided capabilities to the test component.
In the following example, suppose there's a single injected service,
`fuchsia.pkg.FontResolver`:
```json
// my_component_test.cmx
{
"facets": {
"fuchsia.test": {
"injected-services": {
"fuchsia.pkg.FontResolver":
"fuchsia-pkg://fuchsia.com/font_provider_test#meta/mock_font_resolver.cmx"
}
}
},
"program": {
"binary": "bin/my_component_test"
},
"sandbox": {
"services": [
"fuchsia.pkg.FontResolver"
]
}
}
```
To migrate this test to the Test Runner Framework, do the following:
1. Create a CML file for the test component that points to the test binary and
includes the appropriate [test runner][trf-test-runners]:
Note: See [test runners][trf-provided-test-runners] that are provided by the
framework.
```json5
// my_component_test.cml (test component)
{
include: [
// Select the appropriate test runner shard here:
// rust, gtest, go, etc.
"//src/sys/test_runners/rust/default.shard.cml",
],
program: {
// Binary containing tests
binary: "bin/font_provider_test",
},
use: [
...
],
}
```
1. You need CML files for each component that provides a capability needed in
the test. If there is an existing CML file for the component providing the
injected service, you may be able to reuse it. Otherwise **if the mock
component is being ported to v2**, create a new CML file. If the **mock
component has not been ported to v2 yet**, wrap the component using
`cmx_runner`.
* {CML component}
```json5
// mock_font_resolver.cml (capability provider)
{
program: {
runner: "elf",
binary: "bin/mock_font_resolver",
},
use: [
// mock_font_resolver's dependencies.
{
protocol: [ "fuchsia.proto.SomeProtocol" ],
},
],
capabilities: [
{
protocol: [ "fuchsia.pkg.FontResolver" ],
},
],
expose: [
{
protocol: "fuchsia.pkg.FontResolver",
from: "self",
},
],
}
```
* {Wrapped CMX component}
```json5
// mock_font_resolver.cml (capability provider)
{
include: [
// Use `cmx_runner` to wrap the component.
"//src/sys/test_manager/cmx_runner/default.shard.cml",
"syslog/client.shard.cml",
],
program: {
// wrap v1 component
legacy_url: "fuchsia-pkg://fuchsia.com/font_provider_test#meta/mock_font_resolver.cmx",
},
use: [
// if `mock_font_resolver.cmx` depends on some other protocol.
{
protocol: [ "fuchsia.proto.SomeProtocol" ],
},
// Note: Wrapped legacy component can only use protocol capabilities.
],
// expose capability provided by mock component.
capabilities: [
{
protocol: [ "fuchsia.pkg.FontResolver" ],
},
],
expose: [
{
protocol: "fuchsia.pkg.FontResolver",
from: "self",
},
],
}
```
Note: The CML files for the capability providers can be distributed in the
same package that contained the v1 test. Follow the same instructions in
[Migrate the component manifest][migrate-component-manifest] that you used
to package your component.
1. Add the capability provider(s) as children of the test component, and route
the capabilities from each provider.
```json5
// my_component_test.cml (test component)
{
...
// Add capability providers
children: [
{
name: "font_resolver",
url: "#meta/mock_font_resolver.cm",
},
],
// Route capabilities to the test
use: [
{
protocol: [ "fuchsia.pkg.FontResolver" ],
from: "#font_resolver",
},
],
offer: [
{
// offer dependencies to mock font provider.
protocol: [ "fuchsia.proto.SomeProtocol" ],
from: "#some_other_child",
},
],
}
```
1. Package the test component and capability provider(s) together into a
single hermetic `fuchsia_test_package()`:
* {CML component}
```gn
# Test component
fuchsia_component("my_component_test") {
testonly = true
manifest = "meta/my_component_test.cml"
deps = [ ":bin_test" ]
}
fuchsia_component("mock_font_resolver") {
testonly = true
manifest = "meta/mock_font_resolver.cml"
deps = [ ":mock_font_resolver_bin" ]
}
# Hermetic test package
fuchsia_test_package("my_component_tests") {
test_components = [ ":my_component_test" ]
deps = [ ":mock_font_resolver" ]
}
```
* {Wrapped CMX component}
```gn
# Test component
fuchsia_component("my_component_test") {
testonly = true
manifest = "meta/my_component_test.cml"
deps = [ ":bin_test" ]
}
fuchsia_component("mock_font_resolver") {
testonly = true
manifest = "meta/mock_font_resolver.cml"
deps = [ {{ '<var label="legacy_component">"//path/to/legacy(v1)_component"</var>' }} ]
}
# Hermetic test package
fuchsia_test_package("my_component_tests") {
test_components = [ ":my_component_test" ]
deps = [ ":mock_font_resolver" ]
}
```
For more details on providing external capabilities to tests, see
[Integration testing topologies][integration-test].
## Migrate component features {#features}
Explore the following sections for additional migration guidance on
specific features your test components may support:
- [Component sandbox features](features.md)
- [Diagnostics capabilities](diagnostics.md)
- [Other common situations](common.md)
## Verify the migrated tests {#verify-tests}
Build and run your test and verify that it passes:
```posix-terminal
fx build && fx test my_component_tests
```
If your test doesn't run correctly or doesn't start at all, try following the
advice in [Troubleshooting components][troubleshooting-components].
[example-package-rule]: https://fuchsia.googlesource.com/fuchsia/+/cd29e692c5bfdb0979161e52572f847069e10e2f/src/fonts/BUILD.gn
[fuchsia-test-facets]: /docs/concepts/testing/v1_test_component.md
[hermetic-resolution]: /docs/development/testing/components/test_runner_framework.md#hermetic_component_resolution
[integration-test]: /docs/development/testing/components/integration_testing.md
[migrate-component-manifest]: /docs/development/components/v2/migration/components.md#create-component-manifest
[system-services]: /docs/concepts/testing/v1_test_component.md#services
[trf-provided-test-runners]: /src/sys/test_runners
[trf-test-manager]: /docs/development/testing/components/test_runner_framework.md#the_test_manager
[trf-test-runners]: /docs/development/testing/components/test_runner_framework.md#test-runners
[troubleshooting-components]: /docs/development/components/troubleshooting.md
[unit-test-manifests]: /docs/development/components/build.md#unit-tests