Skip to content

Commit 6aa0f47

Browse files
committed
Merge branch 'write-readme-for-ui-tests-ios-479'
2 parents c7f81f5 + ef52d12 commit 6aa0f47

File tree

1 file changed

+78
-27
lines changed

1 file changed

+78
-27
lines changed

ios/MullvadVPNUITests/README.md

+78-27
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,102 @@
1-
# Integration tests
1+
# iOS end to end tests
2+
## Running tests
3+
### Locally using Xcode
4+
Tests can be triggered locally from Xcode in the Test navigator or by running tests from the diamond in the editor gutter.
25

3-
## iOS device setup
6+
#### On GitHub
7+
There are five workflows running tests:
8+
- [ios-end-to-end-tests.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests.yml) - super workflow which other workflows reuse. This is also the workflow you can manually trigger to run all tests or optionally specify which tests to run.
9+
- [ios-end-to-end-tests-nightly.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests-nightly.yml) - scheduled nightly test run, running all tests.
10+
- [ios-end-to-end-tests-merge-to-main.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests-merge-to-main.yml) - automatically triggered by a PR merge to `main`.
11+
- [ios-end-to-end-tests-api.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests-api.yml) - manually triggered tests focusing on making sure the API is functioning as intended on stagemole.
12+
- [ios-end-to-end-tests-settings-migration.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests-settings-migration.yml) - for now this is still manually triggered. Tests installing older version of the app, changing settings, upgrading the app and verifying that settings were correctly migrated.
13+
14+
## Adding more tests
15+
When adding more files with test suites they must be added to the `MullvadVPNUITestsAll` test plan and also added to the appropriate node(s) in `ios/MullvadVPNUITests/tests.json` file in order to run in CI. For new test cases in already existing test suite nothing needs to be done. The test case/suite values in `tests.json` translate to input for `xcodebuild -only-testing` which is in the format `<target-name>/<test-suite-name>/<test-case-name>`. The GitHub actions workflow will add the `<target-name>` part so only `<test-suite-name>/<test-case-name>` is required, where `<test-case-name>` is optional. So for example `AccountTests` and `AccountTests/testLogin` are both valid values.
16+
17+
## Set up local environment
18+
To run tests locally you need to make sure you have copied the configuration template `UITests.xcconfig.template` to `UITests.xcconfig` and set up the configuration attributes. The configuration attributes you're mostly likely to want to set custom values for are at the top:
19+
```
20+
// Pin code of the iOS device under test.
21+
IOS_DEVICE_PIN_CODE =
22+
23+
// UUID to identify test runs. Should be unique per test device. Generate with for example uuidgen on macOS.
24+
TEST_DEVICE_IDENTIFIER_UUID =
25+
```
26+
27+
Look through other configuration attributes as well, but it is likely that their default value should be kept. Default values are set with local test execution in mind. They are changed in CI.
28+
29+
The test device must be on the office WiFi `app-team-ios-tests` in order to be able to run tests making use of the firewall and packet capture APIs.
30+
31+
## CI setup
32+
### iOS device setup
433
1. Make sure device is added to provisioning profiles
5-
2. Disable passcode in iOS settings - otherwise tests cannot be started without manually entering passcode
6-
3. Make sure device is configured in GitHub secrets(see *GitHub setup* below)
7-
4. Make sure the test device is connected to the WiFi `app-team-ios-tests`
8-
5. Make sure iCloud syncing of keychain is off on the device so that the device isn't getting WiFi passwords from another device causing it to sometimes connect to another WiFi.
34+
2. Enable developer mode
35+
3. Disable passcode in iOS settings - otherwise tests cannot be started without manually entering passcode
36+
4. Set the value of `TEST_DEVICE_UDID` to the UDID of the test device in `ios-end-to-end-tests.yml` and `ios-end-to-end-tests-settings-migration.yml`.
37+
5. Make sure the test device is connected to the WiFi `app-team-ios-tests`
38+
6. Make sure iCloud syncing of keychain is off on the device so that the device isn't getting WiFi passwords from another device causing it to sometimes connect to another WiFi.
39+
7. After the device is set up download updated provisioning profiles on the GitHub runner computer(Download manual profiles in Xcode settings)
940

10-
## Set up of runner environment
41+
### Set up of runner build environment
1142
1. Install Xcode
12-
2. Sign in with Apple id in Xcode
43+
2. Sign in with Apple ID in Xcode
1344
3. Download manual provisioning profiles in Xcode
1445
4. Install Xcode command line tools `xcode-select --install`
1546
5. Install yeetd
1647
- `wget https://github.com/biscuitehh/yeetd/releases/download/1.0/yeetd-normal.pkg`
1748
- `sudo installer -pkg yeetd-normal.pkg -target yeetd`
18-
6. Install ios-deploy
19-
- `brew install ios-deploy`
49+
6. Install ios-deploy and jq
50+
- `brew install ios-deploy jq`
2051
7. Install Homebrew and dependencies
2152
- `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
2253
- `brew install xcbeautify wget swiftlint protobuf`
2354
8. Install Ruby
24-
- `\curl -sSL https://get.rvm.io | bash`
55+
- `curl -sSL https://get.rvm.io | bash`
2556
9. Install Rust and add iOS targets
2657
- `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
2758
- `rustup target install aarch64-apple-ios aarch64-apple-ios-sim`
28-
10. Install Go 1.19
29-
- `brew install go@1.19`
59+
10. Install Go 1.20
60+
- `brew install go@1.20`
3061

31-
## GitHub runner setup
62+
### GitHub runner setup
3263
1. Ask GitHub admin for new runner token and setup steps from GitHub. Set it up according to the steps, pass `--labels ios-test` to `config.sh` when running it. By default it will also have the labels `self-hosted` and `macOS` which are required as well.
33-
2. Make sure GitHub actions secrets for the repository are correctly set up:
34-
- `IOS_DEVICE_PIN_CODE` - Device passcode if the device require it, otherwise leave blank. Devices used with CI should not require passcode.
35-
- `IOS_HAS_TIME_ACCOUNT_NUMBER` - Production server account without time left
36-
- `IOS_NO_TIME_ACCOUNT_NUMBER` - Production server account with time added to it
37-
- `IOS_TEST_DEVICE_IDENTIFIER_UUID` - unique identifier for the test device. Create new identifier with `uuidgen`.
38-
- `IOS_TEST_DEVICE_UDID` - the iOS device's UDID.
64+
2. Make sure GitHub actions secrets for the GitHub project are correctly set up:
65+
- `IOS_DEVICE_PIN_CODE` - Device passcode for the device you want to run tests on, otherwise leave blank. Devices used with CI should not require passcode.
66+
- `IOS_HAS_TIME_ACCOUNT_NUMBER` - Production server account with time added to it.
67+
- `IOS_NO_TIME_ACCOUNT_NUMBER` - Production server account with no time. Make sure that the account has not been deleted if left unused for too long.
68+
- `TEST_DEVICE_IDENTIFIER_UUID` - unique identifier for the test device. Create new identifier with `uuidgen`.
3969
- `PARTNER_API_TOKEN` - secret token for partner API. Optional and only intended to be used in CI when running tests against staging environment.
4070

41-
## Test plans
42-
There are a few different test plans which are mainly to be triggered by GitHub action workflows but can also be triggered manually with Xcode:
43-
* `MullvadVPNUITestsAll` - All tests except settings migration tests which are in separate test plan and workflow
44-
* `MullvadVPNUITestsSmoke` - A few tests for smoke testing when merge:ing to `main`
45-
46-
And also the following test plans which are used for testing settings migration(`ios-end-to-end-tests-settings-migration`):
47-
71+
### Specifying which tests run when in CI
72+
Which tests run when is specified in `tests.json`(See _Adding more tests_). Settings migration is an exception, it uses four different test plans and a separate workflow `ios-end-to-end-tests-settings-migration.yml` which executes the test plans in order, do not reinstall the app in between runs but upgrades the app after changing settings:
4873
* `MullvadVPNUITestsChangeDNSSettings` - Change settings for using custom DNS
4974
* `MullvadVPNUITestsVerifyDNSSettingsChanged` - Verify custom DNS settings still changed
5075
* `MullvadVPNUITestsChangeSettings` - Change all settings except custom DNS setting
5176
* `MullvadVPNUITestsVerifySettingsChanged` - Verify all settings except custom DNS setting still changed
77+
78+
### Current test devices
79+
Currently we are using an iPhone 15 Pro(UDID `00008130-0019181022F3803A`) running iOS 17.
80+
81+
## APIs used
82+
The iOS team NUC is hosting APIs consumed by tests:
83+
84+
- **Firewall API** - for creating temporary firewall rules blocking certain traffic. Hosted on NUC.
85+
- **Packet capture API** - for recording packet captures. Outputs both PCAP file and PCAP parsed to JSON(with some limitations). Hosted on NUC.
86+
- **Partner API** - The partner API is used on stagemole for adding time to accounts. Hosted by infra.
87+
- **App API** - The app API is used for managing accounts - creating, deleting, getting account info etc. Hosted by infra.
88+
89+
## Network setup
90+
The NUC is hosting a WiFi which test devices need to be on in order to be able to access the firewall and packet capture APIs. The SSID is `app-team-ios-tests`. The APIs running on the NUC are accessed by using IP address `8.8.8.8` and port `80` from test devices. This is a workaround for local network access not working from UI tests. `8.8.8.8` which is a public IP address is re-routed to the NUC. This way we don't need to allow local network access in order to access the local NUC.
91+
## Troubleshooting
92+
### Restarting services
93+
The easiest way to restart test services running on the NUC is by SSH:ing into it at `192.168.105.1` as `root` (password is written on a sticker under it) and rebooting `sudo shutdown -r now`.
94+
95+
## Gotchas
96+
### GitHub actions concurrency
97+
The way concurrency with GitHub actions work is that multiple workflows run concurrently, but jobs don't run concurrently. So for example if two test workflows are triggered at the same time both will start at the same time, but only one will run the `build` job at a time. When one job has finished its `build` job it will start its `test` job and the other workflow run will start its `build` job.
98+
99+
To make the test workflows not clash with each other the jobs output files to `~/workflow-outputs`. They create a directory which is unique for the test run, and after the test run finished the directory is removed. This is necessary because we cannot depend on the state of the working directory, since if we did test runs would be changing the working directory for each other.
100+
101+
### Packet capture API timeout
102+
Tests always attempt to stop packet capture, but there is no guarantee that it can always be stopped. For example when running tests locally and stopping test execution mid packet capture the test cannot stop the packet capture. So the packet capture API has a timeout (5 minutes) in place. If a packet capture session exceeds this duration it will be stopped. This means that tests cannot do packet capture exceeding this time limit.

0 commit comments

Comments
 (0)