blob: 0478320acfd03ba9ab849260d664bcfd42b0a3b6 [file] [log] [blame] [view]
Mike Baxley47db7d82017-11-16 15:57:171# Automated testing for Chrome for iOS
2
3See the [instructions] for how to check out and build Chromium for iOS.
4
5Automated testing is a crucial part of ensuring the quality of Chromium.
6
7## Unit testing
8
Raphael Kubo da Costa310c40c2025-01-21 15:25:569Unit testing is done via gtests. The easiest way to run a unit test is to use
10the wrapper scripts generated at build time:
11
12```sh
13/bin/run_ [options]
14```
15
16The wrapper scripts take care of invoking `//ios/build/bots/scripts/run.py`
17with options like `--iossim` set appropriately. In general, you need to pass
18at least `--out-dir` (a directory where test results will be stored),
19`--platform` (a device available to the simulator), `--xcode-build` (obtained
20via e.g. About XCode) and `--version` (iOS version to run). The
21`--gtest_filter` option is also supported.
22
23A more complete example looks like this:
24
25```sh
26out/Debug-iphonesimulator/run_base_unittests \
27 --gtest_filter=Base64Test.Basic \
28 --platform "iPhone 16" \
29 --version 18.2 \
30 --xcode-build 16c5032a
31```
Mike Baxley47db7d82017-11-16 15:57:1732
33## Integration testing
34
Zhaoyang Li270020462020-10-27 23:07:2935[EarlGrey] (EG2) is the integration testing framework used by Chromium for iOS.
36
37### Writing EarlGrey tests
38
39#### Before you start
40
41* Just write a unit test if the purpose of your test does not involve UI.
42* Learn about EarlGrey test framework principles and APIs in [EarlGrey].
43* Learn about [Defining Test Cases and Test Methods] from Apple.
44
45#### Creating test files and writing EG2 tests
46
471. EG2 test files are ended with _egtest.mm, and usually located within the same
48directory of the UI code you wish to test.
492. Basic imports of a EG2 test file:
50
51 * Youll have to include:
52 ```
Ernesto Izquierdo Cluaab3923fd2022-03-01 20:42:1553 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
Zhaoyang Li270020462020-10-27 23:07:2954 ```
55 * Youll most likely find util functions in these files helpful.
56 ```
57 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
58 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
59 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
60 ```
61 * Beside these, directly import an EG2 header for an EG2 API you are using.
62
633. TestCase/testMethods definitions. Create `SomeGreatTestCase` as a subclass of
64`ChromeTestCase`. Create test methods, eg `-(void)testMyGreatUIFeature {...}`,
65and put UI actions within the test methods.
66 * Put your setup and tear down code for the *TestCase* in
67`+(void)setUpForTestCase` and `+tearDown`. These will run once before and
68after all tests for the test class.
69 * Put your setup and tear down code for each *test method* in `-(void)setUp`
70and `-(void)tearDown`. These will run before and after every
71`-(void)testMethod` in the file.
724. Writing test contents. See the chrome helpers (imports in 2.) as well as
73[EarlGrey APIs] to write a UI action/assertion in your testMethod.
74
75#### Interacting with the app in a test
76
77##### Relaunch app with different flags
78
79In EG2 tests, the test process launches the host app process at the beginning,
80then runs UI actions/assertions in the app. To pass args or feature flags to the
81app at initial launching, or relaunch the app in the middle of your test, see
82[this AppLaunchManager API].
83
84##### Accessing app internals
85
86EG2 test targets are built with test-related code but without app code.
87
88To access anything from the app side, use an "app interface". App interface is
89implemented as a class that lives in the app process, but can be accessed in the
90test process through [eDO]. You can include the header in your test side code
91and call class methods of the interface class. The methods will execute code in
92the app process and can return basic Objective-C types. See this [Example of App
93 Interface].
94
95See `eg_test_support+eg2` (test side utilities) and `eg_app_support+eg2` (app
96side utilities) targets in `BUILD.gn` files to learn how test utilities are
97organized in targets. If you added an app side helper (app interface), youll
98also need to include your new `eg_app_support+eg2` target in
99`//ios/chrome/test/earl_grey/BUILD.gn`s `eg_app_support+eg2` target. ([Example
100 CL adding App Interface]).
101
102Note that if you create an App interface, you cant build the app interface
Sylvain Defresnea852434c2021-10-15 07:53:39103class in your eg2_tests target, but you need to include and refer to it. To
104satisfy the linker, you'll need to create a `my_test_app_interface_stub.mm`
105file with the following content in it and build it as a dependency of your
106tests that use the app interface.
107
108```objc
109#import "ios_internal/chrome/test/earl_grey2/my_test_app_interface.h"
110
Cameron Higgins0e350192023-03-21 17:43:45111#import "ios/testing/earl_grey/earl_grey_test.h"
Sylvain Defresnea852434c2021-10-15 07:53:39112
Sylvain Defresnea852434c2021-10-15 07:53:39113GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(MyTestAppInterface)
114
Zhaoyang Li270020462020-10-27 23:07:29115```
Sylvain Defresnea852434c2021-10-15 07:53:39116
117If you don't you'll get linker errors that read like “Undefined symbols for
118architecture… MyTestAppInterface”
Zhaoyang Li270020462020-10-27 23:07:29119
120#### Creating test targets and adding the target to test suites
121
1221. Create a test target. Add a target(`source_set`) named "eg2_tests" into the
123closest `BUILD.gn` file. Put the test file into the `sources` array and put the
124targets containing headers used in your test file into `deps` array. This is to
125organize test source files and dependencies so that the GN build system can
126correctly build the test module. The skeleton of the target:
127```
128source_set("eg2_tests") {
129 configs += [
Zhaoyang Li270020462020-10-27 23:07:29130 "//build/config/ios:xctest_config",
131 ]
132 testonly = true
133 sources = [
134 "some_egtest.mm"
135 ]
136 deps = [
137 "//ios/chrome/test/earl_grey:eg_test_support+eg2",
138 "//ios/testing/earl_grey:eg_test_support+eg2",
Zhaoyang Li270020462020-10-27 23:07:29139 ]
Arthur Milchior54e9dc22022-09-21 13:41:52140 frameworks = [ "UIKit.framework" ]
Zhaoyang Li270020462020-10-27 23:07:29141}
142```
1432. Include your test target in the `deps` array of a suitable suite in
144`//src/ios/chrome/test/earl_grey2/BUILD.gn`.
1453. Optional: If you feel like your new test should be in a new suite, or you
146want to delete an existing suite to make tests better organized, you’ll need to
147change the suites in `//src/ios/chrome/test/earl_grey2/BUILD.gn` in the format
148of existing ones. (Do not forget to [config the bots] so the new suite can run
149in infra.)
1504. Ensure your dependencies are correct.
151```
152$ gn gen --check out/Debug-iphonesimulator
153```
Mike Baxley47db7d82017-11-16 15:57:17154
155### Running EarlGrey tests
156
157EarlGrey tests are based on Apple's [XCUITest].
158
159#### Running tests from Xcode
160
Zhaoyang Li270020462020-10-27 23:07:291611. If you added a new test file / suite, run `gclient runhooks` to sync for the
162list of tests in Xcode.
Victor Hugo Vianna Silva703246b2023-07-05 14:06:461632. Run a test suite(module), TestCase or testMethod in test navigator.
Zhaoyang Li270020462020-10-27 23:07:29164Xcode will build the targets and run the test(s) you choose. Alternatively,
165use ⌘+U to run all the tests. See Apple's [Running Tests and Viewing Results].
Victor Hugo Vianna Silva703246b2023-07-05 14:06:461663. You can pass extra arguments to the app process with `--extra-app-args`, e.g.
167`--extra-app-args='--enable-features=Foo'`.
168 * This might not work consistently as tests can re-launch the app with
169 arbitrary command-line arguments.
170
Mike Baxley47db7d82017-11-16 15:57:17171
172#### Running from the command-line
173
Zhaoyang Li270020462020-10-27 23:07:29174EG2 tests can run in the command line with test runner scripts. You’ll need to
175build the targets before running tests in cmd. This is used by continuous
176integration infra and thus not user friendly. Running UI tests directly in Xcode
177is recommended.
178
179Important notes:
180* The test runner can invoke mac_toolchain to install a new Xcode of the version
181specified to the path specified. You may want to choose a different path from
182your daily use Xcode.
183* If test_cases is empty in --args-json, all tests will run. Specifying a
184testMethod to run is currently not supported in the test runner.
185
Mike Baxley47db7d82017-11-16 15:57:17186Example:
187```
Zhaoyang Li270020462020-10-27 23:07:29188src/ios/build/bots/scripts/run.py
189 --app
190 src/out/Debug-iphonesimulator/ios_chrome_ui_eg2tests_module-Runner.app
191 --host-app
192 src/out/Debug-iphonesimulator/ios_chrome_eg2tests.app
193 --args-json
194 {"test_args": [], "xctest": false, "test_cases": ["ReadingListTestCase"],
195 "restart": false, "xcode_parallelization": true, "xcodebuild_device_runner":
196 false}
197 --out-dir
198 path/to/output/dir
199 --retries
200 3
201 --shards
202 1
203 --xcode-build-version
204 11c29
205 --mac-toolchain-cmd
206 path/to/mac_toolchain
207 --xcode-path
208 path/to/Xcode.app
209 --wpr-tools-path
210 NO_PATH
211 --replay-path
212 NO_PATH
213 --iossim
214 src/out/Debug-iphonesimulator/iossim
215 --platform
216 iPad (6th generation)
217 --version
218 13.3
Mike Baxley47db7d82017-11-16 15:57:17219```
Zhaoyang Li270020462020-10-27 23:07:29220The invocation args are logged. You can find the latest arg format at the
221beginning of stdout from an infra test shard if the above doesn't work.
Mike Baxley47db7d82017-11-16 15:57:17222
223
John Palmer046f9872021-05-24 01:24:56224[config the bots]: https://chromium.googlesource.com/chromium/src/testing/+/refs/heads/main/buildbot/README.md#buildbot-testing-configuration-files
Zhaoyang Li270020462020-10-27 23:07:29225[Defining Test Cases and Test Methods]: https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods?language=objc
226[EarlGrey]: https://github.com/google/EarlGrey/tree/earlgrey2
227[EarlGrey APIs]: https://github.com/google/EarlGrey/blob/master/docs/api.md
228[eDO]: https://github.com/google/eDistantObject
Stepan Khapugind8ca0ad2023-11-28 12:49:06229[Example of App Interface]: https://cs.chromium.org/chromium/src/ios/chrome/browser/metrics/model/metrics_app_interface.h
Zhaoyang Li270020462020-10-27 23:07:29230[Example CL adding App Interface]: https://chromium-review.googlesource.com/c/chromium/src/+/1919147
Mike Baxley47db7d82017-11-16 15:57:17231[instructions]: ./build_instructions.md
Zhaoyang Li270020462020-10-27 23:07:29232[Running Tests and Viewing Results]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/05-running_tests.html
John Palmer046f9872021-05-24 01:24:56233[this AppLaunchManager API]: https://source.chromium.org/chromium/chromium/src/+/main:ios/testing/earl_grey/app_launch_manager.h;drc=d0889865de20c5b3bc59d58674eb2dcc02dd2269;l=47
Mike Baxley47db7d82017-11-16 15:57:17234[XCUITest]: https://developer.apple.com/documentation/xctest