Merge pull request #922 from paulromano/unittest

Set up unit testing infrastructure
This commit is contained in:
Sterling Harper 2017-11-07 11:36:45 -05:00 committed by GitHub
commit 1abb1bfa1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 179 additions and 179 deletions

4
.gitignore vendored
View file

@ -97,3 +97,7 @@ examples/jupyter/plots
*.c
*.html
*.so
.cache/
.tox/
.python-version

View file

@ -28,21 +28,7 @@ matrix:
env: OPENMC_CONFIG="check_source"
before_install:
# ============== Handle Python third-party packages ==============
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh;
else
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh;
fi
- bash miniconda.sh -b -p $HOME/miniconda
- export PATH="$HOME/miniconda/bin:$PATH"
- hash -r
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda
- conda info -a
- if [[ $OPENMC_CONFIG != "check_source" ]]; then
conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION six numpy scipy h5py=2.5 pandas;
source activate test-environment;
sudo add-apt-repository ppa:nschloe/hdf5-backports -y;
sudo apt-get update -q;
sudo apt-get install libhdf5-serial-dev libhdf5-mpich-dev -y;
@ -52,7 +38,11 @@ before_install:
export HDF5_DIR=/usr;
fi
install: true
install:
- if [[ $OPENMC_CONFIG != "check_source" ]]; then
pip install numpy cython;
pip install -e .[test];
fi
before_script:
- if [[ $OPENMC_CONFIG != "check_source" ]]; then
@ -72,5 +62,6 @@ script:
./check_source.py;
else
./run_tests.py -C $OPENMC_CONFIG -j 2;
pytest --cov=../openmc unit_tests/;
fi
- cd ..

View file

@ -468,6 +468,11 @@ file(GLOB_RECURSE TESTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_*.py)
# Loop through all the tests
foreach(test ${TESTS})
# Remove unit tests
if(test MATCHES ".*unit_tests.*")
continue()
endif()
# Get test information
get_filename_component(TEST_NAME ${test} NAME)
get_filename_component(TEST_PATH ${test} PATH)

View file

@ -1,25 +0,0 @@
## This file should be placed in the root directory of your project.
## Then modify the CMakeLists.txt file in the root directory of your
## project to incorporate the testing dashboard.
## # The following are required to uses Dart and the Cdash dashboard
## ENABLE_TESTING()
## INCLUDE(CTest)
# Generic information about CDASH site
set(CTEST_PROJECT_NAME "OpenMC")
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "openmc.mit.edu")
set(CTEST_DROP_LOCATION "/cdash/submit.php?project=OpenMC")
set(CTEST_DROP_SITE_CDASH TRUE)
# Set file size larger to see more output
set(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE "20000")
set(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE "20000")
# User/password to CDASH site
# Please contact Nick Horelik <nhorelik@mit.edu> or
# Bryan Herman <bherman@mit.edu> if you want to push
# test suite information to our CDASH site.
set(CTEST_DROP_SITE_USER "")
set(CTEST_DROP_SITE_PASSWORD "")

35
MANIFEST.in Normal file
View file

@ -0,0 +1,35 @@
include CMakeLists.txt
include LICENSE
include schemas.xml
include openmc/data/reconstruct.pyx
include docs/source/_templates/layout.html
include docs/sphinxext/LICENSE
recursive-include . *.rst
recursive-include cmake *.cmake
recursive-include docs *.css
recursive-include docs *.dia
recursive-include docs *.png
recursive-include docs *.py
recursive-include docs *.svg
recursive-include docs *.tex
recursive-include docs *.txt
recursive-include docs Makefile
recursive-include examples *.h5
recursive-include examples *.ipynb
recursive-include examples *.png
recursive-include examples *.py
recursive-include examples *.xml
recursive-include man *.1
recursive-include src *.F90
recursive-include src *.c
recursive-include src *.cc
recursive-include src *.cpp
recursive-include src *.h
recursive-include src *.hpp
recursive-include src *.rnc
recursive-include src *.rng
recursive-include tests *.dat
recursive-include tests *.h5
recursive-include tests *.py
recursive-include tests *.xml
prune docs/build

View file

@ -1,14 +0,0 @@
all:
mkdir -p build
cmake -H. -Bbuild
make -s -C build
clean:
make -s -C build clean
distclean:
rm -fr build
test:
make -s -C build test
install:
make -s -C build install
.PHONY: all clean distclean test install

View file

@ -414,16 +414,19 @@ distributions.
various HDF5 files, h5py is needed to provide access to data within these
files from Python.
.. admonition:: Optional
:class: note
`Matplotlib <http://matplotlib.org/>`_
Matplotlib is used to providing plotting functionality in the API like the
:meth:`Universe.plot` method and the :func:`openmc.plot_xs` function.
`uncertainties <https://pythonhosted.org/uncertainties/>`_
Uncertainties are optionally used for decay data in the :mod:`openmc.data`
module.
Uncertainties are used for decay data in the :mod:`openmc.data` module.
`lxml <http://lxml.de/>`_
lxml is used for the :ref:`scripts_validate` script and various other
parts of the Python API.
.. admonition:: Optional
:class: note
`Cython <http://cython.org/>`_
Cython is used for resonance reconstruction for ENDF data converted to
@ -437,8 +440,8 @@ distributions.
The silomesh package is needed to convert voxel and track files to SILO
format.
`lxml <http://lxml.de/>`_
lxml is used for the :ref:`scripts_validate` script.
`pytest <https://docs.pytest.org>`_
The pytest framework is used for unit testing the Python API.
.. _usersguide_nxml:

View file

@ -2,8 +2,7 @@
OpenMC Monte Carlo Particle Transport Code
==========================================
.. image:: https://travis-ci.org/mit-crpg/openmc.svg?branch=develop
:target: https://travis-ci.org/mit-crpg/openmc
|licensebadge| |travisbadge|
The OpenMC project aims to provide a fully-featured Monte Carlo particle
transport code based on modern methods. It is a constructive solid geometry,
@ -55,3 +54,11 @@ OpenMC is distributed under the MIT/X license_.
.. _Troubleshooting section: http://openmc.readthedocs.io/en/stable/usersguide/troubleshoot.html
.. _Issues: https://github.com/mit-crpg/openmc/issues
.. _license: http://openmc.readthedocs.io/en/stable/license.html
.. |licensebadge| image:: https://img.shields.io/github/license/mit-crpg/openmc.svg
:target: http://openmc.readthedocs.io/en/latest/license.html
:alt: License
.. |travisbadge| image:: https://travis-ci.org/mit-crpg/openmc.svg?branch=develop
:target: https://travis-ci.org/mit-crpg/openmc
:alt: Travis CI build status (Linux)

View file

@ -3,13 +3,8 @@
import glob
import sys
import numpy as np
try:
from setuptools import setup
have_setuptools = True
except ImportError:
from distutils.core import setup
have_setuptools = False
from setuptools import setup, find_packages
try:
from Cython.Build import cythonize
have_cython = True
@ -28,47 +23,53 @@ else:
with open('openmc/__init__.py', 'r') as f:
version = f.readlines()[-1].split()[-1].strip("'")
kwargs = {'name': 'openmc',
'version': version,
'packages': ['openmc', 'openmc.capi', 'openmc.data', 'openmc.mgxs',
'openmc.model', 'openmc.stats'],
'scripts': glob.glob('scripts/openmc-*'),
kwargs = {
'name': 'openmc',
'version': version,
'packages': find_packages(),
'scripts': glob.glob('scripts/openmc-*'),
# Data files and librarries
'package_data': {
'openmc.capi': ['libopenmc.{}'.format(suffix)],
'openmc.data': ['mass.mas12', 'fission_Q_data_endfb71.h5']
},
# Data files and librarries
'package_data': {
'openmc.capi': ['libopenmc.{}'.format(suffix)],
'openmc.data': ['mass.mas12', 'fission_Q_data_endfb71.h5']
},
# Metadata
'author': 'Will Boyd',
'author_email': 'wbinventor@gmail.com',
'description': 'OpenMC Python API',
'url': 'https://github.com/mit-crpg/openmc',
'classifiers': [
'Intended Audience :: Developers',
'Intended Audience :: End Users/Desktop',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Programming Language :: Python',
'Topic :: Scientific/Engineering'
]}
# Metadata
'author': 'The OpenMC Development Team',
'author_email': 'openmc-dev@googlegroups.com',
'description': 'OpenMC',
'url': 'https://github.com/mit-crpg/openmc',
'classifiers': [
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Intended Audience :: End Users/Desktop',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Topic :: Scientific/Engineering'
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
],
if have_setuptools:
kwargs.update({
# Required dependencies
'install_requires': ['six', 'numpy>=1.9', 'h5py', 'scipy', 'pandas>=0.17.0'],
# Required dependencies
'install_requires': [
'six', 'numpy>=1.9', 'h5py', 'scipy', 'ipython', 'matplotlib',
'pandas>=0.17.0', 'lxml', 'uncertainties'
],
# Optional dependencies
'extras_require': {
'decay': ['uncertainties'],
'plot': ['matplotlib', 'ipython'],
'vtk': ['vtk', 'silomesh'],
'validate': ['lxml']
},
})
# Optional dependencies
'extras_require': {
'test': ['pytest', 'pytest-cov'],
'vtk': ['vtk', 'silomesh'],
},
}
# If Cython is present, add resonance reconstruction capability
if have_cython:

View file

@ -10,43 +10,43 @@ import glob
import socket
from subprocess import call, check_output
from collections import OrderedDict
from optparse import OptionParser
from argparse import ArgumentParser
# Command line parsing
parser = OptionParser()
parser.add_option('-j', '--parallel', dest='n_procs', default='1',
help="Number of parallel jobs.")
parser.add_option('-R', '--tests-regex', dest='regex_tests',
help="Run tests matching regular expression. \
Test names are the directories present in tests folder.\
This uses standard regex syntax to select tests.")
parser.add_option('-C', '--build-config', dest='build_config',
help="Build configurations matching regular expression. \
Specific build configurations can be printed out with \
optional argument -p, --print. This uses standard \
regex syntax to select build configurations.")
parser.add_option('-l', '--list', action="store_true",
dest="list_build_configs", default=False,
help="List out build configurations.")
parser.add_option("-p", "--project", dest="project", default="",
help="project name for build")
parser.add_option("-D", "--dashboard", dest="dash",
help="Dash name -- Experimental, Nightly, Continuous")
parser.add_option("-u", "--update", action="store_true", dest="update",
help="Allow CTest to update repo. (WARNING: may overwrite\
changes that were not pushed.")
parser.add_option("-s", "--script", action="store_true", dest="script",
help="Activate CTest scripting mode for coverage, valgrind\
and dashboard capability.")
(options, args) = parser.parse_args()
parser = ArgumentParser()
parser.add_argument('-j', '--parallel', dest='n_procs', default='1',
help="Number of parallel jobs.")
parser.add_argument('-R', '--tests-regex', dest='regex_tests',
help="Run tests matching regular expression. \
Test names are the directories present in tests folder.\
This uses standard regex syntax to select tests.")
parser.add_argument('-C', '--build-config', dest='build_config',
help="Build configurations matching regular expression. \
Specific build configurations can be printed out with \
optional argument -p, --print. This uses standard \
regex syntax to select build configurations.")
parser.add_argument('-l', '--list', action="store_true",
dest="list_build_configs", default=False,
help="List out build configurations.")
parser.add_argument("-p", "--project", dest="project", default="",
help="project name for build")
parser.add_argument("-D", "--dashboard", dest="dash",
help="Dash name -- Experimental, Nightly, Continuous")
parser.add_argument("-u", "--update", action="store_true", dest="update",
help="Allow CTest to update repo. (WARNING: may overwrite\
changes that were not pushed.")
parser.add_argument("-s", "--script", action="store_true", dest="script",
help="Activate CTest scripting mode for coverage, valgrind\
and dashboard capability.")
args = parser.parse_args()
# Default compiler paths
FC='gfortran'
CC='gcc'
CXX='g++'
MPI_DIR='/opt/mpich/3.2-gnu'
HDF5_DIR='/opt/hdf5/1.8.16-gnu'
PHDF5_DIR='/opt/phdf5/1.8.16-gnu'
FC = 'gfortran'
CC = 'gcc'
CXX = 'g++'
MPI_DIR = '/opt/mpich/3.2-gnu'
HDF5_DIR = '/opt/hdf5/1.8.16-gnu'
PHDF5_DIR = '/opt/phdf5/1.8.16-gnu'
# Script mode for extra capability
script_mode = False
@ -115,6 +115,7 @@ endif()
# Define test data structure
tests = OrderedDict()
def cleanup(path):
"""Remove generated output files."""
for dirpath, dirnames, filenames in os.walk(path):
@ -173,7 +174,7 @@ class Test(object):
# Sets the build name that will show up on the CDash
def get_build_name(self):
self.build_name = options.project + '_' + self.name
self.build_name = args.project + '_' + self.name
return self.build_name
# Sets up build options for various tests. It is used both
@ -211,7 +212,7 @@ class Test(object):
os.environ['HDF5_ROOT'] = PHDF5_DIR
else:
os.environ['HDF5_ROOT'] = HDF5_DIR
rc = call(['ctest', '-S', 'ctestscript.run','-V'])
rc = call(['ctest', '-S', 'ctestscript.run', '-V'])
if rc != 0:
self.success = False
self.msg = 'Failed on ctest script.'
@ -243,12 +244,12 @@ class Test(object):
return
# Default make string
make_list = ['make','-s']
make_list = ['make', '-s']
# Check for parallel
if options.n_procs is not None:
if args.n_procs is not None:
make_list.append('-j')
make_list.append(options.n_procs)
make_list.append(args.n_procs)
# Run make
rc = call(make_list)
@ -265,14 +266,14 @@ class Test(object):
ctest_list = ['ctest']
# Check for parallel
if options.n_procs is not None:
if args.n_procs is not None:
ctest_list.append('-j')
ctest_list.append(options.n_procs)
ctest_list.append(args.n_procs)
# Check for subset of tests
if options.regex_tests is not None:
if args.regex_tests is not None:
ctest_list.append('-R')
ctest_list.append(options.regex_tests)
ctest_list.append(args.regex_tests)
# Run ctests
rc = call(ctest_list)
@ -282,7 +283,7 @@ class Test(object):
# Simple function to add a test to the global tests dictionary
def add_test(name, debug=False, optimize=False, mpi=False, openmp=False,\
def add_test(name, debug=False, optimize=False, mpi=False, openmp=False,
phdf5=False, valgrind=False, coverage=False):
tests.update({name: Test(name, debug, optimize, mpi, openmp, phdf5,
valgrind, coverage)})
@ -308,7 +309,7 @@ add_test('hdf5-debug_valgrind', debug=True, valgrind=True)
add_test('hdf5-debug_coverage', debug=True, coverage=True)
# Check to see if we should just print build configuration information to user
if options.list_build_configs:
if args.list_build_configs:
for key in tests:
print('Configuration Name: {0}'.format(key))
print(' Debug Flags:..........{0}'.format(tests[key].debug))
@ -320,10 +321,10 @@ if options.list_build_configs:
exit()
# Delete items of dictionary that don't match regular expression
if options.build_config is not None:
if args.build_config is not None:
to_delete = []
for key in tests:
if not re.search(options.build_config, key):
if not re.search(args.build_config, key):
to_delete.append(key)
for key in to_delete:
del tests[key]
@ -333,27 +334,21 @@ if options.build_config is not None:
# Experimental, Nightly, Continuous. On the CDash end, these can be
# reorganized into groups when a hostname, dashboard and build name
# are matched.
if options.dash is None:
if args.dash is None:
dash = 'Experimental'
submit = ''
else:
dash = options.dash
dash = args.dash
submit = 'ctest_submit()'
# Check for update command, which will run git fetch/merge and will delete
# any changes to repo that were not pushed to remote origin
if options.update:
update = 'ctest_update()'
else:
update = ''
update = 'ctest_update()' if args.update else ''
# Check for CTest scipts mode
# Sets up whether we should use just the basic ctest command or use
# CTest scripting to perform tests.
if not options.dash is None or options.script:
script_mode = True
else:
script_mode = False
script_mode = (args.dash is not None or args.script)
# Setup CTest script vars. Not used in non-script mode
pwd = os.getcwd()
@ -364,17 +359,17 @@ ctest_vars = {
'dashboard': dash,
'submit': submit,
'update': update,
'n_procs': options.n_procs
'n_procs': args.n_procs
}
# Check project name
subprop = """set_property(GLOBAL PROPERTY SubProject {0})"""
if options.project == "" :
ctest_vars.update({'subproject':''})
elif options.project == 'develop':
ctest_vars.update({'subproject':''})
subprop = "set_property(GLOBAL PROPERTY SubProject {0})"
if args.project == "":
ctest_vars.update({'subproject': ''})
elif args.project == 'develop':
ctest_vars.update({'subproject': ''})
else:
ctest_vars.update({'subproject':subprop.format(options.project)})
ctest_vars.update({'subproject': subprop.format(args.project)})
# Set up default valgrind tests (subset of all tests)
# Currently takes too long to run all the tests with valgrind
@ -396,8 +391,8 @@ if not script_mode:
for key in to_delete:
del tests[key]
# Check if tests empty
if len(list(tests.keys())) == 0:
# Check if tests is empty
if not tests:
print('No tests to run.')
exit()
@ -447,16 +442,16 @@ for key in iter(tests):
# Check for user custom tests
# INCLUDE is a CTest command that allows for a subset
# of tests to be executed. Only used in script mode.
if options.regex_tests is None:
ctest_vars.update({'tests' : ''})
if args.regex_tests is None:
ctest_vars.update({'tests': ''})
# No user tests, use default valgrind tests
if test.valgrind:
ctest_vars.update({'tests' : 'INCLUDE {0}'.
ctest_vars.update({'tests': 'INCLUDE {0}'.
format(valgrind_default_tests)})
else:
ctest_vars.update({'tests' : 'INCLUDE {0}'.
format(options.regex_tests)})
ctest_vars.update({'tests': 'INCLUDE {0}'.
format(args.regex_tests)})
# Main part of code that does the ctest execution.
# It is broken up by two modes, script and non-script

View file

@ -5,13 +5,11 @@ import sys
import numpy as np
sys.path.insert(0, os.pardir)
sys.path.insert(0, os.path.join(os.pardir, os.pardir))
from openmc import Material
from openmc.data import NATURAL_ABUNDANCE, atomic_mass
if __name__ == '__main__':
def test_element_wo():
# This test doesn't require an OpenMC run. We just need to make sure the
# element.expand() method expands elements with the proper nuclide
# compositions.