Repository: PlasmaPy/PlasmaPy

Issue:
Make test order deterministic so we can use `pytest-xdist` in `plasmapy.particles`
The order that tests are run in (what will soon be) `plasmapy.particles` is not deterministic.  Some of the functionality in that subpackage uses [set](https://docs.python.org/3/tutorial/datastructures.html#sets) operations, which do not preserve order.  Since the order of our tests sometimes depends on set operations, the order of tests changes.

Nominally, unit tests should be able to be run in any order.  However, I ran into a problem when trying to use [`pytest-xdist`](https://docs.pytest.org/en/3.0.1/xdist.html) to run tests in parallel, as this package currently requires test order to be deterministic when figuring out which tests to send to which processor.  Since our test order will only get bigger with time, it would be helpful to make our test order deterministic so that we have the capability of running tests in parallel.

The two possibilities that I can think of are:
 - Use [OrderedSets](https://pypi.org/project/ordered-set/) instead of regular sets (with the disadvantage that this would require adding another dependency to PlasmaPy)
 - Use sorting in the operations in which tests get selected (probably using `sorted`).  

The files that are affected include:

 - [ ] `test_ionization_state.py`
 - [ ] `test_ionization_states.py`
 - [ ] `test_parsing.py`
 - [ ] `test_particle_class.py`
 - [ ] `test_special_particles.py`

The quick way to test this is to install `pytest-xdist`, go to the tests directory, and then try running in the command prompt: 

```pytest -n 4 test_parsing.py```  

Thanks!
Make `IonizationState` and `IonizationStateCollection` tests independent of each other
I tried running our tests with the pytest extension pytest-randomly, and it turns out that many of the tests in `plasmapy/particles/test_ionization_state.py` and `plasmapy/particles/test_ionization_collection.py` fail when they are run in random order.  This is because the tests depend on each other, which is generally something to avoid, which I only learned recently.  We should modify these tests so that they don't depend on the order of test execution.  That is to say, we should make these tests completely independent of each other.  

I found this out by running these lines in the command line:

```bash
pip install pytest-randomly
pytest --randomly-seed=1235
```

These tests might be a good place to use pytest fixtures.


Discussion:
Oh, so that's what was causing me trouble when adding pytest-xdist to tox! I think I was able to dodge using this line

https://github.com/PlasmaPy/PlasmaPy/blob/da2aaeeca87b1ee2c63a954e37a9c72471671e1e/tox.ini#L13

where `--dist=loadfile` means, AFAIK, the tests are parallelized by file. Thus, the order of tests in a single file doesn't matter.
Hi @namurphy can I take this up?
> Hi @namurphy can I take this up?

Yes, please do!
> > Hi @namurphy can I take this up?
> 
> Yes, please do!

Okay


Resolving patch:
diff --git a/plasmapy/utils/pytest_helpers/pytest_helpers.py b/plasmapy/utils/pytest_helpers/pytest_helpers.py
--- a/plasmapy/utils/pytest_helpers/pytest_helpers.py
+++ b/plasmapy/utils/pytest_helpers/pytest_helpers.py
@@ -218,7 +218,7 @@ def test_func(inputs):
     if kwargs is None:
         kwargs = {}
 
-    if not isinstance(args, tuple):
+    if not type(args) in [tuple, list]:
         args = (args,)
 
     if not callable(func):


Test patch:
diff --git a/plasmapy/particles/tests/test_atomic.py b/plasmapy/particles/tests/test_atomic.py
--- a/plasmapy/particles/tests/test_atomic.py
+++ b/plasmapy/particles/tests/test_atomic.py
@@ -3,6 +3,7 @@
 
 from astropy import constants as const
 from astropy import units as u
+from astropy.tests.helper import assert_quantity_allclose
 
 from plasmapy.particles.exceptions import (
     ChargeError,
@@ -45,345 +46,207 @@
 
 # The following lists (with the name of a function
 
-atomic_symbol_table = [
-    [1, "H"],
-    [1, "H"],
-    ["H", "H"],
-    ["p", "H"],
-    ["T", "H"],
-    ["deuterium", "H"],
-    ["deuteron", "H"],
-    ["Tritium", "H"],
-    ["triton", "H"],
-    ["H-2", "H"],
-    ["D", "H"],
-    ["T", "H"],
-    ["H-3", "H"],
-    ["Hydrogen-3", "H"],
-    ["helium", "He"],
-    [2, "He"],
-    ["alpha", "He"],
-    ["gold", "Au"],
-    ["Gold", "Au"],
-    [79, "Au"],
-    ["79", "Au"],
-    ["P", "P"],
-    [118, "Og"],
-    ["N-14", "N"],
-    ["N", "N"],
-    ["H +1", "H"],
-    ["H 1+", "H"],
-    ["hydrogen 1+", "H"],
-    ["deuterium 1+", "H"],
-    ["Fe 24+", "Fe"],
-    ["Fe +24", "Fe"],
-    ["Fe 2-", "Fe"],
-    ["Fe -2", "Fe"],
-    ["Fe+", "Fe"],
-    ["Fe++", "Fe"],
-    ["Fe-", "Fe"],
-    ["Fe++++++++++++++", "Fe"],
-    ["H-0", InvalidParticleError],
-    [3.14159, TypeError],
-    ["Og-294b", InvalidParticleError],
-    ["H-934361079326356530741942970523610389", InvalidParticleError],
-    ["Fe 2+4", InvalidParticleError],
-    ["Fe+24", InvalidParticleError],
-    ["Fe +59", InvalidParticleError],
-    ["C++++++++++++++++", InvalidParticleError],
-    ["C-++++", InvalidParticleError],
-    ["neutron", InvalidElementError],
-    ["n", InvalidElementError],
-    ["n-1", InvalidElementError],
-    ["h", InvalidParticleError],
-    ["d", InvalidParticleError],
-    ["he", InvalidParticleError],
-    ["au", InvalidParticleError],
-    ["p-", InvalidElementError],
-    [0, InvalidParticleError],
-    [119, InvalidParticleError],
-    ["antiproton", InvalidElementError],
-]
-
-isotope_symbol_table = [
-    [("He", 4), "He-4"],
-    [("helium-4",), "He-4"],
-    [("H-2",), "D"],
-    [("Deuterium",), "D"],
-    [("deuterium",), "D"],
-    [("deuteron",), "D"],
-    [("tritium",), "T"],
-    [("triton",), "T"],
-    [("Hydrogen-3",), "T"],
-    [("hydrogen-3",), "T"],
-    [("H-3",), "T"],
-    [(1, 2), "D"],
-    [("Hydrogen", 3), "T"],
-    [("tritium",), "T"],
-    [("H", 2), "D"],
-    [("Alpha",), "He-4"],
-    [("alpha",), "He-4"],
-    [(79, 197), "Au-197"],
-    [("p",), "H-1"],
-    [("beryllium-8",), "Be-8"],
-    [("N-13",), "N-13"],
-    [("p",), "H-1"],
-    [("proton",), "H-1"],
-    [("protium",), "H-1"],
-    [("N-13 2+",), "N-13"],
-    [("Hydrogen-3 +1",), "T"],
-    ["Md-260", {"mass_numb": 261}, InvalidParticleError],
-    ["protium", {"mass_numb": 2}, InvalidParticleError],
-    ["alpha", {"mass_numb": 3}, InvalidParticleError],
-    ["O-18", {"mass_numb": 19}, InvalidParticleError],
-    ["lead-209", {"mass_numb": 511}, InvalidParticleError],
-    ["He-1", {}, InvalidParticleError],
-    [24, {"mass_numb": 23}, InvalidParticleError],
-    ["H", {"mass_numb": 0}, InvalidParticleError],
-    ["H-1", {"mass_numb": 2}, InvalidParticleError],
-    ["P", {}, InvalidIsotopeError],
-    [1, {}, InvalidIsotopeError],
-    [4, {}, InvalidIsotopeError],
-    ["hydrogen-444444", {}, InvalidParticleError],
-    ["Fe", {"mass_numb": 2.1}, TypeError],
-    ["He", {"mass_numb": "c"}, TypeError],
-    ["He-3", {"mass_numb": 4}, InvalidParticleError],
-    ["D", {"mass_numb": 3}, InvalidParticleError],
-    ["T", {"mass_numb": 2}, InvalidParticleError],
-    ["Fe", {"mass_numb": None}, InvalidIsotopeError],
-    ["He", {"mass_numb": 99}, InvalidParticleError],
-    ["d", {}, InvalidParticleError],
-    ["h-3", {}, InvalidParticleError],
-    ["h", {}, InvalidParticleError],
-    ["d+", {}, InvalidParticleError],
-    ["H-1", {"mass_numb": 1}, ParticleWarning],
-    ["H-2", {"mass_numb": 2}, ParticleWarning],
-    ["T", {"mass_numb": 3}, ParticleWarning],
-    ["Li-6", {"mass_numb": 6}, ParticleWarning],
-    ["lithium-6", {"mass_numb": 6}, ParticleWarning],
-    ["alpha", {"mass_numb": 4}, ParticleWarning],
-    ["p", {"mass_numb": 1}, ParticleWarning],
-]
-
-atomic_number_table = [
-    ["H", 1],
-    ["D", 1],
-    ["deuterium", 1],
-    ["Deuterium", 1],
-    ["tritium", 1],
-    ["p", 1],
-    ["P", 15],
-    ["Alpha", 2],
-    ["C-12", 6],
-    ["Argon", 18],
-    ["protium", 1],
-    ["H-3", 1],
-    ["p+", 1],
-    ["Be-8", 4],
-    ["N", 7],
-    ["N 2+", 7],
-    ["N +1", 7],
-    ["N+++", 7],
-    ["H-3934", InvalidParticleError],
-    ["C-12b", InvalidParticleError],
-    [-1.5, TypeError],
-    ["n", InvalidElementError],
-    ["n-1", InvalidElementError],
-    ["neutron", InvalidElementError],
-    ["Neutron", InvalidElementError],
-    ["d", InvalidParticleError],
-    ["t", InvalidParticleError],
-    ["s-36", InvalidParticleError],
-]
-
-mass_number_table = [
-    ["helium-3", 3],
-    ["Au-197", 197],
-    ["deuterium", 2],
-    ["D", 2],
-    ["H-2", 2],
-    ["tritium", 3],
-    ["T", 3],
-    ["alpha", 4],
-    ["p", 1],
-    ["Be-8", 8],
-    ["N-13", 13],
-    ["N-13 2+", 13],
-    ["N-13 +2", 13],
-    ["N-13+++", 13],
-    ["H-359", InvalidParticleError],
-    ["C-12b", InvalidParticleError],
-    [-1.5, TypeError],
-    ["N-13+-+-", InvalidParticleError],
-    ["h-3", InvalidParticleError],
-    ["n", InvalidIsotopeError],
-    ["n-1", InvalidIsotopeError],
-]
-
-
-element_name_table = [
-    ["D", "hydrogen"],
-    ["deuterium", "hydrogen"],
-    ["Au", "gold"],
-    ["alpha", "helium"],
-    ["helium-4", "helium"],
-    ["H-2", "hydrogen"],
-    ["Deuterium", "hydrogen"],
-    ["Hydrogen-3", "hydrogen"],
-    ["hydrogen-3", "hydrogen"],
-    ["H-3", "hydrogen"],
-    ["tritium", "hydrogen"],
-    ["Alpha", "helium"],
-    ["alpha", "helium"],
-    [1, "hydrogen"],
-    [26, "iron"],
-    [79, "gold"],
-    ["p", "hydrogen"],
-    ["P", "phosphorus"],
-    ["Be-8", "beryllium"],
-    ["Li-7", "lithium"],
-    ["N", "nitrogen"],
-    ["N+++", "nitrogen"],
-    ["D-", "hydrogen"],
-    ["vegancupcakes", InvalidParticleError],
-    ["C-+-", InvalidParticleError],
-    [1.24, TypeError],
-    ["n", InvalidElementError],
-    ["neutron", InvalidElementError],
-    [0, InvalidParticleError],
-    ["H++", InvalidParticleError],
-    ["t", InvalidParticleError],
-    ["pb", InvalidParticleError],
-    ["d", InvalidParticleError],
-    ["h-3", InvalidParticleError],
-    ["Pb-9", InvalidParticleError],
-    ["H 2+", InvalidParticleError],
-]
-
-standard_atomic_weight_table = [
-    ["H", (1.008 * u.u).to(u.kg)],
-    [1, (1.008 * u.u).to(u.kg)],
-    ["Hydrogen", (1.008 * u.u).to(u.kg)],
-    ["Au", u.kg],
-    ["H-1", ParticleError],
-    ["help i'm trapped in a unit test", InvalidParticleError],
-    [1.1, TypeError],
-    ["n", InvalidElementError],
-    ["p", ParticleError],
-    ["alpha", ParticleError],
-    ["deuteron", ParticleError],
-    ["tritium", ParticleError],
-    ["Au+", ParticleError],
-    ["Fe -2", ParticleError],
-    ["Og 2+", ParticleError],
-    ["h", InvalidParticleError],
-    ["fe", InvalidParticleError],
-]
-
-particle_mass_table = [
-    ["proton", const.m_p],
-    ["H-1+", const.m_p],
-    ["H-1 +1", const.m_p],
-    ["H-1 1+", const.m_p],
-    ["H-1", {"Z": 1}, const.m_p],
-    ["hydrogen-1", {"Z": 1}, const.m_p],
-    ["p+", const.m_p],
-    ["F-19", {"Z": 3}, u.kg],
-    ["Og 1+", {}, MissingParticleDataError],
-    ["Fe-56", {"Z": 1.4}, TypeError],
-    ["H-1 +1", {"Z": 0}, InvalidParticleError],
-    [26, {"Z": 1, "mass_numb": "a"}, TypeError],
-    [26, {"Z": 27, "mass_numb": 56}, InvalidParticleError],
-    ["Og", {"Z": 1}, MissingParticleDataError],
-    ["Og", {"mass_numb": 696, "Z": 1}, InvalidParticleError],
-    ["He 1+", {"mass_numb": 99}, InvalidParticleError],
-    ["fe-56 1+", {}, InvalidParticleError],
-    ["H-1", {"mass_numb": 1, "Z": 1}, ParticleWarning],
-    ["H", standard_atomic_weight("H")],
-]
-
-is_stable_table = [
-    ["H-1", True],
-    [(1, 1), True],
-    ["N-14", True],
-    [("N", 14), True],
-    ["P-31", True],
-    [("P", 31), True],
-    ["p", True],
-    ["alpha", True],
-    ["Xe-124", True],
-    ["Fe", {"mass_numb": 56}, True],
-    ["Fe-56", True],
-    ["iron-56", True],
-    ["Iron-56", True],
-    [(26, 56), True],
-    ["Be-8", False],
-    ["U-235", False],
-    ["uranium-235", False],
-    ["T", False],
-    [(4, 8), False],
-    ["tritium", False],
-    ["Pb-209", False],
-    ["lead-209", False],
-    ["Lead-209", False],
-    ["Pb", {"mass_numb": 209}, False],
-    [(82, 209), False],
-    [("hydrogen-444444",), InvalidParticleError],
-    [("hydrogen", 0), InvalidParticleError],
-    [("",), InvalidParticleError],
-    [("pb-209",), InvalidParticleError],
-    [("h",), InvalidParticleError],
-    [("He",), InvalidIsotopeError],
-    [("B",), InvalidIsotopeError],
-]
-
-charge_number_table = [
-    ["H+", 1],
-    ["D +1", 1],
-    ["tritium 1+", 1],
-    ["H-", -1],
-    ["Fe -2", -2],
-    ["Fe 2-", -2],
-    ["N--", -2],
-    ["N++", 2],
-    ["alpha", 2],
-    ["proton", 1],
-    ["deuteron", 1],
-    ["triton", 1],
-    ["electron", -1],
-    ["e-", -1],
-    ["e+", 1],
-    ["positron", 1],
-    ["n", 0],
-    ["neutron", 0],
-    ["p-", -1],
-    ["antiproton", -1],
-    ["fads", InvalidParticleError],
-    ["H++", InvalidParticleError],
-    ["h+", InvalidParticleError],
-    ["fe 1+", InvalidParticleError],
-    ["d+", InvalidParticleError],
-    ["Fe 29+", InvalidParticleError],
-    ["H-1", ChargeError],
-    ["H---", ParticleWarning],
-    ["Fe -26", ParticleWarning],
-    ["Og 10-", ParticleWarning],
+table_functions_args_kwargs_output = [
+    [
+        atomic_symbol,
+        [
+            1,
+        ],
+        {},
+        "H",
+    ],
+    [atomic_symbol, [1], {}, "H"],
+    [atomic_symbol, ["H"], {}, "H"],
+    [atomic_symbol, ["p"], {}, "H"],
+    [atomic_symbol, ["T"], {}, "H"],
+    [atomic_symbol, ["deuterium"], {}, "H"],
+    [atomic_symbol, ["deuteron"], {}, "H"],
+    [atomic_symbol, ["Tritium"], {}, "H"],
+    [atomic_symbol, ["triton"], {}, "H"],
+    [atomic_symbol, ["H-2"], {}, "H"],
+    [atomic_symbol, ["D"], {}, "H"],
+    [atomic_symbol, ["T"], {}, "H"],
+    [atomic_symbol, ["H-3"], {}, "H"],
+    [atomic_symbol, ["Hydrogen-3"], {}, "H"],
+    [atomic_symbol, ["helium"], {}, "He"],
+    [atomic_symbol, [2], {}, "He"],
+    [atomic_symbol, ["alpha"], {}, "He"],
+    [atomic_symbol, ["gold"], {}, "Au"],
+    [atomic_symbol, ["Gold"], {}, "Au"],
+    [atomic_symbol, [79], {}, "Au"],
+    [atomic_symbol, ["79"], {}, "Au"],
+    [atomic_symbol, ["P"], {}, "P"],
+    [atomic_symbol, [118], {}, "Og"],
+    [atomic_symbol, ["N-14"], {}, "N"],
+    [atomic_symbol, ["N"], {}, "N"],
+    [atomic_symbol, ["H +1"], {}, "H"],
+    [atomic_symbol, ["H 1+"], {}, "H"],
+    [atomic_symbol, ["hydrogen 1+"], {}, "H"],
+    [atomic_symbol, ["deuterium 1+"], {}, "H"],
+    [atomic_symbol, ["Fe 24+"], {}, "Fe"],
+    [atomic_symbol, ["Fe +24"], {}, "Fe"],
+    [atomic_symbol, ["Fe 2-"], {}, "Fe"],
+    [atomic_symbol, ["Fe -2"], {}, "Fe"],
+    [atomic_symbol, ["Fe+"], {}, "Fe"],
+    [atomic_symbol, ["Fe++"], {}, "Fe"],
+    [atomic_symbol, ["Fe-"], {}, "Fe"],
+    [atomic_symbol, ["Fe++++++++++++++"], {}, "Fe"],
+    [isotope_symbol, ("He", 4), {}, "He-4"],
+    [isotope_symbol, ("helium-4",), {}, "He-4"],
+    [isotope_symbol, ("H-2",), {}, "D"],
+    [isotope_symbol, ("Deuterium",), {}, "D"],
+    [isotope_symbol, ("deuterium",), {}, "D"],
+    [isotope_symbol, ("deuteron",), {}, "D"],
+    [isotope_symbol, ("tritium",), {}, "T"],
+    [isotope_symbol, ("triton",), {}, "T"],
+    [isotope_symbol, ("Hydrogen-3",), {}, "T"],
+    [isotope_symbol, ("hydrogen-3",), {}, "T"],
+    [isotope_symbol, ("H-3",), {}, "T"],
+    [isotope_symbol, (1, 2), {}, "D"],
+    [isotope_symbol, ("Hydrogen", 3), {}, "T"],
+    [isotope_symbol, ("tritium",), {}, "T"],
+    [isotope_symbol, ("H", 2), {}, "D"],
+    [isotope_symbol, ("Alpha",), {}, "He-4"],
+    [isotope_symbol, ("alpha",), {}, "He-4"],
+    [isotope_symbol, (79, 197), {}, "Au-197"],
+    [isotope_symbol, ("p",), {}, "H-1"],
+    [isotope_symbol, ("beryllium-8",), {}, "Be-8"],
+    [isotope_symbol, ("N-13",), {}, "N-13"],
+    [isotope_symbol, ("p",), {}, "H-1"],
+    [isotope_symbol, ("proton",), {}, "H-1"],
+    [isotope_symbol, ("protium",), {}, "H-1"],
+    [isotope_symbol, ("N-13 2+",), {}, "N-13"],
+    [isotope_symbol, ("Hydrogen-3 +1",), {}, "T"],
+    [atomic_number, ["H"], {}, 1],
+    [atomic_number, ["D"], {}, 1],
+    [atomic_number, ["deuterium"], {}, 1],
+    [atomic_number, ["Deuterium"], {}, 1],
+    [atomic_number, ["tritium"], {}, 1],
+    [atomic_number, ["p"], {}, 1],
+    [atomic_number, ["P"], {}, 15],
+    [atomic_number, ["Alpha"], {}, 2],
+    [atomic_number, ["C-12"], {}, 6],
+    [atomic_number, ["Argon"], {}, 18],
+    [atomic_number, ["protium"], {}, 1],
+    [atomic_number, ["H-3"], {}, 1],
+    [atomic_number, ["p+"], {}, 1],
+    [atomic_number, ["Be-8"], {}, 4],
+    [atomic_number, ["N"], {}, 7],
+    [atomic_number, ["N 2+"], {}, 7],
+    [atomic_number, ["N +1"], {}, 7],
+    [atomic_number, ["N+++"], {}, 7],
+    [mass_number, ["helium-3"], {}, 3],
+    [mass_number, ["Au-197"], {}, 197],
+    [mass_number, ["deuterium"], {}, 2],
+    [mass_number, ["D"], {}, 2],
+    [mass_number, ["H-2"], {}, 2],
+    [mass_number, ["tritium"], {}, 3],
+    [mass_number, ["T"], {}, 3],
+    [mass_number, ["alpha"], {}, 4],
+    [mass_number, ["p"], {}, 1],
+    [mass_number, ["Be-8"], {}, 8],
+    [mass_number, ["N-13"], {}, 13],
+    [mass_number, ["N-13 2+"], {}, 13],
+    [mass_number, ["N-13 +2"], {}, 13],
+    [mass_number, ["N-13+++"], {}, 13],
+    [element_name, ["D"], {}, "hydrogen"],
+    [element_name, ["deuterium"], {}, "hydrogen"],
+    [element_name, ["Au"], {}, "gold"],
+    [element_name, ["alpha"], {}, "helium"],
+    [element_name, ["helium-4"], {}, "helium"],
+    [element_name, ["H-2"], {}, "hydrogen"],
+    [element_name, ["Deuterium"], {}, "hydrogen"],
+    [element_name, ["Hydrogen-3"], {}, "hydrogen"],
+    [element_name, ["hydrogen-3"], {}, "hydrogen"],
+    [element_name, ["H-3"], {}, "hydrogen"],
+    [element_name, ["tritium"], {}, "hydrogen"],
+    [element_name, ["Alpha"], {}, "helium"],
+    [element_name, ["alpha"], {}, "helium"],
+    [element_name, [1], {}, "hydrogen"],
+    [element_name, [26], {}, "iron"],
+    [element_name, [79], {}, "gold"],
+    [element_name, ["p"], {}, "hydrogen"],
+    [element_name, ["P"], {}, "phosphorus"],
+    [element_name, ["Be-8"], {}, "beryllium"],
+    [element_name, ["Li-7"], {}, "lithium"],
+    [element_name, ["N"], {}, "nitrogen"],
+    [element_name, ["N+++"], {}, "nitrogen"],
+    [element_name, ["D-"], {}, "hydrogen"],
+    [standard_atomic_weight, ["H"], {}, (1.008 * u.u).to(u.kg)],
+    [standard_atomic_weight, [1], {}, (1.008 * u.u).to(u.kg)],
+    [standard_atomic_weight, ["Hydrogen"], {}, (1.008 * u.u).to(u.kg)],
+    [standard_atomic_weight, ["Au"], {}, u.kg],
+    [particle_mass, ["proton"], {}, const.m_p],
+    [particle_mass, ["H-1+"], {}, const.m_p],
+    [particle_mass, ["H-1 +1"], {}, const.m_p],
+    [particle_mass, ["H-1 1+"], {}, const.m_p],
+    [particle_mass, ["H-1"], {"Z": 1}, const.m_p],
+    [particle_mass, ["hydrogen-1"], {"Z": 1}, const.m_p],
+    [particle_mass, ["p+"], {}, const.m_p],
+    [particle_mass, ["F-19"], {"Z": 3}, u.kg],
+    [particle_mass, ["H"], {}, standard_atomic_weight("H")],
+    [is_stable, ["H-1"], {}, True],
+    [is_stable, [1, 1], {}, True],
+    [is_stable, ["N-14"], {}, True],
+    [is_stable, ["N", 14], {}, True],
+    [is_stable, ["P-31"], {}, True],
+    [is_stable, ["P", 31], {}, True],
+    [is_stable, ["p"], {}, True],
+    [is_stable, ["alpha"], {}, True],
+    [is_stable, ["Xe-124"], {}, True],
+    [is_stable, ("Fe",), {"mass_numb": 56}, True],
+    [is_stable, ["Fe-56"], {}, True],
+    [is_stable, ["iron-56"], {}, True],
+    [is_stable, ["Iron-56"], {}, True],
+    [is_stable, [26, 56], {}, True],
+    [is_stable, ["Be-8"], {}, False],
+    [is_stable, ["U-235"], {}, False],
+    [is_stable, ["uranium-235"], {}, False],
+    [is_stable, ["T"], {}, False],
+    [is_stable, [4, 8], {}, False],
+    [is_stable, ["tritium"], {}, False],
+    [is_stable, ["Pb-209"], {}, False],
+    [is_stable, ["lead-209"], {}, False],
+    [is_stable, ["Lead-209"], {}, False],
+    [is_stable, ("Pb",), {"mass_numb": 209}, False],
+    [is_stable, [82, 209], {}, False],
+    [charge_number, ["H+"], {}, 1],
+    [charge_number, ["D +1"], {}, 1],
+    [charge_number, ["tritium 1+"], {}, 1],
+    [charge_number, ["H-"], {}, -1],
+    [charge_number, ["Fe -2"], {}, -2],
+    [charge_number, ["Fe 2-"], {}, -2],
+    [charge_number, ["N--"], {}, -2],
+    [charge_number, ["N++"], {}, 2],
+    [charge_number, ["alpha"], {}, 2],
+    [charge_number, ["proton"], {}, 1],
+    [charge_number, ["deuteron"], {}, 1],
+    [charge_number, ["triton"], {}, 1],
+    [charge_number, ["electron"], {}, -1],
+    [charge_number, ["e-"], {}, -1],
+    [charge_number, ["e+"], {}, 1],
+    [charge_number, ["positron"], {}, 1],
+    [charge_number, ["n"], {}, 0],
+    [charge_number, ["neutron"], {}, 0],
+    [charge_number, ["p-"], {}, -1],
+    [charge_number, ["antiproton"], {}, -1],
+    [electric_charge, ["p"], {}, u.C],
+    [electric_charge, ["p"], {}, 1.6021766208e-19 * u.C],
+    [electric_charge, ["e"], {}, -1.6021766208e-19 * u.C],
+    [electric_charge, ["alpha"], {}, 3.2043532416e-19 * u.C],
+    [electric_charge, ["n"], {}, 0 * u.C],
+    [half_life, ["H-1"], {}, u.s],
+    [half_life, ["tritium"], {}, u.s],
+    [half_life, ["H-1"], {}, np.inf * u.s],
 ]
 
-electric_charge_table = [
-    ["p", u.C],
-    ["p", 1.6021766208e-19 * u.C],
-    ["e", -1.6021766208e-19 * u.C],
-    ["alpha", 3.2043532416e-19 * u.C],
-    ["n", 0 * u.C],
-    ["badinput", InvalidParticleError],
-    ["h+", InvalidParticleError],
-    ["Au 81+", InvalidParticleError],
-    ["Au 81-", ParticleWarning],
-    ["H---", ParticleWarning],
-]
 
-half_life_table = [["H-1", u.s], ["tritium", u.s], ["H-1", np.inf * u.s]]
+@pytest.mark.parametrize(
+    "tested_function, args, kwargs, expected_output",
+    table_functions_args_kwargs_output,
+)
+def test_functions_and_values(tested_function, args, kwargs, expected_output):
+    run_test(tested_function, args, kwargs, expected_output)
 
 
 class TestInvalidPeriodicElement:
@@ -404,112 +267,6 @@ def test_periodic_table_group(self):
             periodic_table_group(("B", "Ti", "Ge"))
 
 
-# The tables above do not include the function to be tested in order to
-# avoid cluttering up the code.  The following block of code prepends
-# the correct function to each list containing args, kwargs, and the
-# expected outcome prior to being passed through to run_test.
-
-
-tables_and_functions = [
-    (atomic_symbol, atomic_symbol_table),
-    (isotope_symbol, isotope_symbol_table),
-    (atomic_number, atomic_number_table),
-    (mass_number, mass_number_table),
-    (element_name, element_name_table),
-    (standard_atomic_weight, standard_atomic_weight_table),
-    (is_stable, is_stable_table),
-    (particle_mass, particle_mass_table),
-    (charge_number, charge_number_table),
-    (electric_charge, electric_charge_table),
-    (half_life, half_life_table),
-]
-
-all_tests = []
-
-for func, table in tables_and_functions:
-    for inputs in table:
-        inputs.insert(0, func)
-        if len(inputs) == 3:
-            inputs.insert(2, {})
-    all_tests += table
-
-# Set up tests for a variety of atomic functions to make sure that bad
-# inputs lead to the expected errors.
-
-atomic_TypeError_funcs_table = [
-    atomic_symbol,
-    isotope_symbol,
-    atomic_number,
-    is_stable,
-    half_life,
-    mass_number,
-    element_name,
-    standard_atomic_weight,
-    nuclear_binding_energy,
-    nuclear_reaction_energy,
-]
-
-atomic_TypeError_badargs = [1.1, {"cats": "bats"}, 1 + 1j]
-
-atomic_ParticleErrors_funcs_table = [
-    atomic_symbol,
-    isotope_symbol,
-    atomic_number,
-    is_stable,
-    half_life,
-    mass_number,
-    element_name,
-    standard_atomic_weight,
-    particle_mass,
-    known_isotopes,
-    stable_isotopes,
-    common_isotopes,
-    isotopic_abundance,
-    charge_number,
-    electric_charge,
-]
-
-atomic_ParticleError_badargs = [
-    -1,
-    119,
-    "grumblemuffins",
-    "H-0",
-    "Og-294b",
-    "H-9343610",
-    "Fe 2+4",
-    "Fe+24",
-    "Fe +59",
-    "C++++++++++++++++",
-    "C-++++",
-    "h",
-    "d",
-    "he",
-    "au",
-    "alpha 1+",
-    "alpha-4",
-]
-
-metatable = [
-    (atomic_TypeError_funcs_table, atomic_TypeError_badargs, TypeError),
-    (
-        atomic_ParticleErrors_funcs_table,
-        atomic_ParticleError_badargs,
-        InvalidParticleError,
-    ),
-]
-
-for funcs, badargs, error in metatable:
-    for func in funcs:
-        for badarg in badargs:
-            all_tests += [[func, badarg, error]]
-
-
-@pytest.mark.parametrize("inputs", all_tests)
-def test_atomic_functions(inputs):
-    print(inputs)
-    run_test(inputs)
-
-
 # Next we have tests that do not fall nicely into equality comparisons.
 
 
diff --git a/plasmapy/particles/tests/test_exceptions.py b/plasmapy/particles/tests/test_exceptions.py
new file mode 100644
--- /dev/null
+++ b/plasmapy/particles/tests/test_exceptions.py
@@ -0,0 +1,1077 @@
+import itertools
+import numpy as np
+import pytest
+
+from astropy import units as u
+
+from plasmapy.particles import (
+    atomic_symbol,
+    IonizationState,
+    IonizationStateCollection,
+    nuclear_binding_energy,
+    nuclear_reaction_energy,
+)
+from plasmapy.particles.atomic import (
+    atomic_number,
+    common_isotopes,
+    electric_charge,
+    half_life,
+    integer_charge,
+    is_stable,
+    isotopic_abundance,
+    known_isotopes,
+    mass_number,
+    particle_mass,
+    stable_isotopes,
+    standard_atomic_weight,
+)
+from plasmapy.particles.exceptions import (
+    ChargeError,
+    InvalidElementError,
+    InvalidIsotopeError,
+    InvalidParticleError,
+    MissingParticleDataError,
+    ParticleError,
+    ParticleWarning,
+)
+from plasmapy.particles.nuclear import nuclear_binding_energy, nuclear_reaction_energy
+from plasmapy.particles.symbols import atomic_symbol, element_name, isotope_symbol
+from plasmapy.utils.exceptions import PlasmaPyFutureWarning
+
+tests_for_exceptions = {
+    "too few nstates": (
+        IonizationState,
+        [],
+        {"particle": "H", "ionic_fractions": [1.0]},
+        ParticleError,
+    ),
+    "too many nstates": (
+        IonizationState,
+        [],
+        {"particle": "H", "ionic_fractions": [1, 0, 0, 0]},
+        ParticleError,
+    ),
+    "ionic fraction < 0": (
+        IonizationState,
+        [],
+        {"particle": "He", "ionic_fractions": [-0.1, 0.1, 1]},
+        ParticleError,
+    ),
+    "ionic fraction > 1": (
+        IonizationState,
+        [],
+        {"particle": "He", "ionic_fractions": [1.1, 0.0, 0.0]},
+        ParticleError,
+    ),
+    "invalid ionic fraction": (
+        IonizationState,
+        [],
+        {"particle": "He", "ionic_fractions": [1.0, 0.0, "a"]},
+        ParticleError,
+    ),
+    "bad n_elem units": (
+        IonizationState,
+        [],
+        {"particle": "H", "ionic_fractions": [0, 1], "n_elem": 3 * u.m ** 3},
+        u.UnitTypeError,
+    ),
+    "bad T_e units": (
+        IonizationState,
+        [],
+        {"particle": "H", "ionic_fractions": [0, 1], "T_e": 1 * u.m},
+        u.UnitTypeError,
+    ),
+    "negative n_elem": (
+        IonizationState,
+        [],
+        {
+            "particle": "He",
+            "ionic_fractions": [1.0, 0.0, 0.0],
+            "n_elem": -1 * u.m ** -3,
+        },
+        ParticleError,
+    ),
+    "negative T_e": (
+        IonizationState,
+        [],
+        {"particle": "He", "ionic_fractions": [1.0, 0.0, 0.0], "T_e": -1 * u.K},
+        ParticleError,
+    ),
+    "redundant ndens": (
+        IonizationState,
+        [],
+        {
+            "particle": "H",
+            "ionic_fractions": np.array([3, 4]) * u.m ** -3,
+            "n_elem": 4 * u.m ** -3,
+        },
+        ParticleError,
+    ),
+    "wrong type": (IonizationStateCollection, [], {"inputs": None}, ParticleError),
+    "not normalized": (
+        IonizationStateCollection,
+        [],
+        {"inputs": {"He": [0.4, 0.5, 0.0]}, "tol": 1e-9},
+        ParticleError,
+    ),
+    "negative ionfrac": (
+        IonizationStateCollection,
+        [],
+        {"inputs": {"H": [-0.1, 1.1]}},
+        ParticleError,
+    ),
+    "ion": (
+        IonizationStateCollection,
+        [],
+        {"inputs": {"H": [0.1, 0.9], "He+": [0.0, 0.9, 0.1]}},
+        ParticleError,
+    ),
+    "repeat elements": (
+        IonizationStateCollection,
+        [],
+        {"inputs": {"H": [0.1, 0.9], "hydrogen": [0.2, 0.8]}},
+        ParticleError,
+    ),
+    "isotope of element": (
+        IonizationStateCollection,
+        [],
+        {"inputs": {"H": [0.1, 0.9], "D": [0.2, 0.8]}},
+        ParticleError,
+    ),
+    "negative abundance": (
+        IonizationStateCollection,
+        [],
+        {
+            "inputs": {"H": [0.1, 0.9], "He": [0.4, 0.5, 0.1]},
+            "abundances": {"H": 1, "He": -0.1},
+        },
+        ParticleError,
+    ),
+    "imaginary abundance": (
+        IonizationStateCollection,
+        [],
+        {
+            "inputs": {"H": [0.1, 0.9], "He": [0.4, 0.5, 0.1]},
+            "abundances": {"H": 1, "He": 0.1j},
+        },
+        ParticleError,
+    ),
+    "wrong density units": (
+        IonizationStateCollection,
+        [],
+        {
+            "inputs": {"H": [10, 90] * u.m ** -3, "He": [0.1, 0.9, 0] * u.m ** -2},
+            "abundances": {"H": 1, "He": 0.1},
+        },
+        ParticleError,
+    ),
+    "abundance redundance": (
+        IonizationStateCollection,
+        [],
+        {
+            "inputs": {"H": [10, 90] * u.m ** -3, "He": [0.1, 0.9, 0] * u.m ** -3},
+            "abundances": {"H": 1, "He": 0.1},
+        },
+        ParticleError,
+    ),
+    "abundance contradiction": (
+        IonizationStateCollection,
+        [],
+        {
+            "inputs": {"H": [10, 90] * u.m ** -3, "He": [0.1, 0.9, 0] * u.m ** -3},
+            "abundances": {"H": 1, "He": 0.11},
+        },
+        ParticleError,
+    ),
+    "kappa too small": (
+        IonizationStateCollection,
+        [],
+        {"inputs": ["H"], "kappa": 1.499999},
+        ParticleError,
+    ),
+    "negative n": (
+        IonizationStateCollection,
+        [],
+        {"inputs": ["H"], "n0": -1 * u.cm ** -3},
+        ParticleError,
+    ),
+    "negative T_e for collection": (
+        IonizationStateCollection,
+        [],
+        {"inputs": ["H-1"], "T_e": -1 * u.K},
+        ParticleError,
+    ),
+}
+
+
+@pytest.mark.parametrize(
+    ["tested_object", "args", "kwargs", "expected_exception"],
+    list(tests_for_exceptions.values()),
+    ids=list(tests_for_exceptions.keys()),
+)
+def test_named_tests_for_exceptions(tested_object, args, kwargs, expected_exception):
+    """
+    Test that appropriate exceptions are raised for inappropriate inputs
+    to `IonizationState` or `IonizationStateCollection`
+    """
+    with pytest.raises(expected_exception) as exc_info:
+        tested_object(*args, **kwargs)
+
+    assert expected_exception == exc_info.type
+
+
+tests_from_nuclear = [
+    [
+        nuclear_reaction_energy,
+        [],
+        {"reactants": ["n"], "products": 3},
+        pytest.raises(TypeError),
+    ],
+    [
+        nuclear_reaction_energy,
+        [],
+        {"reactants": ["n"], "products": ["He-4"]},
+        pytest.raises(ParticleError),
+    ],
+    [
+        nuclear_reaction_energy,
+        [],
+        {"reactants": ["h"], "products": ["H-1"]},
+        pytest.raises(ParticleError),
+    ],
+    [
+        nuclear_reaction_energy,
+        [],
+        {"reactants": ["e-", "n"], "products": ["p+"]},
+        pytest.raises(ParticleError),
+    ],
+    [
+        nuclear_reaction_energy,
+        [],
+        {"reactants": ["e+", "n"], "products": ["p-"]},
+        pytest.raises(ParticleError),
+    ],
+    [
+        nuclear_reaction_energy,
+        [],
+        {"reactants": ["ksdf"], "products": ["H-3"]},
+        pytest.raises(ParticleError),
+    ],
+    [
+        nuclear_reaction_energy,
+        [],
+        {"reactants": ["H"], "products": ["H-1"]},
+        pytest.raises(ParticleError),
+    ],
+    [
+        nuclear_reaction_energy,
+        [],
+        {"reactants": ["p"], "products": ["n", "n", "e-"]},
+        pytest.raises(ParticleError),
+    ],
+    [
+        nuclear_reaction_energy,
+        ["p --> p"],
+        {"reactants": "p", "products": "p"},
+        pytest.raises(ParticleError),
+    ],
+    [nuclear_binding_energy, ["H"], {}, pytest.raises(ParticleError)],
+    [nuclear_binding_energy, ["He-99"], {}, pytest.raises(InvalidParticleError)],
+    [
+        nuclear_binding_energy,
+        ["He"],
+        {"mass_numb": 99},
+        pytest.raises(InvalidParticleError),
+    ],
+    [nuclear_binding_energy, [3.1415926535j], {}, pytest.raises(TypeError)],
+]
+
+tests_from_atomic = [
+    [
+        atomic_symbol,
+        [
+            "H-0",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            3.14159,
+        ],
+        {},
+        pytest.raises(TypeError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "Og-294b",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "H-934361079326356530741942970523610389",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "Fe 2+4",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "Fe+24",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "Fe +59",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "C++++++++++++++++",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "C-++++",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "neutron",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "n",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "n-1",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "h",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "d",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "he",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "au",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "p-",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_symbol,
+        [
+            0,
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            119,
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_symbol,
+        [
+            "antiproton",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_number,
+        [
+            "H-3934",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_number,
+        [
+            "C-12b",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_number,
+        [
+            -1.5,
+        ],
+        {},
+        pytest.raises(TypeError),
+    ],
+    [
+        atomic_number,
+        [
+            "n",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_number,
+        [
+            "n-1",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_number,
+        [
+            "neutron",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_number,
+        [
+            "Neutron",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        atomic_number,
+        [
+            "d",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_number,
+        [
+            "t",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        atomic_number,
+        [
+            "s-36",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        mass_number,
+        [
+            "H-359",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        mass_number,
+        [
+            "C-12b",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        mass_number,
+        [
+            -1.5,
+        ],
+        {},
+        pytest.raises(TypeError),
+    ],
+    [
+        mass_number,
+        [
+            "N-13+-+-",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        mass_number,
+        [
+            "h-3",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        mass_number,
+        [
+            "n",
+        ],
+        {},
+        pytest.raises(InvalidIsotopeError),
+    ],
+    [
+        mass_number,
+        [
+            "n-1",
+        ],
+        {},
+        pytest.raises(InvalidIsotopeError),
+    ],
+    [
+        element_name,
+        [
+            "vegancupcakes",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            "C-+-",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            1.24,
+        ],
+        {},
+        pytest.raises(TypeError),
+    ],
+    [
+        element_name,
+        [
+            "n",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        element_name,
+        [
+            "neutron",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        element_name,
+        [
+            0,
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            "H++",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            "t",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            "pb",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            "d",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            "h-3",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            "Pb-9",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        element_name,
+        [
+            "H 2+",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "H-1",
+        ],
+        {},
+        pytest.raises(ParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "help i'm trapped in a unit test",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            1.1,
+        ],
+        {},
+        pytest.raises(TypeError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "n",
+        ],
+        {},
+        pytest.raises(InvalidElementError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "p",
+        ],
+        {},
+        pytest.raises(ParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "alpha",
+        ],
+        {},
+        pytest.raises(ParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "deuteron",
+        ],
+        {},
+        pytest.raises(ParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "tritium",
+        ],
+        {},
+        pytest.raises(ParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "Au+",
+        ],
+        {},
+        pytest.raises(ParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "Fe -2",
+        ],
+        {},
+        pytest.raises(ParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "Og 2+",
+        ],
+        {},
+        pytest.raises(ParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "h",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        standard_atomic_weight,
+        [
+            "fe",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        electric_charge,
+        [
+            "badinput",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        electric_charge,
+        [
+            "h+",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        electric_charge,
+        [
+            "Au 81+",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        electric_charge,
+        [
+            "Au 81-",
+        ],
+        {},
+        pytest.warns(ParticleWarning),
+    ],
+    [
+        electric_charge,
+        [
+            "H---",
+        ],
+        {},
+        pytest.warns(ParticleWarning),
+    ],
+    [
+        integer_charge,
+        [
+            "fads",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        integer_charge,
+        [
+            "H++",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        integer_charge,
+        [
+            "h+",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        integer_charge,
+        [
+            "fe 1+",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        integer_charge,
+        [
+            "d+",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        integer_charge,
+        [
+            "Fe 29+",
+        ],
+        {},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        integer_charge,
+        [
+            "H-1",
+        ],
+        {},
+        pytest.raises(ChargeError),
+    ],
+    [
+        integer_charge,
+        [
+            "H---",
+        ],
+        {},
+        pytest.warns(PlasmaPyFutureWarning),
+    ],
+    [
+        integer_charge,
+        [
+            "Fe -26",
+        ],
+        {},
+        pytest.warns(PlasmaPyFutureWarning),
+    ],
+    [
+        integer_charge,
+        [
+            "Og 10-",
+        ],
+        {},
+        pytest.warns(PlasmaPyFutureWarning),
+    ],
+    [
+        isotope_symbol,
+        ("Md-260",),
+        {"mass_numb": 261},
+        pytest.raises(InvalidParticleError),
+    ],
+    [
+        isotope_symbol,
+        ("protium",),
+        {"mass_numb": 2},
+        pytest.raises(InvalidParticleError),
+    ],
+    [isotope_symbol, ("alpha",), {"mass_numb": 3}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("O-18",), {"mass_numb": 19}, pytest.raises(InvalidParticleError)],
+    [
+        isotope_symbol,
+        ("lead-209",),
+        {"mass_numb": 511},
+        pytest.raises(InvalidParticleError),
+    ],
+    [isotope_symbol, ("He-1",), {}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, [24], {"mass_numb": 23}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("H",), {"mass_numb": 0}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("H-1",), {"mass_numb": 2}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("P",), {}, pytest.raises(InvalidIsotopeError)],
+    [isotope_symbol, [1], {}, pytest.raises(InvalidIsotopeError)],
+    [isotope_symbol, [4], {}, pytest.raises(InvalidIsotopeError)],
+    [isotope_symbol, ("hydrogen-444444",), {}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("Fe",), {"mass_numb": 2.1}, pytest.raises(TypeError)],
+    [isotope_symbol, ("He",), {"mass_numb": "c"}, pytest.raises(TypeError)],
+    [isotope_symbol, ("He-3",), {"mass_numb": 4}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("D",), {"mass_numb": 3}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("T",), {"mass_numb": 2}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("Fe",), {"mass_numb": None}, pytest.raises(InvalidIsotopeError)],
+    [isotope_symbol, ("He",), {"mass_numb": 99}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("d",), {}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("h-3",), {}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("h",), {}, pytest.raises(InvalidParticleError)],
+    [isotope_symbol, ("d+",), {}, pytest.raises(InvalidParticleError)],
+    [particle_mass, ["Og 1+"], {}, pytest.raises(MissingParticleDataError)],
+    [particle_mass, ["Fe-56"], {"Z": 1.4}, pytest.raises(TypeError)],
+    [particle_mass, ["H-1 +1"], {"Z": 0}, pytest.raises(InvalidParticleError)],
+    [particle_mass, [26], {"Z": 1, "mass_numb": "a"}, pytest.raises(TypeError)],
+    [
+        particle_mass,
+        [26],
+        {"Z": 27, "mass_numb": 56},
+        pytest.raises(InvalidParticleError),
+    ],
+    [particle_mass, ["Og"], {"Z": 1}, pytest.raises(MissingParticleDataError)],
+    [
+        particle_mass,
+        ["Og"],
+        {"mass_numb": 696, "Z": 1},
+        pytest.raises(InvalidParticleError),
+    ],
+    [particle_mass, ["He 1+"], {"mass_numb": 99}, pytest.raises(InvalidParticleError)],
+    [particle_mass, ["fe-56 1+"], {}, pytest.raises(InvalidParticleError)],
+    [is_stable, ["hydrogen-444444"], {}, pytest.raises(InvalidParticleError)],
+    [is_stable, ["hydrogen", 0], {}, pytest.raises(InvalidParticleError)],
+    [is_stable, [""], {}, pytest.raises(InvalidParticleError)],
+    [is_stable, ["pb-209"], {}, pytest.raises(InvalidParticleError)],
+    [is_stable, ["h"], {}, pytest.raises(InvalidParticleError)],
+    [is_stable, ["He"], {}, pytest.raises(InvalidIsotopeError)],
+    [is_stable, ["B"], {}, pytest.raises(InvalidIsotopeError)],
+    [particle_mass, ["H-1"], {"mass_numb": 1, "Z": 1}, pytest.warns(ParticleWarning)],
+    [isotope_symbol, ("H-1",), {"mass_numb": 1}, pytest.warns(ParticleWarning)],
+    [isotope_symbol, ("H-2",), {"mass_numb": 2}, pytest.warns(ParticleWarning)],
+    [isotope_symbol, ("T",), {"mass_numb": 3}, pytest.warns(ParticleWarning)],
+    [isotope_symbol, ("Li-6",), {"mass_numb": 6}, pytest.warns(ParticleWarning)],
+    [isotope_symbol, ("lithium-6",), {"mass_numb": 6}, pytest.warns(ParticleWarning)],
+    [isotope_symbol, ("alpha",), {"mass_numb": 4}, pytest.warns(ParticleWarning)],
+    [isotope_symbol, ("p",), {"mass_numb": 1}, pytest.warns(ParticleWarning)],
+]
+
+
+atomic_TypeError_funcs_table = [
+    atomic_symbol,
+    isotope_symbol,
+    atomic_number,
+    is_stable,
+    half_life,
+    mass_number,
+    element_name,
+    standard_atomic_weight,
+    nuclear_binding_energy,
+    nuclear_reaction_energy,
+]
+
+atomic_TypeError_badargs = [1.1, {"cats": "bats"}, 1 + 1j]
+
+atomic_ParticleErrors_funcs_table = [
+    atomic_symbol,
+    isotope_symbol,
+    atomic_number,
+    is_stable,
+    half_life,
+    mass_number,
+    element_name,
+    standard_atomic_weight,
+    particle_mass,
+    known_isotopes,
+    stable_isotopes,
+    common_isotopes,
+    isotopic_abundance,
+    integer_charge,
+    electric_charge,
+]
+
+atomic_ParticleError_badargs = [
+    -1,
+    119,
+    "grumblemuffins",
+    "H-0",
+    "Og-294b",
+    "H-9343610",
+    "Fe 2+4",
+    "Fe+24",
+    "Fe +59",
+    "C++++++++++++++++",
+    "C-++++",
+    "h",
+    "d",
+    "he",
+    "au",
+    "alpha 1+",
+    "alpha-4",
+]
+
+particle_error_tests = [
+    (function, [bad_argument], {}, pytest.raises(InvalidParticleError))
+    for function, bad_argument in itertools.product(
+        atomic_ParticleErrors_funcs_table, atomic_ParticleError_badargs
+    )
+]
+type_error_tests = [
+    (function, [bad_argument], {}, pytest.raises(TypeError))
+    for function, bad_argument in itertools.product(
+        atomic_TypeError_funcs_table, atomic_TypeError_badargs
+    )
+]
+
+
+@pytest.mark.parametrize(
+    ["tested_object", "args", "kwargs", "expectation"],
+    tests_from_nuclear + tests_from_atomic + particle_error_tests + type_error_tests,
+)
+def test_unnamed_tests_exceptions(tested_object, args, kwargs, expectation):
+    """
+    Test that appropriate exceptions are raised for inappropriate inputs
+    to `IonizationState`.
+    """
+    with expectation as exc_info:
+        tested_object(*args, **kwargs)
+
+    if hasattr(expectation, "expected_exception"):
+        assert type(expectation.expected_exception()) == exc_info.type
+
+    # TODO tbh given how ugly this is I don't think we should even be doing this check
+    if hasattr(expectation, "expected_warning"):
+        for expected_warning, recorded_warning in zip(
+            exc_info.expected_warning, exc_info.list
+        ):
+            assert expected_warning == recorded_warning.category
diff --git a/plasmapy/particles/tests/test_ionization_collection.py b/plasmapy/particles/tests/test_ionization_collection.py
--- a/plasmapy/particles/tests/test_ionization_collection.py
+++ b/plasmapy/particles/tests/test_ionization_collection.py
@@ -16,9 +16,9 @@
     mass_number,
     Particle,
     particle_symbol,
+    ParticleList,
 )
 from plasmapy.particles.exceptions import InvalidIsotopeError, ParticleError
-from plasmapy.particles.particle_collections import ParticleList
 from plasmapy.utils.pytest_helpers import run_test
 
 
@@ -743,75 +743,6 @@ def test_base_particles_equal_ionic_fraction_particles(self):
         )
 
 
-IE = collections.namedtuple("IE", ["inputs", "expected_exception"])
-
-tests_for_exceptions = {
-    "wrong type": IE({"inputs": None}, ParticleError),
-    "not normalized": IE(
-        {"inputs": {"He": [0.4, 0.5, 0.0]}, "tol": 1e-9}, ParticleError
-    ),
-    "negative ionfrac": IE({"inputs": {"H": [-0.1, 1.1]}}, ParticleError),
-    "ion": IE({"inputs": {"H": [0.1, 0.9], "He+": [0.0, 0.9, 0.1]}}, ParticleError),
-    "repeat elements": IE(
-        {"inputs": {"H": [0.1, 0.9], "hydrogen": [0.2, 0.8]}}, ParticleError
-    ),
-    "isotope of element": IE(
-        {"inputs": {"H": [0.1, 0.9], "D": [0.2, 0.8]}}, ParticleError
-    ),
-    "negative abundance": IE(
-        {
-            "inputs": {"H": [0.1, 0.9], "He": [0.4, 0.5, 0.1]},
-            "abundances": {"H": 1, "He": -0.1},
-        },
-        ParticleError,
-    ),
-    "imaginary abundance": IE(
-        {
-            "inputs": {"H": [0.1, 0.9], "He": [0.4, 0.5, 0.1]},
-            "abundances": {"H": 1, "He": 0.1j},
-        },
-        ParticleError,
-    ),
-    "wrong density units": IE(
-        {
-            "inputs": {"H": [10, 90] * u.m ** -3, "He": [0.1, 0.9, 0] * u.m ** -2},
-            "abundances": {"H": 1, "He": 0.1},
-        },
-        ParticleError,
-    ),
-    "abundance redundance": IE(
-        {
-            "inputs": {"H": [10, 90] * u.m ** -3, "He": [0.1, 0.9, 0] * u.m ** -3},
-            "abundances": {"H": 1, "He": 0.1},
-        },
-        ParticleError,
-    ),
-    "abundance contradiction": IE(
-        {
-            "inputs": {"H": [10, 90] * u.m ** -3, "He": [0.1, 0.9, 0] * u.m ** -3},
-            "abundances": {"H": 1, "He": 0.11},
-        },
-        ParticleError,
-    ),
-    "kappa too small": IE({"inputs": ["H"], "kappa": 1.499999}, ParticleError),
-    "negative n": IE({"inputs": ["H"], "n0": -1 * u.cm ** -3}, ParticleError),
-    "negative T_e": IE({"inputs": ["H-1"], "T_e": -1 * u.K}, ParticleError),
-}
-
-
-@pytest.mark.parametrize("test_name", tests_for_exceptions.keys())
-def test_exceptions_upon_instantiation(test_name):
-    """
-    Test that appropriate exceptions are raised for inappropriate inputs
-    to IonizationStateCollection when first instantiated.
-    """
-    run_test(
-        IonizationStateCollection,
-        kwargs=tests_for_exceptions[test_name].inputs,
-        expected_outcome=tests_for_exceptions[test_name].expected_exception,
-    )
-
-
 class TestIonizationStateCollectionDensityEqualities:
     """
     Test that IonizationStateCollection instances are equal or not equal to each
diff --git a/plasmapy/particles/tests/test_ionization_state.py b/plasmapy/particles/tests/test_ionization_state.py
--- a/plasmapy/particles/tests/test_ionization_state.py
+++ b/plasmapy/particles/tests/test_ionization_state.py
@@ -456,52 +456,6 @@ def test_State_equality_and_getitem(self):
         assert result_from_charge == result_from_symbol
 
 
-IE = collections.namedtuple("IE", ["inputs", "expected_exception"])
-
-tests_for_exceptions = {
-    "too few nstates": IE({"particle": "H", "ionic_fractions": [1.0]}, ParticleError),
-    "too many nstates": IE(
-        {"particle": "H", "ionic_fractions": [1, 0, 0, 0]}, ParticleError
-    ),
-    "ionic fraction < 0": IE(
-        {"particle": "He", "ionic_fractions": [-0.1, 0.1, 1]}, ParticleError
-    ),
-    "ionic fraction > 1": IE(
-        {"particle": "He", "ionic_fractions": [1.1, 0.0, 0.0]}, ParticleError
-    ),
-    "invalid ionic fraction": IE(
-        {"particle": "He", "ionic_fractions": [1.0, 0.0, "a"]}, ParticleError
-    ),
-    "bad n_elem units": IE(
-        {"particle": "H", "ionic_fractions": [0, 1], "n_elem": 3 * u.m ** 3},
-        u.UnitTypeError,
-    ),
-    "bad T_e units": IE(
-        {"particle": "H", "ionic_fractions": [0, 1], "T_e": 1 * u.m}, u.UnitTypeError
-    ),
-    "negative n_elem": IE(
-        {
-            "particle": "He",
-            "ionic_fractions": [1.0, 0.0, 0.0],
-            "n_elem": -1 * u.m ** -3,
-        },
-        ParticleError,
-    ),
-    "negative T_e": IE(
-        {"particle": "He", "ionic_fractions": [1.0, 0.0, 0.0], "T_e": -1 * u.K},
-        ParticleError,
-    ),
-    "redundant ndens": IE(
-        {
-            "particle": "H",
-            "ionic_fractions": np.array([3, 4]) * u.m ** -3,
-            "n_elem": 4 * u.m ** -3,
-        },
-        ParticleError,
-    ),
-}
-
-
 ions = ["Fe 6+", "p", "He-4 0+", "triton", "alpha", "Ne +0"]
 
 
@@ -515,12 +469,14 @@ def test_IonizationState_ionfracs_from_ion_input(ion):
     expected_ionic_fractions = np.zeros(ion_particle.atomic_number + 1)
     expected_ionic_fractions[ion_particle.charge_number] = 1.0
 
-    if not np.allclose(expected_ionic_fractions, actual_ionic_fractions, atol=1e-16):
-        pytest.fail(
-            f"The returned ionic fraction for IonizationState({repr(ion)}) "
-            f"should have entirely been in the Z = {ion_particle.charge_number} "
-            f"level, but was instead: {ionization_state.ionic_fractions}."
-        )
+    np.testing.assert_allclose(
+        expected_ionic_fractions,
+        actual_ionic_fractions,
+        atol=1e-16,
+        err_msg=f"The returned ionic fraction for IonizationState({repr(ion)}) "
+        f"should have entirely been in the Z = {ion_particle.integer_charge} "
+        f"level.",
+    )
 
 
 @pytest.mark.parametrize("ion", ions)
@@ -546,19 +502,6 @@ def test_IonizationState_base_particles_from_ion_input(ion):
         )
 
 
-@pytest.mark.parametrize("test", tests_for_exceptions.keys())
-def test_IonizationState_exceptions(test):
-    """
-    Test that appropriate exceptions are raised for inappropriate inputs
-    to `IonizationState`.
-    """
-    run_test(
-        IonizationState,
-        kwargs=tests_for_exceptions[test].inputs,
-        expected_outcome=tests_for_exceptions[test].expected_exception,
-    )
-
-
 expected_properties = {
     "T_e": 5000.0 * u.K,
     "tol": 2e-14,
diff --git a/plasmapy/particles/tests/test_nuclear.py b/plasmapy/particles/tests/test_nuclear.py
--- a/plasmapy/particles/tests/test_nuclear.py
+++ b/plasmapy/particles/tests/test_nuclear.py
@@ -3,6 +3,7 @@
 
 from astropy import constants as const
 from astropy import units as u
+from astropy.tests.helper import assert_quantity_allclose
 
 from plasmapy.particles.exceptions import InvalidParticleError, ParticleError
 from plasmapy.particles.nuclear import (
@@ -12,81 +13,6 @@
 )
 from plasmapy.utils.pytest_helpers import run_test, run_test_equivalent_calls
 
-test_nuclear_table = [
-    [nuclear_binding_energy, "p", {}, 0 * u.J],
-    [nuclear_binding_energy, "n", {}, 0 * u.J],
-    [nuclear_binding_energy, "p", {}, 0 * u.J],
-    [nuclear_binding_energy, "H", {}, ParticleError],
-    [nuclear_binding_energy, "He-99", {}, InvalidParticleError],
-    [nuclear_binding_energy, "He", {"mass_numb": 99}, InvalidParticleError],
-    [nuclear_binding_energy, 3.1415926535j, {}, TypeError],
-    [mass_energy, "e-", {}, (const.m_e * const.c ** 2).to(u.J)],
-    [mass_energy, "p+", {}, (const.m_p * const.c ** 2).to(u.J)],
-    [mass_energy, "H-1", {}, (const.m_p * const.c ** 2).to(u.J)],
-    [mass_energy, "H-1 0+", {}, (const.m_p * const.c ** 2).to(u.J)],
-    [mass_energy, "n", {}, (const.m_n * const.c ** 2).to(u.J)],
-    [nuclear_reaction_energy, (), {"reactants": ["n"], "products": 3}, TypeError],
-    [
-        nuclear_reaction_energy,
-        (),
-        {"reactants": ["n"], "products": ["He-4"]},
-        ParticleError,
-    ],
-    [
-        nuclear_reaction_energy,
-        (),
-        {"reactants": ["h"], "products": ["H-1"]},
-        ParticleError,
-    ],
-    [
-        nuclear_reaction_energy,
-        (),
-        {"reactants": ["e-", "n"], "products": ["p+"]},
-        ParticleError,
-    ],
-    [
-        nuclear_reaction_energy,
-        (),
-        {"reactants": ["e+", "n"], "products": ["p-"]},
-        ParticleError,
-    ],
-    [
-        nuclear_reaction_energy,
-        (),
-        {"reactants": ["ksdf"], "products": ["H-3"]},
-        ParticleError,
-    ],
-    [
-        nuclear_reaction_energy,
-        (),
-        {"reactants": ["H"], "products": ["H-1"]},
-        ParticleError,
-    ],
-    [
-        nuclear_reaction_energy,
-        (),
-        {"reactants": ["p"], "products": ["n", "n", "e-"]},
-        ParticleError,
-    ],
-    [nuclear_reaction_energy, "H + H --> H", {}, ParticleError],
-    [nuclear_reaction_energy, "H + H", {}, ParticleError],
-    [nuclear_reaction_energy, 1, {}, TypeError],
-    [nuclear_reaction_energy, "H-1 + H-1 --> H-1", {}, ParticleError],
-    [nuclear_reaction_energy, "p --> n", {}, ParticleError],
-    [
-        nuclear_reaction_energy,
-        "p --> p",
-        {"reactants": "p", "products": "p"},
-        ParticleError,
-    ],
-]
-
-
-@pytest.mark.parametrize("test_inputs", test_nuclear_table)
-def test_nuclear(test_inputs):
-    run_test(*test_inputs, rtol=1e-3)
-
-
 test_nuclear_equivalent_calls_table = [
     [nuclear_binding_energy, ["He-4", {}], ["alpha", {}], ["He", {"mass_numb": 4}]]
 ]
@@ -178,3 +104,22 @@ def test_nuclear_reaction_energy():
     expected = 17.6 * u.MeV
     actual = nuclear_reaction_energy(reactants=reactants, products=products)
     assert u.isclose(actual, expected, rtol=1e-3)
+
+
+table_of_nuclear_tests = [
+    [nuclear_binding_energy, ["p"], {}, 0 * u.J],
+    [nuclear_binding_energy, ["n"], {}, 0 * u.J],
+    [nuclear_binding_energy, ["p"], {}, 0 * u.J],
+    [mass_energy, ["e-"], {}, (const.m_e * const.c ** 2).to(u.J)],
+    [mass_energy, ["p+"], {}, (const.m_p * const.c ** 2).to(u.J)],
+    [mass_energy, ["H-1"], {}, (const.m_p * const.c ** 2).to(u.J)],
+    [mass_energy, ["H-1 0+"], {}, (const.m_p * const.c ** 2).to(u.J)],
+    [mass_energy, ["n"], {}, (const.m_n * const.c ** 2).to(u.J)],
+]
+
+
+@pytest.mark.parametrize(
+    ["tested_object", "args", "kwargs", "expected_value"], table_of_nuclear_tests
+)
+def test_nuclear_table(tested_object, args, kwargs, expected_value):
+    run_test(tested_object, args, kwargs, expected_value, rtol=1e-3)
diff --git a/plasmapy/utils/tests/test_roman.py b/plasmapy/utils/tests/test_roman.py
--- a/plasmapy/utils/tests/test_roman.py
+++ b/plasmapy/utils/tests/test_roman.py
@@ -139,17 +139,16 @@
     (np.int64(14), "XIV"),
 ]
 
-toRoman_exceptions_table = [
-    ("X", TypeError),
-    (-1, roman.OutOfRangeError),
-    (0, roman.OutOfRangeError),
-    (5000, roman.OutOfRangeError),
-]
-
-fromRoman_exceptions_table = [
-    ("asdfasd", roman.InvalidRomanNumeralError),
-    (1, TypeError),
-    ("xi", roman.InvalidRomanNumeralError),
+exceptions_table = [
+    (roman.to_roman, "X", TypeError),
+    (roman.to_roman, -1, roman.OutOfRangeError),
+    (roman.to_roman, 0, roman.OutOfRangeError),
+    (roman.to_roman, 5000, roman.OutOfRangeError),
+    (roman.from_roman, "asdfasd", roman.InvalidRomanNumeralError),
+    (roman.from_roman, 1, TypeError),
+    (roman.from_roman, "xi", roman.InvalidRomanNumeralError),
+    (roman.is_roman_numeral, 1, TypeError),  # TODO: tbh I would just return False here?
+    (roman.is_roman_numeral, ("I", "II"), TypeError),
 ]
 
 
@@ -157,50 +156,31 @@
 def test_to_roman(integer, roman_numeral):
     """
     Test that `~plasmapy.utils.roman.to_roman` correctly converts
-    integers to Roman numerals.
+    integers to Roman numerals, and that the inverse is true as well.
     """
     run_test(func=roman.to_roman, args=integer, expected_outcome=roman_numeral)
-
-
-@pytest.mark.parametrize("integer, roman_numeral", ints_and_roman_numerals)
-def test_from_roman(integer, roman_numeral):
-    """
-    Test that `~plasmapy.utils.roman.from_roman` correctly converts
-    Roman numerals to integers.
-    """
     run_test(func=roman.from_roman, args=roman_numeral, expected_outcome=int(integer))
 
 
-@pytest.mark.parametrize("input, expected_exception", toRoman_exceptions_table)
-def test_to_roman_exceptions(input, expected_exception):
-    """
-    Test that `~plasmapy.utils.roman.to_roman` raises the correct
-    exceptions when necessary.
-    """
-    run_test(func=roman.to_roman, args=input, expected_outcome=expected_exception)
-
-
-@pytest.mark.parametrize("input, expected_exception", fromRoman_exceptions_table)
-def test_from_roman_exceptions(input, expected_exception):
+@pytest.mark.parametrize("function, argument, expected_exception", exceptions_table)
+def test_to_roman_exceptions(function, argument, expected_exception):
     """
-    Test that `~plasmapy.utils.roman.from_roman` raises the correct
+    Test that `~plasmapy.utils.roman` functions raise the correct
     exceptions when necessary.
     """
-    run_test(func=roman.from_roman, args=input, expected_outcome=expected_exception)
+    run_test(func=function, args=argument, expected_outcome=expected_exception)
 
 
 test_is_roman_numeral_table = [
     ("I", True),
     ("i", False),
     ("CLXXXVIII", True),
-    (1, TypeError),
     ("khjfda", False),
     ("VIIII", False),
     ("IXX", False),
-    (("I", "II"), TypeError),
 ]
 
 
-@pytest.mark.parametrize("input, expected", test_is_roman_numeral_table)
-def test_is_roman_numeral(input, expected):
-    run_test(func=roman.is_roman_numeral, args=input, expected_outcome=expected)
+@pytest.mark.parametrize("argument, expected", test_is_roman_numeral_table)
+def test_is_roman_numeral(argument, expected):
+    run_test(func=roman.is_roman_numeral, args=argument, expected_outcome=expected)