Skip to content

Commit 45c4ca3

Browse files
authored
Run tests with pytest, not bash (#216)
1 parent 4af1efa commit 45c4ca3

File tree

4 files changed

+58
-30
lines changed

4 files changed

+58
-30
lines changed

.circleci/config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ jobs:
2525
name: Run Pytorch scripts
2626
command: ./scripts/run_pytorch.sh
2727
no_output_timeout: 1h
28+
- store_test_results:
29+
path: test-results
30+
2831

2932
workflows:
3033
version: 2

scripts/install.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ conda activate base
66

77
conda install -y pytorch torchvision torchaudio -c pytorch-nightly
88

9+
conda install -y pytest
10+
911
# Dependencies required to load models
1012
conda install -y regex pillow tqdm boto3 requests numpy\
1113
h5py scipy matplotlib unidecode ipython pyyaml

scripts/run_pytorch.sh

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,20 @@
22
. ~/miniconda3/etc/profile.d/conda.sh
33
conda activate base
44

5-
ALL_FILE=$(find *.md ! -name README.md)
6-
TEMP_PY="temp.py"
7-
CUDAS="nvidia"
5+
ALL_FILES=$(find *.md ! -name README.md)
6+
PYTHON_CODE_DIR="python_code"
87

9-
declare -i error_code=0
8+
mkdir $PYTHON_CODE_DIR
109

11-
for f in $ALL_FILE
10+
# Quick rundown: for each file we extract the python code that's within
11+
# the ``` markers and we put that code in a corresponding .py file in $PYTHON_CODE_DIR
12+
# Then we execute each of these python files with pytest in test_run_python_code.py
13+
for f in $ALL_FILES
1214
do
13-
echo "Running pytorch example in $f"
14-
# FIXME: NVIDIA models checkoints are on cuda
15-
if [[ $f = $CUDAS* ]]; then
16-
echo "...skipped due to cuda checkpoints."
17-
elif [[ $f = "pytorch_fairseq_translation"* ]]; then
18-
echo "...temporarily disabled"
19-
# FIXME: torch.nn.modules.module.ModuleAttributeError: 'autoShape' object has no attribute 'fuse'
20-
elif [[ $f = "ultralytics_yolov5"* ]]; then
21-
echo "...temporarily disabled"
22-
elif [[ $f = "huggingface_pytorch-transformers"* ]]; then
23-
echo "...temporarily disabled"
24-
# FIXME: TypeError: compose() got an unexpected keyword argument 'strict'
25-
elif [[ $f = "pytorch_fairseq_roberta"* ]]; then
26-
echo "...temporarily disabled"
27-
# FIXME: rate limiting
28-
else
29-
sed -n '/^```python/,/^```/ p' < $f | sed '/^```/ d' > $TEMP_PY
30-
python $TEMP_PY
31-
error_code+=$?
32-
33-
if [ -f "$TEMP_PY" ]; then
34-
rm $TEMP_PY
35-
fi
36-
fi
15+
f_no_ext=${f%.md} # remove .md extension
16+
out_py=$PYTHON_CODE_DIR/$f_no_ext.py
17+
echo "Extracting Python code from $f into $out_py"
18+
sed -n '/^```python/,/^```/ p' < $f | sed '/^```/ d' > $out_py
3719
done
3820

39-
exit $error_code
21+
pytest --junitxml=test-results/junit.xml test_run_python_code.py -vv

test_run_python_code.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from subprocess import check_output, STDOUT, CalledProcessError
2+
import sys
3+
import pytest
4+
import glob
5+
6+
7+
PYTHON_CODE_DIR = "python_code"
8+
ALL_FILES = glob.glob(PYTHON_CODE_DIR + "/*.py")
9+
10+
11+
@pytest.mark.parametrize('file_path', ALL_FILES)
12+
def test_run_file(file_path):
13+
if 'nvidia' in file_path:
14+
# FIXME: NVIDIA models checkoints are on cuda
15+
pytest.skip("temporarily disabled")
16+
if 'pytorch_fairseq_translation' in file_path:
17+
pytest.skip("temporarily disabled")
18+
if 'ultralytics_yolov5' in file_path:
19+
# FIXME torch.nn.modules.module.ModuleAttributeError: 'autoShape' object has no attribute 'fuse
20+
pytest.skip("temporarily disabled")
21+
if 'huggingface_pytorch-transformers' in file_path:
22+
# FIXME torch.nn.modules.module.ModuleAttributeError: 'autoShape' object has no attribute 'fuse
23+
pytest.skip("temporarily disabled")
24+
if 'pytorch_fairseq_roberta' in file_path:
25+
pytest.skip("temporarily disabled")
26+
27+
# We just run the python files in a separate sub-process. We really want a
28+
# subprocess here because otherwise we might run into package versions
29+
# issues: imagine script A that needs torchvivion 0.9 and script B that
30+
# needs torchvision 0.10. If script A is run prior to script B in the same
31+
# process, script B will still be run with torchvision 0.9 because the only
32+
# "import torchvision" statement that counts is the first one, and even
33+
# torchub sys.path shenanigans can do nothing about this. By creating
34+
# subprocesses we're sure that all file executions are fully independent.
35+
try:
36+
# This is inspired (and heavily simplified) from
37+
# https://github.com/cloudpipe/cloudpickle/blob/343da119685f622da2d1658ef7b3e2516a01817f/tests/testutils.py#L177
38+
out = check_output([sys.executable, file_path], stderr=STDOUT)
39+
print(out.decode())
40+
except CalledProcessError as e:
41+
raise RuntimeError(f"Script {file_path} errored with output:\n{e.output.decode()}")

0 commit comments

Comments
 (0)