Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements/test.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,3 +4,4 @@ codecov
coverage
pytest-cov
pytest-env
sympy
85 changes: 0 additions & 85 deletions tests/__init__.py
Original file line numberDiff line numberDiff line change
@@ -1,85 +0,0 @@
#!/usr/bin/env python
##############################################################################
#
# diffpy.srfit by DANSE Diffraction group
# Simon J. L. Billinge
# (c) 2010 The Trustees of Columbia University
# in the City of New York. All rights reserved.
#
# File coded by: Pavol Juhas
#
# See AUTHORS.txt for a list of people who contributed.
# See LICENSE_DANSE.txt for license information.
#
##############################################################################
"""Unit tests for diffpy.srfit."""

import logging
import unittest

# create logger instance for the tests subpackage
logging.basicConfig()
logger = logging.getLogger(__name__)
del logging


def testsuite(pattern=""):
"""Create a unit tests suite for diffpy.srfit package.

Parameters
----------
pattern : str, optional
Regular expression pattern for selecting test cases.
Select all tests when empty. Ignore the pattern when
any of unit test modules fails to import.

Returns
-------
suite : `unittest.TestSuite`
The TestSuite object containing the matching tests.
"""
import re
from itertools import chain
from os.path import dirname

from pkg_resources import resource_filename

loader = unittest.defaultTestLoader
thisdir = resource_filename(__name__, "")
depth = __name__.count(".") + 1
topdir = thisdir
for i in range(depth):
topdir = dirname(topdir)
suite_all = loader.discover(thisdir, top_level_dir=topdir)
# always filter the suite by pattern to test-cover the selection code.
suite = unittest.TestSuite()
rx = re.compile(pattern)
tsuites = list(chain.from_iterable(suite_all))
tsok = all(isinstance(ts, unittest.TestSuite) for ts in tsuites)
if not tsok: # pragma: no cover
return suite_all
tcases = chain.from_iterable(tsuites)
for tc in tcases:
tcwords = tc.id().split(".")
shortname = ".".join(tcwords[-3:])
if rx.search(shortname):
suite.addTest(tc)
# verify all tests are found for an empty pattern.
assert pattern or suite_all.countTestCases() == suite.countTestCases()
return suite


def test():
"""Execute all unit tests for the diffpy.srfit package.

Returns
-------
result : `unittest.TestResult`
"""
suite = testsuite()
runner = unittest.TextTestRunner()
result = runner.run(suite)
return result


# End of file
142 changes: 141 additions & 1 deletion tests/conftest.py
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,92 @@
import importlib.resources
import json
import logging
import sys
from functools import lru_cache
from pathlib import Path

import pytest
import six

import diffpy.srfit.equation.literals as literals
from diffpy.srfit.sas.sasimport import sasimport

@pytest.fixture
logger = logging.getLogger(__name__)


@lru_cache()
def has_sas():
try:
sasimport("sas.pr.invertor")
sasimport("sas.models")
return True
except ImportError:
return False


# diffpy.structure
@lru_cache()
def has_diffpy_structure():
try:
import diffpy.structure as m

del m
return True
except ImportError:
return False
logger.warning(
"Cannot import diffpy.structure, Structure tests skipped."
)


@lru_cache()
def has_pyobjcryst():
try:
import pyobjcryst as m

del m
return True
except ImportError:
return False
logger.warning("Cannot import pyobjcryst, pyobjcryst tests skipped.")


# diffpy.srreal


@lru_cache()
def has_diffpy_srreal():
try:
import diffpy.srreal.pdfcalculator as m

del m
return True
except ImportError:
return False
logger.warning("Cannot import diffpy.srreal, PDF tests skipped.")


@pytest.fixture(scope="session")
def sas_available():
return has_sas()


@pytest.fixture(scope="session")
def diffpy_structure_available():
return has_diffpy_structure()


@pytest.fixture(scope="session")
def diffpy_srreal_available():
return has_diffpy_srreal()


@pytest.fixture(scope="session")
def pyobjcryst_available():
return has_pyobjcryst()


@pytest.fixture(scope="session")
def user_filesystem(tmp_path):
base_dir = Path(tmp_path)
home_dir = base_dir / "home_dir"
Expand All@@ -17,3 +99,61 @@ def user_filesystem(tmp_path):
json.dump(home_config_data, f)

yield tmp_path


@pytest.fixture(scope="session")
def datafile():
"""Fixture to load a test data file from the testdata package directory."""

def _datafile(filename):
return importlib.resources.files("tests.testdata").joinpath(filename)

return _datafile


@pytest.fixture(scope="session")
def make_args():
def _makeArgs(num):
args = []
for i in range(num):
j = i + 1
args.append(literals.Argument(name="v%i" % j, value=j))
return args

return _makeArgs


@pytest.fixture(scope="session")
def noObserversInGlobalBuilders():
def _noObserversInGlobalBuilders():
"""True if no observer function leaks to global builder objects.

Ensure objects are not immortal due to a reference from static
value.
"""
from diffpy.srfit.equation.builder import _builders

rv = True
for n, b in _builders.items():
if b.literal and b.literal._observers:
rv = False
break
return rv

return _noObserversInGlobalBuilders()


@pytest.fixture(scope="session")
def capturestdout():
def _capturestdout(f, *args, **kwargs):
"""Capture the standard output from a call of function f."""
savestdout = sys.stdout
fp = six.StringIO()
try:
sys.stdout = fp
f(*args, **kwargs)
finally:
sys.stdout = savestdout
return fp.getvalue()

return _capturestdout
Loading