| # Testing Rust code |
| |
| This document describes best practices for writing tests for Rust code. |
| Please also refer to the [components testing guide][component-tests] for |
| instructions on defining test packages and components and running them. |
| |
| This document is targeted towards developers working inside of `fuchsia.git`, |
| and the workflow described is unlikely to work for IDK consumers. |
| |
| The source code for this tutorial is available at |
| [`//examples/hello_world/rust`][example-src]. |
| |
| ## Unit tests |
| |
| ### Adding tests to code |
| |
| The idiomatic way for adding Rust unit tests works just as well inside of |
| Fuchsia as it does outside, and can be easily accomplished by dropping the |
| following snippet into the bottom of whatever test you want to write: |
| |
| ```rust |
| {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/hello_world/rust/src/main.rs" region_tag="test_mod" adjust_indentation="auto" %} |
| ``` |
| |
| This will cause a new mod named `tests` to be created, and this mod will only be |
| included when building unit tests. Any functions annotated with |
| `#[fuchsia::test]` will be run as a test, and if the function successfully |
| returns then the test passes. |
| |
| `#[fuchsia::test]` also supports tests exercising asynchronous code. |
| |
| ```rust |
| {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/hello_world/rust/src/main.rs" region_tag="async_test" adjust_indentation="auto" %} |
| ``` |
| |
| The typical `#[test]` annotation also works, but it doesn't support async tests |
| or logging out of the box. Prefer `#[test]` in situations where you think the |
| crate might get used outside of the Fuchsia codebase. |
| |
| ### Building tests |
| |
| The unit tests can be automatically built by Rust targets (i.e. either |
| `rustc_binary` or `rustc_library`). The approaches are by and large similar. |
| |
| #### Building tests for a Rust binary |
| |
| This section is useful if you are testing a rust *binary* (i.e. you have a |
| `main.rs`). If you have a library instead, see the next section. |
| |
| Your `BUILD.gn` file first needs to make available the `rustc_binary` template |
| by importing it: |
| |
| ```gn |
| import("//build/rust/rustc_binary.gni") |
| ``` |
| |
| Unit tests are built by the `rustc_binary` GN template only if the setting |
| `with_unit_tests = true` is added: |
| |
| ```gn |
| {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/hello_world/rust/BUILD.gn" region_tag="rustc_tests" adjust_indentation="auto" %} |
| ``` |
| |
| Setting `with_unit_tests = true` causes this build rule to generate two |
| different executables, one with the provided and one with `_bin_test` appended |
| to the provided name. |
| |
| In our example here, the executable names that are created are called: |
| |
| * `hello_world_rust`; and |
| * `hello_world_rust_bin_test`. |
| |
| #### Building tests for a Rust library |
| |
| Your `BUILD.gn` file first needs to make available the `rustc_library` template |
| by importing it: |
| |
| ```gn |
| import("//build/rust/rustc_library.gni") |
| ``` |
| |
| Unit tests are built by the `rustc_library` GN template only if the setting |
| `with_unit_tests = true` is added, similarly to how it is done in the case |
| of `rustc_binary` above. |
| |
| In this case, however, a **differently named** test binary is created: |
| |
| * `hello_world_rust_lib_test`. Note that the name of the binary is different |
| from the name generated by the library. |
| |
| The binary names are important because they will be used in followup steps. |
| |
| ### Packaging and running tests |
| |
| To run the tests that were generated by previous targets, package them as |
| **test components**. Test components contain a |
| [component manifest][glossary.component-manifest] that declares the capabilities |
| required by your tests. You can package tests using the following build rules: |
| |
| * `fuchsia_test_package()`: Package template that collects multiple test |
| components and their dependencies together in a single package. |
| Test packages are typically used for integration tests. |
| * `fuchsia_unittest_package()`: Specialized template for packages containing |
| unit tests. Unit test packages can generate a minimal component manifest for |
| unit tests with no required capabilities. |
| |
| For the Hello World binary example, the unit test package references the |
| generated targets, `bin_test` (based on target name `bin` and the implicit |
| suffix `_test`), and `hello_world_rust_bin_test` (based on the value of `name` |
| stanza). |
| |
| ```gn |
| {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/hello_world/rust/BUILD.gn" region_tag="fuchsia_test" adjust_indentation="auto" %} |
| ``` |
| |
| To run the tests run: |
| |
| ```posix-terminal |
| fx test hello-world-rust-tests |
| ``` |
| |
| For information on packaging and running tests, see |
| [test components][component-tests] and [building components][build-tests]. |
| |
| ### Helpful crates |
| |
| The following in-tree third-party crates can help you write tests: |
| |
| * [`assert_matches`]: provides the macro `assert_matches!`, making pattern |
| assertions ergonomic. |
| * [`pretty_assertions`]: provides an alternative `assert_eq!` macro that |
| displays a colored diff when the assertion fails. |
| |
| These can be included in your `BUILD.gn` under `test_deps`. |
| |
| ```gn |
| rustc_binary("bin") { |
| name = "my_test" |
| with_unit_tests = true |
| edition = "2021" |
| |
| test_deps = [ |
| "//third_party/rust_crates:matches", |
| "//third_party/rust_crates:pretty_assertions", |
| ] |
| } |
| ``` |
| |
| [build-tests]:/docs/development/components/build.md#test-packages |
| [component-tests]:/docs/development/testing/components/test_component.md |
| [example-src]: /examples/hello_world/rust |
| [glossary.component-manifest]: /docs/glossary/README.md#component-manifest |
| [`assert_matches`]: https://fuchsia-docs.firebaseapp.com/rust/assert_matches/index.html |
| [`pretty_assertions`]: https://fuchsia-docs.firebaseapp.com/rust/pretty_assertions/index.html |