Skip to content

Commit 399f1c5

Browse files
Merge pull request #1989 from recommenders-team/miguel/new_test_categories
Refactor tests into new categories reviewed by Eric Gamma
2 parents caee313 + 0d17767 commit 399f1c5

File tree

77 files changed

+1135
-1261
lines changed

Some content is hidden

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

77 files changed

+1135
-1261
lines changed

.github/actions/get-test-groups/action.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ runs:
2929
if [[ ${{ inputs.TEST_KIND }} == "nightly" ]]; then
3030
test_groups_str=$(python -c 'from tests.ci.azureml_tests.test_groups import nightly_test_groups; print([t for t in nightly_test_groups.keys() if "${{inputs.TEST_ENV}}" in t])')
3131
else
32-
test_groups_str=$(python -c 'from tests.ci.azureml_tests.test_groups import unit_test_groups; print(list(unit_test_groups.keys()))')
32+
test_groups_str=$(python -c 'from tests.ci.azureml_tests.test_groups import pr_gate_test_groups; print(list(pr_gate_test_groups.keys()))')
3333
fi
3434
echo "test_groups=$test_groups_str" >> $GITHUB_OUTPUT

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,13 @@ This project adheres to [Microsoft's Open Source Code of Conduct](CODE_OF_CONDUC
135135

136136
## Build Status
137137

138-
These tests are the nightly builds, which compute the smoke and integration tests. `main` is our principal branch and `staging` is our development branch. We use [pytest](https://docs.pytest.org/) for testing python utilities in [recommenders](recommenders) and [Papermill](https://github.com/nteract/papermill) and [Scrapbook](https://nteract-scrapbook.readthedocs.io/en/latest/) for the [notebooks](examples).
138+
These tests are the nightly builds, which compute the asynchronous tests. `main` is our principal branch and `staging` is our development branch. We use [pytest](https://docs.pytest.org/) for testing python utilities in [recommenders](recommenders) and [Papermill](https://github.com/nteract/papermill) and [Scrapbook](https://nteract-scrapbook.readthedocs.io/en/latest/) for the [notebooks](examples).
139139

140140
For more information about the testing pipelines, please see the [test documentation](tests/README.md).
141141

142142
### AzureML Nightly Build Status
143143

144-
Smoke and integration tests are run daily on AzureML.
144+
The nightly build tests are run daily on AzureML.
145145

146146
| Build Type | Branch | Status | | Branch | Status |
147147
| --- | --- | --- | --- | --- | --- |

SETUP.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,9 @@ First make sure that the tag that you want to add, e.g. `0.6.0`, is added in [`r
156156
1. Make sure that the code in main passes all the tests (unit and nightly tests).
157157
1. Create a tag with the version number: e.g. `git tag -a 0.6.0 -m "Recommenders 0.6.0"`.
158158
1. Push the tag to the remote server: `git push origin 0.6.0`.
159-
1. When the new tag is pushed, a release pipeline is executed. This pipeline runs all the tests again (unit, smoke and integration), generates a wheel and a tar.gz which are uploaded to a [GitHub draft release](https://github.com/microsoft/recommenders/releases).
159+
1. When the new tag is pushed, a release pipeline is executed. This pipeline runs all the tests again (PR gate and nightly builds), generates a wheel and a tar.gz which are uploaded to a [GitHub draft release](https://github.com/microsoft/recommenders/releases).
160160
1. Fill up the draft release with all the recent changes in the code.
161161
1. Download the wheel and tar.gz locally, these files shouldn't have any bug, since they passed all the tests.
162162
1. Install twine: `pip install twine`
163-
1. Publish the wheel and tar.gz to pypi: `twine upload recommenders*`
163+
1. Publish the wheel and tar.gz to PyPI: `twine upload recommenders*`
164164

pyproject.toml

-3
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ build-backend = "setuptools.build_meta"
1414
[tool.pytest.ini_options]
1515
markers = [
1616
"experimental: tests that will not be executed and may need extra dependencies",
17-
"flaky: flaky tests that can fail unexpectedly",
1817
"gpu: tests running on GPU",
19-
"integration: integration tests",
2018
"notebooks: tests for notebooks",
21-
"smoke: smoke tests",
2219
"spark: tests that requires Spark",
2320
]

recommenders/utils/gpu_utils.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def get_cuda_version():
9797
data = f.read().replace("\n", "")
9898
return data
9999
else:
100-
return "Cannot find CUDA in this machine"
100+
return None
101101

102102

103103
def get_cudnn_version():
@@ -125,14 +125,14 @@ def find_cudnn_in_headers(candiates):
125125
if version:
126126
return version
127127
else:
128-
return "Cannot find CUDNN version"
128+
return None
129129
else:
130-
return "Cannot find CUDNN version"
130+
return None
131131

132132
try:
133133
import torch
134134

135-
return torch.backends.cudnn.version()
135+
return str(torch.backends.cudnn.version())
136136
except (ImportError, ModuleNotFoundError):
137137
if sys.platform == "win32":
138138
candidates = [r"C:\NVIDIA\cuda\include\cudnn.h"]

setup.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"transformers>=2.5.0,<5",
4343
"category_encoders>=1.3.0,<2",
4444
"jinja2>=2,<3.1",
45-
"requests>=2.0.0,<3",
45+
"requests>=2.31.0,<3",
4646
"cornac>=1.1.2,<1.15.2;python_version<='3.7'",
4747
"cornac>=1.15.2,<2;python_version>='3.8'", # After 1.15.2, Cornac requires python 3.8
4848
"retrying>=1.3.3",
@@ -64,7 +64,7 @@
6464
"tensorflow~=2.6.1;python_version=='3.6'",
6565
"tensorflow~=2.7.0;python_version>='3.7'",
6666
"tf-slim>=1.1.0",
67-
"torch>=1.8", # for CUDA 11 support
67+
"torch>=1.13.1", # for CUDA 11 support
6868
"fastai>=1.0.46,<2",
6969
],
7070
"spark": [
@@ -89,6 +89,7 @@
8989
"vowpalwabbit>=8.9.0,<9",
9090
# nni needs to be upgraded
9191
"nni==1.5",
92+
"pymanopt>=0.2.5",
9293
]
9394

9495
# The following dependency can be installed as below, however PyPI does not allow direct URLs.

tests/README.md

+28-115
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ In this section we show how to create tests and add them to the test pipeline. T
6363
1. Create your code in the library and/or notebooks.
6464
1. Design the unit tests for the code.
6565
1. If you have written a notebook, design the notebook tests and check that the metrics they return is what you expect.
66-
1. Add the tests to the AzureML pipeline in the corresponding [test group](./ci/azureml_tests/test_groups.py). **Please note that if you don't add your tests to the pipeline, they will not be executed.**
66+
1. Add the tests to the AzureML pipeline in the corresponding [test group](./ci/azureml_tests/test_groups.py).
67+
68+
**Please note that if you don't add your tests to the pipeline, they will not be executed.**
6769

6870
### How to create tests for the Recommenders library
6971

@@ -74,8 +76,6 @@ You want to make sure that all your code works before you submit it to the repos
7476
* Use the mark `@pytest.mark.gpu` if you want the test to be executed
7577
in a GPU environment. Use `@pytest.mark.spark` if you want the test
7678
to be executed in a Spark environment.
77-
* Use `@pytest.mark.smoke` and `@pytest.mark.integration` to mark the
78-
tests as smoke tests and integration tests.
7979
* Use `@pytest.mark.notebooks` if you are testing a notebook.
8080
* Avoid using `is` in the asserts, instead use the operator `==`.
8181
* Follow the pattern `assert computation == value`, for example:
@@ -113,7 +113,7 @@ For executing this test, first make sure you are in the correct environment as d
113113
*Notice that the next instruction executes the tests from the root folder.*
114114

115115
```bash
116-
pytest tests/unit/test_notebooks_python.py::test_sar_single_node_runs
116+
pytest tests/unit/examples/test_notebooks_python.py::test_sar_single_node_runs
117117
```
118118

119119
#### Developing nightly tests with Papermill and Scrapbook
@@ -124,7 +124,7 @@ The first step is to tag the parameters that we are going to inject. For it we n
124124

125125
The way papermill works to inject parameters is very simple, it generates a copy of the notebook (in our code we call it `OUTPUT_NOTEBOOK`), and creates a new cell with the injected variables.
126126

127-
The second modification that we need to do to the notebook is to record the metrics we want to test using `sb.glue("output_variable", python_variable_name)`. We normally use the last cell of the notebook to record all the metrics. These are the metrics that we are going to control in the smoke and integration tests.
127+
The second modification that we need to do to the notebook is to record the metrics we want to test using `sb.glue("output_variable", python_variable_name)`. We normally use the last cell of the notebook to record all the metrics. These are the metrics that we are going to control in the smoke and functional tests.
128128

129129
This is an example on how we do a smoke test. The complete code can be found in [smoke/examples/test_notebooks_python.py](./smoke/examples/test_notebooks_python.py):
130130

@@ -136,7 +136,6 @@ import scrapbook as sb
136136
TOL = 0.05
137137
ABS_TOL = 0.05
138138

139-
@pytest.mark.smoke
140139
def test_sar_single_node_smoke(notebooks, output_notebook, kernel_name):
141140
notebook_path = notebooks["sar_single_node"]
142141
pm.execute_notebook(
@@ -159,14 +158,14 @@ For executing this test, first make sure you are in the correct environment as d
159158
*Notice that the next instructions execute the tests from the root folder.*
160159

161160
```
162-
pytest tests/smoke/test_notebooks_python.py::test_sar_single_node_smoke
161+
pytest tests/smoke/examples/test_notebooks_python.py::test_sar_single_node_smoke
163162
```
164163

165164
More details on how to integrate Papermill with notebooks can be found in their [repo](https://github.com/nteract/papermill). Also, you can check the [Scrapbook repo](https://github.com/nteract/scrapbook).
166165

167166
### How to add tests to the AzureML pipeline
168167

169-
To add a new test to the AzureML pipeline, add the test path to an appropriate test group listed in [test_groups.py](https://github.com/microsoft/recommenders/blob/main/tests/ci/azureml_tests/test_groups.py).
168+
To add a new test to the AzureML pipeline, add the test path to an appropriate test group listed in [test_groups.py](./ci/azureml_tests/test_groups.py).
170169

171170
Tests in `group_cpu_xxx` groups are executed on a CPU-only AzureML compute cluster node. Tests in `group_gpu_xxx` groups are executed on a GPU-enabled AzureML compute cluster node with GPU related dependencies added to the AzureML run environment. Tests in `group_pyspark_xxx` groups are executed on a CPU-only AzureML compute cluster node, with the PySpark related dependencies added to the AzureML run environment.
172171

@@ -177,15 +176,13 @@ Example of adding a new test:
177176
1. In the environment that you are running your code, first see if there is a group whose total runtime is less than the threshold.
178177
```python
179178
"group_spark_001": [ # Total group time: 271.13s
180-
"tests/smoke/recommenders/dataset/test_movielens.py::test_load_spark_df", # 4.33s
181-
"tests/integration/recommenders/datasets/test_movielens.py::test_load_spark_df", # 25.58s + 101.99s + 139.23s
179+
"tests/data_validation/recommenders/datasets/test_movielens.py::test_load_spark_df", # 4.33s+ 25.58s + 101.99s + 139.23s
182180
],
183181
```
184182
2. Add the test to the group, add the time it takes to compute, and update the total group time.
185183
```python
186184
"group_spark_001": [ # Total group time: 571.13s
187-
"tests/smoke/recommenders/dataset/test_movielens.py::test_load_spark_df", # 4.33s
188-
"tests/integration/recommenders/datasets/test_movielens.py::test_load_spark_df", # 25.58s + 101.99s + 139.23s
185+
"tests/data_validation/recommenders/datasets/test_movielens.py::test_load_spark_df", # 4.33s+ 25.58s + 101.99s + 139.23s
189186
#
190187
"tests/path/to/test_new.py::test_new_function", # 300s
191188
],
@@ -217,133 +214,50 @@ Then, follow the steps below to create the AzureML infrastructure:
217214

218215
To manually execute the tests in the CPU, GPU or Spark environments, first **make sure you are in the correct environment as described in the [SETUP.md](../SETUP.md)**.
219216

220-
*Click on the following menus* to see more details on how to execute the unit, smoke and integration tests:
221-
222-
<details>
223-
<summary><strong><em>Unit tests</em></strong></summary>
224-
225-
Unit tests ensure that each class or function behaves as it should. Every time a developer makes a pull request to staging or main branch, a battery of unit tests is executed.
226-
227-
*Note that the next instructions execute the tests from the root folder.*
228-
229-
For executing the Python unit tests for the utilities:
230-
231-
pytest tests/unit -m "not notebooks and not spark and not gpu" --durations 0
232-
233-
For executing the Python unit tests for the notebooks:
234-
235-
pytest tests/unit -m "notebooks and not spark and not gpu" --durations 0
236-
237-
For executing the Python GPU unit tests for the utilities:
238-
239-
pytest tests/unit -m "not notebooks and not spark and gpu" --durations 0
240-
241-
For executing the Python GPU unit tests for the notebooks:
242-
243-
pytest tests/unit -m "notebooks and not spark and gpu" --durations 0
244-
245-
For executing the PySpark unit tests for the utilities:
246-
247-
pytest tests/unit -m "not notebooks and spark and not gpu" --durations 0
248-
249-
For executing the PySpark unit tests for the notebooks:
250-
251-
pytest tests/unit -m "notebooks and spark and not gpu" --durations 0
252-
253-
*NOTE: Adding `--durations 0` shows the computation time of all tests.*
254-
255-
*NOTE: Adding `--disable-warnings` will disable the warning messages.*
256-
257-
</details>
258-
259-
<details>
260-
<summary><strong><em>Smoke tests</em></strong></summary>
261-
262-
Smoke tests make sure that the system works and are executed just before the integration tests every night.
217+
### CPU tests
263218

264219
*Note that the next instructions execute the tests from the root folder.*
265220

266-
For executing the Python smoke tests:
221+
For executing the CPU tests for the utilities:
267222

268-
pytest tests/smoke -m "smoke and not spark and not gpu" --durations 0
223+
pytest tests -m "not notebooks and not spark and not gpu" --durations 0 --disable-warnings
269224

270-
For executing the Python GPU smoke tests:
225+
For executing the CPU tests for the notebooks:
271226

272-
pytest tests/smoke -m "smoke and not spark and gpu" --durations 0
227+
pytest tests -m "notebooks and not spark and not gpu" --durations 0 --disable-warnings
273228

274-
For executing the PySpark smoke tests:
229+
If you want to execute a specific test, you can use the following command:
275230

276-
pytest tests/smoke -m "smoke and spark and not gpu" --durations 0
231+
pytest tests/data_validation/recommenders/datasets/test_mind.py::test_mind_url --durations 0 --disable-warnings
277232

278-
*NOTE: Adding `--durations 0` shows the computation time of all tests.*
233+
If you want to execute any of the tests types (data_validation, unit, smoke, functional, etc.) you can use the following command:
279234

280-
*NOTE: Adding `--disable-warnings` will disable the warning messages.*
235+
pytest tests/data_validation -m "not notebooks and not spark and not gpu" --durations 0 --disable-warnings
281236

282-
</details>
237+
### GPU tests
283238

284-
<details>
285-
<summary><strong><em>Integration tests</em></strong></summary>
239+
For executing the GPU tests for the utilities:
286240

287-
Integration tests make sure that the program results are acceptable.
241+
pytest tests -m "not notebooks and not spark and gpu" --durations 0 --disable-warnings
288242

289-
*Note that the next instructions execute the tests from the root folder.*
243+
For executing the GPU tests for the notebooks:
290244

291-
For executing the Python integration tests:
245+
pytest tests -m "notebooks and not spark and gpu" --durations 0 --disable-warnings
292246

293-
pytest tests/integration -m "integration and not spark and not gpu" --durations 0
247+
### Spark tests
294248

295-
For executing the Python GPU integration tests:
249+
For executing the PySpark tests for the utilities:
296250

297-
pytest tests/integration -m "integration and not spark and gpu" --durations 0
251+
pytest tests -m "not notebooks and spark and not gpu" --durations 0 --disable-warnings
298252

299-
For executing the PySpark integration tests:
253+
For executing the PySpark tests for the notebooks:
300254

301-
pytest tests/integration -m "integration and spark and not gpu" --durations 0
255+
pytest tests -m "notebooks and spark and not gpu" --durations 0 --disable-warnings
302256

303257
*NOTE: Adding `--durations 0` shows the computation time of all tests.*
304258

305259
*NOTE: Adding `--disable-warnings` will disable the warning messages.*
306260

307-
</details>
308-
309-
<details>
310-
<summary><strong><em>Current Skipped Tests</em></strong></summary>
311-
312-
Several of the tests are skipped for various reasons which are noted below.
313-
314-
<table>
315-
<tr>
316-
<td>Test Module</td>
317-
<td>Test</td>
318-
<td>Test Environment</td>
319-
<td>Reason</td>
320-
</tr>
321-
<tr>
322-
<td>unit/recommenders/datasets/test_wikidata</td>
323-
<td>*</td>
324-
<td>Linux</td>
325-
<td>Wikidata API is unstable</td>
326-
</tr>
327-
<tr>
328-
<td>integration/recommenders/datasets/test_notebooks_python</td>
329-
<td>test_wikidata</td>
330-
<td>Linux</td>
331-
<td>Wikidata API is unstable</td>
332-
</tr>
333-
<tr>
334-
<td>*/test_notebooks_python</td>
335-
<td>test_vw*</td>
336-
<td>Linux</td>
337-
<td>VW pip package has installation incompatibilities</td>
338-
</tr>
339-
<tr>
340-
<td>*/test_notebooks_python</td>
341-
<td>test_nni*</td>
342-
<td>Linux</td>
343-
<td>NNI pip package has installation incompatibilities</td>
344-
</tr>
345-
</table>
346-
347261
In order to skip a test because there is an OS or upstream issue which cannot be resolved you can use pytest [annotations](https://docs.pytest.org/en/latest/skipping.html).
348262

349263
Example:
@@ -353,4 +267,3 @@ Example:
353267
def test_to_skip():
354268
assert False
355269

356-
</details>

tests/ci/azureml_tests/run_groupwise_pytest.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import argparse
1414
import glob
1515
from azureml.core import Run
16-
from test_groups import nightly_test_groups, unit_test_groups
16+
from test_groups import nightly_test_groups, pr_gate_test_groups
1717

1818
if __name__ == "__main__":
1919

@@ -46,7 +46,7 @@
4646
if args.testkind == "nightly":
4747
test_group = nightly_test_groups[args.testgroup]
4848
else:
49-
test_group = unit_test_groups[args.testgroup]
49+
test_group = pr_gate_test_groups[args.testgroup]
5050

5151
logger.info("Tests to be executed")
5252
logger.info(str(test_group))

0 commit comments

Comments
 (0)