diff --git a/.github/workflows/tests-on-pr.yml b/.github/workflows/tests-on-pr.yml index f9b4d90..dfdbc77 100644 --- a/.github/workflows/tests-on-pr.yml +++ b/.github/workflows/tests-on-pr.yml @@ -36,8 +36,8 @@ jobs: - name: Install diffpy.srreal and requirements run: | conda install --file requirements/test.txt - conda install --file requirements/conda.txt + conda install boost numpy libdiffpy setuptools diffpy.structure periodictable gsl python -m pip install . --no-deps - name: Validate diffpy.pdfgui - run: python -m diffpy.srreal.tests.run + run: pytest tests diff --git a/src/diffpy/srreal/tests/__init__.py b/src/diffpy/srreal/tests/__init__.py deleted file mode 100644 index c4e942b..0000000 --- a/src/diffpy/srreal/tests/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.srreal by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2012 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.srreal.""" - -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.srreal 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.srreal package. - - Returns - ------- - result : `unittest.TestResult` - """ - suite = testsuite() - runner = unittest.TextTestRunner() - result = runner.run(suite) - return result - - -# End of file diff --git a/src/diffpy/srreal/tests/debug.py b/src/diffpy/srreal/tests/debug.py deleted file mode 100644 index 47197f9..0000000 --- a/src/diffpy/srreal/tests/debug.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.srreal Complex Modeling Initiative -# (c) 2016 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Convenience module for debugging the unit tests using. - -python -m diffpy.srreal.tests.debug - -Exceptions raised by failed tests or other errors are not caught. -""" - - -if __name__ == "__main__": - import sys - - from diffpy.srreal.tests import testsuite - - pattern = sys.argv[1] if len(sys.argv) > 1 else "" - suite = testsuite(pattern) - suite.debug() - - -# End of file diff --git a/src/diffpy/srreal/tests/run.py b/src/diffpy/srreal/tests/run.py deleted file mode 100644 index 9d10705..0000000 --- a/src/diffpy/srreal/tests/run.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.srreal 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. -# -############################################################################## -"""Convenience module for executing all unit tests with. - -python -m diffpy.srreal.tests.run -""" - - -if __name__ == "__main__": - import sys - - # show warnings by default - if not sys.warnoptions: - import os - import warnings - - warnings.simplefilter("default") - # also affect subprocesses - os.environ["PYTHONWARNINGS"] = "default" - from diffpy.srreal.tests import test - - # produce zero exit code for a successful test - sys.exit(not test().wasSuccessful()) - -# End of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..ac3c222 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,75 @@ +import json +import logging +from pathlib import Path + +import pytest + +from diffpy.srreal.structureconverters import convertObjCrystCrystal + + +@pytest.fixture +def user_filesystem(tmp_path): + base_dir = Path(tmp_path) + home_dir = base_dir / "home_dir" + home_dir.mkdir(parents=True, exist_ok=True) + cwd_dir = base_dir / "cwd_dir" + cwd_dir.mkdir(parents=True, exist_ok=True) + + home_config_data = {"username": "home_username", "email": "home@email.com"} + with open(home_dir / "diffpyconfig.json", "w") as f: + json.dump(home_config_data, f) + + yield tmp_path + + +# Resolve availability of optional packages. + +# pyobjcryst + + +@pytest.fixture(scope="session") +def _msg_nopyobjcryst(): + return "No module named 'pyobjcryst'" + + +@pytest.fixture(scope="session") +def has_pyobjcryst(): + try: + import pyobjcryst.crystal + + convertObjCrystCrystal(pyobjcryst.crystal.Crystal()) + has_pyobjcryst = True + except ImportError: + has_pyobjcryst = False + logging.warning("Cannot import pyobjcryst, pyobjcryst tests skipped.") + print("Cannot import pyobjcryst, pyobjcryst tests skipped.") + except TypeError: + has_pyobjcryst = False + logging.warning("Compiled without ObjCryst, pyobjcryst tests skipped.") + print("Compiled without ObjCryst, pyobjcryst tests skipped.") + + return has_pyobjcryst + + +# periodictable + + +@pytest.fixture(scope="session") +def _msg_noperiodictable(): + return "No module named 'periodictable'" + + +@pytest.fixture(scope="session") +def has_periodictable(): + try: + import periodictable + + has_periodictable = True + + # silence the pyflakes syntax checker + del periodictable + except ImportError: + has_periodictable = False + logging.warning("Cannot import periodictable, periodictable tests skipped.") + + return has_periodictable diff --git a/src/diffpy/srreal/tests/testatomradiitable.py b/tests/test_atomradiitable.py similarity index 96% rename from src/diffpy/srreal/tests/testatomradiitable.py rename to tests/test_atomradiitable.py index f5c2265..158a6f4 100644 --- a/src/diffpy/srreal/tests/testatomradiitable.py +++ b/tests/test_atomradiitable.py @@ -6,14 +6,14 @@ import pickle import unittest +import pytest + from diffpy.srreal.atomradiitable import AtomRadiiTable, ConstantRadiiTable, CovalentRadiiTable -from diffpy.srreal.tests.testutils import _msg_noperiodictable, has_periodictable # ---------------------------------------------------------------------------- class TestAtomRadiiTable(unittest.TestCase): - def setUp(self): self.rtb = AtomRadiiTable() self.ctb = ConstantRadiiTable() @@ -103,9 +103,13 @@ def test_toString(self): # ---------------------------------------------------------------------------- -@unittest.skipUnless(has_periodictable, _msg_noperiodictable) class TestCovalentRadiiTable(unittest.TestCase): + @pytest.fixture(autouse=True) + def _check_periodictable(self, has_periodictable, _msg_noperiodictable): + if not has_periodictable: + pytest.skip(_msg_noperiodictable) + def setUp(self): self.rtb = CovalentRadiiTable() return diff --git a/src/diffpy/srreal/tests/testattributes.py b/tests/test_attributes.py similarity index 100% rename from src/diffpy/srreal/tests/testattributes.py rename to tests/test_attributes.py diff --git a/src/diffpy/srreal/tests/testbondcalculator.py b/tests/test_bondcalculator.py similarity index 97% rename from src/diffpy/srreal/tests/testbondcalculator.py rename to tests/test_bondcalculator.py index cbbe609..cd69fe5 100644 --- a/src/diffpy/srreal/tests/testbondcalculator.py +++ b/tests/test_bondcalculator.py @@ -7,15 +7,10 @@ import unittest import numpy +import pytest +from testutils import loadDiffPyStructure, loadObjCrystCrystal, pickle_with_attr from diffpy.srreal.bondcalculator import BondCalculator -from diffpy.srreal.tests.testutils import ( - _msg_nopyobjcryst, - has_pyobjcryst, - loadDiffPyStructure, - loadObjCrystCrystal, - pickle_with_attr, -) # ---------------------------------------------------------------------------- @@ -81,7 +76,7 @@ def test_pickling(self): def test_pickling_derived_structure(self): """Check pickling of BondCalculator with DerivedStructureAdapter.""" - from diffpy.srreal.tests.testutils import DerivedStructureAdapter + from testutils import DerivedStructureAdapter bdc = self.bdc stru0 = DerivedStructureAdapter() @@ -249,9 +244,13 @@ def test_setTypeMask(self): # ---------------------------------------------------------------------------- -@unittest.skipUnless(has_pyobjcryst, _msg_nopyobjcryst) class TestBondCalculatorObjCryst(unittest.TestCase): + @pytest.fixture(autouse=True) + def _check_periodictable(self, has_pyobjcryst, _msg_nopyobjcryst): + if not has_pyobjcryst: + pytest.skip(_msg_nopyobjcryst) + def setUp(self): self.bdc = BondCalculator() if not hasattr(self, "rutile"): diff --git a/src/diffpy/srreal/tests/testbvscalculator.py b/tests/test_bvscalculator.py similarity index 97% rename from src/diffpy/srreal/tests/testbvscalculator.py rename to tests/test_bvscalculator.py index aceac21..c2f3838 100644 --- a/src/diffpy/srreal/tests/testbvscalculator.py +++ b/tests/test_bvscalculator.py @@ -6,8 +6,9 @@ import pickle import unittest +from testutils import loadDiffPyStructure, pickle_with_attr + from diffpy.srreal.bvscalculator import BVSCalculator -from diffpy.srreal.tests.testutils import loadDiffPyStructure, pickle_with_attr ############################################################################## @@ -139,7 +140,7 @@ def test_table_pickling(self): def test_pickling_derived_structure(self): """Check pickling of BVSCalculator with DerivedStructureAdapter.""" - from diffpy.srreal.tests.testutils import DerivedStructureAdapter + from testutils import DerivedStructureAdapter bvc = self.bvc stru0 = DerivedStructureAdapter() diff --git a/src/diffpy/srreal/tests/testdebyepdfcalculator.py b/tests/test_debyepdfcalculator.py similarity index 97% rename from src/diffpy/srreal/tests/testdebyepdfcalculator.py rename to tests/test_debyepdfcalculator.py index fd8c07d..693a7ab 100644 --- a/src/diffpy/srreal/tests/testdebyepdfcalculator.py +++ b/tests/test_debyepdfcalculator.py @@ -7,10 +7,9 @@ import unittest import numpy +from testutils import _maxNormDiff, loadDiffPyStructure, pickle_with_attr from diffpy.srreal.pdfcalculator import DebyePDFCalculator, PDFCalculator -from diffpy.srreal.tests.testpdfcalculator import _maxNormDiff -from diffpy.srreal.tests.testutils import loadDiffPyStructure, pickle_with_attr ############################################################################## @@ -189,7 +188,7 @@ def test_mask_pickling(self): def test_pickling_derived_structure(self): """Check pickling of DebyePDFCalculator with DerivedStructureAdapter.""" - from diffpy.srreal.tests.testutils import DerivedStructureAdapter + from testutils import DerivedStructureAdapter dpdfc = self.dpdfc stru0 = DerivedStructureAdapter() diff --git a/src/diffpy/srreal/tests/testoverlapcalculator.py b/tests/test_overlapcalculator.py similarity index 98% rename from src/diffpy/srreal/tests/testoverlapcalculator.py rename to tests/test_overlapcalculator.py index aabda0e..5a7a204 100644 --- a/src/diffpy/srreal/tests/testoverlapcalculator.py +++ b/tests/test_overlapcalculator.py @@ -8,16 +8,11 @@ import unittest import numpy +import pytest +from testutils import loadDiffPyStructure, loadObjCrystCrystal, pickle_with_attr from diffpy.srreal.atomradiitable import CovalentRadiiTable from diffpy.srreal.overlapcalculator import OverlapCalculator -from diffpy.srreal.tests.testutils import ( - _msg_nopyobjcryst, - has_pyobjcryst, - loadDiffPyStructure, - loadObjCrystCrystal, - pickle_with_attr, -) # ---------------------------------------------------------------------------- @@ -117,7 +112,7 @@ def test_pickling_artb(self): def test_pickling_derived_structure(self): """Check pickling of OverlapCalculator with DerivedStructureAdapter.""" - from diffpy.srreal.tests.testutils import DerivedStructureAdapter + from testutils import DerivedStructureAdapter olc = self.olc stru0 = DerivedStructureAdapter() @@ -332,9 +327,13 @@ def test_neighborhoods(self): # ---------------------------------------------------------------------------- -@unittest.skipUnless(has_pyobjcryst, _msg_nopyobjcryst) class TestOverlapCalculatorObjCryst(unittest.TestCase): + @pytest.fixture(autouse=True) + def _check_periodictable(self, has_pyobjcryst, _msg_nopyobjcryst): + if not has_pyobjcryst: + pytest.skip(_msg_nopyobjcryst) + def setUp(self): self.olc = OverlapCalculator() if not hasattr(self, "rutile"): diff --git a/src/diffpy/srreal/tests/testpairquantity.py b/tests/test_pairquantity.py similarity index 98% rename from src/diffpy/srreal/tests/testpairquantity.py rename to tests/test_pairquantity.py index c07da95..01e3bd9 100644 --- a/src/diffpy/srreal/tests/testpairquantity.py +++ b/tests/test_pairquantity.py @@ -6,11 +6,11 @@ import unittest import numpy +from testutils import mod_structure from diffpy.srreal.pairquantity import PairQuantity from diffpy.srreal.pdfcalculator import PDFCalculator from diffpy.srreal.srreal_ext import BasePairQuantity -from diffpy.srreal.tests.testutils import mod_structure # ---------------------------------------------------------------------------- @@ -169,7 +169,7 @@ def eval_as(evtp, pq, stru): def test_pickling(self): """Check pickling and unpickling of PairQuantity.""" - from diffpy.srreal.tests.testutils import DerivedStructureAdapter + from testutils import DerivedStructureAdapter stru0 = DerivedStructureAdapter() self.pq.setStructure(stru0) diff --git a/src/diffpy/srreal/tests/testparallel.py b/tests/test_parallel.py similarity index 98% rename from src/diffpy/srreal/tests/testparallel.py rename to tests/test_parallel.py index e6ae9c1..3bc524c 100644 --- a/src/diffpy/srreal/tests/testparallel.py +++ b/tests/test_parallel.py @@ -7,9 +7,9 @@ import unittest import numpy +from testutils import loadDiffPyStructure from diffpy.srreal.parallel import createParallelCalculator -from diffpy.srreal.tests.testutils import loadDiffPyStructure ############################################################################## diff --git a/src/diffpy/srreal/tests/testpdfbaseline.py b/tests/test_pdfbaseline.py similarity index 99% rename from src/diffpy/srreal/tests/testpdfbaseline.py rename to tests/test_pdfbaseline.py index 152119e..20535ce 100644 --- a/src/diffpy/srreal/tests/testpdfbaseline.py +++ b/tests/test_pdfbaseline.py @@ -7,10 +7,10 @@ import unittest import numpy +from testutils import pickle_with_attr from diffpy.srreal.pdfbaseline import LinearBaseline, PDFBaseline, ZeroBaseline, makePDFBaseline from diffpy.srreal.pdfcalculator import PDFCalculator -from diffpy.srreal.tests.testutils import pickle_with_attr # ---------------------------------------------------------------------------- diff --git a/src/diffpy/srreal/tests/testpdfcalcobjcryst.py b/tests/test_pdfcalcobjcryst.py similarity index 92% rename from src/diffpy/srreal/tests/testpdfcalcobjcryst.py rename to tests/test_pdfcalcobjcryst.py index 01ef21b..3fd4d4c 100644 --- a/src/diffpy/srreal/tests/testpdfcalcobjcryst.py +++ b/tests/test_pdfcalcobjcryst.py @@ -7,10 +7,10 @@ import unittest import numpy +import pytest +from testutils import _maxNormDiff, datafile, loadObjCrystCrystal from diffpy.srreal.pdfcalculator import PDFCalculator -from diffpy.srreal.tests.testpdfcalculator import _maxNormDiff -from diffpy.srreal.tests.testutils import _msg_nopyobjcryst, datafile, has_pyobjcryst, loadObjCrystCrystal # helper functions @@ -59,9 +59,13 @@ def _makePDFCalculator(crst, cfgdict): # ---------------------------------------------------------------------------- -@unittest.skipUnless(has_pyobjcryst, _msg_nopyobjcryst) class TestPDFCalcObjcryst(unittest.TestCase): + @pytest.fixture(autouse=True) + def _check_periodictable(self, has_pyobjcryst, _msg_nopyobjcryst): + if not has_pyobjcryst: + pytest.skip(_msg_nopyobjcryst) + def _comparePDFs(self, nickname, pdfbasename, cifbasename): def setself(**kwtoset): for n, v in kwtoset.items(): diff --git a/src/diffpy/srreal/tests/testpdfcalculator.py b/tests/test_pdfcalculator.py similarity index 96% rename from src/diffpy/srreal/tests/testpdfcalculator.py rename to tests/test_pdfcalculator.py index 5b79003..ef45a6b 100644 --- a/src/diffpy/srreal/tests/testpdfcalculator.py +++ b/tests/test_pdfcalculator.py @@ -7,22 +7,13 @@ import unittest import numpy +from testutils import _maxNormDiff, datafile, loadDiffPyStructure, pickle_with_attr from diffpy.srreal.pdfcalculator import PDFCalculator, fftftog, fftgtof -from diffpy.srreal.tests.testutils import datafile, loadDiffPyStructure, pickle_with_attr # helper functions -def _maxNormDiff(yobs, ycalc): - """Returned maximum difference normalized by RMS of the yobs.""" - yobsa = numpy.array(yobs) - obsmax = numpy.max(numpy.fabs(yobsa)) or 1 - ynmdiff = (yobsa - ycalc) / obsmax - rv = max(numpy.fabs(ynmdiff)) - return rv - - # ---------------------------------------------------------------------------- @@ -274,7 +265,7 @@ def test_mask_pickling(self): def test_pickling_derived_structure(self): """Check pickling of PDFCalculator with DerivedStructureAdapter.""" - from diffpy.srreal.tests.testutils import DerivedStructureAdapter + from testutils import DerivedStructureAdapter pdfc = self.pdfcalc stru0 = DerivedStructureAdapter() diff --git a/src/diffpy/srreal/tests/testpdfenvelope.py b/tests/test_pdfenvelope.py similarity index 99% rename from src/diffpy/srreal/tests/testpdfenvelope.py rename to tests/test_pdfenvelope.py index cf84055..7ea75f4 100644 --- a/src/diffpy/srreal/tests/testpdfenvelope.py +++ b/tests/test_pdfenvelope.py @@ -7,6 +7,7 @@ import unittest import numpy +from testutils import pickle_with_attr from diffpy.srreal.pdfcalculator import DebyePDFCalculator, PDFCalculator from diffpy.srreal.pdfenvelope import ( @@ -17,7 +18,6 @@ StepCutEnvelope, makePDFEnvelope, ) -from diffpy.srreal.tests.testutils import pickle_with_attr # ---------------------------------------------------------------------------- diff --git a/src/diffpy/srreal/tests/testpeakprofile.py b/tests/test_peakprofile.py similarity index 98% rename from src/diffpy/srreal/tests/testpeakprofile.py rename to tests/test_peakprofile.py index 56e3943..9b739c1 100644 --- a/src/diffpy/srreal/tests/testpeakprofile.py +++ b/tests/test_peakprofile.py @@ -7,10 +7,10 @@ import unittest import numpy +from testutils import mod_structure, pickle_with_attr from diffpy.srreal.pdfcalculator import PDFCalculator from diffpy.srreal.peakprofile import PeakProfile -from diffpy.srreal.tests.testutils import mod_structure, pickle_with_attr # ---------------------------------------------------------------------------- diff --git a/src/diffpy/srreal/tests/testpeakwidthmodel.py b/tests/test_peakwidthmodel.py similarity index 99% rename from src/diffpy/srreal/tests/testpeakwidthmodel.py rename to tests/test_peakwidthmodel.py index 0ba053f..6c83cd1 100644 --- a/src/diffpy/srreal/tests/testpeakwidthmodel.py +++ b/tests/test_peakwidthmodel.py @@ -7,10 +7,11 @@ import pickle import unittest +from testutils import loadDiffPyStructure + from diffpy.srreal.pdfcalculator import DebyePDFCalculator, PDFCalculator from diffpy.srreal.peakwidthmodel import DebyeWallerPeakWidth, JeongPeakWidth, PeakWidthModel from diffpy.srreal.structureadapter import createStructureAdapter -from diffpy.srreal.tests.testutils import loadDiffPyStructure # ---------------------------------------------------------------------------- diff --git a/src/diffpy/srreal/tests/testscatteringfactortable.py b/tests/test_scatteringfactortable.py similarity index 99% rename from src/diffpy/srreal/tests/testscatteringfactortable.py rename to tests/test_scatteringfactortable.py index e4c95be..3d327ae 100644 --- a/src/diffpy/srreal/tests/testscatteringfactortable.py +++ b/tests/test_scatteringfactortable.py @@ -7,6 +7,7 @@ import unittest import numpy +from testutils import pickle_with_attr from diffpy.srreal.pdfcalculator import DebyePDFCalculator, PDFCalculator from diffpy.srreal.scatteringfactortable import ( @@ -16,7 +17,6 @@ SFTNeutron, SFTXray, ) -from diffpy.srreal.tests.testutils import pickle_with_attr # ---------------------------------------------------------------------------- diff --git a/src/diffpy/srreal/tests/testsfaverage.py b/tests/test_sfaverage.py similarity index 93% rename from src/diffpy/srreal/tests/testsfaverage.py rename to tests/test_sfaverage.py index 6efaa98..87dd9a1 100644 --- a/src/diffpy/srreal/tests/testsfaverage.py +++ b/tests/test_sfaverage.py @@ -6,15 +6,11 @@ import unittest import numpy +import pytest +from testutils import loadDiffPyStructure, loadObjCrystCrystal from diffpy.srreal.scatteringfactortable import ScatteringFactorTable from diffpy.srreal.sfaverage import SFAverage -from diffpy.srreal.tests.testutils import ( - _msg_nopyobjcryst, - has_pyobjcryst, - loadDiffPyStructure, - loadObjCrystCrystal, -) # ---------------------------------------------------------------------------- @@ -78,9 +74,13 @@ def test_fromComposition(self): # ---------------------------------------------------------------------------- -@unittest.skipUnless(has_pyobjcryst, _msg_nopyobjcryst) class TestSFAverageObjCryst(unittest.TestCase): + @pytest.fixture(autouse=True) + def _check_periodictable(self, has_pyobjcryst, _msg_nopyobjcryst): + if not has_pyobjcryst: + pytest.skip(_msg_nopyobjcryst) + def setUp(self): self.sftx = ScatteringFactorTable.createByType("X") return diff --git a/src/diffpy/srreal/tests/teststructureadapter.py b/tests/test_structureadapter.py similarity index 97% rename from src/diffpy/srreal/tests/teststructureadapter.py rename to tests/test_structureadapter.py index 55a3604..697c355 100644 --- a/src/diffpy/srreal/tests/teststructureadapter.py +++ b/tests/test_structureadapter.py @@ -7,8 +7,17 @@ import unittest import numpy +import pytest +from testutils import ( + DerivedAtomicStructureAdapter, + DerivedCrystalStructureAdapter, + DerivedPeriodicStructureAdapter, + DerivedStructureAdapter, + loadCrystalStructureAdapter, + loadDiffPyStructure, + loadObjCrystCrystal, +) -import diffpy.srreal.tests.testutils as testutils from diffpy.srreal.pdfcalculator import PDFCalculator from diffpy.srreal.structureadapter import ( Atom, @@ -20,13 +29,6 @@ nometa, nosymmetry, ) -from diffpy.srreal.tests.testutils import ( - _msg_nopyobjcryst, - has_pyobjcryst, - loadCrystalStructureAdapter, - loadDiffPyStructure, - loadObjCrystCrystal, -) # ---------------------------------------------------------------------------- @@ -110,7 +112,7 @@ def test_pickle_nonwrapped(self): class TestDerivedAdapter(unittest.TestCase): "Check functionality in a Python-derived StructureAdapter class." - DerivedCls = testutils.DerivedStructureAdapter + DerivedCls = DerivedStructureAdapter def setUp(self): self.adpt = self.DerivedCls() @@ -145,15 +147,15 @@ def test_pickling(self): class TestDerivedAtomicAdapter(TestDerivedAdapter): - DerivedCls = testutils.DerivedAtomicStructureAdapter + DerivedCls = DerivedAtomicStructureAdapter class TestDerivedPeriodicAdapter(TestDerivedAdapter): - DerivedCls = testutils.DerivedPeriodicStructureAdapter + DerivedCls = DerivedPeriodicStructureAdapter class TestDerivedCrystalAdapter(TestDerivedAdapter): - DerivedCls = testutils.DerivedCrystalStructureAdapter + DerivedCls = DerivedCrystalStructureAdapter # ---------------------------------------------------------------------------- @@ -268,9 +270,13 @@ def test_nosymmetry_pickling(self): # ---------------------------------------------------------------------------- -@unittest.skipUnless(has_pyobjcryst, _msg_nopyobjcryst) class TestPyObjCrystAdapter(unittest.TestCase): + @pytest.fixture(autouse=True) + def _check_periodictable(self, has_pyobjcryst, _msg_nopyobjcryst): + if not has_pyobjcryst: + pytest.skip(_msg_nopyobjcryst) + def setUp(self): rutile_crystal = loadObjCrystCrystal("TiO2_rutile-fit.cif") self.rutile = createStructureAdapter(rutile_crystal) @@ -408,7 +414,7 @@ def test_getEquivalentAtoms(self): class TestDerivedStructureAdapter(IndexRangeTests, TestCase): - AdptClass = testutils.DerivedStructureAdapter + AdptClass = DerivedStructureAdapter def setUp(self): IndexRangeTests.setUp(self) diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 0000000..d50b30d --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,10 @@ +"""Unit tests for __version__.py.""" + +import diffpy.srreal + + +def test_package_version(): + """Ensure the package version is defined and not set to the initial + placeholder.""" + assert hasattr(diffpy.srreal, "__version__") + assert diffpy.srreal.__version__ != "0.0.0" diff --git a/src/diffpy/srreal/tests/testdata/C60bucky.stru b/tests/testdata/C60bucky.stru similarity index 100% rename from src/diffpy/srreal/tests/testdata/C60bucky.stru rename to tests/testdata/C60bucky.stru diff --git a/src/diffpy/srreal/tests/testdata/CdSe_cadmoselite.cif b/tests/testdata/CdSe_cadmoselite.cif similarity index 100% rename from src/diffpy/srreal/tests/testdata/CdSe_cadmoselite.cif rename to tests/testdata/CdSe_cadmoselite.cif diff --git a/src/diffpy/srreal/tests/testdata/CdSe_cadmoselite_N.fgr b/tests/testdata/CdSe_cadmoselite_N.fgr similarity index 100% rename from src/diffpy/srreal/tests/testdata/CdSe_cadmoselite_N.fgr rename to tests/testdata/CdSe_cadmoselite_N.fgr diff --git a/src/diffpy/srreal/tests/testdata/CdSe_cadmoselite_X.fgr b/tests/testdata/CdSe_cadmoselite_X.fgr similarity index 100% rename from src/diffpy/srreal/tests/testdata/CdSe_cadmoselite_X.fgr rename to tests/testdata/CdSe_cadmoselite_X.fgr diff --git a/src/diffpy/srreal/tests/testdata/Ni-fit.fgr b/tests/testdata/Ni-fit.fgr similarity index 100% rename from src/diffpy/srreal/tests/testdata/Ni-fit.fgr rename to tests/testdata/Ni-fit.fgr diff --git a/src/diffpy/srreal/tests/testdata/Ni.cif b/tests/testdata/Ni.cif similarity index 100% rename from src/diffpy/srreal/tests/testdata/Ni.cif rename to tests/testdata/Ni.cif diff --git a/src/diffpy/srreal/tests/testdata/Ni.stru b/tests/testdata/Ni.stru similarity index 100% rename from src/diffpy/srreal/tests/testdata/Ni.stru rename to tests/testdata/Ni.stru diff --git a/src/diffpy/srreal/tests/testdata/Ni_primitive.stru b/tests/testdata/Ni_primitive.stru similarity index 100% rename from src/diffpy/srreal/tests/testdata/Ni_primitive.stru rename to tests/testdata/Ni_primitive.stru diff --git a/src/diffpy/srreal/tests/testdata/TiO2_rutile-fit.cif b/tests/testdata/TiO2_rutile-fit.cif similarity index 100% rename from src/diffpy/srreal/tests/testdata/TiO2_rutile-fit.cif rename to tests/testdata/TiO2_rutile-fit.cif diff --git a/src/diffpy/srreal/tests/testdata/TiO2_rutile-fit.fgr b/tests/testdata/TiO2_rutile-fit.fgr similarity index 100% rename from src/diffpy/srreal/tests/testdata/TiO2_rutile-fit.fgr rename to tests/testdata/TiO2_rutile-fit.fgr diff --git a/src/diffpy/srreal/tests/testdata/TiO2_rutile-fit.stru b/tests/testdata/TiO2_rutile-fit.stru similarity index 100% rename from src/diffpy/srreal/tests/testdata/TiO2_rutile-fit.stru rename to tests/testdata/TiO2_rutile-fit.stru diff --git a/src/diffpy/srreal/tests/testdata/rutile.cif b/tests/testdata/rutile.cif similarity index 100% rename from src/diffpy/srreal/tests/testdata/rutile.cif rename to tests/testdata/rutile.cif diff --git a/src/diffpy/srreal/tests/testdata/silicon.cif b/tests/testdata/silicon.cif similarity index 100% rename from src/diffpy/srreal/tests/testdata/silicon.cif rename to tests/testdata/silicon.cif diff --git a/src/diffpy/srreal/tests/testdata/sphalerite.cif b/tests/testdata/sphalerite.cif similarity index 100% rename from src/diffpy/srreal/tests/testdata/sphalerite.cif rename to tests/testdata/sphalerite.cif diff --git a/src/diffpy/srreal/tests/testutils.py b/tests/testutils.py similarity index 68% rename from src/diffpy/srreal/tests/testutils.py rename to tests/testutils.py index 8cbb3ec..5f594af 100644 --- a/src/diffpy/srreal/tests/testutils.py +++ b/tests/testutils.py @@ -8,67 +8,23 @@ import numpy +import diffpy.structure as mod_structure from diffpy.srreal.structureadapter import ( AtomicStructureAdapter, CrystalStructureAdapter, PeriodicStructureAdapter, StructureAdapter, ) -from diffpy.srreal.structureconverters import convertObjCrystCrystal -from diffpy.srreal.tests import logger - -# Deprecated in 1.3 - import of old camel-case diffpy.Structure names. -# TODO drop this in version 1.4. - -try: - import diffpy.structure as mod_structure - from diffpy.structure.parsers import getParser -except ImportError as e: - try: - import diffpy.Structure as mod_structure - from diffpy.Structure.Parsers import getParser - except ImportError: - raise e - del e - -# Resolve availability of optional packages. - -# pyobjcryst - -_msg_nopyobjcryst = "No module named 'pyobjcryst'" -try: - import pyobjcryst.crystal - - convertObjCrystCrystal(pyobjcryst.crystal.Crystal()) - has_pyobjcryst = True -except ImportError: - has_pyobjcryst = False - logger.warning("Cannot import pyobjcryst, pyobjcryst tests skipped.") -except TypeError: - has_pyobjcryst = False - logger.warning("Compiled without ObjCryst, pyobjcryst tests skipped.") - -# periodictable - -_msg_noperiodictable = "No module named 'periodictable'" -try: - import periodictable - - has_periodictable = True - # silence the pyflakes syntax checker - del periodictable -except ImportError: - has_periodictable = False - logger.warning("Cannot import periodictable, periodictable tests skipped.") +from diffpy.structure.parsers import getParser # helper functions def datafile(filename): - from pkg_resources import resource_filename + from pathlib import Path - rv = resource_filename(__name__, "testdata/" + filename) - return rv + rv = Path(__file__).parent / "testdata" / filename + return str(rv) def loadObjCrystCrystal(filename): @@ -108,6 +64,15 @@ def pickle_with_attr(obj, **attr): return rv +def _maxNormDiff(yobs, ycalc): + """Returned maximum difference normalized by RMS of the yobs.""" + yobsa = numpy.array(yobs) + obsmax = numpy.max(numpy.fabs(yobsa)) or 1 + ynmdiff = (yobsa - ycalc) / obsmax + rv = max(numpy.fabs(ynmdiff)) + return rv + + # helper class for testing overloading of StructureAdapter