Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some test modernization #425

Merged
merged 22 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion pyiron_atomistics/atomistics/structure/neighbors.py
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ def shells(self):
"""
Neighbor shell indices (excluding itself) of each atom computed using the get_neighbors_traj() method.

For trajectories with non constant amount of particles this array may contain -1 for invalid values, i.e.
For trajectories with non constant amount of particles this array may contain -1 for invalid values, i.e.

Returns:
ndarray: An int array of dimension N_steps / stride x N_atoms x N_neighbors x 3
Expand Down
36 changes: 15 additions & 21 deletions tests/atomistics/job/test_atomistic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,31 @@
import numpy as np
import os
import shutil
from pyiron_atomistics.project import Project
from pathlib import Path
from pyiron_base import ProjectHDFio
from pyiron_base._tests import TestWithCleanProject
from pyiron_atomistics.atomistics.job.atomistic import AtomisticGenericJob
from pyiron_atomistics.atomistics.structure.atoms import Atoms, CrystalStructure
import warnings


class TestAtomisticGenericJob(unittest.TestCase):
class TestAtomisticGenericJob(TestWithCleanProject):

@classmethod
def setUpClass(cls):
super().setUpClass()
cls.execution_path = os.path.dirname(os.path.abspath(__file__))
cls.project = Project(os.path.join(cls.execution_path, "test_job"))
cls.job = AtomisticGenericJob(
project=ProjectHDFio(project=cls.project, file_name="test_job"),

def setUp(self) -> None:
super().setUp()
self.job = AtomisticGenericJob(
project=ProjectHDFio(project=self.project, file_name="test_job"),
job_name="test_job",
)
cls.job.structure = CrystalStructure(
self.job.structure = CrystalStructure(
element="Al", bravais_basis="fcc", lattice_constants=4
).repeat(4)

@classmethod
def tearDownClass(cls):
cls.execution_path = os.path.dirname(os.path.abspath(__file__))
project = Project(os.path.join(cls.execution_path, "test_job"))
project.remove_jobs_silently(recursive=True)
project.remove(enable=True)

def test_attributes(self):
self.assertIsInstance(self.job.structure, Atoms)

Expand Down Expand Up @@ -77,19 +74,16 @@ def test_get_structure(self):
# tested here with lammps as a concrete instantiation of AtomisticGenericJob
# have to do extra tango because Project.unpack is weird right now
cwd = os.curdir
to_dir = os.path.join(self.project.path, "..")
shutil.copy("tests/static/lammps_test_files/get_structure_test.tar.gz", to_dir)
shutil.copy("tests/static/lammps_test_files/export.csv", to_dir)
os.chdir(to_dir)
tests_loc = Path(__file__).parents[2]
shutil.copy(os.path.join(tests_loc, "static/lammps_test_files/get_structure_test.tar.gz"), cwd)
shutil.copy(os.path.join(tests_loc, "static/lammps_test_files/export.csv"), cwd)
self.project.unpack("get_structure_test")
job = self.project.load("inter_calculator")
os.chdir(cwd)
os.unlink("export.csv")
os.unlink("get_structure_test.tar.gz")

for i, struct in enumerate(job.iter_structures()):
# breakpoint()
self.assertTrue(np.allclose(job.output.positions[i], struct.positions))
self.assertTrue(np.allclose(job.output.cells[i], struct.cell.array))
self.assertTrue(np.allclose(job.output.indices[i], struct.indices))

if __name__ == "__main__":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the tests don't work in the terminal I'd like to keep these ones

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry, I didn't see this in the mobile app.

Anyhow, it really necessary? I guess if you do python tests/atomistics/job/test_atomistic.py it is, but if you do python -m unittest discover tests/atomistics/job it will run this and the other ones there... but maybe you can append /test_atomistic.py to get just these? Tbh I haven't played around with it much from command line, but I'm 99% sure you can swing it this way

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with python -m unittest path/to/test_file.py you run all tests in this file (If you point to one specific one, you do not need to discover). So Sam, just make an alias run_test_py="python -m unittest discover " and you may fire any directory you want by run_test_py test_dir :)

unittest.main()
59 changes: 40 additions & 19 deletions tests/atomistics/structure/test_potentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,72 @@
import unittest
from pyiron_atomistics.lammps.potential import LammpsPotentialFile
from pyiron_atomistics.vasp.potential import VaspPotential
from pyiron_base import state
from abc import ABC


class TestLammpsPotentialFile(unittest.TestCase):
class _PotentialTester(unittest.TestCase, ABC):
"""Overrides the settings so that the tests/static directory is used as the resources, then refreshes afterwards"""

@classmethod
def setUpClass(cls):
state.update({'resource_paths': os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../static")})

@classmethod
def tearDownClass(cls) -> None:
state.update()


class TestLammpsPotentialFile(_PotentialTester):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.kim = LammpsPotentialFile()
cls.potential_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "../../static/lammps/potentials"
)

def test_find(self):
Fe_lst = ["Fe_C_Becquart_eam", "Fe_C_Hepburn_Ackland_eam"]

self.assertEqual(sorted(list(self.kim.find("Fe")["Name"])), sorted(Fe_lst))
AlMg_lst = ["Al_Mg_Mendelev_eam"]
self.assertEqual(sorted(list(self.kim.find({"Al", "Mg"})["Name"])), AlMg_lst)
Fe_desired = ["Fe_C_Becquart_eam", "Fe_C_Hepburn_Ackland_eam"]
Fe_available = list(self.kim.find("Fe")["Name"])
for potl in Fe_desired:
self.assertIn(
potl, Fe_available,
msg=f"Failed to find {potl}, which is expected since it is in the tests/static resources"
)
self.assertIn(
"Al_Mg_Mendelev_eam", list(self.kim.find({"Al", "Mg"})["Name"]),
msg="Failed to find Al_Mg_Mendelev_eam, which is expected since it is in the tests/static resources"
)

def test_pythonic_functions(self):
self.assertEqual(
list(self.kim.find("Fe")["Name"]), list(self.kim["Fe"].list()["Name"])
list(self.kim.find("Fe")["Name"]), list(self.kim["Fe"].list()["Name"]),
msg="List conversion method failed."
)
self.assertEqual(
list(self.kim.find("Fe")["Name"]), list(self.kim.Fe.list()["Name"])
list(self.kim.find("Fe")["Name"]), list(self.kim.Fe.list()["Name"]),
msg="Element symbol attribute does not find element."
)
self.assertEqual(
list(self.kim.find({"Al", "Mg"})["Name"]),
list(self.kim["Al"]["Mg"].list()["Name"]),
msg="Double find not equivalent to nested dictionary access."
)
self.assertEqual(
list(self.kim.find({"Al", "Mg"})["Name"]),
list(self.kim.Al.Mg.list()["Name"]),
msg="Nested attribute access failed"
)
self.assertEqual(
list(self.kim.Mg.Al.list()["Name"]),
list(self.kim.Al.Mg.list()["Name"]),
msg="Elemental pairs should be commutative"
)


class TestVaspPotential(unittest.TestCase):
class TestVaspPotential(_PotentialTester):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.vasp = VaspPotential()
cls.potential_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "../../static/vasp/potentials"
)

def test_find(self):
self.assertEqual(
Expand Down Expand Up @@ -101,7 +126,3 @@ def test_pythonic_functions(self):
"Fe_sv_GW-gga-pbe",
],
)


if __name__ == "__main__":
unittest.main()
20 changes: 12 additions & 8 deletions tests/gpaw/test_gpaw.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
# Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department
# Distributed under the terms of "New BSD License", see the LICENSE file.

import unittest
import os
import numpy as np
from pyiron_base import Project, ProjectHDFio
from pyiron_base import ProjectHDFio
from pyiron_atomistics.gpaw.gpaw import Gpaw
from pyiron_atomistics.atomistics.structure.atoms import Atoms
from pyiron_base._tests import TestWithProject


class TestGpaw(unittest.TestCase):
class TestGpaw(TestWithProject):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.execution_path = os.path.dirname(os.path.abspath(__file__))
cls.project = Project(os.path.join(cls.execution_path, "gpaw"))
atoms = Atoms("Fe1", positions=np.zeros((1, 3)), cell=np.eye(3))
job = Gpaw(
project=ProjectHDFio(project=cls.project, file_name="gpaw"),
Expand All @@ -23,12 +23,16 @@ def setUpClass(cls):
job.structure = atoms
job.encut = 300
job.set_kpoints([5, 5, 5])
job.to_hdf()
cls.job = Gpaw(
project=ProjectHDFio(project=cls.project, file_name="gpaw"),
cls.job = job

def test_serialization(self):
self.job.to_hdf()
loaded = Gpaw(
project=ProjectHDFio(project=self.project, file_name="gpaw"),
job_name="gpaw",
)
cls.job.from_hdf()
loaded.from_hdf()
self.assertEqual(self.job.encut, loaded.encut)

def test_encut(self):
self.assertEqual(self.job.encut, 300)
Expand Down
Loading