Skip to content

Commit a49d6d6

Browse files
authored
[Test Proxy] Update migration guide, add troubleshooting guide (Azure#22175)
1 parent bcd8015 commit a49d6d6

File tree

2 files changed

+191
-12
lines changed

2 files changed

+191
-12
lines changed

doc/dev/test_proxy_migration_guide.md

Lines changed: 113 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@ the Azure SDK test proxy.
66
Documentation of the motivations and goals of the test proxy can be found [here][general_docs] in the azure-sdk-tools
77
GitHub repository, and documentation of how to set up and use the proxy can be found [here][detailed_docs].
88

9+
## Table of contents
10+
- [Update existing tests](#update-existing-tests)
11+
- [Using resource preparers](#using-resource-preparers)
12+
- [Run tests](#run-tests)
13+
- [Perform one-time setup](#perform-one-time-setup)
14+
- [Start the proxy server](#start-the-proxy-server)
15+
- [Record or play back tests](#record-or-play-back-tests)
16+
- [Register sanitizers](#register-sanitizers)
17+
- [Enable the test proxy in CI](#enable-the-test-proxy-in-ci)
18+
- [Fetch environment variables](#fetch-environment-variables)
19+
- [Record test variables](#record-test-variables)
20+
- [Migrate management-plane tests](#migrate-management-plane-tests)
21+
- [Advanced details](#advanced-details)
22+
- [What does the test proxy do?](#what-does-the-test-proxy-do)
23+
- [How does the test proxy know when and what to record or play back?](#how-does-the-test-proxy-know-when-and-what-to-record-or-play-back)
24+
- [Start the proxy manually](#start-the-proxy-manually)
25+
926
## Update existing tests
1027

1128
### Current test structure
@@ -52,22 +69,37 @@ way as `recorded_by_proxy`.
5269
> with "Test" in order to be properly collected by pytest by default. For more information, please refer to
5370
> [pytest's documentation][pytest_collection].
5471
55-
## Run the tests
72+
### Using resource preparers
73+
74+
Test suites that haven't fully migrated to using a `test-resources.json` file for test resource deployment might use
75+
resource preparers, such as
76+
[ResourceGroupPreparer](https://github.com/Azure/azure-sdk-for-python/blob/main/tools/azure-sdk-tools/devtools_testutils/resource_testcase.py).
77+
Migrating to [PowerShell test resource deployment][test_resources] is recommended (and test proxy migration might be a
78+
good opportunity to look into this), but the test proxy can work with resource preparers.
79+
80+
Resource preparers need a management client to function, so test classes that use them will need to inherit from
81+
[AzureMgmtRecordedTestCase][mgmt_recorded_test_case] instead of AzureRecordedTestCase.
82+
83+
## Run tests
5684

5785
### Perform one-time setup
5886

87+
Docker is a requirement for using the test proxy. You can install Docker from
88+
[docs.docker.com](https://docs.docker.com/get-docker/). After installing, make sure Docker is running and is using
89+
Linux containers before running tests.
90+
5991
The test proxy is made available for your tests via a Docker container. Some tests require an SSL connection to work, so
6092
the Docker image used for the container has a certificate imported that you need to trust on your machine. Instructions
61-
on how to do so can be found [here][proxy_cert_docs].
93+
on how to do so can be found [here][proxy_cert_docs] and need to be followed before running tests.
6294

6395
### Start the proxy server
6496

6597
The test proxy has to be available in order for tests to work in live or playback mode. There's a
6698
[section](#manually-start-the-proxy) under [Advanced details](#advanced-details) that describes how to do this manually,
6799
but it's recommended that tests use a `pytest` fixture to start and stop the proxy automatically when running tests.
68100

69-
In a `conftest.py` file for your package's tests, add a session-level fixture that accepts `devtools_testutils.test_proxy`
70-
as a parameter (and has `autouse` set to `True`):
101+
In a `conftest.py` file for your package's tests, add a session-level fixture that accepts
102+
`devtools_testutils.test_proxy` as a parameter (and has `autouse` set to `True`):
71103

72104
```python
73105
from devtools_testutils import test_proxy
@@ -78,18 +110,24 @@ def start_proxy(test_proxy):
78110
return
79111
```
80112

113+
The `test_proxy` fixture will fetch the test proxy Docker image and create a new container called
114+
`ambitious_azsdk_test_proxy` if one doesn't exist already. If the container already exists, the fixture will start the
115+
container if it's currently stopped. The container will be stopped after tests finish running, but will stay running if
116+
test execution is interrupted.
117+
81118
If your tests already use an `autouse`d, session-level fixture for tests, you can accept the `test_proxy` parameter in
82119
that existing fixture instead of adding a new one. For an example, see the [Register sanitizers](#register-sanitizers)
83120
section of this document.
84121

85-
In general, if any fixture requires the test proxy to be available by the time it's used, that fixture should accept this
86-
`test_proxy` parameter.
122+
In general, if any fixture requires the test proxy to be available by the time it's used, that fixture should accept
123+
this `test_proxy` parameter.
87124

88125
### Record or play back tests
89126

90127
Configuring live and playback tests is done with the `AZURE_TEST_RUN_LIVE` environment variable. When this variable is
91-
set to "true" or "yes", live tests will run and produce recordings. When this variable is set to "false" or "no", or
92-
not set at all, tests will run in playback mode and attempt to match existing recordings.
128+
set to "true" or "yes", live tests will run and produce recordings unless the `AZURE_SKIP_LIVE_RECORDING` environment
129+
variable is set to "true". When `AZURE_TEST_RUN_LIVE` is set to "false" or "no", or not set at all, tests will run in
130+
playback mode and attempt to match existing recordings.
93131

94132
Recordings for a given package will end up in that package's `/tests/recordings` directory, just like they currently
95133
do. Recordings that use the test proxy are `.json` files instead of `.yml` files, so migrated test suites no longer
@@ -98,6 +136,10 @@ need old `.yml` recordings.
98136
> **Note:** at this time, support for configuring live or playback tests with a `testsettings_local.cfg` file has been
99137
> deprecated in favor of using just `AZURE_TEST_RUN_LIVE`.
100138
139+
> **Note:** the recording storage location is determined when the proxy Docker container is created. If there are
140+
> multiple local copies of the `azure-sdk-for-python` repo on your machine, you will need to delete any existing
141+
> `ambitious_azsdk_test_proxy` container before recordings can be stored in a different repo copy.
142+
101143
### Register sanitizers
102144

103145
Since the test proxy doesn't use [`vcrpy`][vcrpy], tests don't use a scrubber to sanitize values in recordings.
@@ -145,12 +187,60 @@ made to `https://fakeendpoint-secondary.table.core.windows.net`, and URIs will a
145187

146188
For more details about sanitizers and their options, please refer to [devtools_testutils/sanitizers.py][py_sanitizers].
147189

148-
### Enabling the test proxy in CI
190+
#### Note regarding body matching
191+
192+
In the old, `vcrpy`-based testing system, request and response bodies weren't compared in playback mode by default in
193+
most packages. The test proxy system enables body matching by default, which can introduce failures for tests that
194+
passed in the old system. For example, if a test sends a request that includes the current Unix time in its body, the
195+
body will contain a new value when run in playback mode at a later time. This request might still match the recording if
196+
body matching is disabled, but not if it's enabled.
149197

150-
To enable using the test proxy in CI, you need to set the parameter `TestProxy: true` in the `ci.yml` and `tests.yml`
151-
files in the service level folder. For example, in `sdk/eventgrid/ci.yml`:
198+
Body matching can be turned off with the test proxy by calling the `set_bodiless_matcher` method from
199+
[devtools_testutils/sanitizers.py][py_sanitizers] at the very start of a test method. This matcher applies only to the
200+
test method that `set_bodiless_matcher` is called from, so other tests in the `pytest` session will still have body
201+
matching enabled by default.
202+
203+
### Enable the test proxy in CI
204+
205+
To enable using the test proxy in CI, you need to set the parameter `TestProxy: true` in the `ci.yml` file in the
206+
service-level folder. For example, in `sdk/eventgrid/ci.yml`:
152207

153208
![image](https://user-images.githubusercontent.com/45376673/142270668-5be58bca-87e5-45f5-b593-44f8b1f757bc.png)
209+
210+
The test proxy is only used in playback pipeline testing, so this parameter doesn't need to be set in `tests.yml`. For
211+
live pipeline testing, requests are made directly to the service instead of going through the proxy first.
212+
213+
### Fetch environment variables
214+
215+
Fetching environment variables, passing them directly to tests, and sanitizing their real values can be done all at once
216+
by using the `devtools_testutils`
217+
[PowerShellPreparer](https://github.com/Azure/azure-sdk-for-python/blob/main/tools/azure-sdk-tools/devtools_testutils/powershell_preparer.py).
218+
219+
The name "PowerShellPreparer" comes from its intended use with the PowerShell test resource management commands that are
220+
documented in [/eng/common/TestResources][test_resources]. It's recommended that all test suites use these scripts for
221+
live test resource management.
222+
223+
For an example of using the PowerShellPreparer with the test proxy, you can refer to the Tables SDK. The CosmosPreparer
224+
and TablesPreparer defined in this [preparers.py][tables_preparers] file each define an instance of the
225+
PowerShellPreparer, which are used to fetch environment variables for Cosmos and Tables, respectively. These preparers
226+
can be used to decorate test methods directly; for example:
227+
228+
```python
229+
from devtools_testutils import AzureRecordedTestCase, recorded_by_proxy
230+
from .preparers import TablesPreparer
231+
232+
class TestExample(AzureRecordedTestCase):
233+
234+
@TablesPreparer()
235+
@recorded_by_proxy
236+
def test_example_with_preparer(self, tables_storage_account_name, tables_primary_storage_account_key):
237+
...
238+
```
239+
240+
Or, they can be used in a custom decorator, as they are in the `cosmos_decorator` and `tables_decorator` defined in
241+
[preparers.py][tables_preparers]. `@tables_decorator`, for instance, is then used in place of `@TablesPreparer()` for
242+
the example above (note that the method-style `tables_decorator` is used without parentheses).
243+
154244
### Record test variables
155245

156246
To run recorded tests successfully when there's an element of non-secret randomness to them, the test proxy provides a
@@ -188,6 +278,14 @@ class TestExample(AzureRecordedTestCase):
188278
return variables
189279
```
190280

281+
## Migrate management-plane tests
282+
283+
For management-plane packages, test classes should inherit from [AzureMgmtRecordedTestCase][mgmt_recorded_test_case]
284+
instead of AzureRecordedTestCase.
285+
286+
The rest of the information in this guide applies to management-plane packages as well, except for possible specifics
287+
regarding test resource deployment.
288+
191289
## Advanced details
192290

193291
### What does the test proxy do?
@@ -235,7 +333,7 @@ Running tests in playback follows the same pattern, except that requests will be
235333
The `recorded_by_proxy` and `recorded_by_proxy_async` decorators send the appropriate requests at the start and end of
236334
each test case.
237335

238-
### Manually start the proxy
336+
### Start the proxy manually
239337

240338
There are two options for manually starting and stopping the test proxy: one uses a PowerShell command, and one uses
241339
methods from `devtools_testutils`.
@@ -270,9 +368,12 @@ For more details on proxy startup, please refer to the [proxy documentation][det
270368
[detailed_docs]: https://github.com/Azure/azure-sdk-tools/tree/main/tools/test-proxy/Azure.Sdk.Tools.TestProxy/README.md
271369
[docker_start_proxy]: https://github.com/Azure/azure-sdk-for-python/blob/main/eng/common/testproxy/docker-start-proxy.ps1
272370
[general_docs]: https://github.com/Azure/azure-sdk-tools/blob/main/tools/test-proxy/README.md
371+
[mgmt_recorded_test_case]: https://github.com/Azure/azure-sdk-for-python/blob/main/tools/azure-sdk-tools/devtools_testutils/mgmt_recorded_testcase.py
273372
[proxy_cert_docs]: https://github.com/Azure/azure-sdk-tools/blob/main/tools/test-proxy/documentation/trusting-cert-per-language.md
274373
[py_sanitizers]: https://github.com/Azure/azure-sdk-for-python/blob/main/tools/azure-sdk-tools/devtools_testutils/sanitizers.py
275374
[pytest_collection]: https://docs.pytest.org/latest/goodpractices.html#test-discovery
276375
[pytest_fixtures]: https://docs.pytest.org/latest/fixture.html#scope-sharing-fixtures-across-classes-modules-packages-or-session
277376
[sanitizers]: https://github.com/Azure/azure-sdk-tools/blob/main/tools/test-proxy/Azure.Sdk.Tools.TestProxy/README.md#session-and-test-level-transforms-sanitiziers-and-matchers
377+
[tables_preparers]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/tables/azure-data-tables/tests/preparers.py
378+
[test_resources]: https://github.com/Azure/azure-sdk-for-python/tree/main/eng/common/TestResources#readme
278379
[vcrpy]: https://vcrpy.readthedocs.io

doc/dev/test_proxy_troubleshooting.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Guide for test proxy troubleshooting
2+
3+
This guide details some common errors that can come up when migrating to and using the Azure SDK test proxy. For more
4+
information about migrating existing tests to the test proxy, please refer to the
5+
[test proxy migration guide][migration_guide].
6+
7+
Documentation of the motivations and goals of the test proxy can be found [here][general_docs] in the azure-sdk-tools
8+
GitHub repository, and documentation of how to set up and use the proxy can be found [here][detailed_docs].
9+
10+
## Table of contents
11+
- [General troubleshooting tip](#general-troubleshooting-tip)
12+
- [Test collection failure](#test-collection-failure)
13+
- [Errors in tests using resource preparers](#errors-in-tests-using-resource-preparers)
14+
- [Playback failures from body matching errors](#playback-failures-from-body-matching-errors)
15+
- [Recordings not being produced](#recordings-not-being-produced)
16+
- [KeyError during container startup](#keyerror-during-container-startup)
17+
- [ConnectionError during test startup](#connectionerror-during-test-startup)
18+
19+
## General troubleshooting tip
20+
21+
For any issue that may come up, it's generally a good idea to first try deleting any existing proxy container (which
22+
will be called `ambitious_azsdk_test_proxy`) and creating a new one by running tests. This will fetch the latest tag of
23+
the test proxy Docker container, meaning the latest version of the proxy tool will be used.
24+
25+
## Test collection failure
26+
27+
Because tests are now using pure `pytest` conventions without `unittest.TestCase` components, discovering tests with
28+
`pytest` is a bit more strict. Make sure that all test class names begin with "Test", and that all test method names
29+
begin with "test_". For more information about `pytest` test collection, please refer to the [docs][pytest_collection].
30+
31+
## Errors in tests using resource preparers
32+
33+
Test suites that haven't fully migrated to using a `test-resources.json` file for test resource deployment might use
34+
resource preparers, such as
35+
[ResourceGroupPreparer](https://github.com/Azure/azure-sdk-for-python/blob/main/tools/azure-sdk-tools/devtools_testutils/resource_testcase.py).
36+
Resource preparers need a management client to function, so test classes that use them will need to inherit from
37+
[AzureMgmtRecordedTestCase][mgmt_recorded_test_case] instead of AzureRecordedTestCase.
38+
39+
## Playback failures from body matching errors
40+
41+
In the old, `vcrpy`-based testing system, request and response bodies weren't compared in playback mode by default in
42+
most packages. The test proxy system enables body matching by default, which can introduce failures for tests that
43+
passed in the old system. For example, if a test sends a request that includes the current Unix time in its body, the
44+
body will contain a new value when run in playback mode at a later time. This request might still match the recording if
45+
body matching is disabled, but not if it's enabled.
46+
47+
Body matching can be turned off with the test proxy by calling the `set_bodiless_matcher` method from
48+
[devtools_testutils/sanitizers.py][py_sanitizers] at the very start of a test method. This matcher applies only to the
49+
test method that `set_bodiless_matcher` is called from, so other tests in the `pytest` session will still have body
50+
matching enabled by default.
51+
52+
## Recordings not being produced
53+
54+
First, make sure that the environment variable `AZURE_SKIP_LIVE_RECORDING` isn't set to "true". If it's not and live
55+
tests still aren't producing recordings, try deleting the `ambitious_azsdk_test_proxy` Docker container and re-running
56+
tests. The recording storage location is determined when the test proxy Docker container is created. If there are
57+
multiple local copies of the `azure-sdk-for-python` repo on your machine, the container could be storing recordings in
58+
the wrong repo.
59+
60+
## KeyError during container startup
61+
62+
Try updating your machine's version of Docker. Older versions of Docker may not return a status to indicate whether or
63+
not the proxy container is running, which the
64+
[proxy_docker_startup.py](https://github.com/Azure/azure-sdk-for-python/blob/main/tools/azure-sdk-tools/devtools_testutils/proxy_docker_startup.py)
65+
script needs to determine.
66+
67+
## ConnectionError during test startup
68+
69+
For example, you may see a `requests.exceptions.ConnectionError` when trying to contact URL `/Info/Available`. This
70+
means that the test proxy tool wasn't started up properly, so requests to the tool are failing. Make sure Docker is
71+
installed and is up to date, and ensure that Linux containers are being used.
72+
73+
[detailed_docs]: https://github.com/Azure/azure-sdk-tools/tree/main/tools/test-proxy/Azure.Sdk.Tools.TestProxy/README.md
74+
[general_docs]: https://github.com/Azure/azure-sdk-tools/blob/main/tools/test-proxy/README.md
75+
[mgmt_recorded_test_case]: https://github.com/Azure/azure-sdk-for-python/blob/main/tools/azure-sdk-tools/devtools_testutils/mgmt_recorded_testcase.py
76+
[migration_guide]: https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/test_proxy_migration_guide.md
77+
[py_sanitizers]: https://github.com/Azure/azure-sdk-for-python/blob/main/tools/azure-sdk-tools/devtools_testutils/sanitizers.py
78+
[pytest_collection]: https://docs.pytest.org/latest/goodpractices.html#test-discovery

0 commit comments

Comments
 (0)