blob: e7af76f5c46dae6a98a8c9dd26ee32dafefb1dd5 [file] [log] [blame] [view]
# Building and Testing with Bazel
This directory contains the core files to run studio-main tests using
bazel.
*** note
**Warning**: This does not currently work for AOSP
[Issue 126764883](https://issuetracker.google.com/126764883).
The required binaries are checked in as prebuilts, so you can run tests using
Intellij (tools/base and tools/idea projects), Ant (Studio only) and Gradle
(Build system and command line tools).
***
## Running bazel
Bazel has the concept of a _workspace_: the root of all your source files. For
us, it is where we `repo init` our source tree. For google3 vets, this is the
"google3" directory. In this document we assume the current directory to be the
workspace, but note that bazel can be run from anywhere in the tree.
Bazel is checked-in at `tools/base/bazel/bazel`. To make things easy you might
want to link it like this (assuming `~/bin` is in `$PATH`)
```shell
ln -s <workspace>/tools/base/bazel ~/bin/bazel
```
Then no matter where you are in the workspace, bazel will find the right
platform-specific binary and run it.
__macOS users:___ You may run into a clang error after reinstalling or updating XCode.
To resolve this error, clear bazel of previous configurations with the following command:
```
$ bazel clean --expunge
```
## Running all the tests
The command to run all the bazel tests run by the PSQ is:
```shell
bazel test $(<tools/base/bazel/targets)
```
The test output is typically present in `bazel-testlogs/pkg/target/test.xml` (or `test.log`)
To run all the tests found in `tools/base`:
```shell
bazel test //tools/base/...
```
To run all the tests in the IntelliJ Android plugin:
```
bazel test //tools/adt/idea/android/...
```
> Note: The file `tools/base/bazel/targets` contains the up-to-date list of test targets.
To build Studio without running the tests:
```
bazel build //tools/adt/idea/...
```
To run a single test:
```
# when test splitting is used, specify the $moduleName_tests__all target
bazel test //tools/adt/idea/android:intellij.android.core.tests_tests__all --test_filter=AndroidLayoutDomTest --test_output=streamed
```
To debug a single test, which will open remote debugging:
```
bazel test //tools/adt/idea/android:intellij.android.core.tests_tests__all --test_filter=AndroidLayoutDomTest --java_debug
```
## Useful Bazel options
* `--nocache_test_results` may be required if you are trying to re-run a test without changing
anything.
* `--test_filter=<TestName>` to run a specific test (when test splits are not already in use)
## Running with coverage
We currently do not use the in-built Bazel coverage support.
To enable a test in coverage runs do the following:
1. If you used `java_test`, then you need to replace it with `coverage_java_test` from //tools/base/bazel:coverage.bzl
2. Add the test target to the "all" coverage_report in tools/base/bazel/coverage/BUILD for inclusion in overall coverage
3. (Optional) Create your own coverage_report target in tools/base/bazel/coverage/BUILD for your team/feature
To build a coverage report do:
./tools/base/bazel/coverage/report.sh <name of coverage_report target> <directory to output HTML report>
## BUILD files
BUILD files define a package with a set build and test rules. In order to
support Android Studio we created a new kind of rule, that matches an IntelliJ
module: the `iml_module` rule.
> Note that we modify these BUILD files manually, so whenever you make a change
> to an `.iml` file, its corresponding `BUILD` file will have to be changed. This should be
> done using `bazel run //tools/base/bazel:iml_to_build`. If you create a new
> `.iml` file, you must create the corresponding (empty) `BUILD` file before
> running `iml_to_build`.
### iml_module
```
iml_module(name, srcs, test_srcs, exclude, resources, test_resources, deps, test_runtime_deps,
visibility, exports,javacopts, test_data, test_timeout, test_class, test_shard_count, tags)
```
This rule will generate the targets:
* _name_: The production library for this module.
* _name_\_testlib: The test library for this module.
* _name_\_tests: The test target to run this module's tests.
#### Example
```
iml_module(
name = "android",
srcs = ["src/main/java"],
resources = ["src/main/resources"],
test_data = glob(["testData/**"]),
test_resources = ["src/test/resources"],
test_srcs = ["src/test/java"],
deps = [
"//a/module/only/needed/in/tests:name[module, test]",
"//a/standard/java/dependency:dep",
"//path/to/libs:junit-4.12[test]",
"//path/to/module:name[module]",
],
)
```
Attribute | Description
---------------- | -----------
`name` | The name of the rule (usually matching Studio's module name).
`srcs` | A list of directories containing the sources. .java, .groovy, .kotlin and .form files are supported.
`resources` | A list directories with the production resources.
`deps` | A tag-enhanced list of dependencies, of the form `//label[tag1,tag2,...]`. Supported tags are: `module`, for iml_module dependencies, and `test` for test only dependencies.
`test_srcs` | A list of directories with the test sources.
`test_resources` | A list of directories with the test resources.
`test_data` | A list of files needed to run the test.
`exclude` | A list of files to be excluded from both src and test_srcs. This requires a change to tools/idea/.idea/compiler.xml
`test_timeout` | The timeout value of the test, see: [blaze timeout](https://docs.bazel.build/versions/master/test-encyclopedia.html#timeout)
> A major difference with actual iml modules is that in bazel we must specify
> the files needed to run the tests. These files are known as _runfiles_ and are
> specified via the `test_data` attribute. This is essential to determining
> which test targets need to be run when an arbitrary file has changed.
More details on the implementation of the `iml_module` rule can be found in
[docs/iml-module.md](docs/iml-module.md).
## Circular Dependencies
_Just don't_. IntelliJ has support for circular dependencies of modules, but we
do not use it in our code base.
## Fetching new Maven Dependencies
In order to fetch new Maven artifacts into the local Maven repository under
`//prebuilts/tools/common/m2/`, follow these steps:
1. Add the dependency to the `artifacts` or `data` section of the
`local_maven_repository` rule in the `tools/base/bazel/toplevel.WORKSPACE`
file.
* If the artifact is needed as a compile or runtime Java dependency in Bazel,
then add it to `artifacts`.
* If the artifact will only be used in tests as data (i.e., passed into
`maven_repository` rules), then add it to `data`.
2. Use the following script to download the artifacts:
```
tools/base/bazel/maven/maven_fetch.sh
```
3. In order to use the new artifact, use `@maven//:` prefix. If you added
your artifact to `artifacts`, then do not add the artifact version,
if you added your artifact to `data`, then use the artifact version.
E.g., `@maven//:com.google.guava.guava" (for artifacts)
`@maven//:com.google.guava.guava_30.1-jre` (for data).
* The `@maven//` prefix points to a dynamically generated Bazel-external
repository. You can access the generated file at
`$REPO/bazel-studio-main/external/maven/BUILD`.
4. Check-in your new artifact (and any new transitive dependencies)
under `//prebuilts/tools/common/m2/`.
See the `toplevel.WORKSPACE` file for examples on how to express non-jar dependency
types and classifiers (e.g., `linux-x86_64`).