Skip to content

Commit 0066659

Browse files
authored
[Test proxy] Default to HTTP (Azure#42662)
1 parent 5d78f06 commit 0066659

File tree

4 files changed

+73
-48
lines changed

4 files changed

+73
-48
lines changed

.vscode/cspell.json

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,13 @@
135135
"eng/common/docgeneration/Generate-DocIndex.ps1",
136136
"eng/**/*.py",
137137
".gitignore",
138-
"tools/azure-sdk-tools/ci_tools/github_tools.py",
139-
"tools/azure-sdk-tools/devtools_testutils/fake_credentials.py",
140-
"tools/azure-sdk-tools/packaging_tools/**",
141-
"tools/azure-sdk-tools/setup.py",
138+
"eng/tools/azure-sdk-tools/ci_tools/github_tools.py",
139+
"eng/tools/azure-sdk-tools/devtools_testutils/fake_credentials.py",
140+
"eng/tools/azure-sdk-tools/packaging_tools/**",
141+
"eng/tools/azure-sdk-tools/setup.py",
142142
"sdk/webpubsub/azure-messaging-webpubsubclient/azure/messaging/webpubsubclient/_serialization.py",
143143
"sdk/webpubsub/azure-messaging-webpubsubclient/azure/messaging/webpubsubclient/_model_base.py",
144-
"tools/azure-sdk-tools/tests/test_servicemetadata.py",
144+
"eng/tools/azure-sdk-tools/tests/test_servicemetadata.py",
145145
"conda/conda-recipes/azure-ai-ml/meta.yaml",
146146
"conda/conda-recipes/azure-eventhub/meta.yaml",
147147
"conda/conda-recipes/azure-mgmt/meta.yaml",
@@ -563,21 +563,27 @@
563563
"CSCAN"
564564
]
565565
},
566+
{
567+
"filename": "doc/dev/tests-advanced.md",
568+
"words": [
569+
"xunit"
570+
]
571+
},
566572
{
567573
"filename": "doc/dev/pylint_checking.md",
568574
"words": [
569575
"pylintrc"
570576
]
571577
},
572578
{
573-
"filename": "tools/azure-sdk-tools/devtools_testutils/proxy_startup.py",
579+
"filename": "eng/tools/azure-sdk-tools/devtools_testutils/proxy_startup.py",
574580
"words": [
575581
"certifi",
576582
"passenv"
577583
]
578584
},
579585
{
580-
"filename": "tools/azure-sdk-tools/tests/integration/test_proxy_startup.py",
586+
"filename": "eng/tools/azure-sdk-tools/tests/integration/test_proxy_startup.py",
581587
"words": [
582588
"spinup"
583589
]
@@ -589,22 +595,22 @@
589595
]
590596
},
591597
{
592-
"filename": "tools/azure-sdk-tools/ci_tools/deps.html.j2",
598+
"filename": "eng/tools/azure-sdk-tools/ci_tools/deps.html.j2",
593599
"words": [
594600
"isfork",
595601
"ISFORK",
596602
"thead"
597603
]
598604
},
599605
{
600-
"filename": "tools/azure-sdk-tools/gh_tools/**",
606+
"filename": "eng/tools/azure-sdk-tools/gh_tools/**",
601607
"words": [
602608
"JOBID",
603609
"vnext"
604610
]
605611
},
606612
{
607-
"filename": "tools/azure-sdk-tools/tests/test_labels.py",
613+
"filename": "eng/tools/azure-sdk-tools/tests/test_labels.py",
608614
"words": [
609615
"vnext"
610616
]

doc/dev/test_proxy_troubleshooting.md

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ GitHub repository, but this isn't necessary to read for Python testing.
88
## Table of contents
99

1010
- [Debugging tip](#debugging-tip)
11-
- [ServiceRequestError: Cannot connect to host](#servicerequesterror-cannot-connect-to-host)
1211
- [ResourceNotFoundError: Playback failure](#resourcenotfounderror-playback-failure)
1312
- [Test collection failure](#test-collection-failure)
1413
- [Errors in tests using resource preparers](#errors-in-tests-using-resource-preparers)
@@ -23,6 +22,7 @@ GitHub repository, but this isn't necessary to read for Python testing.
2322
- [Test setup failure in test pipeline](#test-setup-failure-in-test-pipeline)
2423
- [Fixture not found error](#fixture-not-found-error)
2524
- [PermissionError during startup](#permissionerror-during-startup)
25+
- [ServiceRequestError: Cannot connect to host](#servicerequesterror-cannot-connect-to-host)
2626

2727
## Debugging tip
2828

@@ -40,32 +40,6 @@ containing the strings `test_delete` or `test_upload`.
4040

4141
For more information about `pytest` invocations, refer to [Usage and Invocations][pytest_commands].
4242

43-
## ServiceRequestError: Cannot connect to host
44-
45-
Tests may fail during startup with the following exception:
46-
47-
```text
48-
azure.core.exceptions.ServiceRequestError: Cannot connect to host localhost:5001
49-
ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate
50-
verify failed: self signed certificate (_ssl.c:1123)')]
51-
```
52-
53-
This is caused by the test proxy's certificate being incorrectly configured. First, update your branch to include the
54-
latest changes from `main` -- this ensures you have the latest certificate version (it needs to be occasionally
55-
rotated).
56-
57-
If tests continue to fail, this is likely due to an async-specific environment issue. The certificate is
58-
[automatically configured][cert_setup] during proxy startup, but async environments can still nondeterministically fail.
59-
60-
To work around this, set the following environment variable in your `.env` file:
61-
62-
```text
63-
PROXY_URL='http://localhost:5000'
64-
```
65-
66-
This will target an HTTP endpoint for the test proxy that doesn't require certificates. Service requests will still be
67-
sent securely from your client; this change only affects test proxy interactions.
68-
6943
## ResourceNotFoundError: Playback failure
7044

7145
Test playback errors typically raise with a message similar to the following:
@@ -459,6 +433,27 @@ Alternatively, you can delete the installed tool and re-run your tests to automa
459433
- Delete the `.proxy` folder at the root of your local `azure-sdk-for-python` clone.
460434
- Re-run your tests; the test proxy will be reinstalled and should correctly set file permissions.
461435

436+
## ServiceRequestError: Cannot connect to host
437+
438+
When [using HTTPS][proxy_https] via `PROXY_URL='https://localhost:5001'`, tests may fail during startup with the
439+
following exception:
440+
441+
```text
442+
azure.core.exceptions.ServiceRequestError: Cannot connect to host localhost:5001
443+
ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate
444+
verify failed: self signed certificate (_ssl.c:1123)')]
445+
```
446+
447+
This is caused by the test proxy's certificate being incorrectly configured. First, update your branch to include the
448+
latest changes from `main` -- this ensures you have the latest certificate version (it needs to be occasionally
449+
rotated).
450+
451+
If tests continue to fail, this is likely due to an async-specific environment issue. The certificate is
452+
[automatically configured][cert_setup] during proxy startup, but async environments can still nondeterministically fail.
453+
454+
To work around this, unset the `PROXY_URL` environment variable to default to HTTP, which doesn't require a certificate.
455+
If your tests require an HTTPS endpoint, reach out to the Azure SDK team for assistance.
456+
462457
<!-- Links -->
463458

464459
[cert_setup]: https://github.com/Azure/azure-sdk-for-python/blob/9958caf6269247f940c697a3f982bbbf0a47a19b/eng/tools/azure-sdk-tools/devtools_testutils/proxy_startup.py#L210
@@ -473,6 +468,7 @@ Alternatively, you can delete the installed tool and re-run your tests to automa
473468
[pipelines_ci]: https://github.com/Azure/azure-sdk-for-python/blob/5ba894966ed6b0e1ee8d854871f8c2da36a73d79/sdk/eventgrid/ci.yml#L30
474469
[pipelines_live]: https://github.com/Azure/azure-sdk-for-python/blob/e2b5852deaef04752c1323d2ab0958f83b98858f/sdk/textanalytics/tests.yml#L26-L27
475470
[playback_request_failure]: https://github.com/Azure/azure-sdk-for-python/blob/9958caf6269247f940c697a3f982bbbf0a47a19b/eng/tools/azure-sdk-tools/devtools_testutils/proxy_testcase.py#L102
471+
[proxy_https]: https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/tests-advanced.md#use-https-test-proxy-endpoint
476472
[py_sanitizers]: https://github.com/Azure/azure-sdk-for-python/blob/main/eng/tools/azure-sdk-tools/devtools_testutils/sanitizers.py
477473
[pytest_collection]: https://docs.pytest.org/latest/goodpractices.html#test-discovery
478474
[pytest_commands]: https://docs.pytest.org/latest/usage.html

doc/dev/tests-advanced.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ This guide covers advanced testing scenarios for Azure SDK for Python libraries.
33

44
## Table of contents
55

6-
- [Mixin classes](#test-mixin-classes)
6+
- [Mixin classes](#mixin-classes)
77
- [Pre-test setup](#pre-test-setup)
88
- [xunit-style setup](#xunit-style-setup)
99
- [Fixture setup](#fixture-setup)
10+
- [Use HTTPS test proxy endpoint](#use-https-test-proxy-endpoint)
1011

1112
## Mixin classes
1213
Many of our test suites use a base/mixin class to consolidate shared test logic. Mixin classes can define instance attributes to handle environment variables, make complex assertions, and more. By inheriting from these mixins, test classes can then share this logic throughout multiple files.
1314

14-
For example, in the Tables test suite there is a `_shared` directory containing two of these mixin classes: a [sync version](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/tables/azure-data-tables/tests/_shared/testcase.py) and an [async version](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py).
15+
For example, in the Tables test suite there is a `_shared` directory containing two of these mixin classes: a
16+
[sync version][mixin_sync] and an [async version][mixin_async].
1517

1618
```python
1719
class TableTestCase(object):
@@ -86,8 +88,7 @@ Tests will often use shared resources that make sense to set up before tests exe
8688
approaches for this kind of setup, with each having benefits and drawbacks.
8789

8890
### xunit-style setup
89-
Pytest has documentation describing this setup style: https://docs.pytest.org/en/latest/how-to/xunit_setup.html. For
90-
example:
91+
Pytest has [documentation][xunit_setup] describing this setup style. For example:
9192

9293
```python
9394
from devtools_testutils.azure_recorded_testcase import get_credential
@@ -115,8 +116,8 @@ instance attributes on the class. You can still set attributes on the test class
115116
module-level utilities can be used in place of instance attributes, as shown in the example above.
116117

117118
### Fixture setup
118-
Pytest has documentation explaining how to implement and use fixtures:
119-
https://docs.pytest.org/en/latest/how-to/fixtures.html. For example, in a library's `conftest.py`:
119+
Pytest has [documentation][fixtures] explaining how to implement and use fixtures. For example, in a library's
120+
`conftest.py`:
120121

121122
```python
122123
from devtools_testutils.azure_recorded_testcase import get_credential
@@ -141,14 +142,36 @@ class TestService(AzureRecordedTestCase):
141142
By requesting a fixture from the test class, the fixture will execute before any tests in the class do. Fixtures are the
142143
preferred solution from pytest's perspective and offer a great deal of modular functionality.
143144

144-
As shown in the example above, the
145-
[`yield`](https://docs.pytest.org/latest/how-to/fixtures.html#yield-fixtures-recommended) command will defer to test
146-
execution -- after tests finish running, the fixture code after `yield` will execute. This enables the use of a fixture
147-
for both setup and teardown.
145+
As shown in the example above, the [`yield`][fixture_yield] command will defer to test execution -- after tests finish
146+
running, the fixture code after `yield` will execute. This enables the use of a fixture for both setup and teardown.
148147

149148
However, fixtures in this context have similar drawbacks to the `setup_class` method described in
150149
[xunit-style setup](#xunit-style-setup). Since their scope is outside of the test class, test class instance utilities
151150
can't be accessed and class state can't be modified.
152151

153152
By convention, fixtures should be defined in a library's `tests/conftest.py` file. This will provide access to the
154153
fixture across test files, and the fixture can be requested without having to manually import it.
154+
155+
## Use HTTPS test proxy endpoint
156+
157+
By default, the test proxy is reached at `http://localhost:5000`. Service requests are ultimately made as usual with a
158+
secure connection, but some libraries may require that the immediate proxy endpoint uses an SSL connection.
159+
160+
In that scenario, you can set the `PROXY_URL` environment variable to target the test proxy at an HTTPS URL:
161+
162+
```text
163+
PROXY_URL='https://localhost:5001'
164+
```
165+
166+
The test proxy's certificate is [automatically configured][cert_setup] during proxy startup, though async tests may
167+
exhibit [inconsistent behavior][async_cert_troubleshoot].
168+
169+
<!-- Links -->
170+
171+
[async_cert_troubleshoot]: https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/test_proxy_troubleshooting.md#servicerequesterror-cannot-connect-to-host
172+
[cert_setup]: https://github.com/Azure/azure-sdk-for-python/blob/9958caf6269247f940c697a3f982bbbf0a47a19b/eng/tools/azure-sdk-tools/devtools_testutils/proxy_startup.py#L210
173+
[fixture_yield]: https://docs.pytest.org/latest/how-to/fixtures.html#yield-fixtures-recommended
174+
[fixtures]: https://docs.pytest.org/en/latest/how-to/fixtures.html
175+
[mixin_async]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py
176+
[mixin_sync]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/tables/azure-data-tables/tests/_shared/testcase.py
177+
[xunit_setup]: https://docs.pytest.org/en/latest/how-to/xunit_setup.html

eng/tools/azure-sdk-tools/devtools_testutils/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313

1414
ENV_LIVE_TEST = "AZURE_TEST_RUN_LIVE"
15-
PROXY_URL = os.getenv("PROXY_URL", "https://localhost:5001").rstrip("/")
15+
PROXY_URL = os.getenv("PROXY_URL", "http://localhost:5000").rstrip("/")
1616
TEST_SETTING_FILENAME = "testsettings_local.cfg"
1717

1818

0 commit comments

Comments
 (0)