Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes transform.ipynb and adds notebook testing (#3497)
Fixes a missing import statement from transform.ipynb, also, adds notebook tests. The notebook tests run in parallel and each of them in their own virtual env, ensuring that the `pip install` statements work well. This mirrors how the tests are run on devsite pipelines as well. Hopefully we can catch errors faster this way! Follow-up potentials: - run the notebooks in non-isolated virtualenv _as well_ - so that we test the "running jupyter notebook from the repo" use case too. - parallelize on the Github Action job level the notebooks - it is already taking 11 mins :( I tested treebeard (#3504) github action, and finally settled on rolling my own driver with an executor. For executor I chose papermill as it simply worked just fine with xdist. Though probably I could use treebeard (?) - not sure what the benefit would be for individual notebook execution. `jupyter nbconvert --execute` didn't seem to execute `pip installs`? But I haven't gone too deep in that direction. Fixes #2711.
- Loading branch information
Showing
7 changed files
with
164 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Copyright 2020 The Cirq Developers | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import pytest | ||
|
||
|
||
def pytest_configure(config): | ||
config.addinivalue_line("markers", "slow: mark tests as slow") | ||
|
||
|
||
def pytest_collection_modifyitems(config, items): | ||
keywordexpr = config.option.keyword | ||
markexpr = config.option.markexpr | ||
if keywordexpr or markexpr: | ||
return # let pytest handle this | ||
|
||
skip_slow_marker = pytest.mark.skip(reason='slow marker not selected') | ||
for item in items: | ||
if 'slow' in item.keywords: | ||
item.add_marker(skip_slow_marker) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# Copyright 2020 The Cirq Developers | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
import functools | ||
import glob | ||
import os | ||
import sys | ||
|
||
import pytest | ||
from filelock import FileLock | ||
|
||
from dev_tools import shell_tools | ||
from dev_tools.env_tools import create_virtual_env | ||
|
||
SKIP_NOTEBOOKS = [ | ||
# skipping vendor notebooks as we don't have auth sorted out | ||
"**/google/*.ipynb", | ||
"**/pasqal/*.ipynb", | ||
"**/aqt/*.ipynb", | ||
|
||
# skipping quantum volume notebooks as they have issues | ||
# see https://github.com/quantumlib/Cirq/issues/3501 | ||
"examples/advanced/*.ipynb", | ||
|
||
# skipping fidelity estimation due to | ||
# https://github.com/quantumlib/Cirq/issues/3502 | ||
"examples/*fidelity*" | ||
] | ||
|
||
|
||
def _tested_notebooks(): | ||
all_notebooks = set(glob.glob("**/*.ipynb", recursive=True)) | ||
skipped_notebooks = functools.reduce( | ||
lambda a, b: a.union(b), | ||
list(set(glob.glob(g, recursive=True)) for g in SKIP_NOTEBOOKS)) | ||
|
||
# sorted is important otherwise pytest-xdist will complain that | ||
# the workers have differnent parametrization: | ||
# https://github.com/pytest-dev/pytest-xdist/issues/432 | ||
return sorted( | ||
os.path.abspath(n) for n in all_notebooks.difference(skipped_notebooks)) | ||
|
||
|
||
TESTED_NOTEBOOKS = _tested_notebooks() | ||
|
||
PACKAGES = [ | ||
# for running the notebooks | ||
"papermill", | ||
"jupyter", | ||
"virtualenv-clone", | ||
# assumed to be part of colab | ||
"seaborn", | ||
] | ||
|
||
|
||
@pytest.mark.slow | ||
@pytest.fixture(scope="session") | ||
def base_env(tmp_path_factory, worker_id): | ||
# get the temp directory shared by all workers | ||
root_tmp_dir = tmp_path_factory.getbasetemp().parent.parent | ||
proto_dir = root_tmp_dir / "proto_dir" | ||
with FileLock(str(proto_dir) + ".lock"): | ||
if proto_dir.is_dir(): | ||
print(f"{worker_id} returning as {proto_dir} is a dir!") | ||
print(f"If all the notebooks are failing, the test framework might " | ||
f"have left this directory around. Try 'rm -rf {proto_dir}'") | ||
else: | ||
print(f"{worker_id} creating stuff...") | ||
create_base_env(proto_dir) | ||
|
||
return root_tmp_dir, proto_dir | ||
|
||
|
||
def create_base_env(proto_dir): | ||
create_virtual_env(str(proto_dir), [], sys.executable, True) | ||
pip_path = str(proto_dir / "bin" / "pip") | ||
shell_tools.run_cmd(pip_path, "install", *PACKAGES) | ||
|
||
|
||
@pytest.mark.slow | ||
@pytest.mark.parametrize("notebook_path", TESTED_NOTEBOOKS) | ||
def test_notebooks(notebook_path, base_env): | ||
"""Ensures testing the notebooks in isolated virtual environments.""" | ||
tmpdir, proto_dir = base_env | ||
|
||
notebook_file = os.path.basename(notebook_path) | ||
dir_name = notebook_file.rstrip(".ipynb") | ||
|
||
notebook_env = os.path.join(tmpdir, f"{dir_name}") | ||
cmd = f""" | ||
{proto_dir}/bin/virtualenv-clone {proto_dir} {notebook_env} | ||
cd {notebook_env} | ||
. ./bin/activate | ||
papermill {notebook_path}""" | ||
stdout, stderr, status = shell_tools.run_shell(cmd=cmd, | ||
log_run_to_stderr=False, | ||
raise_on_fail=False, | ||
out=shell_tools.TeeCapture(), | ||
err=shell_tools.TeeCapture()) | ||
|
||
if status != 0: | ||
print(stdout) | ||
print(stderr) | ||
pytest.fail(f"Notebook failure: {notebook_file}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters