Skip to content

Commit

Permalink
Merge pull request #669 from odlgroup/distribute_tests
Browse files Browse the repository at this point in the history
Distribute tests
  • Loading branch information
Holger Kohr authored Oct 24, 2016
2 parents d445705 + 9f05097 commit 9054a0f
Show file tree
Hide file tree
Showing 16 changed files with 130 additions and 63 deletions.
12 changes: 9 additions & 3 deletions .pypirc
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
[distutils]
index-servers=pypi
index-servers=
pypi
pypitest

[pypi]
repository = https://pypi.python.org/pypi
username = kohr-h
repository = https://upload.pypi.org/legacy
username = odlgroup

[pypitest]
repository = https://test.pypi.org/legacy
username = kohr-h
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ before_script:

script:
# Run tests, including PEP8 check, and produce a coverage report
- py.test --doctest-modules --cov --cov-report term-missing --pep8
- py.test --doctest-modules --cov --cov-report term-missing --pep8 $TRAVIS_BUILD_DIR/odl
# Build the Sphinx doc (only for Python 3.5 and the master branch)
- if [[ "$TRAVIS_PYTHON_VERSION" == "3.5" && "$TRAVIS_BRANCH" == "master" ]]; then
cd $TRAVIS_BUILD_DIR/doc/source && python generate_doc.py && cd -;
Expand Down
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ include requirements.txt
include setup.cfg
include setup.py
include test_requirements.txt
include odl/pytest.ini
exclude pytest.ini
recursive-include odl/test test*.py *test.py
8 changes: 5 additions & 3 deletions conda/meta.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package:
name: odl
version: "0.5.0"
version: "0.5.1"

source:
git_url: https://github.com/odlgroup/odl
git_rev: master # for testing, put any branch here
# git_rev: v0.5.0 # release
# git_rev: master # for testing, put any branch here
git_rev: v0.5.1 # release

build:
noarch_python: True
Expand All @@ -30,6 +30,8 @@ requirements:
test:
imports:
- odl
commands:
- python -c "import odl; odl.test()"

about:
home: https://github.com/odlgroup/odl
Expand Down
6 changes: 3 additions & 3 deletions doc/source/getting_started/installing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ After that, follow the `build instructions there <https://github.com/odlgroup/od

ASTRA for X-ray tomography
==========================
To calculate fast forward and backward projections for image reconstruction in X-ray tomography, install the `ASTRA tomography toolbox`_.
To calculate fast forward and backward projections for image reconstruction in X-ray tomography, install the `ASTRA tomography toolbox <https://github.com/astra-toolbox/astra-toolbox>`_.
ASTRA projectors are fully supported in ODL.

You can try using the conda package, but we can give no guarantee that it works out of the box:
Expand All @@ -417,7 +417,7 @@ You can try using the conda package, but we can give no guarantee that it works
$ conda install -c astra-toolbox astra-toolbox
For further instructions, check `the ASTRA GitHub page <ASTRA tomography toolbox>`_.
For further instructions, check `the ASTRA GitHub page <https://github.com/astra-toolbox/astra-toolbox>`_.


STIR for emission tomography
Expand Down Expand Up @@ -467,5 +467,5 @@ If that does not help, `make an issue on GitHub <https://github.com/odlgroup/odl
.. _CVXPY: http://www.cvxpy.org/en/latest/
.. _odlcuda: https://github.com/odlgroup/odlcuda
.. _CUDA toolkit: https://developer.nvidia.com/cuda-toolkit
.. _ASTRA tomography toolbox: https://github.com/astra-toolbox/astra-toolbox
.. _ASTRA: https://github.com/astra-toolbox/astra-toolbox
.. _STIR: https://github.com/UCL/STIR
6 changes: 6 additions & 0 deletions doc/source/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ Release Notes
Next release
============

ODL 0.5.1 Release Notes (2016-10-22)
====================================

This is a maintenance release since the test suite was not bundled with PyPI and Conda packages as intended already in 0.5.0.
From this version on, users can run ``python -c "import odl; odl.test()"`` with all types of installations (from PyPI, Conda or from source).


ODL 0.5.0 Release Notes (2016-10-21)
====================================
Expand Down
2 changes: 1 addition & 1 deletion odl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

from __future__ import absolute_import

__version__ = '0.5.0'
__version__ = '0.5.1'
__all__ = ('diagnostics', 'discr', 'operator', 'set', 'space', 'solvers',
'tomo', 'trafos', 'util', 'phantom', 'deform')

Expand Down
File renamed without changes.
13 changes: 10 additions & 3 deletions odl/test/test_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
from doctest import IGNORE_EXCEPTION_DETAIL, ELLIPSIS, NORMALIZE_WHITESPACE
import os
import pytest
try:
import matplotlib
matplotlib.use('Agg') # To avoid the backend freezing
import matplotlib.pyplot as plt
except ImportError:
pass

# Modules to be added to testing globals
import numpy
Expand Down Expand Up @@ -69,13 +75,14 @@ def doc_src_file(request):
return request.param


@pytest.mark.skipif("not pytest.config.getoption('--documentation')",
reason='Need --documentation option to run')
@pytest.mark.skipif("not pytest.config.getoption('--doctest-doc')",
reason='Need --doctest-doc option to run')
def test_file(doc_src_file):
doctest.testfile(doc_src_file, module_relative=False, report=True,
extraglobs=doctest_extraglobs, verbose=True,
optionflags=doctest_optionflags)
plt.close('all')


if __name__ == '__main__':
pytest.main([str(__file__.replace('\\', '/')), '-v', '--documentation'])
pytest.main([str(__file__.replace('\\', '/')), '-v', '--doctest-doc'])
2 changes: 1 addition & 1 deletion odl/test/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def example(request):
reason='Need --examples option to run')
def test_example(example):
imp.load_source('tmp', example)
plt.close("all")
plt.close('all')


if __name__ == '__main__':
Expand Down
3 changes: 3 additions & 0 deletions odl/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@
from .numerics import *
__all__ += numerics.__all__

from .vectorization import *
__all__ += vectorization.__all__

from . import ufuncs
47 changes: 29 additions & 18 deletions conftest.py → odl/util/pytest_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,26 @@

import numpy as np
import operator
import pytest
import os

import odl
from odl.trafos.backends import PYFFTW_AVAILABLE, PYWT_AVAILABLE
from odl.util import dtype_repr
from odl.util import dtype_repr, OptionalArgDecorator

try:
from pytest import fixture
except ImportError:
# Make trivial decorator
class fixture(OptionalArgDecorator):
@staticmethod
def _wrapper(f, *a, **kw):
return f


# --- Add numpy and ODL to all doctests ---


@pytest.fixture(autouse=True)
@fixture(autouse=True)
def add_doctest_np_odl(doctest_namespace):
doctest_namespace['np'] = np
doctest_namespace['odl'] = odl
Expand All @@ -42,14 +51,19 @@ def add_doctest_np_odl(doctest_namespace):
# --- Files to be ignored by the tests ---


collect_ignore = ['setup.py']
this_dir = os.path.dirname(__file__)
odl_root = os.path.abspath(os.path.join(this_dir, os.pardir, os.pardir))
collect_ignore = [os.path.join(odl_root, 'setup.py')]

if not PYFFTW_AVAILABLE:
collect_ignore.append('odl/trafos/backends/pyfftw_bindings.py')
collect_ignore.append(
os.path.join(odl_root, 'odl/trafos/backends/pyfftw_bindings.py'))
if not PYWT_AVAILABLE:
collect_ignore.append('odl/trafos/backends/pywt_bindings.py')
collect_ignore.append(
os.path.join(odl_root, 'odl/trafos/backends/pywt_bindings.py'))
# Currently `pywt` is the only implementation
collect_ignore.append('odl/trafos/wavelet.py')
collect_ignore.append(
os.path.join(odl_root, 'odl/trafos/wavelet.py'))


def pytest_addoption(parser):
Expand All @@ -62,7 +76,7 @@ def pytest_addoption(parser):
parser.addoption('--examples', action='store_true',
help='Run examples')

parser.addoption('--documentation', action='store_true',
parser.addoption('--doctest-doc', action='store_true',
help='Run doctests in the documentation')


Expand All @@ -71,7 +85,7 @@ def pytest_addoption(parser):
fn_impl_ids = [" impl='{}' ".format(p) for p in fn_impl_params]


@pytest.fixture(scope="module", ids=fn_impl_ids, params=fn_impl_params)
@fixture(scope="module", ids=fn_impl_ids, params=fn_impl_params)
def fn_impl(request):
"""String with an available `FnBase` implementation name."""
return request.param
Expand All @@ -80,8 +94,7 @@ def fn_impl(request):
ntuples_impl_ids = [" impl='{}' ".format(p) for p in ntuples_impl_params]


@pytest.fixture(scope="module", ids=ntuples_impl_ids,
params=ntuples_impl_params)
@fixture(scope="module", ids=ntuples_impl_ids, params=ntuples_impl_params)
def ntuples_impl(request):
"""String with an available `NtuplesBase` implementation name."""
return request.param
Expand All @@ -92,8 +105,7 @@ def ntuples_impl(request):
for dt in floating_dtype_params]


@pytest.fixture(scope="module", ids=floating_dtype_ids,
params=floating_dtype_params)
@fixture(scope="module", ids=floating_dtype_ids, params=floating_dtype_params)
def floating_dtype(request):
"""Floating point (real or complex) dtype."""
return request.param
Expand All @@ -106,8 +118,7 @@ def floating_dtype(request):
for dt in scalar_dtype_params]


@pytest.fixture(scope="module", ids=scalar_dtype_ids,
params=scalar_dtype_params)
@fixture(scope="module", ids=scalar_dtype_ids, params=scalar_dtype_params)
def scalar_dtype(request):
"""Scalar (integers or real or complex) dtype."""
return request.param
Expand All @@ -117,7 +128,7 @@ def scalar_dtype(request):
ufunc_ids = [' ufunc={} '.format(p[0]) for p in ufunc_params]


@pytest.fixture(scope="module", ids=ufunc_ids, params=ufunc_params)
@fixture(scope="module", ids=ufunc_ids, params=ufunc_params)
def ufunc(request):
"""Tuple with information on a ufunc.
Expand All @@ -139,7 +150,7 @@ def ufunc(request):
reduction_ids = [' reduction={} '.format(p[0]) for p in reduction_params]


@pytest.fixture(scope="module", ids=reduction_ids, params=reduction_params)
@fixture(scope="module", ids=reduction_ids, params=reduction_params)
def reduction(request):
"""Tuple with information on a reduction.
Expand All @@ -164,7 +175,7 @@ def reduction(request):
' += ', ' /= ', ' *= ', ' -= ']


@pytest.fixture(ids=arithmetic_op_ids, params=arithmetic_op_par)
@fixture(ids=arithmetic_op_ids, params=arithmetic_op_par)
def arithmetic_op(request):
"""An arithmetic operator, e.g. +, -, // etc."""
return request.param
15 changes: 10 additions & 5 deletions odl/util/testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,13 +589,18 @@ def test(arguments=None):
'\nRun `$ pip install [--user] odl[testing]` in '
'order to install `pytest`.')

from .pytest_plugins import collect_ignore

this_dir = os.path.dirname(__file__)
odl_root = os.path.abspath(os.path.join(this_dir, os.pardir, os.pardir))
base_args = ['-x', '{root}/odl'.format(root=odl_root)]
if arguments is None:
args = base_args
else:
args = base_args + list(arguments)

args = ['-x', '{root}/odl'.format(root=odl_root)]

ignores = ['--ignore={}'.format(file) for file in collect_ignore]
args.extend(ignores)

if arguments is not None:
args.extend(arguments)

pytest.main(args)

Expand Down
3 changes: 2 additions & 1 deletion odl/util/vectorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@


__all__ = ('is_valid_input_array', 'is_valid_input_meshgrid',
'out_shape_from_meshgrid', 'out_shape_from_array', 'vectorize')
'out_shape_from_meshgrid', 'out_shape_from_array',
'OptionalArgDecorator', 'vectorize')


def is_valid_input_array(x, ndim=None):
Expand Down
41 changes: 28 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,12 @@
import sys


if os.environ.get('READTHEDOCS', None) == 'True':
# Mock requires in conf.py
requires = ''
test_requires = []
else:
requires = open(
os.path.join(os.path.dirname(__file__),
'requirements.txt')).readlines()
test_requires = open(
os.path.join(os.path.dirname(__file__),
'test_requirements.txt')).readlines()
root_path = os.path.dirname(__file__)


requires = open(os.path.join(root_path, 'requirements.txt')).readlines()
test_requires = open(
os.path.join(root_path, 'test_requirements.txt')).readlines()


class PyTest(TestCommand):
Expand All @@ -61,6 +56,23 @@ def run_tests(self):
errno = pytest.main(self.pytest_args)
sys.exit(errno)


test_path = os.path.join(root_path, 'odl', 'test')


def find_tests():
tests = []
for path, _, filenames in os.walk(os.path.join(root_path, test_path)):
for filename in filenames:
basename, suffix = os.path.splitext(filename)
if (suffix == '.py' and
(basename.startswith('test_') or
basename.endswith('_test'))):
tests.append(os.path.join(path, filename))

return tests


long_description = """
Operator Discretization Library (ODL) is a Python library for fast prototyping focusing on (but not restricted to) inverse problems. ODL is being developed at `KTH Royal Institute of Technology <https://www.kth.se/en/sci/institutioner/math>`_.
Expand Down Expand Up @@ -89,7 +101,7 @@ def run_tests(self):
setup(
name='odl',

version='0.5.0',
version='0.5.1',

description='Operator Discretization Library',
long_description=long_description,
Expand Down Expand Up @@ -124,8 +136,11 @@ def run_tests(self):

keywords='research development mathematics prototyping imaging tomography',

packages=find_packages(exclude=['*test*']),
packages=find_packages(),
package_dir={'odl': 'odl'},
package_data={'odl': find_tests() + ['odl/pytest.ini']},
include_package_data=True,
entry_points={'pytest11': ['odl_plugins = odl.util.pytest_plugins']},

install_requires=[requires],
tests_require=['pytest'],
Expand Down
Loading

0 comments on commit 9054a0f

Please sign in to comment.