Skip to content

Commit 11f4440

Browse files
committed
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-python into switch_to_protocol
* 'main' of https://github.com/Azure/azure-sdk-for-python: (85 commits) [rest] add backcompat mixin to rest requests (Azure#20599) [EventHubs] Stress test refactor (Azure#20389) Clean-up changelog scripts (Azure#20779) [AutoRelease] t2-containerinstance-2021-09-17-04542 (Azure#20733) [SchemaRegistry] remove cache from client (Azure#20760) Update add_sanitizer and doc (Azure#20769) Enable release stage selection at queue time (Azure#20767) [Key Vault] Add certificate import sample (Azure#20641) Fixing VCR redirection (Azure#20747) Link to Log Analytics throttling guidance from Monitor Query README (Azure#20759) Fix broken anchor tags (Azure#20751) avroserializer pins its dependency, which makes regression testing a … (Azure#20735) [AutoRelease] t2-eventhub-2021-09-17-55263(Do not merge) (Azure#20739) Fix broken link in python repo (Azure#20746) [Storage]Unify service version and update changelog (Azure#20723) Sync eng/common directory with azure-sdk-tools for PR 2010 (Azure#20729) [AutoRelease] t2-azurearcdata-2021-09-15-74995 (Azure#20714) [Test Proxy] Make add_sanitizer a module-level method (Azure#20701) [Test proxy] Add migration guide (Azure#20469) Sync eng/common directory with azure-sdk-tools for PR 2011 (Azure#20702) ...
2 parents 8e4febd + 30b196e commit 11f4440

File tree

898 files changed

+235806
-20058
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

898 files changed

+235806
-20058
lines changed

doc/dev/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Overview of the documents:
66
- [Developer Set-Up](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/dev_setup.md) : How to create a development environment for this repo
77
- [Release](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/release.md) : How to release a package when ready
88
- [Packaging](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/packaging.md) : How to organize packaging information for packages under `azure`
9-
- [Testing](./tests.md): How to write unit and functional tests for a library
9+
- [Testing](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/tests.md): How to write unit and functional tests for a library
1010
- [Docstrings and Type hints](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/docstring_typehint.md): How to document an SDK for compatability with internal tools (API View) and our documentation at [MS Docs][ms_docs] and the [azure.github.io][azure_github_io] site.
1111

1212
The [mgmt](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/mgmt) folder contains information specific to management packages (i.e. packages prefixed by `azure-mgmt`)

doc/dev/docstring_typehint.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ All public methods should have docstrings to document the parameters, keywords,
44

55
* [Docstrings](#docstrings)
66
* [Method Docstrings](#method_docstrings)
7-
* [Model and Client Docstrings](#Model_and_Client_Docstrings)
7+
* [Model and Client Docstrings](#model_and_client_docstrings)
88
* [Type Hints](#type_hints)
99
* [Type Hints for Python 2.7 and 3.5+](#type_hints_for_python_2.7_and_3.5+)
1010
* [Type Hints for Python 3.5+](#type_hints_for_python_3.5+)
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Guide for migrating to the test proxy from vcrpy
2+
3+
This guide describes the changes that service SDKs should make to their test frameworks in order to take advantage of
4+
the Azure SDK test proxy.
5+
6+
Documentation of the motivations and goals of the test proxy can be found [here][general_docs] in the azure-sdk-tools
7+
GitHub repository, and documentation of how to set up and use the proxy can be found [here][detailed_docs].
8+
9+
## Update existing tests
10+
11+
### Current test structure
12+
13+
Test classes currently inherit from AzureTestCase, and test methods can optionally use decorators:
14+
15+
```py
16+
from devtools_testutils import AzureTestCase
17+
18+
class TestExample(AzureTestCase):
19+
20+
def test_example(self):
21+
...
22+
23+
@ExamplePreparer()
24+
def test_example_with_preparer(self):
25+
...
26+
```
27+
28+
### New test structure
29+
30+
To use the proxy, test classes should inherit from AzureRecordedTestCase and recorded test methods should use a
31+
RecordedByProxy decorator:
32+
33+
```py
34+
from devtools_testutils import AzureRecordedTestCase, RecordedByProxy
35+
36+
class TestExample(AzureRecordedTestCase):
37+
38+
@RecordedByProxy
39+
def test_example(self):
40+
...
41+
42+
@ExamplePreparer()
43+
@RecordedByProxy
44+
def test_example_with_preparer(self):
45+
...
46+
```
47+
48+
For async tests, import the RecordedByProxyAsync decorator from `devtools_testutils.aio` and use it in the same
49+
way as RecordedByProxy.
50+
51+
> **Note:** since AzureRecordedTestCase doesn't inherit from `unittest.TestCase`, test class names need to start
52+
> with "Test" in order to be properly collected by pytest by default. For more information, please refer to
53+
> [pytest's documentation][pytest_collection].
54+
55+
## Run the tests
56+
57+
### Perform one-time setup
58+
59+
The test proxy is made available for your tests via a Docker container. Some tests require an SSL connection to work, so
60+
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].
62+
63+
### Start the proxy server
64+
65+
There is a [PowerShell script][docker_start_proxy] in `eng/common/testproxy` that will fetch the proxy Docker image if
66+
you don't already have it, and will start or stop a container running the image for you. You can run the following
67+
command from the root of the `azure-sdk-for-python` directory to start the container whenever you want to make the test
68+
proxy available for running tests:
69+
70+
```powershell
71+
.\eng\common\testproxy\docker-start-proxy.ps1 "start"
72+
```
73+
74+
Note that the proxy is available as long as the container is running. In other words, you don't need to start and
75+
stop the container for each test run or between tests for different SDKs. You can run the above command in the morning
76+
and just stop the container whenever you'd like. To stop the container, run the same command but with `"stop"` in place
77+
of `"start"`. In the future, the proxy container will be set up and started automatically when tests are run, and
78+
starting it manually will be optional.
79+
80+
For more details on proxy startup, please refer to the [proxy documentation][detailed_docs].
81+
82+
### Record or play back tests
83+
84+
Configuring live and playback tests is done with the `AZURE_TEST_RUN_LIVE` environment variable. When this variable is
85+
set to "true" or "yes", live tests will run and produce recordings. When this variable is set to "false" or "no", or
86+
not set at all, tests will run in playback mode and attempt to match existing recordings.
87+
88+
Recordings for a given package will end up in that package's `/tests/recordings` directory, just like they currently
89+
do.
90+
91+
> **Note:** at this time, support for configuring live or playback tests with a `testsettings_local.cfg` file has been
92+
> deprecated in favor of using just `AZURE_TEST_RUN_LIVE`.
93+
94+
### Register sanitizers
95+
96+
Since the test proxy doesn't use [`vcrpy`][vcrpy], tests don't use a scrubber to sanitize values in recordings.
97+
Instead, sanitizers (as well as matchers and transforms) can be registered on the proxy as detailed in
98+
[this][sanitizers] section of the proxy documentation. At the time of writing, sanitizers can be registered via the
99+
`add_sanitizer` method in `devtools_testutils`.
100+
101+
Sanitizers, matchers, and transforms remain registered until the proxy container is stopped, so for any sanitizers that
102+
are shared by different tests, using a session fixture declared in a `conftest.py` file is recommended. Please refer to
103+
[pytest's scoped fixture documentation][pytest_fixtures] for more details.
104+
105+
For example, to sanitize URIs in recordings, you can set up a URI sanitizer for all tests in the pytest session by
106+
adding something like the following in the package's `conftest.py` file:
107+
108+
```python
109+
from devtools_testutils import add_sanitizer
110+
111+
# autouse=True will trigger this fixture on each pytest run, even if it's not explicitly used by a test method
112+
@pytest.fixture(scope="session", autouse=True)
113+
def sanitize_uris():
114+
add_sanitizer(ProxyRecordingSanitizer.URI, value="fakeendpoint")
115+
```
116+
117+
`add_sanitizer` accepts a sanitizer, matcher, or transform type from the ProxyRecordingSanitizer enum as a required
118+
parameter. Keyword-only arguments can be provided to customize the sanitizer; for example, in the snippet above, any
119+
request URIs that match the default URI regular expression will have their domain name replaced with "fakeendpoint". A
120+
request made to `https://tableaccount.table.core.windows.net` will be recorded as being made to
121+
`https://fakeendpoint.table.core.windows.net`.
122+
123+
## Implementation details
124+
125+
### What does the test proxy do?
126+
127+
The gist of the test proxy is that it stands in between your tests and the service. What this means is that test
128+
requests which would usually go straight to the service should instead point to the locally-hosted test proxy.
129+
130+
For example, if an operation would typically make a GET request to
131+
`https://fakeazsdktestaccount.table.core.windows.net/Tables`, that operation should now be sent to
132+
`https://localhost:5001/Tables` instead. The original endpoint should be stored in an `x-recording-upstream-base-uri` --
133+
the proxy will send the original request and record the result.
134+
135+
The RecordedByProxy and RecordedByProxyAsync decorators patch test requests to do this for you.
136+
137+
### How does the test proxy know when and what to record or play back?
138+
139+
This is achieved by making POST requests to the proxy server that say whether to start or stop recording or playing
140+
back, as well as what test is being run.
141+
142+
To start recording a test, the server should be primed with a POST request:
143+
144+
```
145+
URL: https://localhost:5001/record/start
146+
headers {
147+
"x-recording-file": "<path-to-test>/recordings/<testfile>.<testname>"
148+
}
149+
```
150+
151+
This will return a recording ID in an `x-recording-id` header. This ID should be sent as an `x-recording-id` header in
152+
all further requests during the test.
153+
154+
After the test has finished, a POST request should be sent to indicate that recording is complete:
155+
156+
```
157+
URL: https://localhost:5001/record/stop
158+
headers {
159+
"x-recording-id": "<x-recording-id>"
160+
}
161+
```
162+
163+
Running tests in playback follows the same pattern, except that requests will be sent to `/playback/start` and
164+
`/playback/stop` instead. A header, `x-recording-mode`, should be set to `record` for all requests when recording and
165+
`playback` when playing recordings back. More details can be found [here][detailed_docs].
166+
167+
The RecordedByProxy and RecordedByProxyAsync decorators send the appropriate requests at the start and end of each test
168+
case.
169+
170+
[detailed_docs]: https://github.com/Azure/azure-sdk-tools/tree/main/tools/test-proxy/Azure.Sdk.Tools.TestProxy/README.md
171+
[docker_start_proxy]: https://github.com/Azure/azure-sdk-for-python/blob/main/eng/common/testproxy/docker-start-proxy.ps1
172+
[general_docs]: https://github.com/Azure/azure-sdk-tools/blob/main/tools/test-proxy/README.md
173+
[proxy_cert_docs]: https://github.com/Azure/azure-sdk-tools/blob/main/tools/test-proxy/documentation/trusting-cert-per-language.md
174+
[pytest_collection]: https://docs.pytest.org/latest/goodpractices.html#test-discovery
175+
[pytest_fixtures]: https://docs.pytest.org/latest/fixture.html#scope-sharing-fixtures-across-classes-modules-packages-or-session
176+
[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
177+
[vcrpy]: https://vcrpy.readthedocs.io

eng/CredScanSuppression.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@
4040
"eng/common/testproxy/dotnet-devcert.pfx",
4141
"sdk/confidentialledger/azure-confidentialledger/tests/_shared/constants.py",
4242
"sdk/keyvault/azure-keyvault-certificates/tests/ca.key",
43-
"sdk/identity/azure-identity/tests/ec-certificate.pem",
4443
"sdk/identity/azure-identity/tests/certificate.pfx",
4544
"sdk/identity/azure-identity/tests/certificate-with-password.pfx",
45+
"sdk/identity/azure-identity/tests/credscan_ignore.py",
46+
"sdk/identity/azure-identity/tests/ec-certificate.pem",
4647
"sdk/core/azure-servicemanagement-legacy/tests/legacy_mgmt_settings_fake.py",
4748
"sdk/storage/azure-storage-blob/tests/fake_credentials.py",
4849
"sdk/storage/azure-storage-file-datalake/tests/fake_credentials.py",

0 commit comments

Comments
 (0)