Repository: openpathsampling/openpathsampling (language: python)

Issue:
Python 3.12 breaks `nose`; all `nose` based testing should be removed
To be honest, we should have removed the `nose` requirement when we switched to pytest. But there were enough legacy tests that it was a headache to switch. Now it becomes actually important.

Apparently the main issue is that Python 3.12 [removed the `imp` module](https://docs.python.org/3.12/whatsnew/3.12.html), so `nose` now raises import errors. The best solution, by far, is for us to finally get rid of nose-based testing.


Discussion / hints:

Fix patch:
diff --git a/.coveragerc b/.coveragerc
index 4cc9f5177..5c8936335 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,7 +1,6 @@
 [report]
 omit = 
     */python?.?/*
-    */site-packages/nose/*
     */openpathsampling/tests/*
     */mdtraj/*
     */openpathsampling/experimental/*
diff --git a/.gitignore b/.gitignore
index 295a7407d..607e931bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -96,7 +96,6 @@ htmlcov/
 .tox/
 .coverage
 .cache
-nosetests.xml
 coverage.xml
 
 # Translations
diff --git a/docs/developers/index.rst b/docs/developers/index.rst
index 24d401e1d..c0d20c4d6 100644
--- a/docs/developers/index.rst
+++ b/docs/developers/index.rst
@@ -32,7 +32,7 @@ standard.
 .. rubric:: Tests and Examples
 
 Additions to OPS should include thorough tests. We use `pytest`_ to run our
-tests, although we require `nose`_ for some legacy portions of the tests.
+tests.
 Unit/integration tests are located in the ``openpathsampling/tests/``
 directory.  Examples and integration tests should be written as Jupyter
 notebooks and placed in the ``examples/`` directory.  Pull requests to the
@@ -40,7 +40,6 @@ OPS GitHub repository will automatically run all unit tests with each push.
 We also run a subset of the system tests on each push, using `ipynbtest`_.
 
 .. _pytest: http://pytest.org
-.. _nose: http://nose.readthedocs.io/
 .. _ipynbtest: https://github.com/jhprinz/ipynb-test
 
 -----
diff --git a/docs/install.rst b/docs/install.rst
index 856e2e47c..0e9c93100 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -120,10 +120,10 @@ Testing your installation
 
 OpenPathSampling includes a thorough test suite, and running the test suite
 is a good start to troubleshooting any installation problems. The OPS test
-suite requires the packages ``pytest`` and (for legacy reasons) ``nose``.
-These can be  installed with either ``conda`` or ``pip``. For example: ::
+suite requires ``pytest``, which
+can be installed with either ``conda`` or ``pip``. For example: ::
 
-  $ conda install pytest nose
+  $ conda install pytest
 
 Once those are installed, you can run the test suite on your installation
 with the command: ::
diff --git a/setup.cfg b/setup.cfg
index 066dc0090..bcf29bb81 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -26,8 +26,7 @@ classifiers =
 
 [options]
 include_package_data = True
-python_requires = >3.7,<3.12
-# pin to <3.12 until nose is removed from testing
+python_requires = >3.7
 install_requires = 
     future
     psutil
@@ -49,7 +48,6 @@ packages = find:
 
 [options.extras_require]
 test = 
-    nose
     pytest
     pytest-cov
     coveralls


Test patch:
diff --git a/.autorelease/test-testpypi b/.autorelease/test-testpypi
index 7c3b02fb2..f1fc4c695 100644
--- a/.autorelease/test-testpypi
+++ b/.autorelease/test-testpypi
@@ -1,4 +1,4 @@
 #!/bin/bash
 
-python -m pip install pytest nose sqlalchemy
+python -m pip install pytest sqlalchemy
 py.test --pyargs openpathsampling.tests
diff --git a/devtools/ci/pytests.sh b/devtools/ci/pytests.sh
index 97fe8c8e0..ab3ffccaa 100755
--- a/devtools/ci/pytests.sh
+++ b/devtools/ci/pytests.sh
@@ -5,7 +5,6 @@ echo Run pytest tests ...
 
 testfail=0
 pytest -vv -s --cov --cov-report xml:cov.xml || testfail=1
-#nosetests -v -s --with-coverage || testfail=1
 COVERALLS_PARALLEL=true coveralls
 echo travis_fold:end:pytests
 
diff --git a/devtools/minimal_testing.txt b/devtools/minimal_testing.txt
index c3f4152f8..c7c53a12c 100644
--- a/devtools/minimal_testing.txt
+++ b/devtools/minimal_testing.txt
@@ -1,4 +1,3 @@
-nose
 pytest
 pytest-cov
 coveralls
diff --git a/examples/tests/test_cv.ipynb b/examples/tests/test_cv.ipynb
index bc71383c1..88f1b2747 100644
--- a/examples/tests/test_cv.ipynb
+++ b/examples/tests/test_cv.ipynb
@@ -6,7 +6,7 @@
    "source": [
     "### Test of CV functionality. \n",
     "\n",
-    "Most storage related tests are nosetests now. So look in `testcollectivevariable.py` please."
+    "Most storage related tests are unit tests now. So look in `testcollectivevariable.py` please."
    ]
   },
   {
@@ -620,7 +620,7 @@
  "metadata": {
   "anaconda-cloud": {},
   "kernelspec": {
-   "display_name": "Python 3",
+   "display_name": "Python 3 (ipykernel)",
    "language": "python",
    "name": "python3"
   },
@@ -634,7 +634,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.7.3"
+   "version": "3.11.7"
   },
   "toc": {
    "base_numbering": 1,
@@ -680,5 +680,5 @@
   }
  },
  "nbformat": 4,
- "nbformat_minor": 1
+ "nbformat_minor": 4
 }
diff --git a/openpathsampling/tests/pathsimulators/test_hooks.py b/openpathsampling/tests/pathsimulators/test_hooks.py
index 3a23e94bf..0cd3acc75 100644
--- a/openpathsampling/tests/pathsimulators/test_hooks.py
+++ b/openpathsampling/tests/pathsimulators/test_hooks.py
@@ -1,7 +1,4 @@
 from __future__ import absolute_import
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises)
-from nose.plugins.skip import Skip, SkipTest
 
 import io
 import sys
@@ -105,15 +102,15 @@ def test_attach_hooks_class(self):
         sim = TrivialPathSimulator(storage=None)
         sim.attach_hook(hook)
         for k in sim.hook_names:
-            assert_equal(len(sim.hooks[k]), 1)
+            assert len(sim.hooks[k]) == 1
 
     def test_attach_hooks_method(self):
         hook_instance = StupiderHook()
         sim = NoStepHookPathSimulator(storage=None)
         sim.attach_hook(hook_instance.hook_method, hook_for='extra_hook')
-        assert_not_equal(hook_instance.foo, "foo")
+        assert hook_instance.foo != "foo"
         sim.run(1)
-        assert_equal(hook_instance.foo, "foo")
+        assert hook_instance.foo == "foo"
 
     def test_trivial_simulation_hooks(self):
         sim = TrivialPathSimulator(storage=None)
@@ -125,31 +122,31 @@ def test_trivial_simulation_hooks(self):
                                                              "foo")
         sim.attach_hook(extra, hook_for='after_simulation')
         # before running, check that state is as expected
-        assert_equal(stupid.began_simulation, False)
-        assert_equal(stupid.finished_simulation, False)
-        assert_equal(stupid.began_steps, 0)
-        assert_equal(stupid.finished_steps, 0)
-        assert_not_equal(stupider.foo, "foo")
+        assert stupid.began_simulation is False
+        assert stupid.finished_simulation is False
+        assert stupid.began_steps == 0
+        assert stupid.finished_steps == 0
+        assert stupider.foo != "foo"
         # run
         sim.run(3)
         # check results
-        assert_equal(stupid.began_simulation, True)
-        assert_equal(stupid.finished_simulation, True)
-        assert_equal(stupid.began_steps, 3)
-        assert_equal(stupid.finished_steps, 3)
-        assert_equal(stupider.foo, "foo")
+        assert stupid.began_simulation is True
+        assert stupid.finished_simulation is True
+        assert stupid.began_steps == 3
+        assert stupid.finished_steps == 3
+        assert stupider.foo == "foo"
 
-    @raises(TypeError)
     def test_bad_extra_hook_method(self):
         sim = NoStepHookPathSimulator(storage=None)
         stupid = StupidHook()
-        sim.attach_hook(stupid)
+        with pytest.raises(TypeError):
+            sim.attach_hook(stupid)
 
-    @raises(TypeError)
     def test_bad_hook_name(self):
         sim = NoStepHookPathSimulator(storage=None)
         stupider = StupiderHook()
-        sim.attach_hook(stupider.hook_method, "blah")
+        with pytest.raises(TypeError):
+            sim.attach_hook(stupider.hook_method, "blah")
 
     def test_no_step_hook_simulation_hooks(self):
         sim = NoStepHookPathSimulator(storage=None)
@@ -158,15 +155,15 @@ def test_no_step_hook_simulation_hooks(self):
         sim.attach_hook(stupid.before_simulation,
                         hook_for='before_simulation')
         sim.attach_hook(stupider.hook_method, hook_for='extra_hook')
-        assert_equal(len(sim.hooks), len(sim.hook_names))
+        assert len(sim.hooks) == len(sim.hook_names)
         for hook in sim.hooks:
-            assert_equal(len(sim.hooks[hook]), 1)
+            assert len(sim.hooks[hook]) == 1
 
-        assert_equal(stupid.began_simulation, False)
-        assert_not_equal(stupider.foo, "foo")
+        assert stupid.began_simulation is False
+        assert stupider.foo != "foo"
         sim.run(1)
-        assert_equal(stupid.began_simulation, True)
-        assert_equal(stupider.foo, "foo")
+        assert stupid.began_simulation is True
+        assert stupider.foo == "foo"
 
 
 class TestSelfOrSimProperty(object):
diff --git a/openpathsampling/tests/test_attribute.py b/openpathsampling/tests/test_attribute.py
index 88226ee33..dd163a066 100644
--- a/openpathsampling/tests/test_attribute.py
+++ b/openpathsampling/tests/test_attribute.py
@@ -5,8 +5,6 @@
 from .test_helpers import data_filename, assert_close_unit, make_1d_traj, md
 import pytest
 
-from nose.plugins.skip import SkipTest
-
 import openpathsampling.engines.openmm as peng
 from openpathsampling.netcdfplus import FunctionPseudoAttribute
 
@@ -17,7 +15,7 @@
 class TestFunctionPseudoAttribute(object):
     def setup_method(self):
         if not md:
-            raise SkipTest("mdtraj not installed")
+            pytest.skip("mdtraj not installed")
         self.mdtraj = md.load(data_filename("ala_small_traj.pdb"))
         pytest.importorskip("simtk.unit")
         self.traj_topology = peng.trajectory_from_mdtraj(self.mdtraj)
diff --git a/openpathsampling/tests/test_bias_function.py b/openpathsampling/tests/test_bias_function.py
index 57196b04a..faea98bb0 100644
--- a/openpathsampling/tests/test_bias_function.py
+++ b/openpathsampling/tests/test_bias_function.py
@@ -4,10 +4,10 @@
 from builtins import range
 from builtins import object
 from past.utils import old_div
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises, assert_in)
 
-from nose.plugins.skip import Skip, SkipTest
+import pytest
+import numpy.testing as npt
+
 from .test_helpers import true_func, assert_equal_array_array, make_1d_traj
 
 import numpy as np
@@ -86,7 +86,7 @@ def test_bias_ensemble_new_to_old(self):
         }
         for change in list(change_vals.keys()):
             test_val = min(1.0, change_vals[change])
-            assert_almost_equal(
+            npt.assert_almost_equal(
                 self.bias.probability_new_to_old(self.sample_set, change),
                 test_val
             )
@@ -106,7 +106,7 @@ def test_bias_ensemble_old_to_new(self):
         }
         for change in list(change_vals.keys()):
             test_val = min(1.0, change_vals[change])
-            assert_almost_equal(
+            npt.assert_almost_equal(
                 self.bias.probability_old_to_new(self.sample_set, change),
                 test_val
             )
@@ -134,13 +134,13 @@ def test_combo_bias(self):
         ])
         change_210 = move_210.move(self.sample_set)
 
-        # assert_almost_equal(
+        # npt.assert_almost_equal(
             # self.bias.probability_old_to_new(change_210, self.sample_set), 1.0
         # )
-        # assert_almost_equal(
+        # npt.assert_almost_equal(
             # self.bias.probability_new_to_old(change_210, self.sample_set), 0.2
         # )
-        raise SkipTest
+        pytest.skip()
 
     def test_add_biases(self):
         # this is where we combine multiple biases into one
@@ -180,12 +180,12 @@ def test_add_biases(self):
         bias_C = BiasEnsembleTable.ratios_from_dictionary(dict_C)
         bias_AB = bias_A + bias_B
         # check the ensembles_to_ids
-        assert_equal(len(bias_AB.ensembles_to_ids), 7)
+        assert len(bias_AB.ensembles_to_ids) == 7
         for ens in ens_A:
-            assert_in(bias_AB.ensembles_to_ids[ens], [0, 1, 2])
+            assert bias_AB.ensembles_to_ids[ens] in [0, 1, 2]
         for ens in ens_B:
-            assert_in(bias_AB.ensembles_to_ids[ens], [3, 4, 5])
-        assert_equal(bias_AB.ensembles_to_ids[ms_outer], 6)
+            assert bias_AB.ensembles_to_ids[ens] in [3, 4, 5]
+        assert bias_AB.ensembles_to_ids[ms_outer] == 6
 
         # check values
         df_A = bias_A.dataframe
@@ -203,14 +203,14 @@ def test_add_biases(self):
                 col_AB = bias_AB.ensembles_to_ids[ens2]
                 val_A = df_A.loc[idx_A, col_A]
                 val_AB = df_AB.loc[idx_AB, col_AB]
-                assert_equal(val_A, val_AB)
+                assert val_A == val_AB
             for ens2 in ens_B:
                 col_AB = bias_AB.ensembles_to_ids[ens2]
-                assert_equal(np.isnan(df_AB.loc[idx_AB, col_AB]), True)
-            assert_equal(df_A.loc[idx_A, col_A_msouter],
-                         df_AB.loc[idx_AB, col_AB_msouter])
-            assert_equal(df_A.loc[col_A_msouter, idx_A],
-                         df_AB.loc[col_AB_msouter, idx_AB])
+                assert np.isnan(df_AB.loc[idx_AB, col_AB])
+            assert (df_A.loc[idx_A, col_A_msouter]
+                    == df_AB.loc[idx_AB, col_AB_msouter])
+            assert (df_A.loc[col_A_msouter, idx_A]
+                    == df_AB.loc[col_AB_msouter, idx_AB])
 
         for ens1 in ens_B:
             idx_B = bias_B.ensembles_to_ids[ens1]
@@ -220,14 +220,14 @@ def test_add_biases(self):
                 col_AB = bias_AB.ensembles_to_ids[ens2]
                 val_B = df_B.loc[idx_B, col_B]
                 val_AB = df_AB.loc[idx_AB, col_AB]
-                assert_equal(val_B, val_AB)
+                assert val_B == val_AB
             for ens2 in ens_A:
                 col_AB = bias_AB.ensembles_to_ids[ens2]
-                assert_equal(np.isnan(df_AB.loc[idx_AB, col_AB]), True)
-            assert_equal(df_B.loc[idx_B, col_B_msouter],
-                         df_AB.loc[idx_AB, col_AB_msouter])
-            assert_equal(df_B.loc[col_B_msouter, idx_B],
-                         df_AB.loc[col_AB_msouter, idx_AB])
+                assert np.isnan(df_AB.loc[idx_AB, col_AB])
+            assert (df_B.loc[idx_B, col_B_msouter]
+                    == df_AB.loc[idx_AB, col_AB_msouter])
+            assert (df_B.loc[col_B_msouter, idx_B]
+                    == df_AB.loc[col_AB_msouter, idx_AB])
 
         # just to make sure no errors raise when there are NaNs in table
         bias_ABC = bias_A + bias_B + bias_C
@@ -265,27 +265,26 @@ def test_bias_from_network(self):
         # check reciprocal of symmetric partners
         for i in range(4):
             for j in range(i, 4):
-                assert_equal(bias.dataframe.loc[i, j],
-                             old_div(1.0, bias.dataframe.loc[j, i]))
+                assert (bias.dataframe.loc[i, j]
+                        == old_div(1.0, bias.dataframe.loc[j, i]))
 
         for i in range(len(transition.ensembles) - 1):
             ens_to = transition.ensembles[i]
             ens_from = transition.ensembles[i + 1]
-            assert_equal(bias.bias_value(ens_from, ens_to), 0.5)
+            assert bias.bias_value(ens_from, ens_to) == 0.5
 
         for i in range(len(transition.ensembles) - 2):
             ens_to = transition.ensembles[i]
             ens_from = transition.ensembles[i + 2]
-            assert_equal(bias.bias_value(ens_from, ens_to), 0.25)
+            assert bias.bias_value(ens_from, ens_to) == 0.25
 
-    @raises(RuntimeError)
     def test_fail_without_tcp(self):
         network = paths.MISTISNetwork([
             (self.stateA, self.ifacesA, self.stateB)
         ])
-        bias = paths.SRTISBiasFromNetwork(network)
+        with pytest.raises(RuntimeError):
+            bias = paths.SRTISBiasFromNetwork(network)
 
-    @raises(RuntimeError)
     def test_fail_without_lambdas(self):
         fake_ifaceA = paths.InterfaceSet(cv=self.ifacesA.cv,
                                          volumes=self.ifacesA.volumes,
@@ -294,7 +293,8 @@ def test_fail_without_lambdas(self):
             (self.stateA, fake_ifaceA, self.stateB)
         ])
         network.sampling_transitions[0].tcp = self.tcp_A
-        bias = paths.SRTISBiasFromNetwork(network)
+        with pytest.raises(RuntimeError):
+            bias = paths.SRTISBiasFromNetwork(network)
 
     def test_bias_from_ms_network(self):
         ms_outer = paths.MSOuterTISInterface.from_lambdas(
@@ -333,27 +333,25 @@ def test_bias_from_ms_network(self):
         for i in range(len(transition_AB.ensembles) - 1):
             ens_to = transition_AB.ensembles[i]
             ens_from = transition_AB.ensembles[i + 1]
-            assert_almost_equal(bias.bias_value(ens_from, ens_to), 0.5)
+            npt.assert_almost_equal(bias.bias_value(ens_from, ens_to), 0.5)
 
         for i in range(len(transition_BA.ensembles) - 1):
             ens_to = transition_BA.ensembles[i]
             ens_from = transition_BA.ensembles[i + 1]
-            assert_almost_equal(bias.bias_value(ens_from, ens_to), 0.2)
+            npt.assert_almost_equal(bias.bias_value(ens_from, ens_to), 0.2)
 
         for ensA in transition_AB.ensembles:
             for ensB in transition_BA.ensembles:
-                assert_equal(np.isnan(bias.bias_value(ensA, ensB)), True)
-                assert_equal(np.isnan(bias.bias_value(ensB, ensA)), True)
+                assert np.isnan(bias.bias_value(ensA, ensB))
+                assert np.isnan(bias.bias_value(ensB, ensA))
 
-        assert_almost_equal(bias.bias_value(transition_BA.ensembles[-1],
-                                            network.ms_outers[0]),
+        npt.assert_almost_equal(bias.bias_value(transition_BA.ensembles[-1],
+                                                network.ms_outers[0]),
                             old_div(5.0, 2))
-        assert_almost_equal(bias.bias_value(transition_AB.ensembles[-1],
-                                            network.ms_outers[0]),
+        npt.assert_almost_equal(bias.bias_value(transition_AB.ensembles[-1],
+                                                network.ms_outers[0]),
                             old_div(2.0, 2))
 
 
 
 
-
-        raise SkipTest
diff --git a/openpathsampling/tests/test_channel_analysis.py b/openpathsampling/tests/test_channel_analysis.py
index 708615a1c..2cfb16686 100644
--- a/openpathsampling/tests/test_channel_analysis.py
+++ b/openpathsampling/tests/test_channel_analysis.py
@@ -1,8 +1,7 @@
 from __future__ import absolute_import
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, raises,
-                        assert_almost_equal)
-from nose.plugins.skip import SkipTest
+import pytest
+
 from numpy.testing import assert_array_almost_equal
 from .test_helpers import make_1d_traj, data_filename, assert_items_equal
 
@@ -85,7 +84,7 @@ def test_storage(self):
 
         new_store = paths.Storage(data_filename('test.nc'), 'r')
         reloaded = storage.tag['analyzer']
-        assert_equal(reloaded._results, self.toy_results)
+        assert reloaded._results == self.toy_results
 
         if os.path.isfile(data_filename('test.nc')):
             os.remove(data_filename('test.nc'))
@@ -96,8 +95,8 @@ def test_analyze_incr_decr(self):
             paths.MCStep(mccycle=1, active=self.decr_1)
         ]
         results = paths.ChannelAnalysis(steps, self.channels)
-        assert_equal(results._results,
-                     {'incr': [(0,1)], 'decr': [(1,2)], None: []})
+        expected = {'incr': [(0,1)], 'decr': [(1,2)], None: []}
+        assert results._results == expected
 
     def test_analyze_incr_incr(self):
         steps = [
@@ -105,8 +104,7 @@ def test_analyze_incr_incr(self):
             paths.MCStep(mccycle=1, active=self.incr_2)
         ]
         results = paths.ChannelAnalysis(steps, self.channels)
-        assert_equal(results._results,
-                     {'incr': [(0,2)], 'decr': [], None: []})
+        assert results._results == {'incr': [(0,2)], 'decr': [], None: []}
 
     def test_analyze_incr_both_decr(self):
         steps = [
@@ -116,8 +114,8 @@ def test_analyze_incr_both_decr(self):
             paths.MCStep(mccycle=3, active=self.decr_1)
         ]
         results = paths.ChannelAnalysis(steps, self.channels)
-        assert_equal(results._results,
-                     {'incr': [(0,3)], 'decr': [(1,4)], None: []})
+        expected = {'incr': [(0,3)], 'decr': [(1,4)], None: []}
+        assert results._results == expected
 
     def test_analyze_incr_both_incr(self):
         steps = [
@@ -126,8 +124,8 @@ def test_analyze_incr_both_incr(self):
             paths.MCStep(mccycle=2, active=self.incr_2)
         ]
         results = paths.ChannelAnalysis(steps, self.channels)
-        assert_equal(results._results,
-                     {'incr': [(0,3)], 'decr': [(1,2)], None: []})
+        expected = {'incr': [(0,3)], 'decr': [(1,2)], None: []}
+        assert results._results == expected
 
     def test_analyze_incr_same_decr(self):
         steps = [
@@ -136,8 +134,8 @@ def test_analyze_incr_same_decr(self):
             paths.MCStep(mccycle=2, active=self.incr_2)
         ]
         results = paths.ChannelAnalysis(steps, self.channels)
-        assert_equal(results._results,
-                     {'incr': [(0,3)], 'decr': [], None: []})
+        expected = {'incr': [(0,3)], 'decr': [], None: []}
+        assert results._results == expected
 
     def test_analyze_incr_none_incr(self):
         steps = [
@@ -146,8 +144,8 @@ def test_analyze_incr_none_incr(self):
             paths.MCStep(mccycle=2, active=self.incr_2)
         ]
         results = paths.ChannelAnalysis(steps, self.channels)
-        assert_equal(results._results,
-                     {'incr': [(0,1), (2,3)], 'decr': [], None: [(1,2)]})
+        expected = {'incr': [(0,1), (2,3)], 'decr': [], None: [(1,2)]}
+        assert results._results == expected
 
     def test_analyze_incr_none_decr(self):
         steps = [
@@ -156,74 +154,79 @@ def test_analyze_incr_none_decr(self):
             paths.MCStep(mccycle=2, active=self.decr_1)
         ]
         results = paths.ChannelAnalysis(steps, self.channels)
-        assert_equal(results._results,
-                     {'incr': [(0,1)], 'decr': [(2,3)], None: [(1,2)]})
+        expected = {'incr': [(0,1)], 'decr': [(2,3)], None: [(1,2)]}
+        assert results._results == expected
 
     def test_expand_results(self):
         expanded = paths.ChannelAnalysis._expand_results(self.toy_results)
-        assert_equal(expanded, self.toy_expanded_results)
+        assert expanded == self.toy_expanded_results
 
     def test_labels_by_step_newest(self):
         test_set = self.toy_expanded_results
         relabeled = paths.ChannelAnalysis._labels_by_step_newest(test_set)
-        assert_equal(relabeled, [(0, 3, self.set_a), (3, 7, self.set_b),
-                                 (7, 8, self.set_c), (8, 10, self.set_a)])
+        expected = [(0, 3, self.set_a), (3, 7, self.set_b),
+                    (7, 8, self.set_c), (8, 10, self.set_a)]
+        assert relabeled == expected
 
         test_set = self.expanded_results_simultaneous_ending
         relabeled = paths.ChannelAnalysis._labels_by_step_newest(test_set)
-        assert_equal(relabeled, [(0, 3, self.set_a), (3, 7, self.set_b),
-                                 (7, 8, self.set_c), (8, 10, self.set_a)])
+        expected =  [(0, 3, self.set_a), (3, 7, self.set_b),
+                     (7, 8, self.set_c), (8, 10, self.set_a)]
+        assert relabeled == expected
 
     def test_labels_by_step_oldest(self):
         test_set = self.toy_expanded_results
         relabeled = paths.ChannelAnalysis._labels_by_step_oldest(test_set)
-        assert_equal(relabeled, [(0, 5, self.set_a), (5, 9, self.set_b),
-                                 (9, 10, self.set_a)])
+        expected = [(0, 5, self.set_a), (5, 9, self.set_b),
+                    (9, 10, self.set_a)]
+        assert relabeled == expected
 
         test_set = self.expanded_results_simultaneous_ending
         relabeled = paths.ChannelAnalysis._labels_by_step_oldest(test_set)
-        assert_equal(relabeled, [(0, 5, self.set_a), (5, 9, self.set_b),
-                                 (9, 10, self.set_c)])
+        expected = [(0, 5, self.set_a), (5, 9, self.set_b),
+                    (9, 10, self.set_c)]
+        assert relabeled == expected
 
         test_set = self.expanded_oldest_skips_internal
         relabeled = paths.ChannelAnalysis._labels_by_step_oldest(test_set)
-        assert_equal(relabeled, [(0, 5, self.set_a), (5, 9, self.set_b),
-                                 (9, 10, self.set_a), (10, 11, self.set_b)])
+        expected = [(0, 5, self.set_a), (5, 9, self.set_b),
+                    (9, 10, self.set_a), (10, 11, self.set_b)]
+        assert relabeled == expected
 
 
     def test_labels_by_step_multiple(self):
         test_set = self.toy_expanded_results
         relabeled = paths.ChannelAnalysis._labels_by_step_multiple(test_set)
-        assert_equal(relabeled,
-                     [(0, 3, self.set_a),
-                      (3, 5, self.set_a | self.set_b),
-                      (5, 7, self.set_b),
-                      (7, 8, self.set_b | self.set_c),
-                      (8, 9, self.set_b | self.set_c | self.set_a),
-                      (9, 10, self.set_a)])
+        expected = [(0, 3, self.set_a),
+                    (3, 5, self.set_a | self.set_b),
+                    (5, 7, self.set_b),
+                    (7, 8, self.set_b | self.set_c),
+                    (8, 9, self.set_b | self.set_c | self.set_a),
+                    (9, 10, self.set_a)]
+        assert relabeled == expected
 
     def test_empty(self):
         obj = paths.ChannelAnalysis(steps=None, channels=self.channels)
         empty_results = {c: [] for c in list(self.channels.keys()) + [None]}
-        assert_equal(obj._results, empty_results)
+        assert obj._results == empty_results
 
     def test_treat_multiples(self):
         obj = paths.ChannelAnalysis(steps=None, channels=self.channels)
-        assert_equal(obj.treat_multiples, 'all')
+        assert obj.treat_multiples == 'all'
         obj.treat_multiples = 'oldest'
-        assert_equal(obj.treat_multiples, 'oldest')
+        assert obj.treat_multiples == 'oldest'
         obj.treat_multiples = 'newest'
-        assert_equal(obj.treat_multiples, 'newest')
+        assert obj.treat_multiples == 'newest'
         obj.treat_multiples = 'multiple'
-        assert_equal(obj.treat_multiples, 'multiple')
+        assert obj.treat_multiples == 'multiple'
         obj.treat_multiples = 'all'
-        assert_equal(obj.treat_multiples, 'all')
+        assert obj.treat_multiples == 'all'
 
-    @raises(ValueError)
     def test_bad_treat_multiples(self):
         obj = paths.ChannelAnalysis(steps=None, channels=self.channels)
-        assert_equal(obj.treat_multiples, 'all')
-        obj.treat_multiples = 'bad_string'
+        assert obj.treat_multiples == 'all'
+        with pytest.raises(ValueError):
+            obj.treat_multiples = 'bad_string'
 
     def test_labels_as_sets_sort_function(self):
         sort_key = paths.ChannelAnalysis._labels_as_sets_sort_function
@@ -232,7 +235,7 @@ def test_labels_as_sets_sort_function(self):
         sorted_set_list = sorted(inp_list, key=sort_key)
         sorted_labels = [paths.ChannelAnalysis.label_to_string(e)
                          for e in sorted_set_list]
-        assert_equal(sorted_labels, ['a', 'b', 'c'])
+        assert sorted_labels == ['a', 'b', 'c']
 
         inp_list = [self.set_a, self.set_a | self.set_b, self.set_b,
                     self.set_c | self.set_b,
@@ -240,7 +243,7 @@ def test_labels_as_sets_sort_function(self):
         sorted_set_list = sorted(inp_list, key=sort_key)
         sorted_labels = [paths.ChannelAnalysis.label_to_string(e)
                          for e in sorted_set_list]
-        assert_equal(sorted_labels, ['a', 'b', 'a,b', 'b,c', 'a,b,c'])
+        assert sorted_labels == ['a', 'b', 'a,b', 'b,c', 'a,b,c']
 
     def test_labels_sort_function_with_none(self):
         sort_key = paths.ChannelAnalysis._labels_as_sets_sort_function
@@ -248,7 +251,7 @@ def test_labels_sort_function_with_none(self):
         sorted_set_list = sorted(inp_list, key=sort_key)
         sorted_labels = [paths.ChannelAnalysis.label_to_string(e)
                          for e in sorted_set_list]
-        assert_equal(sorted_labels, ['None', 'a', 'b'])
+        assert sorted_labels == ['None', 'a', 'b']
 
     def test_switching(self):
         analysis = paths.ChannelAnalysis(steps=None, channels=self.channels)
@@ -299,28 +302,28 @@ def test_residence_times(self):
 
         analysis.treat_multiples = 'newest'
         residence_times = analysis.residence_times
-        assert_equal(residence_times, {'a': [3, 2], 'b': [4], 'c': [1]})
+        assert residence_times == {'a': [3, 2], 'b': [4], 'c': [1]}
 
         analysis.treat_multiples = 'oldest'
         residence_times = analysis.residence_times
-        assert_equal(residence_times, {'a': [5, 1], 'b': [4]})
+        assert residence_times == {'a': [5, 1], 'b': [4]}
 
         analysis.treat_multiples = 'all'
         residence_times = analysis.residence_times
-        assert_equal(residence_times, {'a': [5, 2], 'b': [6], 'c': [2]})
+        assert residence_times == {'a': [5, 2], 'b': [6], 'c': [2]}
 
         analysis.treat_multiples = 'multiple'
         residence_times = analysis.residence_times
-        assert_equal(residence_times, {'a': [3, 1], 'b': [2], 'a,b': [2],
-                                       'b,c': [1], 'a,b,c': [1]})
+        assert residence_times == {
+            'a': [3, 1], 'b': [2], 'a,b': [2], 'b,c': [1], 'a,b,c': [1]
+        }
 
     def test_residence_times_with_none(self):
         analysis = paths.ChannelAnalysis(steps=None, channels=self.channels)
         analysis._results = self.results_with_none
 
         residence_times = analysis.residence_times
-        assert_equal(residence_times,
-                     {'a': [2, 3], 'b': [2, 1], 'None': [3]})
+        assert residence_times == {'a': [2, 3], 'b': [2, 1], 'None': [3]}
 
     def test_total_time(self):
         analysis = paths.ChannelAnalysis(steps=None, channels=self.channels)
@@ -328,28 +331,27 @@ def test_total_time(self):
 
         analysis.treat_multiples = 'newest'
         total_time = analysis.total_time
-        assert_equal(total_time, {'a': 5, 'b': 4, 'c': 1})
+        assert total_time == {'a': 5, 'b': 4, 'c': 1}
 
         analysis.treat_multiples = 'oldest'
         total_time = analysis.total_time
-        assert_equal(total_time, {'a': 6, 'b': 4})
-        assert_equal(total_time['c'], 0)
+        assert total_time == {'a': 6, 'b': 4}
+        assert total_time['c'] == 0
 
         analysis.treat_multiples = 'all'
         total_time = analysis.total_time
-        assert_equal(total_time, {'a': 7, 'b': 6, 'c': 2})
+        assert total_time == {'a': 7, 'b': 6, 'c': 2}
 
         analysis.treat_multiples = 'multiple'
         total_time = analysis.total_time
-        assert_equal(total_time, {'a': 4, 'b': 2, 'a,b': 2, 'b,c': 1,
-                                  'a,b,c': 1})
+        assert total_time == {'a': 4, 'b': 2, 'a,b': 2, 'b,c': 1, 'a,b,c': 1}
 
     def test_total_time_with_none(self):
         analysis = paths.ChannelAnalysis(steps=None, channels=self.channels)
         analysis._results = self.results_with_none
 
         total_time = analysis.total_time
-        assert_equal(total_time, {'a': 5, 'b': 3, 'None': 3})
+        assert total_time == {'a': 5, 'b': 3, 'None': 3}
 
 
     def test_status(self):
@@ -357,29 +359,29 @@ def test_status(self):
         analysis._results = self.toy_results
 
         analysis.treat_multiples = 'newest'
-        assert_equal(analysis.status(4), 'b')
-        assert_equal(analysis.status(8), 'a')
+        assert analysis.status(4) == 'b'
+        assert analysis.status(8) == 'a'
 
         analysis.treat_multiples = 'oldest'
-        assert_equal(analysis.status(4), 'a')
-        assert_equal(analysis.status(8), 'b')
+        assert analysis.status(4) == 'a'
+        assert analysis.status(8) == 'b'
 
         analysis.treat_multiples = 'multiple'
-        assert_equal(analysis.status(4), 'a,b')
-        assert_equal(analysis.status(8), 'a,b,c')
+        assert analysis.status(4) == 'a,b'
+        assert analysis.status(8) == 'a,b,c'
 
         analysis.treat_multiples = 'all'
-        assert_equal(analysis.status(4), 'a,b')
-        assert_equal(analysis.status(8), 'a,b,c')
+        assert analysis.status(4) == 'a,b'
+        assert analysis.status(8) == 'a,b,c'
 
     def test_status_with_none(self):
         analysis = paths.ChannelAnalysis(steps=None, channels=self.channels)
         analysis._results = self.results_with_none
-        assert_equal(analysis.status(4), 'None')
+        assert analysis.status(4) == 'None'
 
-    @raises(RuntimeError)
     def test_bad_status_number(self):
         analysis = paths.ChannelAnalysis(steps=None, channels=self.channels)
         analysis._results = self.toy_results
 
-        analysis.status(10)
+        with pytest.raises(RuntimeError):
+            analysis.status(10)
diff --git a/openpathsampling/tests/test_collectivevariable.py b/openpathsampling/tests/test_collectivevariable.py
index 6d1fe8ec0..4c199957e 100644
--- a/openpathsampling/tests/test_collectivevariable.py
+++ b/openpathsampling/tests/test_collectivevariable.py
@@ -8,7 +8,6 @@
 from .test_helpers import data_filename, assert_close_unit, md
 
 import pytest
-from nose.plugins.skip import SkipTest
 
 import numpy as np
 
@@ -31,7 +30,7 @@
 class TestFunctionCV(object):
     def setup_method(self):
         if not md:
-            raise SkipTest("mdtraj not installed")
+            pytest.skip("mdtraj not installed")
         self.mdtraj = md.load(data_filename("ala_small_traj.pdb"))
         _ = pytest.importorskip('simtk.unit')
         self.traj_topology = peng.trajectory_from_mdtraj(self.mdtraj)
@@ -87,7 +86,7 @@ def test_atom_pair_featurizer(self):
         """ Create an atom pair collectivevariable using MSMSBuilder3 """
 
         if not has_msmbuilder:
-            raise SkipTest("MSMBuilder not installed")
+            pytest.skip("MSMBuilder not installed")
         atom_pairs = [[0, 1], [10, 14]]
         atom_pair_op = op.MSMBFeaturizerCV(
             "atom_pairs",
@@ -105,7 +104,7 @@ def test_atom_pair_featurizer(self):
     def test_return_parameters_from_template(self):
 
         if not has_msmbuilder:
-            raise SkipTest("MSMBuilder not installed")
+            pytest.skip("MSMBuilder not installed")
         atom_pairs = [[0, 1], [10, 14]]
         atom_pair_op = op.MSMBFeaturizerCV(
             "atom_pairs",
diff --git a/openpathsampling/tests/test_dynamicsengine.py b/openpathsampling/tests/test_dynamicsengine.py
index 48927f6db..cf762ab21 100644
--- a/openpathsampling/tests/test_dynamicsengine.py
+++ b/openpathsampling/tests/test_dynamicsengine.py
@@ -3,8 +3,6 @@
 import pytest
 import openpathsampling as paths
 
-from nose.tools import (assert_equal, assert_not_equal, raises, assert_true)
-from nose.plugins.skip import SkipTest
 from .test_helpers import make_1d_traj, raises_with_message_like
 
 try:
@@ -58,7 +56,7 @@ def setup_method(self):
         self.stupid = StupidEngine(options, descriptor)
 
     def test_getattr_from_options(self):
-        assert_equal(self.stupid.random_option, True)
+        assert self.stupid.random_option is True
 
     def test_getattr_property_fails(self):
         # py2: "'newobject' object has no attribute 'b'"
@@ -67,7 +65,7 @@ def test_getattr_property_fails(self):
         try:
             self.stupid.bad_property
         except AttributeError as e:
-            assert_true(str(e).endswith(error_string_end))
+            assert str(e).endswith(error_string_end)
 
         else:
             raise AssertionError("Did not raise appropriate AttributeError")
diff --git a/openpathsampling/tests/test_ensemble.py b/openpathsampling/tests/test_ensemble.py
index 8c1bb4234..3ab96a428 100644
--- a/openpathsampling/tests/test_ensemble.py
+++ b/openpathsampling/tests/test_ensemble.py
@@ -4,9 +4,7 @@
 from builtins import str
 from builtins import range
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, raises, assert_true,
-                        assert_false)
-from nose.plugins.skip import SkipTest
+import pytest
 from .test_helpers import (CallIdentity, prepend_exception_message,
                           make_1d_traj, raises_with_message_like,
                           CalvinistDynamics)
@@ -45,9 +43,9 @@ def wrap_traj(traj, start, length):
 def test_wrap_traj():
     """Testing wrap_traj (oh gods, the meta! a test for a test function!)"""
     intraj = [1, 2, 3]
-    assert_equal(wrap_traj(intraj, 3, 6), [1, 1, 1, 1, 2, 3])
-    assert_equal(wrap_traj(intraj, 3, 8), [1, 1, 1, 1, 2, 3, 3, 3])
-    assert_equal(wrap_traj(intraj, 3, 8)[slice(3, 6)], intraj)
+    assert wrap_traj(intraj, 3, 6) == [1, 1, 1, 1, 2, 3]
+    assert wrap_traj(intraj, 3, 8) == [1, 1, 1, 1, 2, 3, 3, 3]
+    assert wrap_traj(intraj, 3, 8)[slice(3, 6)] == intraj
 
 def build_trajdict(trajtypes, lower, upper):
     upperadddict = {'a' : 'in', 'b' : 'out', 'c' : 'cross', 'o' : 'hit'}
@@ -143,7 +141,7 @@ def in_out_parser(testname):
 class EnsembleTest(object):
     def _single_test(self, ensemble_fcn, traj, res, failmsg):
         try:
-            assert_equal(ensemble_fcn(traj), res)
+            assert ensemble_fcn(traj) == res
         except AssertionError as e:
             prepend_exception_message(e, failmsg)
             raise
@@ -232,14 +230,14 @@ def test_strict_can_prepend(self):
 
     def test_leaveX_0(self):
         """PartOutXEnsemble treatment of zero-length trajectory"""
-        assert_equal(self.leaveX(paths.Trajectory([])), False)
-        assert_equal(self.leaveX.can_append(paths.Trajectory([])), True)
-        assert_equal(self.leaveX.can_prepend(paths.Trajectory([])), True)
+        assert self.leaveX(paths.Trajectory([])) is False
+        assert self.leaveX.can_append(paths.Trajectory([])) is True
+        assert self.leaveX.can_prepend(paths.Trajectory([])) is True
 
     def test_leaveX_str(self):
         volstr = "{x|Id(x) in [0.1, 0.5]}"
-        assert_equal(self.leaveX.__str__(),
-                     "exists t such that x[t] in (not "+volstr+")")
+        expected_str = "exists t such that x[t] in (not "+volstr+")"
+        assert self.leaveX.__str__() == expected_str
 
 class TestAllInXEnsemble(EnsembleTest):
     def setup_method(self):
@@ -296,14 +294,13 @@ def test_strict_can_prepend(self):
 
     def test_inX_0(self):
         """AllInXEnsemble treatment of zero-length trajectory"""
-        assert_equal(self.inX(paths.Trajectory([])), False)
-        assert_equal(self.inX.can_append(paths.Trajectory([])), True)
-        assert_equal(self.inX.can_prepend(paths.Trajectory([])), True)
+        assert self.inX(paths.Trajectory([])) is False
+        assert self.inX.can_append(paths.Trajectory([])) is True
+        assert self.inX.can_prepend(paths.Trajectory([])) is True
 
     def test_inX_str(self):
         volstr = "{x|Id(x) in [0.1, 0.5]}"
-        assert_equal(self.inX.__str__(),
-                     "x[t] in "+volstr+" for all t")
+        assert self.inX.__str__() == "x[t] in "+volstr+" for all t"
 
 class TestAllOutXEnsemble(EnsembleTest):
     def setup_method(self):
@@ -359,14 +356,13 @@ def test_strict_can_prepend(self):
 
     def test_outX_0(self):
         """AllOutXEnsemble treatment of zero-length trajectory"""
-        assert_equal(self.outX(paths.Trajectory([])), False)
-        assert_equal(self.outX.can_append(paths.Trajectory([])), True)
-        assert_equal(self.outX.can_prepend(paths.Trajectory([])), True)
+        assert self.outX(paths.Trajectory([])) is False
+        assert self.outX.can_append(paths.Trajectory([])) is True
+        assert self.outX.can_prepend(paths.Trajectory([])) is True
 
     def test_outX_str(self):
         volstr = "{x|Id(x) in [0.1, 0.5]}"
-        assert_equal(self.outX.__str__(),
-                     "x[t] in (not "+volstr+") for all t")
+        assert self.outX.__str__() == "x[t] in (not "+volstr+") for all t"
 
 class TestPartInXEnsemble(EnsembleTest):
     def setup_method(self):
@@ -396,14 +392,13 @@ def test_strict_can_prepend(self):
 
     def test_hitX_0(self):
         """PartInXEnsemble treatment of zero-length trajectory"""
-        assert_equal(self.hitX(paths.Trajectory([])), False)
-        assert_equal(self.hitX.can_append(paths.Trajectory([])), True)
-        assert_equal(self.hitX.can_prepend(paths.Trajectory([])), True)
+        assert self.hitX(paths.Trajectory([])) is False
+        assert self.hitX.can_append(paths.Trajectory([])) is True
+        assert self.hitX.can_prepend(paths.Trajectory([])) is True
 
     def test_hitX_str(self):
         volstr = "{x|Id(x) in [0.1, 0.5]}"
-        assert_equal(self.hitX.__str__(),
-                     "exists t such that x[t] in "+volstr)
+        assert self.hitX.__str__() == "exists t such that x[t] in " + volstr
 
 
 class TestSequentialEnsemble(EnsembleTest):
@@ -436,50 +431,52 @@ def setup_method(self):
             self.inX & self.length1,
         ])
 
-    @raises(ValueError)
     def test_maxminoverlap_size(self):
         """SequentialEnsemble errors if max/min overlap sizes different"""
-        SequentialEnsemble([self.inX, self.outX, self.inX], (0,0), (0,0,0))
+        with pytest.raises(ValueError):
+            SequentialEnsemble([self.inX, self.outX, self.inX],
+                               (0,0), (0,0,0))
 
-    @raises(ValueError)
     def test_maxoverlap_ensemble_size(self):
         """SequentialEnsemble errors if overlap sizes don't match ensemble size"""
-        SequentialEnsemble([self.inX, self.outX, self.inX], (0,0,0), (0,0,0))
+        with pytest.raises(ValueError):
+            SequentialEnsemble([self.inX, self.outX, self.inX],
+                               (0,0,0), (0,0,0))
 
-    @raises(ValueError)
     def test_minmax_order(self):
         """SequentialEnsemble errors if min_overlap > max_overlap"""
-        SequentialEnsemble([self.inX, self.outX, self.inX], (0,1), (0,0))
+        with pytest.raises(ValueError):
+            SequentialEnsemble([self.inX, self.outX, self.inX], (0,1), (0,0))
 
     def test_allowed_initializations(self):
         """SequentialEnsemble initializes correctly with defaults"""
         A = SequentialEnsemble([self.inX, self.outX, self.inX], (0,0), (0,0))
         B = SequentialEnsemble([self.inX, self.outX, self.inX],0,0)
         C = SequentialEnsemble([self.inX, self.outX, self.inX])
-        assert_equal(A.min_overlap,B.min_overlap)
-        assert_equal(A.min_overlap,C.min_overlap)
-        assert_equal(A.max_overlap,B.max_overlap)
-        assert_equal(A.max_overlap,C.max_overlap)
+        assert A.min_overlap == B.min_overlap
+        assert A.min_overlap == C.min_overlap
+        assert A.max_overlap == B.max_overlap
+        assert A.max_overlap == C.max_overlap
 
     def test_overlap_max(self):
         """SequentialEnsemble allows overlaps up to overlap max, no more"""
-        raise SkipTest
+        pytest.skip()
 
     def test_overlap_min(self):
         """SequentialEnsemble requires overlaps of at least overlap min"""
-        raise SkipTest
+        pytest.skip()
 
     def test_overlap_max_inf(self):
         """SequentialEnsemble works if max overlap in infinite"""
-        raise SkipTest
+        pytest.skip()
 
     def test_overlap_min_gap(self):
         """SequentialEnsemble works in mix overlap is negative (gap)"""
-        raise SkipTest
+        pytest.skip()
 
     def test_overlap_max_gap(self):
         """SequentialEnsemble works if max overlap is negative (gap)"""
-        raise SkipTest
+        pytest.skip()
 
     def test_seqens_order_combo(self):
         # regression test for #229
@@ -504,13 +501,13 @@ def test_seqens_order_combo(self):
         seq1 = SequentialEnsemble([combo1])
         seq2 = SequentialEnsemble([combo2])
         logger.debug("Checking combo1")
-        assert_equal(combo1.can_append(traj), True)
+        assert combo1.can_append(traj) is True
         logger.debug("Checking combo2")
-        assert_equal(combo2.can_append(traj), True)
+        assert combo2.can_append(traj) is True
         logger.debug("Checking seq1")
-        assert_equal(seq1.can_append(traj), True)
+        assert seq1.can_append(traj) is True
         logger.debug("Checking seq2")
-        assert_equal(seq2.can_append(traj), True)
+        assert seq2.can_append(traj) is True
 
 
     def test_can_append_tis(self):
@@ -922,12 +919,12 @@ def test_sequential_generate_first_tis(self):
     def test_sequential_enter_exit(self):
         """SequentialEnsembles based on Enters/ExitsXEnsemble"""
         # TODO: this includes a test of the overlap ability
-        raise SkipTest
+        pytest.skip()
 
 
 
     def test_str(self):
-        assert_equal(self.pseudo_tis.__str__(), """[
+        assert self.pseudo_tis.__str__() == """[
 (
   x[t] in {x|Id(x) in [0.1, 0.5]} for all t
 )
@@ -943,7 +940,7 @@ def test_str(self):
 (
   len(x) = 1
 )
-]""")
+]"""
 
 
 class TestSequentialEnsembleCombination(EnsembleTest):
@@ -1193,22 +1190,22 @@ def setup_method(self):
 
     def test_tis_trajectory_summary(self):
         summ = self.tis.trajectory_summary(self.traj)
-        assert_equal(summ['initial_state'], 0)
-        assert_equal(summ['final_state'], 0)
-        assert_equal(summ['max_lambda'], self.maxl)
-        assert_equal(summ['min_lambda'], self.minl)
+        assert summ['initial_state'] == 0
+        assert summ['final_state'] == 0
+        assert summ['max_lambda'] == self.maxl
+        assert summ['min_lambda'] == self.minl
 
     def test_tis_trajectory_summary_str(self):
         mystr = self.tis.trajectory_summary_str(self.traj)
         teststr = ("initial_state=stateA final_state=stateA min_lambda=" +
                    str(self.minl) + " max_lambda=" + str(self.maxl) + " ")
-        assert_equal(mystr, teststr)
+        assert mystr == teststr
 
     def test_no_frame_after_interface(self):
         traj_3 = make_1d_traj([0.2, 0.6,  2.1])
-        assert_equal(self.tis(traj_3), True)
+        assert self.tis(traj_3) is True
         traj_2 = make_1d_traj([0.2, 2.1])
-        assert_equal(self.tis(traj_2), True)
+        assert self.tis(traj_2) is True
 
     def test_tis_ensemble_candidate(self):
         tis = TISEnsemble(vol1, vol3, vol2, op, lambda_i=0.7)
@@ -1275,94 +1272,94 @@ def setup_method(self):
         self.traj = ttraj['lower_in_out_in_in_out_in']
 
     def test_initially_reset(self):
-        assert_equal(self._was_cache_reset(self.fwd), True)
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.fwd) is True
+        assert self._was_cache_reset(self.rev) is True
 
     def test_change_trajectory(self):
         traj2 = ttraj['lower_in_out_in']
         # tests for forward
         self.fwd.contents = { 'test' : 'object' }
-        assert_equal(self._was_cache_reset(self.fwd), False)
+        assert self._was_cache_reset(self.fwd) is False
         self.fwd.check(self.traj)
-        assert_equal(self._was_cache_reset(self.fwd), True)
+        assert self._was_cache_reset(self.fwd) is True
         self.fwd.contents['ens_num'] = 1
-        assert_equal(self._was_cache_reset(self.fwd), False)
+        assert self._was_cache_reset(self.fwd) is False
         self.fwd.check(traj2)
-        assert_equal(self._was_cache_reset(self.fwd), True)
+        assert self._was_cache_reset(self.fwd) is True
         # tests for backward
         self.rev.contents = { 'test' : 'object' }
-        assert_equal(self._was_cache_reset(self.rev), False)
+        assert self._was_cache_reset(self.rev) is False
         self.rev.check(self.traj)
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.rev) is True
         self.rev.contents['ens_num'] = 1
-        assert_equal(self._was_cache_reset(self.rev), False)
+        assert self._was_cache_reset(self.rev) is False
         self.rev.check(traj2)
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.rev) is True
 
     def test_trajectory_by_frame(self):
         # tests for forward
         self.fwd.check(self.traj[0:1])
-        assert_equal(self._was_cache_reset(self.fwd), True)
+        assert self._was_cache_reset(self.fwd) is True
         self.fwd.contents = { 'test' : 'object' }
-        assert_equal(self._was_cache_reset(self.fwd), False)
+        assert self._was_cache_reset(self.fwd) is False
         self.fwd.check(self.traj[0:2])
-        assert_equal(self._was_cache_reset(self.fwd), False)
+        assert self._was_cache_reset(self.fwd) is False
         # tests for backward
         self.rev.check(self.traj[-1:])
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.rev) is True
         self.rev.contents = { 'test' : 'object' }
-        assert_equal(self._was_cache_reset(self.rev), False)
+        assert self._was_cache_reset(self.rev) is False
         self.rev.check(self.traj[-2:])
-        assert_equal(self._was_cache_reset(self.rev), False)
+        assert self._was_cache_reset(self.rev) is False
 
     def test_same_traj_twice_no_reset(self):
         # tests for forward
         self.fwd.check(self.traj)
-        assert_equal(self._was_cache_reset(self.fwd), True)
+        assert self._was_cache_reset(self.fwd) is True
         self.fwd.contents = { 'test' : 'object' }
         self.fwd.check(self.traj)
-        assert_equal(self._was_cache_reset(self.fwd), False)
+        assert self._was_cache_reset(self.fwd) is False
         # tests for backward
         self.rev.check(self.traj)
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.rev) is True
         self.rev.contents = { 'test' : 'object' }
         self.rev.check(self.traj)
-        assert_equal(self._was_cache_reset(self.rev), False)
+        assert self._was_cache_reset(self.rev) is False
 
 
     def test_trajectory_skips_frame(self):
         # tests for forward
         self.fwd.check(self.traj[0:1])
-        assert_equal(self._was_cache_reset(self.fwd), True)
+        assert self._was_cache_reset(self.fwd) is True
         self.fwd.contents = { 'test' : 'object' }
-        assert_equal(self._was_cache_reset(self.fwd), False)
+        assert self._was_cache_reset(self.fwd) is False
         self.fwd.check(self.traj[0:3])
-        assert_equal(self._was_cache_reset(self.fwd), True)
+        assert self._was_cache_reset(self.fwd) is True
         # tests for backward
         self.rev.check(self.traj[-1:])
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.rev) is True
         self.rev.contents = { 'test' : 'object' }
-        assert_equal(self._was_cache_reset(self.rev), False)
+        assert self._was_cache_reset(self.rev) is False
         self.rev.check(self.traj[-3:])
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.rev) is True
 
     def test_trajectory_middle_frame_changes(self):
         # tests for forward
         self.fwd.check(self.traj[0:2])
-        assert_equal(self._was_cache_reset(self.fwd), True)
+        assert self._was_cache_reset(self.fwd) is True
         self.fwd.contents = { 'test' : 'object' }
-        assert_equal(self._was_cache_reset(self.fwd), False)
+        assert self._was_cache_reset(self.fwd) is False
         new_traj = self.traj[0:1] + self.traj[3:5]
         self.fwd.check(new_traj)
-        assert_equal(self._was_cache_reset(self.fwd), True)
+        assert self._was_cache_reset(self.fwd) is True
         # tests for backward
         self.rev.check(self.traj[0:2])
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.rev) is True
         self.rev.contents = { 'test' : 'object' }
-        assert_equal(self._was_cache_reset(self.rev), False)
+        assert self._was_cache_reset(self.rev) is False
         new_traj = self.traj[-4:-2] + self.traj[-1:]
         self.rev.check(new_traj)
-        assert_equal(self._was_cache_reset(self.rev), True)
+        assert self._was_cache_reset(self.rev) is True
 
 
 class TestSequentialEnsembleCache(EnsembleCacheTest):
@@ -1383,92 +1380,94 @@ def test_all_in_as_seq_can_append(self):
         ens = SequentialEnsemble([AllInXEnsemble(vol1 | vol2 | vol3)])
         cache = ens._cache_can_append
         traj = ttraj['upper_in_in_out_out_in_in']
-        assert_equal(ens.can_append(traj[0:1]), True)
-        assert_equal(ens.can_append(traj[0:2]), True)
-        assert_equal(ens.can_append(traj[0:3]), True)
-        assert_equal(ens.can_append(traj[0:4]), True)
-        assert_equal(ens.can_append(traj[0:5]), True)
-        assert_equal(ens.can_append(traj[0:6]), True)
+        assert ens.can_append(traj[0:1]) is True
+        assert ens.can_append(traj[0:2]) is True
+        assert ens.can_append(traj[0:3]) is True
+        assert ens.can_append(traj[0:4]) is True
+        assert ens.can_append(traj[0:5]) is True
+        assert ens.can_append(traj[0:6]) is True
 
     def test_sequential_caching_can_append(self):
         cache = self.pseudo_minus._cache_can_append
-        assert_equal(self.pseudo_minus.can_append(self.traj[0:1]), True)
-        assert_equal(cache.contents['ens_num'], 1)
-        assert_equal(cache.contents['ens_from'], 0)
-        assert_equal(cache.contents['subtraj_from'], 1)
+        assert self.pseudo_minus.can_append(self.traj[0:1]) is True
+        assert cache.contents['ens_num'] == 1
+        assert cache.contents['ens_from'] == 0
+        assert cache.contents['subtraj_from'] == 1
         logging.getLogger('openpathsampling.ensemble').debug("Starting [0:2]")
-        assert_equal(self.pseudo_minus.can_append(self.traj[0:2]), True)
-        assert_equal(cache.contents['ens_num'], 1)
-        assert_equal(cache.contents['ens_from'], 0)
-        assert_equal(cache.contents['subtraj_from'], 1)
+        assert self.pseudo_minus.can_append(self.traj[0:2]) is True
+        assert cache.contents['ens_num'] == 1
+        assert cache.contents['ens_from'] == 0
+        assert cache.contents['subtraj_from'] == 1
         logging.getLogger('openpathsampling.ensemble').debug("Starting [0:3]")
-        assert_equal(self.pseudo_minus.can_append(self.traj[0:3]), True)
-        assert_equal(cache.contents['ens_num'], 2)
-        assert_equal(cache.contents['ens_from'], 0)
-        assert_equal(cache.contents['subtraj_from'], 2)
+        assert self.pseudo_minus.can_append(self.traj[0:3]) is True
+        assert cache.contents['ens_num'] == 2
+        assert cache.contents['ens_from'] == 0
+        assert cache.contents['subtraj_from'] == 2
         logging.getLogger('openpathsampling.ensemble').debug("Starting [0:4]")
-        assert_equal(self.pseudo_minus.can_append(self.traj[0:4]), True)
-        assert_equal(cache.contents['ens_num'], 2)
-        assert_equal(cache.contents['ens_from'], 0)
-        assert_equal(cache.contents['subtraj_from'], 2)
+        assert self.pseudo_minus.can_append(self.traj[0:4]) is True
+        assert cache.contents['ens_num'] == 2
+        assert cache.contents['ens_from'] == 0
+        assert cache.contents['subtraj_from'] == 2
         logging.getLogger('openpathsampling.ensemble').debug("Starting [0:5]")
-        assert_equal(self.pseudo_minus.can_append(self.traj[0:5]), True)
-        assert_equal(cache.contents['ens_num'], 3)
-        assert_equal(cache.contents['ens_from'], 0)
-        assert_equal(cache.contents['subtraj_from'], 4)
+        assert self.pseudo_minus.can_append(self.traj[0:5]) is True
+        assert cache.contents['ens_num'] == 3
+        assert cache.contents['ens_from'] == 0
+        assert cache.contents['subtraj_from'] == 4
         logging.getLogger('openpathsampling.ensemble').debug("Starting [0:6]")
-        assert_equal(self.pseudo_minus.can_append(self.traj[0:6]), False)
-        assert_equal(cache.contents['ens_num'], 4)
-        assert_equal(cache.contents['ens_from'], 0)
-        assert_equal(cache.contents['subtraj_from'], 5)
+        assert self.pseudo_minus.can_append(self.traj[0:6]) is False
+        assert cache.contents['ens_num'] == 4
+        assert cache.contents['ens_from'] == 0
+        assert cache.contents['subtraj_from'] == 5
 
     def test_sequential_caching_resets(self):
         #cache = self.pseudo_minus._cache_can_append
-        assert_equal(self.pseudo_minus.can_append(self.traj[2:3]), True)
-        assert_equal(self.pseudo_minus(self.traj[2:3]), False)
+        assert self.pseudo_minus.can_append(self.traj[2:3]) is True
+        assert self.pseudo_minus(self.traj[2:3]) is False
         #assert_equal(self._was_cache_reset(cache), True)
-        assert_equal(self.pseudo_minus.can_append(self.traj[2:4]), True)
-        assert_equal(self.pseudo_minus(self.traj[2:4]), False)
+        assert self.pseudo_minus.can_append(self.traj[2:4]) is True
+        assert self.pseudo_minus(self.traj[2:4]) is False
         #assert_equal(self._was_cache_reset(cache), True)
         for i in range(4, len(self.traj)-1):
-            assert_equal(self.pseudo_minus.can_append(self.traj[2:i+1]), True)
-            assert_equal(self.pseudo_minus(self.traj[2:i+1]), False)
+            assert self.pseudo_minus.can_append(self.traj[2:i+1]) is True
+            assert self.pseudo_minus(self.traj[2:i+1]) is False
             #assert_equal(self._was_cache_reset(cache), False)
-        assert_equal(self.pseudo_minus.can_append(self.traj[2:]), False)
-        assert_equal(self.pseudo_minus(self.traj[2:]), False)
+        assert self.pseudo_minus.can_append(self.traj[2:]) is False
+        assert self.pseudo_minus(self.traj[2:]) is False
         #assert_equal(self._was_cache_reset(cache), False)
+
+    def test_sequential_caching_resets_backward(self):
         # TODO: same story backward
-        raise SkipTest
+        pytest.skip()
 
     def test_sequential_caching_call(self):
-        raise SkipTest
+        pytest.skip()
 
     def test_sequential_caching_can_prepend(self):
         cache = self.pseudo_minus._cache_can_prepend
-        assert_equal(self.pseudo_minus.can_prepend(self.traj[5:6]), True)
-        assert_equal(cache.contents['ens_num'], 3)
-        assert_equal(cache.contents['ens_from'], 4)
-        assert_equal(cache.contents['subtraj_from'], -1)
-        assert_equal(self.pseudo_minus.can_prepend(self.traj[4:6]), True)
-        assert_equal(cache.contents['ens_num'], 3)
-        assert_equal(cache.contents['ens_from'], 4)
-        assert_equal(cache.contents['subtraj_from'], -1)
-        assert_equal(self.pseudo_minus.can_prepend(self.traj[3:6]), True)
-        assert_equal(cache.contents['ens_num'], 2)
-        assert_equal(cache.contents['ens_from'], 4)
-        assert_equal(cache.contents['subtraj_from'], -2)
-        assert_equal(self.pseudo_minus.can_prepend(self.traj[2:6]), True)
-        assert_equal(cache.contents['ens_num'], 2)
-        assert_equal(cache.contents['ens_from'], 4)
-        assert_equal(cache.contents['subtraj_from'], -2)
-        assert_equal(self.pseudo_minus.can_prepend(self.traj[1:6]), True)
-        assert_equal(cache.contents['ens_num'], 1)
-        assert_equal(cache.contents['ens_from'], 4)
-        assert_equal(cache.contents['subtraj_from'], -4)
-        assert_equal(self.pseudo_minus.can_prepend(self.traj[0:6]), False)
-        assert_equal(cache.contents['ens_num'], 0)
-        assert_equal(cache.contents['ens_from'], 4)
-        assert_equal(cache.contents['subtraj_from'], -5)
+        assert self.pseudo_minus.can_prepend(self.traj[5:6]) is True
+        assert cache.contents['ens_num'] == 3
+        assert cache.contents['ens_from'] == 4
+        assert cache.contents['subtraj_from'] == -1
+        assert self.pseudo_minus.can_prepend(self.traj[4:6]) is True
+        assert cache.contents['ens_num'] == 3
+        assert cache.contents['ens_from'] == 4
+        assert cache.contents['subtraj_from'] == -1
+        assert self.pseudo_minus.can_prepend(self.traj[3:6]) is True
+        assert cache.contents['ens_num'] == 2
+        assert cache.contents['ens_from'] == 4
+        assert cache.contents['subtraj_from'] == -2
+        assert self.pseudo_minus.can_prepend(self.traj[2:6]) is True
+        assert cache.contents['ens_num'] == 2
+        assert cache.contents['ens_from'] == 4
+        assert cache.contents['subtraj_from'] == -2
+        assert self.pseudo_minus.can_prepend(self.traj[1:6]) is True
+        assert cache.contents['ens_num'] == 1
+        assert cache.contents['ens_from'] == 4
+        assert cache.contents['subtraj_from'] == -4
+        assert self.pseudo_minus.can_prepend(self.traj[0:6]) is False
+        assert cache.contents['ens_num'] == 0
+        assert cache.contents['ens_from'] == 4
+        assert cache.contents['subtraj_from'] == -5
 
 
 
@@ -1478,8 +1477,8 @@ def test_sliced_ensemble_init(self):
         init_as_int = SlicedTrajectoryEnsemble(AllInXEnsemble(vol1), 3)
         init_as_slice = SlicedTrajectoryEnsemble(AllInXEnsemble(vol1),
                                                  slice(3, 4))
-        assert_equal(init_as_int, init_as_slice)
-        assert_equal(init_as_slice.region, init_as_int.region)
+        assert init_as_int == init_as_slice
+        assert init_as_slice.region == init_as_int.region
 
     def test_sliced_as_TISEnsemble(self):
         '''SlicedTrajectory and Sequential give same TIS results'''
@@ -1507,7 +1506,7 @@ def test_slice_outside_trajectory_range(self):
         test = 'upper_in'
         # the slice should return the empty trajectory, and therefore should
         # return false
-        assert_equal(ens(ttraj[test]), False)
+        assert ens(ttraj[test]) is False
 
     def test_even_sliced_trajectory(self):
         even_slice = slice(None, None, 2)
@@ -1591,14 +1590,14 @@ def test_sliced_str(self):
         slice_no_ends = slice(1, -1)
         inX = AllInXEnsemble(vol1)
         inXstr = "x[t] in {x|Id(x) in [0.1, 0.5]} for all t"
-        assert_equal(SlicedTrajectoryEnsemble(inX, even_slice).__str__(),
-                     "("+inXstr+" in {:} every 2)")
-        assert_equal(SlicedTrajectoryEnsemble(inX, slice_1_10).__str__(),
-                     "("+inXstr+" in {1:10})")
-        assert_equal(SlicedTrajectoryEnsemble(inX, slice_1_end).__str__(),
-                     "("+inXstr+" in {1:})")
-        assert_equal(SlicedTrajectoryEnsemble(inX, slice_no_ends).__str__(),
-                     "("+inXstr+" in {1:-1})")
+        assert (SlicedTrajectoryEnsemble(inX, even_slice).__str__()
+                == "("+inXstr+" in {:} every 2)")
+        assert (SlicedTrajectoryEnsemble(inX, slice_1_10).__str__()
+                == "("+inXstr+" in {1:10})")
+        assert (SlicedTrajectoryEnsemble(inX, slice_1_end).__str__()
+                == "("+inXstr+" in {1:})")
+        assert (SlicedTrajectoryEnsemble(inX, slice_no_ends).__str__()
+                == "("+inXstr+" in {1:-1})")
 
 class TestOptionalEnsemble(EnsembleTest):
     def setup_method(self):
@@ -1854,7 +1853,7 @@ def test_optional_middle_strict_can_prepend(self):
     def test_optional_str(self):
         inX = AllInXEnsemble(vol1)
         opt_inX = OptionalEnsemble(inX)
-        assert_equal(opt_inX.__str__(), "{"+inX.__str__()+"} (OPTIONAL)")
+        assert opt_inX.__str__() == "{"+inX.__str__()+"} (OPTIONAL)"
 
 class TestPrefixTrajectoryEnsemble(EnsembleTest):
     def setup_method(self):
@@ -1866,9 +1865,9 @@ def test_bad_start_traj(self):
             SequentialEnsemble([self.inX]),
             traj[0:2]
         )
-        assert_equal(ens.can_append(traj[0:3]), False)
-        assert_equal(ens.strict_can_append(traj[0:3]), False)
-        assert_equal(ens(traj[0:3]), False)
+        assert ens.can_append(traj[0:3]) is False
+        assert ens.strict_can_append(traj[0:3]) is False
+        assert ens(traj[0:3]) is False
 
     def test_good_start_traj(self):
         traj = ttraj['upper_in_in_in']
@@ -1876,27 +1875,27 @@ def test_good_start_traj(self):
             SequentialEnsemble([self.inX]),
             traj[0:2]
         )
-        assert_equal(ens.can_append(traj[2:3]), True)
-        assert_equal(ens.strict_can_append(traj[2:3]), True)
-        assert_equal(ens(traj[2:3]), True)
+        assert ens.can_append(traj[2:3]) is True
+        assert ens.strict_can_append(traj[2:3]) is True
+        assert ens(traj[2:3]) is True
 
-    @raises(RuntimeError)
     def test_can_prepend(self):
         traj = ttraj['upper_in_in_in']
         ens = PrefixTrajectoryEnsemble(
             SequentialEnsemble([self.inX]),
             traj[0:2]
         )
-        ens.can_prepend(traj[2:3])
+        with pytest.raises(RuntimeError):
+            ens.can_prepend(traj[2:3])
 
-    @raises(RuntimeError)
     def test_strict_can_prepend(self):
         traj = ttraj['upper_in_in_in']
         ens = PrefixTrajectoryEnsemble(
             SequentialEnsemble([self.inX]),
             traj[0:2]
         )
-        ens.strict_can_prepend(traj[2:3])
+        with pytest.raises(RuntimeError):
+            ens.strict_can_prepend(traj[2:3])
 
     def test_caching_in_fwdapp_seq(self):
         inX = AllInXEnsemble(vol1)
@@ -1911,21 +1910,21 @@ def test_caching_in_fwdapp_seq(self):
         ])
         traj = ttraj['upper_in_out_in_in_out_in']
         ens = PrefixTrajectoryEnsemble(pseudo_minus, traj[0:2])
-        assert_equal(ens.can_append(traj[2:3]), True)
-        assert_equal(ens._cached_trajectory, traj[0:3])
-        assert_equal(ens._cache_can_append.trusted, False)
+        assert ens.can_append(traj[2:3]) is True
+        assert ens._cached_trajectory == traj[0:3]
+        assert ens._cache_can_append.trusted is False
 
-        assert_equal(ens.can_append(traj[2:4]), True)
-        assert_equal(ens._cached_trajectory, traj[0:4])
-        assert_equal(ens._cache_can_append.trusted, True)
+        assert ens.can_append(traj[2:4]) is True
+        assert ens._cached_trajectory == traj[0:4]
+        assert ens._cache_can_append.trusted is True
 
-        assert_equal(ens.can_append(traj[2:5]), True)
-        assert_equal(ens._cached_trajectory, traj[0:5])
-        assert_equal(ens._cache_can_append.trusted, True)
+        assert ens.can_append(traj[2:5]) is True
+        assert ens._cached_trajectory == traj[0:5]
+        assert ens._cache_can_append.trusted is True
 
-        assert_equal(ens.can_append(traj[2:6]), False)
-        assert_equal(ens._cached_trajectory, traj[0:6])
-        assert_equal(ens._cache_can_append.trusted, True)
+        assert ens.can_append(traj[2:6]) is False
+        assert ens._cached_trajectory == traj[0:6]
+        assert ens._cache_can_append.trusted is True
 
 
 class TestSuffixTrajectoryEnsemble(EnsembleTest):
@@ -1941,9 +1940,9 @@ def test_bad_end_traj(self):
             SequentialEnsemble([self.inX]),
             traj[-2:]
         )
-        assert_equal(ens.can_prepend(traj[-3:2]), False)
-        assert_equal(ens.strict_can_prepend(traj[-3:2]), False)
-        assert_equal(ens(traj[-3:2]), False)
+        assert ens.can_prepend(traj[-3:2]) is False
+        assert ens.strict_can_prepend(traj[-3:2]) is False
+        assert ens(traj[-3:2]) is False
 
     def test_good_end_traj(self):
         traj = ttraj['upper_out_in_in_in']
@@ -1951,30 +1950,30 @@ def test_good_end_traj(self):
             SequentialEnsemble([self.inX]),
             traj[-2:]
         )
-        assert_equal(ens.can_prepend(traj[-3:-2]), True)
-        assert_equal(ens.strict_can_prepend(traj[-3:-2]), True)
-        assert_equal(ens(traj[-3:-2]), True)
-        assert_equal(ens.can_prepend(traj[-4:-2]), False)
-        assert_equal(ens.strict_can_prepend(traj[-4:-2]), False)
-        assert_equal(ens(traj[-4:-2]), False)
-
-    @raises(RuntimeError)
+        assert ens.can_prepend(traj[-3:-2]) is True
+        assert ens.strict_can_prepend(traj[-3:-2]) is True
+        assert ens(traj[-3:-2]) is True
+        assert ens.can_prepend(traj[-4:-2]) is False
+        assert ens.strict_can_prepend(traj[-4:-2]) is False
+        assert ens(traj[-4:-2]) is False
+
     def test_can_append(self):
         traj = ttraj['upper_out_in_in_in']
         ens = SuffixTrajectoryEnsemble(
             SequentialEnsemble([self.inX]),
             traj[-2:]
         )
-        ens.can_append(traj)
+        with pytest.raises(RuntimeError):
+            ens.can_append(traj)
 
-    @raises(RuntimeError)
     def test_strict_can_append(self):
         traj = ttraj['upper_out_in_in_in']
         ens = SuffixTrajectoryEnsemble(
             SequentialEnsemble([self.inX]),
             traj[-2:]
         )
-        ens.strict_can_append(traj)
+        with pytest.raises(RuntimeError):
+            ens.strict_can_append(traj)
 
     def test_caching_in_bkwdprep_seq(self):
         length1 = LengthEnsemble(1)
@@ -1988,25 +1987,25 @@ def test_caching_in_bkwdprep_seq(self):
         traj = ttraj['upper_in_out_in_in_out_in']
 
         # sanity checks before running the suffixed version
-        assert_equal(pseudo_minus(traj), True)
+        assert pseudo_minus(traj) is True
         for i in range(-1, -6):
-            assert_equal(pseudo_minus.can_prepend(traj[i:]), True)
+            assert pseudo_minus.can_prepend(traj[i:]) is True
 
         logger.debug("alltraj " + str([id(i) for i in traj]))
         ens = SuffixTrajectoryEnsemble(pseudo_minus, traj[-3:])
-        assert_equal(len(ens._cached_trajectory), 3)
+        assert len(ens._cached_trajectory) == 3
 
-        assert_equal(ens.can_prepend(traj[-4:-3].reversed), True)
-        assert_equal(len(ens._cached_trajectory), 4)
-        assert_equal(ens._cache_can_prepend.trusted, False)
+        assert ens.can_prepend(traj[-4:-3].reversed) is True
+        assert len(ens._cached_trajectory) == 4
+        assert ens._cache_can_prepend.trusted is False
 
-        assert_equal(ens.can_prepend(traj[-5:-3].reversed), True)
-        assert_equal(len(ens._cached_trajectory), 5)
-        assert_equal(ens._cache_can_prepend.trusted, True)
+        assert ens.can_prepend(traj[-5:-3].reversed) is True
+        assert len(ens._cached_trajectory) == 5
+        assert ens._cache_can_prepend.trusted is True
 
-        assert_equal(ens.can_prepend(traj[-6:-3].reversed), False)
-        assert_equal(len(ens._cached_trajectory), 6)
-        assert_equal(ens._cache_can_prepend.trusted, True)
+        assert ens.can_prepend(traj[-6:-3].reversed) is False
+        assert len(ens._cached_trajectory) == 6
+        assert ens._cache_can_prepend.trusted is True
 
 class TestMinusInterfaceEnsemble(EnsembleTest):
     def setup_method(self):
@@ -2034,13 +2033,13 @@ def test_dict_round_trip(self):
         dct = self.minus_nl2.to_dict()
         rebuilt = MinusInterfaceEnsemble.from_dict(dct)
         dct2 = rebuilt.to_dict()
-        assert_equal(dct, dct2)
+        assert dct == dct2
 
-    @raises(ValueError)
     def test_minus_nl1_fail(self):
-        minus_nl1 = MinusInterfaceEnsemble(state_vol=vol1,
-                                           innermost_vols=vol2,
-                                           n_l=1)
+        with pytest.raises(ValueError):
+            minus_nl1 = MinusInterfaceEnsemble(state_vol=vol1,
+                                               innermost_vols=vol2,
+                                               n_l=1)
 
 
     def test_minus_nl2_ensemble(self):
@@ -2311,13 +2310,13 @@ def test_extend_sample_from_trajectories(self):
             sset, replica=-1, engine=engine, level='complex'
         )
 
-        assert_equal(sample.ensemble(sample.trajectory), True)
-        assert_equal(sample.ensemble, self.minus_nl2)
-        assert_equal(sample.replica, -1)
-        assert_equal(len(sample.trajectory), 5)
+        assert sample.ensemble(sample.trajectory) is True
+        assert sample.ensemble == self.minus_nl2
+        assert sample.replica == -1
+        assert len(sample.trajectory) == 5
         expected = trajB + ttraj['upper_out_in']
         for (t, b) in zip(sample.trajectory, expected):
-            assert_equal(t.xyz[0][0], b.xyz[0][0])
+            assert t.xyz[0][0] == b.xyz[0][0]
 
         # test with a different trajectory
         predestined_snaps = [trajB[-1]]+ttraj['upper_in_out_in']
@@ -2327,13 +2326,13 @@ def test_extend_sample_from_trajectories(self):
             sset, replica=-1, engine=engine, level='complex'
         )
 
-        assert_equal(sample.ensemble(sample.trajectory), True)
-        assert_equal(sample.ensemble, self.minus_nl2)
-        assert_equal(sample.replica, -1)
-        assert_equal(len(sample.trajectory), 6)
+        assert sample.ensemble(sample.trajectory) is True
+        assert sample.ensemble == self.minus_nl2
+        assert sample.replica == -1
+        assert len(sample.trajectory) == 6
         expected = trajB + ttraj['upper_in_out_in']
         for (t, b) in zip(sample.trajectory, expected):
-            assert_equal(t.xyz[0][0], b.xyz[0][0])
+            assert t.xyz[0][0] == b.xyz[0][0]
 
 
 # TODO: this whole class should become a single test in SeqEns
@@ -2360,30 +2359,29 @@ def setup_method(self):
         self.outA = AllOutXEnsemble(vol1)
 
     def test_split(self):
-#        raise SkipTest
         traj1 = ttraj['upper_in_out_in_in']
         # print [s for s in traj1]
         subtrajs_in_1 = self.inA.split(traj1)
         # print subtrajs_in_1
         # print [[s for s in t] for t in subtrajs_in_1]
-        assert_equal(len(subtrajs_in_1), 2)
-        assert_equal(len(subtrajs_in_1[0]), 1)
-        assert_equal(len(subtrajs_in_1[1]), 2)
+        assert len(subtrajs_in_1) == 2
+        assert len(subtrajs_in_1[0]) == 1
+        assert len(subtrajs_in_1[1]) == 2
         subtrajs_out_1 = self.outA.split(traj1)
-        assert_equal(len(subtrajs_out_1), 1)
+        assert len(subtrajs_out_1) == 1
 
         traj2 = ttraj['upper_in_out_in_in_out_in']
         # print [s for s in traj2]
         subtrajs_in_2 = self.inA.split(traj2)
         # print [[s for s in t] for t in subtrajs_in_2]
-        assert_equal(len(subtrajs_in_2), 3)
-        assert_equal(len(subtrajs_in_2[0]), 1)
-        assert_equal(len(subtrajs_in_2[1]), 2)
-        assert_equal(len(subtrajs_in_2[2]), 1)
+        assert len(subtrajs_in_2) == 3
+        assert len(subtrajs_in_2[0]) == 1
+        assert len(subtrajs_in_2[1]) == 2
+        assert len(subtrajs_in_2[2]) == 1
         subtrajs_out_2 = self.outA.split(traj2)
-        assert_equal(len(subtrajs_out_2), 2)
-        assert_equal(len(subtrajs_out_2[0]), 1)
-        assert_equal(len(subtrajs_out_2[1]), 1)
+        assert len(subtrajs_out_2) == 2
+        assert len(subtrajs_out_2[0]) == 1
+        assert len(subtrajs_out_2[1]) == 1
 
         ensembleAXA = paths.SequentialEnsemble([
             self.inA,
@@ -2397,54 +2395,54 @@ def test_split(self):
         assert(self.outA(paths.Trajectory([traj3[1]])))
 
         subtrajs_in_3 = ensembleAXA.split(traj3)
-        assert_equal((len(subtrajs_in_3)), 2)
-        assert_equal((len(subtrajs_in_3[0])), 3)
-        assert_equal((len(subtrajs_in_3[1])), 3)
+        assert (len(subtrajs_in_3)) == 2
+        assert (len(subtrajs_in_3[0])) == 3
+        assert (len(subtrajs_in_3[1])) == 3
         assert(traj3.subtrajectory_indices(subtrajs_in_3[0]) == [0, 1, 2])
         assert(traj3.subtrajectory_indices(subtrajs_in_3[1]) == [2, 3, 4])
 
         subtrajs_in_3 = ensembleAXA.split(traj3, reverse=True)
-        assert_equal((len(subtrajs_in_3)), 2)
-        assert_equal((len(subtrajs_in_3[0])), 3)
-        assert_equal((len(subtrajs_in_3[1])), 3)
+        assert (len(subtrajs_in_3)) == 2
+        assert (len(subtrajs_in_3[0])) == 3
+        assert (len(subtrajs_in_3[1])) == 3
         assert(traj3.subtrajectory_indices(subtrajs_in_3[0]) == [2, 3, 4])
         assert(traj3.subtrajectory_indices(subtrajs_in_3[1]) == [0, 1, 2])
 
         subtrajs_in_3 = ensembleAXA.split(traj3, overlap=0)
-        assert_equal((len(subtrajs_in_3)), 1)
-        assert_equal((len(subtrajs_in_3[0])), 3)
+        assert (len(subtrajs_in_3)) == 1
+        assert (len(subtrajs_in_3[0])) == 3
         assert(traj3.subtrajectory_indices(subtrajs_in_3[0]) == [0, 1, 2])
 
         subtrajs_in_3 = ensembleAXA.split(traj3, reverse=True, overlap=0)
-        assert_equal((len(subtrajs_in_3)), 1)
-        assert_equal((len(subtrajs_in_3[0])), 3)
+        assert (len(subtrajs_in_3)) == 1
+        assert (len(subtrajs_in_3[0])) == 3
         assert(traj3.subtrajectory_indices(subtrajs_in_3[0]) == [2, 3, 4])
 
         subtrajs_in_3 = ensembleAXA.split(traj3, overlap=1, max_length=2)
-        assert_equal((len(subtrajs_in_3)), 0)
+        assert (len(subtrajs_in_3)) == 0
 
         subtrajs_in_3 = ensembleAXA.split(traj3, reverse=True, max_length=2)
-        assert_equal((len(subtrajs_in_3)), 0)
+        assert (len(subtrajs_in_3)) == 0
 
         subtrajs_in_3 = ensembleAXA.split(traj3, max_length=3)
-        assert_equal(len(subtrajs_in_3), 2)
-        assert_equal((len(subtrajs_in_3[0])), 3)
-        assert_equal((len(subtrajs_in_3[1])), 3)
+        assert len(subtrajs_in_3) == 2
+        assert (len(subtrajs_in_3[0])) == 3
+        assert (len(subtrajs_in_3[1])) == 3
         assert(traj3.subtrajectory_indices(subtrajs_in_3[0]) == [0, 1, 2])
         assert(traj3.subtrajectory_indices(subtrajs_in_3[1]) == [2, 3, 4])
 
         subtrajs_in_3 = ensembleAXA.split(traj3, reverse=True, max_length=3)
-        assert_equal((len(subtrajs_in_3)), 2)
-        assert_equal((len(subtrajs_in_3[0])), 3)
-        assert_equal((len(subtrajs_in_3[1])), 3)
+        assert (len(subtrajs_in_3)) == 2
+        assert (len(subtrajs_in_3[0])) == 3
+        assert (len(subtrajs_in_3[1])) == 3
         assert(traj3.subtrajectory_indices(subtrajs_in_3[1]) == [0, 1, 2])
         assert(traj3.subtrajectory_indices(subtrajs_in_3[0]) == [2, 3, 4])
 
         subtrajs_in_3 = ensembleAXA.split(traj3, reverse=False, min_length=4)
-        assert_equal((len(subtrajs_in_3)), 0)
+        assert (len(subtrajs_in_3)) == 0
 
         subtrajs_in_3 = ensembleAXA.split(traj3, reverse=True, min_length=4)
-        assert_equal((len(subtrajs_in_3)), 0)
+        assert (len(subtrajs_in_3)) == 0
 
         sub_traj = ensembleAXA.find_first_subtrajectory(traj3)
         assert(traj3.subtrajectory_indices(sub_traj) == [0,1,2])
@@ -2492,11 +2490,11 @@ def _test_trusted(self, trajectory, function, results,
                 end = len(trajectory)
                 start = end - (i+start_traj_len)
             # test untrusted
-            assert_equal(function(trajectory[start:end]), results[i])
+            assert function(trajectory[start:end]) == results[i]
             # test trusted
             trusted_val = function(trajectory[start:end], trusted=True)
             # print i, "["+str(start)+":"+str(end)+"]", trusted_val, results[i]
-            assert_equal(trusted_val, results[i])
+            assert trusted_val == results[i]
             for cache in list(cache_results.keys()):
                 # TODO: this is currently very specific to the caches used
                 # by volumes ensembles. That should be generalized by
@@ -2510,8 +2508,8 @@ def _test_trusted(self, trajectory, function, results,
                         contents = None
                     #print contents, cache_results[cache][i]
 
-                    assert_equal(cache.contents['previous'],
-                                 cache_results[cache][i])
+                    assert (cache.contents['previous']
+                            == cache_results[cache][i])
 
     def test_call_outA_or_outB(self):
         # print self.local_ttraj['upper_out_in_out_out_cross'].xyz[:,0,0]
@@ -2722,8 +2720,8 @@ class TestEnsembleEquality(object):
     def test_empty_ensemble_equality(self):
         ens1 = paths.EmptyEnsemble()
         ens2 = paths.EmptyEnsemble()
-        assert_true(ens1 == ens2)
-        assert_false(ens1 != ens2)
+        assert ens1 == ens2
+        assert not ens1 != ens2  # needed __ne__ tested in the Py27 days
 
     # TODO: may add tests for other ensembles, or may move this test
     # somewhere else
diff --git a/openpathsampling/tests/test_features.py b/openpathsampling/tests/test_features.py
index 6c833a7e6..59a52ad54 100644
--- a/openpathsampling/tests/test_features.py
+++ b/openpathsampling/tests/test_features.py
@@ -1,9 +1,8 @@
 from __future__ import absolute_import
 from builtins import hex
 from builtins import object
-from nose.tools import raises
 
-from nose.plugins.skip import SkipTest
+import pytest
 from .test_helpers import u
 
 import logging
@@ -42,7 +41,7 @@ def test_copy_with_replacement_toy(self):
 
     def test_copy_with_replacement_openmm(self):
         if not paths.integration_tools.HAS_OPENMM or omt is None:
-            raise SkipTest
+            pytest.skip()
         # test an openmm snapshot
         sys = omt.testsystems.AlanineDipeptideVacuum()
         omm_snap = omm_engine.snapshot_from_testsystem(sys)
@@ -63,10 +62,10 @@ def test_copy_with_replacement_openmm(self):
         assert(hex(id(omm_snap.kinetics)) == hex(id(omm_copy.kinetics)))
         assert(hex(id(omm_snap.statics)) != hex(id(omm_copy.statics)))
 
-    @raises(TypeError)
     def test_parameter_error(self):
         init_coord = np.array([1.0, 2.0])
         init_vel = np.array([3.0, 4.0])
         toy_snap = toy_engine.Snapshot(
             coordinates=init_coord, velocities=init_vel)
-        toy_snap.copy_with_replacement(dummy=0)
+        with pytest.raises(TypeError):
+            toy_snap.copy_with_replacement(dummy=0)
diff --git a/openpathsampling/tests/test_gromacs_engine.py b/openpathsampling/tests/test_gromacs_engine.py
index 906666b20..a1282278a 100644
--- a/openpathsampling/tests/test_gromacs_engine.py
+++ b/openpathsampling/tests/test_gromacs_engine.py
@@ -1,9 +1,5 @@
 import pytest
 import numpy.testing as npt
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises, assert_true)
-from nose.plugins.skip import Skip, SkipTest
-import numpy.testing as npt
 import tempfile
 
 from .test_helpers import data_filename, assert_items_equal
@@ -113,30 +109,30 @@ def test_read_frame_from_file_success(self):
         # when the frame is present, we should return it
         fname = os.path.join(self.test_dir, "project_trr", "0000000.trr")
         result = self.engine.read_frame_from_file(fname, 0)
-        assert_true(isinstance(result, ExternalMDSnapshot))
-        assert_equal(result.file_name, fname)
-        assert_equal(result.file_position, 0)
+        assert isinstance(result, ExternalMDSnapshot)
+        assert result.file_name == fname
+        assert result.file_position == 0
         # TODO: add caching of xyz, vel, box; check that we have it now
 
         fname = os.path.join(self.test_dir, "project_trr", "0000000.trr")
         result = self.engine.read_frame_from_file(fname, 3)
-        assert_true(isinstance(result, ExternalMDSnapshot))
-        assert_equal(result.file_name, fname)
-        assert_equal(result.file_position, 3)
+        assert isinstance(result, ExternalMDSnapshot)
+        assert result.file_name == fname
+        assert result.file_position == 3
 
     def test_read_frame_from_file_partial(self):
         # if a frame is partial, return 'partial'
         fname = os.path.join(self.test_dir, "project_trr", "0000099.trr")
         frame_2 = self.engine.read_frame_from_file(fname, 49)
-        assert_true(isinstance(frame_2, ExternalMDSnapshot))
+        assert isinstance(frame_2, ExternalMDSnapshot)
         frame_3 = self.engine.read_frame_from_file(fname, 50)
-        assert_equal(frame_3, "partial")
+        assert frame_3 == "partial"
 
     def test_read_frame_from_file_none(self):
         # if a frame is beyond the last frame, return None
         fname = os.path.join(self.test_dir, "project_trr", "0000000.trr")
         result = self.engine.read_frame_from_file(fname, 4)
-        assert_equal(result, None)
+        assert result is None
 
     def test_write_frame_to_file_read_back(self):
         # write random frame; read back
@@ -158,8 +154,8 @@ def test_write_frame_to_file_read_back(self):
         self.engine.write_frame_to_file(traj_50, snap)
 
         snap2 = self.engine.read_frame_from_file(traj_50, 0)
-        assert_equal(snap2.file_name, traj_50)
-        assert_equal(snap2.file_position, 0)
+        assert snap2.file_name == traj_50
+        assert snap2.file_position == 0
         npt.assert_array_almost_equal(snap.xyz, snap2.xyz)
         npt.assert_array_almost_equal(snap.velocities, snap2.velocities)
         npt.assert_array_almost_equal(snap.box_vectors, snap2.box_vectors)
@@ -176,20 +172,25 @@ def test_set_filenames_int(self):
                 os.path.join(self.test_dir, "initial_frame.trr")
         assert test_engine.output_file == \
                 os.path.join(self.test_dir, "proj_trr", "0000001.trr")
-        assert_equal(test_engine.edr_file,
-                     os.path.join(self.test_dir, "proj_edr", "0000001.edr"))
-        assert_equal(test_engine.log_file,
-                     os.path.join(self.test_dir, "proj_log", "0000001.log"))
+        assert test_engine.edr_file == os.path.join(self.test_dir,
+                                                    "proj_edr",
+                                                    "0000001.edr")
+        assert test_engine.log_file == os.path.join(self.test_dir,
+                                                    "proj_log",
+                                                    "0000001.log")
 
         test_engine.set_filenames(99)
-        assert_equal(test_engine.input_file,
-                     os.path.join(self.test_dir, "initial_frame.trr"))
-        assert_equal(test_engine.output_file,
-                     os.path.join(self.test_dir, "proj_trr", "0000100.trr"))
-        assert_equal(test_engine.edr_file,
-                     os.path.join(self.test_dir, "proj_edr", "0000100.edr"))
-        assert_equal(test_engine.log_file,
-                     os.path.join(self.test_dir, "proj_log", "0000100.log"))
+        assert test_engine.input_file == os.path.join(self.test_dir,
+                                                      "initial_frame.trr")
+        assert test_engine.output_file == os.path.join(self.test_dir,
+                                                       "proj_trr",
+                                                       "0000100.trr")
+        assert test_engine.edr_file == os.path.join(self.test_dir,
+                                                    "proj_edr",
+                                                    "0000100.edr")
+        assert test_engine.log_file == os.path.join(self.test_dir,
+                                                    "proj_log",
+                                                    "0000100.log")
 
     def test_set_filenames_fixed(self):
         test_engine = Engine(gro="conf.gro", mdp="md.mdp", top="topol.top",
@@ -234,12 +235,12 @@ def test_generate(self):
 
         ens = paths.LengthEnsemble(5)
         traj = self.engine.generate(snap, running=[ens.can_append])
-        assert_equal(self.engine.proc.is_running(), False)
-        assert_equal(len(traj), 5)
+        assert self.engine.proc.is_running() is False
+        assert len(traj) == 5
         ttraj = md.load(self.engine.trajectory_filename(1),
                         top=self.engine.gro)
         # the mdp suggests a max length of 100 frames
-        assert_true(len(ttraj) < 100)
+        assert len(ttraj) < 100
 
     def test_prepare(self):
         if not has_gmx:
@@ -253,7 +254,7 @@ def test_prepare(self):
             if os.path.isfile(f):
                 raise AssertionError("File " + str(f) + " already exists!")
 
-        assert_equal(self.engine.prepare(), 0)
+        assert self.engine.prepare() == 0
         for f in files:
             if not os.path.isfile(f):
                 raise AssertionError("File " + str(f) + " was not created!")
diff --git a/openpathsampling/tests/test_helpers.py b/openpathsampling/tests/test_helpers.py
index 198a9a9f4..3ed2ed199 100644
--- a/openpathsampling/tests/test_helpers.py
+++ b/openpathsampling/tests/test_helpers.py
@@ -278,7 +278,10 @@ def generate_next_frame(self):
 
 def raises_with_message_like(err, message=None):
     """
-    Decorator that allows to run nosetests with raises and testing if the message starts with a txt.
+    Decorator that allows to run tests with raises and testing if the
+    message starts with a txt.
+
+    TODO: this should be deprecated in favor of pytest functionality
 
     Notes
     -----
diff --git a/openpathsampling/tests/test_interface_set.py b/openpathsampling/tests/test_interface_set.py
index 8c0bf033b..d0f684da8 100644
--- a/openpathsampling/tests/test_interface_set.py
+++ b/openpathsampling/tests/test_interface_set.py
@@ -2,9 +2,8 @@
 from builtins import zip
 from builtins import range
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises)
-from nose.plugins.skip import Skip, SkipTest
+
+import pytest
 from .test_helpers import (
     true_func, assert_equal_array_array, make_1d_traj, data_filename,
     assert_items_equal
@@ -35,37 +34,37 @@ def setup_method(self):
         self.no_lambda_set = paths.InterfaceSet(self.volumes, self.cv)
 
     def test_direction(self):
-        assert_equal(self.interface_set.direction, 1)
-        assert_equal(self.no_lambda_set.direction, 0)
-        assert_equal(self.decreasing.direction, -1)
+        assert self.interface_set.direction == 1
+        assert self.no_lambda_set.direction == 0
+        assert self.decreasing.direction == -1
 
     def test_get_lambda(self):
         for (v, l) in zip(self.volumes, self.lambdas):
-            assert_equal(self.interface_set.get_lambda(v), l)
-            assert_equal(self.no_lambda_set.get_lambda(v), None)
+            assert self.interface_set.get_lambda(v) == l
+            assert self.no_lambda_set.get_lambda(v) is None
 
     def test_list_behavior(self):
         # len
-        assert_equal(len(self.interface_set), 4)
-        assert_equal(len(self.no_lambda_set), 4)
+        assert len(self.interface_set) == 4
+        assert len(self.no_lambda_set) == 4
         # getitem, contains
         for i in range(4):
-            assert_equal(self.volumes[i], self.interface_set[i])
-            assert_equal(self.volumes[i] in self.interface_set, True)
+            assert self.volumes[i] == self.interface_set[i]
+            assert self.volumes[i] in self.interface_set
         # getitem for slices
         sliced = self.interface_set[0:2]
         for vol in sliced:
-            assert_equal(sliced.get_lambda(vol),
-                         self.interface_set.get_lambda(vol))
+            assert (sliced.get_lambda(vol)
+                    == self.interface_set.get_lambda(vol))
         # special case of -1 needs to work (used frequently!)
-        assert_equal(self.volumes[-1], self.interface_set[-1])
+        assert self.volumes[-1] == self.interface_set[-1]
         # iter
         for vol in self.interface_set:
-            assert_equal(vol in self.volumes, True)
+            assert vol in self.volumes
         # reversed
         i = 0
         for vol in reversed(self.interface_set):
-            assert_equal(vol, self.volumes[3-i])
+            assert vol == self.volumes[3-i]
             i += 1
 
     def test_no_direction_possible(self):
@@ -74,33 +73,33 @@ def test_no_direction_possible(self):
         volumes = [paths.CVDefinedVolume(self.cv, min_v, max_v)
                    for min_v, max_v in zip(min_vals, max_vals)]
         ifaces = paths.InterfaceSet(volumes)
-        assert_equal(ifaces.cv, None)
-        assert_equal(ifaces.cv_max, None)
-        assert_equal(ifaces.direction, 0)
+        assert ifaces.cv is None
+        assert ifaces.cv_max is None
+        assert ifaces.direction == 0
 
 
 class TestGenericVolumeInterfaceSet(object):
     def test_sanitize_input(self):
         # this is just to make the rest a little more readable
         sanitize = GenericVolumeInterfaceSet._sanitize_input
-        assert_equal(([float("-inf")]*3, [0.0, 0.1, 0.2], 1),
-                     sanitize(float("-inf"), [0.0, 0.1, 0.2]))
-        assert_equal(([0.2, 0.1, 0.0], [float("inf")]*3, -1),
-                     sanitize([0.2, 0.1, 0.0], float("inf")))
-        assert_equal(([-0.1, -0.2], [0.1, 0.2], 0),
-                     sanitize([-0.1, -0.2], [0.1, 0.2]))
-        assert_equal(([0.0, 0.0], [0.1, 0.2], 1),
-                     sanitize([0.0, 0.0], [0.1, 0.2]))
-        assert_equal(([-0.1, -0.2], [0.0, 0.0], -1),
-                     sanitize([-0.1, -0.2], [0.0, 0.0]))
+        assert (([float("-inf")]*3, [0.0, 0.1, 0.2], 1)
+                 == sanitize(float("-inf"), [0.0, 0.1, 0.2]))
+        assert (([0.2, 0.1, 0.0], [float("inf")]*3, -1)
+                 == sanitize([0.2, 0.1, 0.0], float("inf")))
+        assert (([-0.1, -0.2], [0.1, 0.2], 0)
+                 == sanitize([-0.1, -0.2], [0.1, 0.2]))
+        assert (([0.0, 0.0], [0.1, 0.2], 1)
+                 == sanitize([0.0, 0.0], [0.1, 0.2]))
+        assert (([-0.1, -0.2], [0.0, 0.0], -1)
+                 == sanitize([-0.1, -0.2], [0.0, 0.0]))
         # and the idiot case:
-        assert_equal(([-0.1, -0.1], [0.1, 0.1], 0),
-                     sanitize([-0.1, -0.1], [0.1, 0.1]))
+        assert (([-0.1, -0.1], [0.1, 0.1], 0)
+                 == sanitize([-0.1, -0.1], [0.1, 0.1]))
 
-    @raises(RuntimeError)
     def test_bad_sanitize(self):
-        GenericVolumeInterfaceSet._sanitize_input([0.0, -0.1],
-                                                  [0.1, 0.2, 0.3])
+        with pytest.raises(RuntimeError):
+            GenericVolumeInterfaceSet._sanitize_input([0.0, -0.1],
+                                                      [0.1, 0.2, 0.3])
 
 
 class TestVolumeInterfaceSet(object):
@@ -118,31 +117,31 @@ def setup_method(self):
                                                   maxvals=[0.1, 0.2])
 
     def test_initialization(self):
-        assert_equal(len(paths.InterfaceSet._cv_max_dict), 1)
+        assert len(paths.InterfaceSet._cv_max_dict) == 1
         cv_max = list(paths.InterfaceSet._cv_max_dict.values())[0]
 
-        assert_equal(len(self.increasing_set), 2)
-        assert_equal(self.increasing_set.direction, 1)
-        assert_equal(self.increasing_set.lambdas, [0.0, 0.1])
-        assert_equal(self.increasing_set.cv_max, cv_max)
+        assert len(self.increasing_set) == 2
+        assert self.increasing_set.direction == 1
+        assert self.increasing_set.lambdas == [0.0, 0.1]
+        assert self.increasing_set.cv_max == cv_max
 
-        assert_equal(len(self.decreasing_set), 2)
-        assert_equal(self.decreasing_set.direction, -1)
-        assert_equal(self.decreasing_set.lambdas, [0.0, -0.1])
+        assert len(self.decreasing_set) == 2
+        assert self.decreasing_set.direction == -1
+        assert self.decreasing_set.lambdas == [0.0, -0.1]
         # TODO: decide what to do about cv_max for decreasing/weird
 
-        assert_equal(len(self.weird_set), 2)
-        assert_equal(self.weird_set.direction, 0)
-        assert_equal(self.weird_set.lambdas, None)
+        assert len(self.weird_set) == 2
+        assert self.weird_set.direction == 0
+        assert self.weird_set.lambdas is None
 
     def test_new_interface(self):
         new_iface = self.increasing_set.new_interface(0.25)
         expected = paths.CVDefinedVolume(self.cv, float("-inf"), 0.25)
-        assert_equal(expected, new_iface)
+        assert expected == new_iface
 
-    @raises(TypeError)
     def test_bad_new_interface(self):
-        self.weird_set.new_interface(0.25)
+        with pytest.raises(TypeError):
+            self.weird_set.new_interface(0.25)
 
     def test_storage(self):
         import os
@@ -161,10 +160,10 @@ def test_storage(self):
 
         assert_items_equal(reloaded.lambdas, self.increasing_set.lambdas)
         for (truth, beauty) in zip(self.increasing_set, reloaded):
-            assert_equal(truth, beauty)
+            assert truth == beauty
 
         for (v, l) in zip(reloaded.volumes, reloaded.lambdas):
-            assert_equal(reloaded.get_lambda(v), l)
+            assert reloaded.get_lambda(v) == l
 
         if os.path.isfile(fname):
             os.remove(fname)
@@ -183,14 +182,14 @@ def setup_method(self):
         )
 
     def test_initialization(self):
-        assert_equal(self.increasing_set.direction, 1)
-        assert_equal(len(self.increasing_set), 3)
-        assert_equal(self.increasing_set.lambdas, [100, 150, -160])
+        assert self.increasing_set.direction == 1
+        assert len(self.increasing_set) == 3
+        assert self.increasing_set.lambdas == [100, 150, -160]
 
     def test_new_interface(self):
         new_iface = self.increasing_set.new_interface(-140)
         expected = paths.PeriodicCVDefinedVolume(self.cv, 0.0, -140, -180, 180)
-        assert_equal(new_iface, expected)
+        assert new_iface == expected
 
     def test_storage(self):
         import os
@@ -208,13 +207,13 @@ def test_storage(self):
         reloaded = storage_r.interfacesets[0]
 
         assert_items_equal(reloaded.lambdas, self.increasing_set.lambdas)
-        assert_equal(reloaded.period_min, self.increasing_set.period_min)
-        assert_equal(reloaded.period_max, self.increasing_set.period_max)
+        assert reloaded.period_min == self.increasing_set.period_min
+        assert reloaded.period_max == self.increasing_set.period_max
         for (truth, beauty) in zip(self.increasing_set, reloaded):
-            assert_equal(truth, beauty)
+            assert truth == beauty
 
         for (v, l) in zip(reloaded.volumes, reloaded.lambdas):
-            assert_equal(reloaded.get_lambda(v), l)
+            assert reloaded.get_lambda(v) == l
 
         storage_r.close()
         storage_w.close()
diff --git a/openpathsampling/tests/test_lookup_function.py b/openpathsampling/tests/test_lookup_function.py
index 1e35b2545..51266ad1e 100644
--- a/openpathsampling/tests/test_lookup_function.py
+++ b/openpathsampling/tests/test_lookup_function.py
@@ -1,11 +1,10 @@
 from __future__ import absolute_import
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises, assert_in)
-from nose.plugins.skip import SkipTest
 from numpy import isnan
+from numpy.testing import assert_almost_equal
 from .test_helpers import assert_items_almost_equal, assert_items_equal
 import collections
+import pytest
 
 import logging
 
@@ -84,15 +83,15 @@ def setup_method(self):
 
     def test_keys(self):
         keys = [(0,0), (0,2), (1,4), (-1,-1)]
-        assert_equal(len(list(self.lookup.keys())), len(keys))
+        assert len(list(self.lookup.keys())) == len(keys)
         for key in list(self.lookup.keys()):
-            assert_in(key, keys)
+            assert key in keys
 
     def test_values(self):
         values = [1.0, 2.0, 4.0, 5.0]
-        assert_equal(len(list(self.lookup.values())), len(values))
+        assert len(list(self.lookup.values())) == len(values)
         for val in list(self.lookup.values()):
-            assert_in(val, values)
+            assert val in values
 
     def test_bin_to_left_edge(self):
         assert_items_equal(self.lookup.bin_to_left_edge((0,0)), (-1.0, 1.0))
@@ -100,41 +99,41 @@ def test_bin_to_left_edge(self):
 
     def test_val_to_bin(self):
         result_bin = self.lookup.val_to_bin((-0.25, 2.0))
-        assert_equal(len(result_bin), 2)
+        assert len(result_bin) == 2
         assert_items_equal(result_bin, [1.5, 4.0])
 
     def test_counter_by_bin_edges(self):
         bin_edge_counter = self.lookup.counter_by_bin_edges
         expected = {(-1.0, 1.0): 1.0, (-1.0,1.5): 2.0, (-0.5, 2.0): 4.0,
                     (-1.5, 0.75): 5.0}
-        assert_equal(len(expected), len(bin_edge_counter))
+        assert len(expected) == len(bin_edge_counter)
         for k in list(expected.keys()):
-            assert_equal(bin_edge_counter[k], expected[k])
+            assert bin_edge_counter[k] == expected[k]
 
     def test_df_2d(self):
         df1 = self.lookup.df_2d()
         assert_items_equal(df1.index, [-1, 0, 1])
         assert_items_equal(df1.columns, [-1, 0, 2, 4])
-        assert_equal(df1.at[-1, -1], 5.0)
-        assert_equal(isnan(df1.at[0, 4]), True)
+        assert df1.at[-1, -1] == 5.0
+        assert isnan(df1.at[0, 4])
 
         df2 = self.lookup.df_2d(x_range=(-1, 3), y_range=(-1, 4))
         assert_items_equal(df2.index, [-1, 0, 1, 2, 3])
         assert_items_equal(df2.columns, [-1, 0, 1, 2, 3, 4])
-        assert_equal(df2.at[-1, -1], 5.0)
-        assert_equal(isnan(df2.at[0, 4]), True)
-        assert_equal(isnan(df2.at[2, 3]), True)
+        assert df2.at[-1, -1] == 5.0
+        assert isnan(df2.at[0, 4])
+        assert isnan(df2.at[2, 3])
 
-    @raises(RuntimeError)
     def test_df_2d_not_2d(self):
         counter = collections.Counter({(0,0,0): 1.0})
         luf = VoxelLookupFunction(left_bin_edges=(0,0,0),
                                   bin_widths=(1,1,1),
                                   counter=counter)
-        luf.df_2d()
+        with pytest.raises(RuntimeError):
+            luf.df_2d()
 
     def test_call(self):
-        assert_equal(self.lookup((0.0, 0.0)), 0.0)   # no bin
-        assert_equal(self.lookup((-0.5, 2.0)), 4.0)  # bin edge
-        assert_equal(self.lookup((-0.4, 2.1)), 4.0)  # in bin
+        assert self.lookup((0.0, 0.0)) == 0.0   # no bin
+        assert self.lookup((-0.5, 2.0)) == 4.0  # bin edge
+        assert self.lookup((-0.4, 2.1)) == 4.0  # in bin
 
diff --git a/openpathsampling/tests/test_mdtraj_support.py b/openpathsampling/tests/test_mdtraj_support.py
index d1d71def4..8a14571eb 100644
--- a/openpathsampling/tests/test_mdtraj_support.py
+++ b/openpathsampling/tests/test_mdtraj_support.py
@@ -4,10 +4,6 @@
 
 import pytest
 
-from nose.tools import (
-    assert_equal, assert_not_equal, raises
-)
-from nose.plugins.skip import SkipTest
 import numpy.testing as nptest
 from .test_helpers import data_filename, assert_items_equal, md, u
 
@@ -29,7 +25,7 @@
 class TestMDTrajSupport(object):
     def setup_method(self):
         if not md:
-            raise SkipTest("mdtraj not installed")
+            pytest.skip("mdtraj not installed")
         self.md_trajectory = md.load(data_filename("ala_small_traj.pdb"))
         _ = pytest.importorskip("simtk.unit")
         self.ops_trajectory = trajectory_from_mdtraj(self.md_trajectory)
@@ -49,16 +45,16 @@ def test_trajectory_mdtraj_round_trip(self):
         nptest.assert_allclose(self.md_trajectory.unitcell_vectors,
                                md_trajectory_2.unitcell_vectors)
 
-    @raises(ValueError)
     def test_empty_traj_to_mdtraj(self):
         empty = paths.Trajectory([])
-        empty.to_mdtraj()
+        with pytest.raises(ValueError):
+            empty.to_mdtraj()
 
     def test_trajectory_to_mdtraj_other_input(self):
         snap = self.ops_trajectory[0]
         md1 = trajectory_to_mdtraj(snap)
         md2 = trajectory_to_mdtraj([snap])
-        assert_equal(md1, md2)
+        assert md1 == md2
 
     def test_ops_load_trajectory_pdb(self):
         pdb_file = data_filename("ala_small_traj.pdb")
diff --git a/openpathsampling/tests/test_movescheme.py b/openpathsampling/tests/test_movescheme.py
index f58ec3685..5663cfe35 100644
--- a/openpathsampling/tests/test_movescheme.py
+++ b/openpathsampling/tests/test_movescheme.py
@@ -5,10 +5,7 @@
 from builtins import range
 from builtins import object
 from past.utils import old_div
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        assert_in, raises, assert_is, assert_is_not,
-                        assert_true)
-from nose.plugins.skip import Skip, SkipTest
+from numpy.testing import assert_almost_equal
 from .test_helpers import (true_func, assert_equal_array_array,
                            make_1d_traj, assert_items_equal)
 
@@ -414,69 +411,69 @@ def test_append_individuals_default_levels(self):
         shootstrat = OneWayShootingStrategy()
         repexstrat = NearestNeighborRepExStrategy()
         defaultstrat = OrganizeByMoveGroupStrategy()
-        assert_equal(len(list(self.scheme.strategies.keys())), 0)
+        assert len(list(self.scheme.strategies.keys())) == 0
         self.scheme.append(shootstrat)
         self.scheme.append(repexstrat)
         self.scheme.append(defaultstrat)
 
         strats = self.scheme.strategies
-        assert_equal(len(list(strats.keys())), 3)
+        assert len(list(strats.keys())) == 3
         pairs = [(levels.MOVER, shootstrat), (levels.SIGNATURE, repexstrat),
                  (levels.GLOBAL, defaultstrat)]
         for (k, v) in pairs:
-            assert_in(v, strats[k])
+            assert v in strats[k]
 
     def test_append_groups_default_levels(self):
         shootstrat = OneWayShootingStrategy()
         repexstrat = NearestNeighborRepExStrategy()
         defaultstrat = OrganizeByMoveGroupStrategy()
-        assert_equal(len(list(self.scheme.strategies.keys())), 0)
+        assert len(list(self.scheme.strategies.keys())) == 0
         self.scheme.append([shootstrat, repexstrat, defaultstrat])
 
         strats = self.scheme.strategies
-        assert_equal(len(list(strats.keys())), 3)
+        assert len(list(strats.keys())) == 3
         pairs = [(levels.MOVER, shootstrat), (levels.SIGNATURE, repexstrat),
                  (levels.GLOBAL, defaultstrat)]
         for (k, v) in pairs:
-            assert_in(v, strats[k])
+            assert v in strats[k]
 
 
     def test_append_individuals_custom_levels(self):
         shootstrat = OneWayShootingStrategy()
         repexstrat = NearestNeighborRepExStrategy()
         defaultstrat = OrganizeByMoveGroupStrategy()
-        assert_equal(len(list(self.scheme.strategies.keys())), 0)
+        assert len(list(self.scheme.strategies.keys())) == 0
         self.scheme.append(shootstrat, 60)
         self.scheme.append(repexstrat, 60)
         self.scheme.append(defaultstrat, 60)
 
         strats = self.scheme.strategies
-        assert_equal(len(list(strats.keys())), 1)
+        assert len(list(strats.keys())) == 1
         assert_items_equal(strats[60], [shootstrat, repexstrat, defaultstrat])
 
     def test_append_groups_same_custom_level(self):
         shootstrat = OneWayShootingStrategy()
         repexstrat = NearestNeighborRepExStrategy()
         defaultstrat = OrganizeByMoveGroupStrategy()
-        assert_equal(len(list(self.scheme.strategies.keys())), 0)
+        assert len(list(self.scheme.strategies.keys())) == 0
         self.scheme.append([shootstrat, repexstrat, defaultstrat], 60)
 
         strats = self.scheme.strategies
-        assert_equal(len(list(strats.keys())), 1)
+        assert len(list(strats.keys())) == 1
         assert_items_equal(strats[60], [shootstrat, repexstrat, defaultstrat])
 
     def test_append_group_different_custom_levels(self):
         shootstrat = OneWayShootingStrategy()
         repexstrat = NearestNeighborRepExStrategy()
         defaultstrat = OrganizeByMoveGroupStrategy()
-        assert_equal(len(list(self.scheme.strategies.keys())), 0)
+        assert len(list(self.scheme.strategies.keys())) == 0
         self.scheme.append([shootstrat, repexstrat, defaultstrat],
                            [45, 55, 65])
 
         strats = self.scheme.strategies
-        assert_equal(len(list(strats.keys())), 3)
+        assert len(list(strats.keys())) == 3
         for (k, v) in [(45, shootstrat), (55, repexstrat), (65, defaultstrat)]:
-            assert_in(v, strats[k])
+            assert v in strats[k]
 
     def test_apply_strategy(self):
         if self.scheme.movers == {}:
@@ -500,36 +497,36 @@ def test_apply_strategy(self):
 
         self.scheme.apply_strategy(shoot_strat_1)
         assert_items_equal(list(self.scheme.movers.keys()), ['shooting'])
-        assert_equal(len(self.scheme.movers['shooting']), 3)
+        assert len(self.scheme.movers['shooting']) == 3
 
         self.scheme.apply_strategy(shoot_strat_2)
         assert_items_equal(list(self.scheme.movers.keys()), ['shooting'])
-        assert_equal(len(self.scheme.movers['shooting']), 7)
+        assert len(self.scheme.movers['shooting']) == 7
         old_movers = copy.copy(self.scheme.movers['shooting'])
 
         self.scheme.apply_strategy(shoot_strat_3)
         assert_items_equal(list(self.scheme.movers.keys()), ['shooting'])
-        assert_equal(len(self.scheme.movers['shooting']), 7)
+        assert len(self.scheme.movers['shooting']) == 7
         new_movers = self.scheme.movers['shooting']
         for (o, n) in zip(old_movers, new_movers):
-            assert_equal(o is n, False)
+            assert o is not n
 
         shoot_strat_3.replace_signatures = True
         self.scheme.apply_strategy(shoot_strat_3)
-        assert_equal(len(self.scheme.movers['shooting']), 6)
+        assert len(self.scheme.movers['shooting']) == 6
 
         self.scheme.movers = {}
         shoot_strat_1.set_replace(True)
         self.scheme.apply_strategy(shoot_strat_1)
-        assert_equal(len(self.scheme.movers['shooting']), 3)
+        assert len(self.scheme.movers['shooting']) == 3
         old_movers = copy.copy(self.scheme.movers['shooting'])
 
         shoot_strat_3.replace_signatures = False
         self.scheme.apply_strategy(shoot_strat_3)
-        assert_equal(len(self.scheme.movers['shooting']), 6)
+        assert len(self.scheme.movers['shooting']) == 6
         new_movers = self.scheme.movers['shooting']
         for (o, n) in zip(old_movers, new_movers):
-            assert_equal(o is n, False)
+            assert o is not n
 
     def test_move_decision_tree(self):
         shoot = OneWayShootingStrategy()
@@ -537,24 +534,24 @@ def test_move_decision_tree(self):
         default = OrganizeByMoveGroupStrategy()
         self.scheme.append([default, shoot, repex])
 
-        assert_equal(self.scheme.root_mover, None)
+        assert self.scheme.root_mover is None
         root = self.scheme.move_decision_tree()
-        assert_not_equal(self.scheme.root_mover, None)
+        assert self.scheme.root_mover is not None
 
-        assert_equal(len(root.movers), 2)
+        assert len(root.movers) == 2
         names = ['ShootingChooser', 'RepexChooser']
         name_dict = {root.movers[i].name : i for i in range(len(root.movers))}
         for name in names:
-            assert_in(name, list(name_dict.keys()))
+            assert name in list(name_dict.keys())
 
-        assert_equal(len(root.movers[name_dict['ShootingChooser']].movers), 6)
-        assert_equal(len(root.movers[name_dict['RepexChooser']].movers), 4)
+        assert len(root.movers[name_dict['ShootingChooser']].movers) == 6
+        assert len(root.movers[name_dict['RepexChooser']].movers) == 4
 
         new_root = self.scheme.move_decision_tree()
-        assert_is(new_root, root)
+        assert new_root is root
 
         new_root = self.scheme.move_decision_tree(rebuild=True)
-        assert_is_not(new_root, root)
+        assert new_root is not root
 
     def test_repex_style_switching(self):
         nn_repex = NearestNeighborRepExStrategy()
@@ -563,15 +560,15 @@ def test_repex_style_switching(self):
 
         self.scheme.append([default, nn_repex])
         root = self.scheme.move_decision_tree(rebuild=True)
-        assert_equal(len(self.scheme.movers['repex']), 4)
+        assert len(self.scheme.movers['repex']) == 4
 
         self.scheme.append(all_repex, force=True)
         root = self.scheme.move_decision_tree(rebuild=True)
-        assert_equal(len(self.scheme.movers['repex']), 6)
+        assert len(self.scheme.movers['repex']) == 6
 
         self.scheme.append(nn_repex, force=True)
         root = self.scheme.move_decision_tree(rebuild=True)
-        assert_equal(len(self.scheme.movers['repex']), 4)
+        assert len(self.scheme.movers['repex']) == 4
 
     def test_build_balance_partners(self):
         ensA = self.scheme.network.sampling_transitions[0].ensembles[0]
@@ -582,15 +579,14 @@ def test_build_balance_partners(self):
         self.scheme.append(strategies.OrganizeByMoveGroupStrategy())
         root = self.scheme.move_decision_tree()
         self.scheme.build_balance_partners()
-        assert_equal(self.scheme.balance_partners[hopAB], [hopBA])
-        assert_equal(self.scheme.balance_partners[hopBA], [hopAB])
+        assert self.scheme.balance_partners[hopAB] == [hopBA]
+        assert self.scheme.balance_partners[hopBA] == [hopAB]
 
-    @raises(RuntimeWarning)
     def test_build_balance_partners_premature(self):
         self.scheme.movers = {}
-        self.scheme.build_balance_partners()
+        with pytest.raises(RuntimeWarning):
+            self.scheme.build_balance_partners()
 
-    @raises(RuntimeWarning)
     def test_build_balance_partners_no_partner(self):
         ensA = self.scheme.network.sampling_transitions[0].ensembles[0]
         ensB = self.scheme.network.sampling_transitions[0].ensembles[1]
@@ -599,9 +595,9 @@ def test_build_balance_partners_no_partner(self):
         self.scheme.movers['hop'] = [hopAB]
         self.scheme.append(strategies.OrganizeByMoveGroupStrategy())
         root = self.scheme.move_decision_tree()
-        self.scheme.build_balance_partners()
+        with pytest.raises(RuntimeWarning):
+            self.scheme.build_balance_partners()
 
-    @raises(RuntimeWarning)
     def test_build_balance_partners_two_partners(self):
         ensA = self.scheme.network.sampling_transitions[0].ensembles[0]
         ensB = self.scheme.network.sampling_transitions[0].ensembles[1]
@@ -611,7 +607,8 @@ def test_build_balance_partners_two_partners(self):
         self.scheme.movers['hop'] = [hopAB, hopBA, hopAB2]
         self.scheme.append(strategies.OrganizeByMoveGroupStrategy())
         root = self.scheme.move_decision_tree()
-        self.scheme.build_balance_partners()
+        with pytest.raises(RuntimeWarning):
+            self.scheme.build_balance_partners()
 
     def test_sanity_check_sane(self):
         self.scheme.append([NearestNeighborRepExStrategy(),
@@ -620,7 +617,6 @@ def test_sanity_check_sane(self):
         root = self.scheme.move_decision_tree()
         self.scheme.sanity_check()
 
-    @raises(AssertionError)
     def test_sanity_check_unused_sampling(self):
         ensemble_subset = self.scheme.network.sampling_transitions[0].ensembles
         self.scheme.append([
@@ -628,9 +624,9 @@ def test_sanity_check_unused_sampling(self):
             OrganizeByMoveGroupStrategy()
         ])
         root = self.scheme.move_decision_tree()
-        self.scheme.sanity_check()
+        with pytest.raises(AssertionError):
+            self.scheme.sanity_check()
 
-    @raises(AssertionError)
     def test_sanity_check_choice_prob_fails(self):
         self.scheme.append([NearestNeighborRepExStrategy(),
                             OneWayShootingStrategy(),
@@ -638,9 +634,9 @@ def test_sanity_check_choice_prob_fails(self):
         root = self.scheme.move_decision_tree()
         key0 = list(self.scheme.choice_probability.keys())[0]
         self.scheme.choice_probability[key0] = 0.0
-        self.scheme.sanity_check()
+        with pytest.raises(AssertionError):
+            self.scheme.sanity_check()
 
-    @raises(AssertionError)
     def test_sanity_check_duplicated_movers(self):
         ensemble_subset = self.scheme.network.sampling_transitions[0].ensembles
         self.scheme.append([
@@ -649,13 +645,14 @@ def test_sanity_check_duplicated_movers(self):
         ])
         root = self.scheme.move_decision_tree()
         self.scheme.movers['foo'] = [self.scheme.movers['shooting'][0]]
-        self.scheme.sanity_check()
+        with pytest.raises(AssertionError):
+            self.scheme.sanity_check()
 
-    @raises(TypeError)
     def test_select_movers_no_choice_probability(self):
         self.scheme.append([OneWayShootingStrategy(),
                             OrganizeByMoveGroupStrategy()])
-        movers = self.scheme._select_movers('shooting')
+        with pytest.raises(TypeError):
+            movers = self.scheme._select_movers('shooting')
 
     def test_select_movers(self):
         self.scheme.append([
@@ -667,13 +664,13 @@ def test_select_movers(self):
         some_shooters = self.scheme.movers['shooting'][0:2]
 
         movers = self.scheme._select_movers('shooting')
-        assert_equal(movers, self.scheme.movers['shooting'])
+        assert movers == self.scheme.movers['shooting']
 
         movers = self.scheme._select_movers(some_shooters)
-        assert_equal(movers, some_shooters)
+        assert movers == some_shooters
 
         movers = self.scheme._select_movers(some_shooters[0])
-        assert_equal(movers, [some_shooters[0]])
+        assert movers == [some_shooters[0]]
 
     def test_n_trials_for_steps(self):
         self.scheme.append([
@@ -760,35 +757,28 @@ def test_default_scheme(self):
             'Ms_outer_shootingChooser' : paths.OneWayShootingMover
         }
         names = list(chooser_type_dict.keys())
-        assert_equal(len(root.movers), len(names))
+        assert len(root.movers) == len(names)
 
         name_dict = {root.movers[i].name : i for i in range(len(root.movers))}
         for name in names:
-            assert_in(name, list(name_dict.keys()))
+            assert name in list(name_dict.keys())
 
         n_normal_repex = 4
         n_msouter_repex = 2
         n_repex = n_normal_repex + n_msouter_repex
 
-        assert_equal(
-            len(root.movers[name_dict['ShootingChooser']].movers), 6
-        )
-        assert_equal(
-            len(root.movers[name_dict['PathreversalChooser']].movers), 7
-        )
-        assert_equal(
-            len(root.movers[name_dict['RepexChooser']].movers), n_repex
-        )
-        assert_equal(
-            len(root.movers[name_dict['MinusChooser']].movers), 2
-        )
-        assert_equal(
-            len(root.movers[name_dict['Ms_outer_shootingChooser']].movers), 1
+        assert len(root.movers[name_dict['ShootingChooser']].movers) == 6
+        assert len(root.movers[name_dict['PathreversalChooser']].movers) == 7
+        assert len(root.movers[name_dict['RepexChooser']].movers) == n_repex
+        assert len(root.movers[name_dict['MinusChooser']].movers) == 2
+        assert (
+            len(root.movers[name_dict['Ms_outer_shootingChooser']].movers)
+            == 1
         )
 
         for choosername in names:
             for mover in root.movers[name_dict[choosername]].movers:
-                assert_equal(type(mover), chooser_type_dict[choosername])
+                assert type(mover) == chooser_type_dict[choosername]
 
     def test_default_scheme_no_ms_outer(self):
         scheme = DefaultScheme(self.no_ms_outer)
@@ -800,28 +790,20 @@ def test_default_scheme_no_ms_outer(self):
             'MinusChooser' : paths.MinusMover
         }
         names = list(chooser_type_dict.keys())
-        assert_equal(len(root.movers), len(names))
+        assert len(root.movers) == len(names)
 
         name_dict = {root.movers[i].name : i for i in range(len(root.movers))}
         for name in names:
-            assert_in(name, list(name_dict.keys()))
+            assert name in list(name_dict.keys())
 
         n_normal_repex = 4
         n_msouter_repex = 0
         n_repex = n_normal_repex + n_msouter_repex
 
-        assert_equal(
-            len(root.movers[name_dict['ShootingChooser']].movers), 6
-        )
-        assert_equal(
-            len(root.movers[name_dict['PathreversalChooser']].movers), 6
-        )
-        assert_equal(
-            len(root.movers[name_dict['RepexChooser']].movers), n_repex
-        )
-        assert_equal(
-            len(root.movers[name_dict['MinusChooser']].movers), 2
-        )
+        assert len(root.movers[name_dict['ShootingChooser']].movers) == 6
+        assert len(root.movers[name_dict['PathreversalChooser']].movers) == 6
+        assert len(root.movers[name_dict['RepexChooser']].movers) == n_repex
+        assert len(root.movers[name_dict['MinusChooser']].movers) == 2
 
     def test_default_sanity(self):
         scheme = DefaultScheme(self.network)
@@ -832,13 +814,13 @@ def test_default_hidden_ensembles(self):
         scheme = DefaultScheme(self.network)
         root = scheme.move_decision_tree()
         hidden = scheme.find_hidden_ensembles()
-        assert_equal(len(hidden), 2)
+        assert len(hidden) == 2
 
     def test_default_unused_ensembles(self):
         scheme = DefaultScheme(self.network)
         root = scheme.move_decision_tree()
         unused = scheme.find_unused_ensembles()
-        assert_equal(len(unused), 0) # will change when minus/msouter
+        assert len(unused) == 0  # will change when minus/msouter
 
     def test_default_balance_partners(self):
         scheme = DefaultScheme(self.network)
@@ -847,7 +829,7 @@ def test_default_balance_partners(self):
         # by default, every mover is its own balance partner
         for group in list(scheme.movers.values()):
             for mover in group:
-                assert_equal(scheme.balance_partners[mover], [mover])
+                assert scheme.balance_partners[mover] == [mover]
 
     def test_default_choice_probability(self):
         scheme = DefaultScheme(self.network)
@@ -878,7 +860,7 @@ def test_default_choice_probability(self):
     def test_initial_conditions_from_trajectory(self):
         scheme = DefaultScheme(self.network)
         # root = scheme.move_decision_tree()
-        assert_equal(len(scheme.list_initial_ensembles()), 9)
+        assert len(scheme.list_initial_ensembles()) == 9
 
         traj1 = make_1d_traj([-0.6, -0.2, -0.6])
         traj2 = make_1d_traj([-0.6, -0.2, -0.05, -0.4, -0.6])
@@ -897,12 +879,12 @@ def assert_init_cond(sample_set, ensembles, expected):
 
             sample_set.sanity_check()
 
-            assert_equal(len(sample_set), len(expected))
+            assert len(sample_set) == len(expected)
 
             for ensemble, traj in zip(ensembles, expected):
                 # print ensemble.name, sample_set[ensemble].trajectory.xyz[:,0,0], traj.xyz[:, 0,0],
                 # print hex(id(traj)), hex(id(sample_set[ensemble].trajectory.xyz[:,0,0]))
-                assert_equal(sample_set[ensemble].trajectory, traj)
+                assert sample_set[ensemble].trajectory == traj
 
         transAB = transBA = None
         for trans in self.network.sampling_transitions:
@@ -974,21 +956,21 @@ def assert_init_cond(sample_set, ensembles, expected):
         )
 
         init_cond.sanity_check()
-        assert_equal(len(init_cond), 7)
+        assert len(init_cond) == 7
 
         for ensemble, traj in zip(ensembles[:3], [traj1, traj2, traj3]):
-            assert_equal(init_cond[ensemble].trajectory, traj)
+            assert init_cond[ensemble].trajectory == traj
         for ensemble, traj in zip(ensembles[4:], [traj3r] * 3):
-            assert_equal(init_cond[ensemble].trajectory, traj)
+            assert init_cond[ensemble].trajectory == traj
 
         # because of the way the scheme ensembles are creating involving a
         # set, the order in which the ensemble are created changes.
         # in some cases traj3 is used and hence avoided in the outer
         # in some cases traj3r, but both are fine.
         try:
-            assert_equal(init_cond[ensembles[3]].trajectory, traj3)
+            assert init_cond[ensembles[3]].trajectory == traj3
         except AssertionError:
-            assert_equal(init_cond[ensembles[3]].trajectory, traj3r)
+            assert init_cond[ensembles[3]].trajectory == traj3r
 
         init_cond = scheme.initial_conditions_from_trajectories(
             trajectories=all_trajs,
@@ -997,17 +979,17 @@ def assert_init_cond(sample_set, ensembles, expected):
             strategies=['get']
         )
         init_cond.sanity_check()
-        assert_equal(len(init_cond), 7)
+        assert len(init_cond) == 7
 
         for ensemble, traj in zip(ensembles[:3], [traj1, traj1r, traj3]):
-            assert_equal(init_cond[ensemble].trajectory, traj)
+            assert init_cond[ensemble].trajectory == traj
         for ensemble, traj in zip(ensembles[4:], [traj3r] * 3):
-            assert_equal(init_cond[ensemble].trajectory, traj)
+            assert init_cond[ensemble].trajectory == traj
 
         try:
-            assert_equal(init_cond[ensembles[3]].trajectory, traj3)
+            assert init_cond[ensembles[3]].trajectory == traj3
         except AssertionError:
-            assert_equal(init_cond[ensembles[3]].trajectory, traj3r)
+            assert init_cond[ensembles[3]].trajectory == traj3r
 
         # this one avoids reversed copies
         init_cond = scheme.initial_conditions_from_trajectories(
@@ -1061,23 +1043,22 @@ def test_check_initial_conditions(self):
         traj3 = make_1d_traj([-0.6, -0.2, 0.2, 0.6])
         # cheating a bit, since we know what this gives
         init_cond = scheme.initial_conditions_from_trajectories(traj3)
-        assert_equal(len(init_cond), 7)
-        assert_equal(len(scheme.list_initial_ensembles()), 9)
+        assert len(init_cond) == 7
+        assert len(scheme.list_initial_ensembles()) == 9
         (missing, extra) = scheme.check_initial_conditions(init_cond)
-        assert_equal(len(missing), 2)
-        assert_equal(len(extra), 0)
+        assert len(missing) == 2
+        assert len(extra) == 0
         for ens in list(self.network.special_ensembles['minus'].keys()):
-            assert_in([ens], missing)
+            assert [ens] in missing
         init_cond.append_as_new_replica(
             paths.Sample(trajectory=traj3,
                          ensemble=paths.LengthEnsemble(4),
                          replica=None)
         )
         (missing, extra) = scheme.check_initial_conditions(init_cond)
-        assert_equal(len(missing), 2)
-        assert_equal(len(extra), 1)
+        assert len(missing) == 2
+        assert len(extra) == 1
 
-    @raises(AssertionError)
     def test_assert_initial_conditions(self):
         scheme = DefaultScheme(self.network)
         traj3 = make_1d_traj([-0.6, -0.2, 0.2, 0.6])
@@ -1087,7 +1068,8 @@ def test_assert_initial_conditions(self):
                          ensemble=paths.LengthEnsemble(4),
                          replica=None)
         )
-        scheme.assert_initial_conditions(init_cond)
+        with pytest.raises(AssertionError):
+            scheme.assert_initial_conditions(init_cond)
 
     def test_initial_conditions_report(self):
         scheme = DefaultScheme(self.network)
@@ -1106,9 +1088,9 @@ def test_initial_conditions_report(self):
         expected_BA = start + missing_B + missing_A + finish
         result = scheme.initial_conditions_report(init_cond)
         try:
-            assert_equal(result, expected_AB)
+            assert result == expected_AB
         except AssertionError:
-            assert_equal(result, expected_BA)
+            assert result == expected_BA
 
 
 class TestLockedMoveScheme(object):
@@ -1134,39 +1116,39 @@ def setup_method(self):
 
     def test_initialization(self):
         scheme = LockedMoveScheme(self.root_mover, self.network)
-        assert_equal(scheme.network, self.network)
-        assert_equal(scheme.move_decision_tree(), self.root_mover)
+        assert scheme.network == self.network
+        assert scheme.move_decision_tree() == self.root_mover
 
     def test_build_move_decision_tree(self):
         scheme = LockedMoveScheme(self.root_mover, self.network)
         scheme.move_decision_tree(rebuild=True)
-        assert_equal(scheme.move_decision_tree(), self.root_mover)
+        assert scheme.move_decision_tree() == self.root_mover
 
-    @raises(TypeError)
     def test_append(self):
         scheme = LockedMoveScheme(self.root_mover, self.network)
-        scheme.append(AllSetRepExStrategy())
+        with pytest.raises(TypeError):
+            scheme.append(AllSetRepExStrategy())
 
-    @raises(TypeError)
     def test_apply_strategy(self):
         scheme = LockedMoveScheme(self.root_mover, self.network)
         strategy = AllSetRepExStrategy()
-        scheme.apply_strategy(strategy)
+        with pytest.raises(TypeError):
+            scheme.apply_strategy(strategy)
 
-    @raises(AttributeError)
     def test_choice_probability_fail(self):
         scheme = LockedMoveScheme(self.root_mover, self.network)
-        vals = scheme.choice_probability
+        with pytest.raises(AttributeError):
+            vals = scheme.choice_probability
 
     def test_choice_probability_works(self):
         scheme = LockedMoveScheme(self.root_mover, self.network)
         scheme.choice_probability = self.basic_scheme.choice_probability
         vals = scheme.choice_probability
 
-    @raises(AttributeError)
     def test_movers_fail(self):
         scheme = LockedMoveScheme(self.root_mover, self.network)
-        vals = scheme.movers
+        with pytest.raises(AttributeError):
+            vals = scheme.movers
 
     def test_movers_works(self):
         scheme = LockedMoveScheme(self.root_mover, self.network)
@@ -1196,8 +1178,8 @@ def setup_method(self):
     def test_scheme(self):
         scheme = OneWayShootingMoveScheme(self.network)
         root = scheme.move_decision_tree()
-        assert_equal(len(scheme.movers), 1)
-        assert_equal(len(root.movers), 1)
+        assert len(scheme.movers) == 1
+        assert len(root.movers) == 1
 
     def test_sanity(self):
         scheme = OneWayShootingMoveScheme(self.network)
@@ -1211,14 +1193,14 @@ def test_unused_ensembles(self):
         specials = self.network.special_ensembles
         expected_unused = sum([list(specials[special_type].keys())
                                for special_type in specials], [])
-        assert_equal(set(expected_unused), set(unused))
+        assert set(expected_unused) == set(unused)
 
     def test_check_initial_conditions(self):
         scheme = OneWayShootingMoveScheme(self.network)
         traj3 = make_1d_traj([-0.6, -0.2, 0.2, 0.6])
         init_cond = scheme.initial_conditions_from_trajectories(traj3)
-        assert_equal(len(scheme.list_initial_ensembles()), 6)
-        assert_equal(len(init_cond), 6)
+        assert len(scheme.list_initial_ensembles()) == 6
+        assert len(init_cond) == 6
         scheme.assert_initial_conditions(init_cond)
-        assert_equal(scheme.initial_conditions_report(init_cond),
-                     "No missing ensembles.\nNo extra ensembles.\n")
+        assert (scheme.initial_conditions_report(init_cond)
+                == "No missing ensembles.\nNo extra ensembles.\n")
diff --git a/openpathsampling/tests/test_movestrategy.py b/openpathsampling/tests/test_movestrategy.py
index 8b6985522..2118b8e62 100644
--- a/openpathsampling/tests/test_movestrategy.py
+++ b/openpathsampling/tests/test_movestrategy.py
@@ -5,9 +5,7 @@
 from builtins import range
 from past.utils import old_div
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises, assert_in, assert_not_in)
-from nose.plugins.skip import Skip, SkipTest
+from numpy.testing import assert_almost_equal
 from .test_helpers import (
     true_func, assert_equal_array_array, make_1d_traj, MoverWithSignature,
     setify_ensemble_signature, reorder_ensemble_signature
@@ -46,13 +44,13 @@ def find_mover(scheme, group, sig):
 
 class TestStrategyLevels(object):
     def test_level_type(self):
-        assert_equal(levels.level_type(10), levels.SIGNATURE)
-        assert_equal(levels.level_type(1), levels.SIGNATURE)
-        assert_equal(levels.level_type(19), levels.SIGNATURE)
-        assert_equal(levels.level_type(20), None)
-        assert_equal(levels.level_type(21), levels.MOVER)
-        assert_equal(levels.level_type(35), levels.MOVER)
-        assert_equal(levels.level_type(100), levels.GLOBAL)
+        assert levels.level_type(10) == levels.SIGNATURE
+        assert levels.level_type(1) == levels.SIGNATURE
+        assert levels.level_type(19) == levels.SIGNATURE
+        assert levels.level_type(20) is None
+        assert levels.level_type(21) == levels.MOVER
+        assert levels.level_type(35) == levels.MOVER
+        assert levels.level_type(100) == levels.GLOBAL
 
 
 class MoveStrategyTestSetup(object):
@@ -78,21 +76,21 @@ def setup_method(self):
 class TestMoveStrategy(MoveStrategyTestSetup):
     def test_levels(self):
         strategy = MockMoveStrategy(ensembles=None, group="test", replace=True)
-        assert_equal(strategy.level, -1)
-        assert_equal(strategy.replace_signatures, False)
-        assert_equal(strategy.replace_movers, False)
+        assert strategy.level == -1
+        assert strategy.replace_signatures is False
+        assert strategy.replace_movers is False
         strategy.level = 10
-        assert_equal(strategy.level, levels.SIGNATURE)
-        assert_equal(strategy.replace_signatures, True)
-        assert_equal(strategy.replace_movers, False)
+        assert strategy.level == levels.SIGNATURE
+        assert strategy.replace_signatures
+        assert not strategy.replace_movers
         strategy.level = 25
-        assert_not_equal(strategy.level, levels.MOVER)
-        assert_equal(levels.level_type(strategy.level), levels.MOVER)
-        assert_equal(strategy.replace_signatures, False)
-        assert_equal(strategy.replace_movers, True)
+        assert strategy.level != levels.MOVER
+        assert levels.level_type(strategy.level) == levels.MOVER
+        assert not strategy.replace_signatures
+        assert strategy.replace_movers
         strategy.level = 99
-        assert_equal(strategy.replace_signatures, False)
-        assert_equal(strategy.replace_movers, False)
+        assert not strategy.replace_signatures
+        assert not strategy.replace_movers
 
     def test_get_ensembles(self):
         self.strategy = MockMoveStrategy(ensembles=None, group="test",
@@ -102,27 +100,27 @@ def test_get_ensembles(self):
         transition_ensembles = []
         for transition in self.network.sampling_transitions:
             transition_ensembles.append(transition.ensembles)
-        assert_equal(len(transition_ensembles), 2)
+        assert len(transition_ensembles) == 2
         for ens_set in transition_ensembles:
-            assert_equal(len(ens_set), 3)
+            assert len(ens_set) == 3
         ensA = self.network.from_state[self.stateA].ensembles
-        assert_equal(len(ensA), 3)
+        assert len(ensA) == 3
         # if you error before this, something is wrong in setup
         ensembles = self.strategy.get_ensembles(scheme, None)
-        assert_equal(ensembles, transition_ensembles)
+        assert ensembles == transition_ensembles
 
         ensembles = self.strategy.get_ensembles(scheme, ensA)
-        assert_equal(ensembles, [ensA])
+        assert ensembles == [ensA]
 
         extra_ens = transition_ensembles[1][0]
         weird_ens_list = [[ensA[0]], ensA[1], [extra_ens]]
         ensembles = self.strategy.get_ensembles(scheme, weird_ens_list)
-        assert_equal(ensembles, [[ensA[0]], [ensA[1]], [extra_ens]])
+        assert ensembles == [[ensA[0]], [ensA[1]], [extra_ens]]
 
         ensembles = self.strategy.get_ensembles(scheme, extra_ens)
-        assert_equal(len(ensembles), 1)
-        assert_equal(len(ensembles[0]), 1)
-        assert_equal(ensembles[0][0], extra_ens)
+        assert len(ensembles) == 1
+        assert len(ensembles[0]) == 1
+        assert ensembles[0][0] == extra_ens
 
 
 class TestSingleEnsembleMoveStrategy(MoveStrategyTestSetup):
@@ -171,10 +169,10 @@ def test_make_movers(self):
         strategy = ForwardShootingStrategy()
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 6)
+        assert len(movers) == 6
         for mover in movers:
-            assert_equal(type(mover), paths.ForwardShootMover)
-            assert_equal(type(mover.selector), paths.UniformSelector)
+            assert type(mover) == paths.ForwardShootMover
+            assert type(mover.selector) == paths.UniformSelector
 
     def test_make_movers_with_list(self):
         list_of_selectors = [
@@ -187,13 +185,13 @@ def test_make_movers_with_list(self):
         )
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 6)
-        assert_equal(len(list_of_selectors), 6)
+        assert len(movers) == 6
+        assert len(list_of_selectors) == 6
         for mover, sel in zip(movers, list_of_selectors):
-            assert_equal(type(mover), paths.ForwardShootMover)
-            assert_equal(type(mover.selector),
-                         paths.shooting.InterfaceConstrainedSelector)
-            assert_equal(mover.selector, sel)
+            assert type(mover) == paths.ForwardShootMover
+            assert (type(mover.selector)
+                    == paths.shooting.InterfaceConstrainedSelector)
+            assert mover.selector == sel
 
 
 class TestOneWayShootingStrategy(MoveStrategyTestSetup):
@@ -201,32 +199,32 @@ def test_make_movers(self):
         strategy = OneWayShootingStrategy()
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 6)
+        assert len(movers) == 6
         for mover in movers:
-            assert_equal(type(mover), paths.OneWayShootingMover)
-            assert_equal(type(mover.selector), paths.UniformSelector)
+            assert type(mover) == paths.OneWayShootingMover
+            assert type(mover.selector) == paths.UniformSelector
 
 class TestTwoWayShootingStrategy(MoveStrategyTestSetup):
     def test_make_movers(self):
         strategy = TwoWayShootingStrategy(modifier=paths.NoModification())
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 6)
+        assert len(movers) == 6
         for mover in movers:
-            assert_equal(type(mover), paths.TwoWayShootingMover)
-            assert_equal(type(mover.selector), paths.UniformSelector)
-            assert_equal(type(mover.modifier), paths.NoModification)
+            assert type(mover) == paths.TwoWayShootingMover
+            assert type(mover.selector) == paths.UniformSelector
+            assert type(mover.modifier) == paths.NoModification
 
     def test_composition_with_default_scheme(self):
         strategy = TwoWayShootingStrategy(modifier=paths.NoModification())
         scheme = DefaultScheme(self.network, engine=None)
         scheme.append(strategy)
         scheme.build_move_decision_tree()
-        assert_equal(len(scheme.movers['shooting']), 6)
+        assert len(scheme.movers['shooting']) == 6
         for mover in scheme.movers['shooting']:
-            assert_equal(type(mover), paths.TwoWayShootingMover)
-            assert_equal(type(mover.selector), paths.UniformSelector)
-            assert_equal(type(mover.modifier), paths.NoModification)
+            assert type(mover) == paths.TwoWayShootingMover
+            assert type(mover.selector) == paths.UniformSelector
+            assert type(mover.modifier) == paths.NoModification
 
 
 class TestNearestNeighborRepExStrategy(MoveStrategyTestSetup):
@@ -234,24 +232,24 @@ def test_make_movers(self):
         strategy = NearestNeighborRepExStrategy()
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 4)
+        assert len(movers) == 4
         ens0 = self.network.sampling_transitions[0].ensembles
         ens1 = self.network.sampling_transitions[1].ensembles
-        assert_equal(movers[0].ensemble_signature_set,
-                     (set([ens0[0], ens0[1]]), set([ens0[0], ens0[1]])))
-        assert_equal(movers[1].ensemble_signature_set,
-                     (set([ens0[1], ens0[2]]), set([ens0[1], ens0[2]])))
-        assert_equal(movers[2].ensemble_signature_set,
-                     (set([ens1[0], ens1[1]]), set([ens1[0], ens1[1]])))
-        assert_equal(movers[3].ensemble_signature_set,
-                     (set([ens1[1], ens1[2]]), set([ens1[1], ens1[2]])))
+        assert (movers[0].ensemble_signature_set
+                == (set([ens0[0], ens0[1]]), set([ens0[0], ens0[1]])))
+        assert (movers[1].ensemble_signature_set
+                == (set([ens0[1], ens0[2]]), set([ens0[1], ens0[2]])))
+        assert (movers[2].ensemble_signature_set
+                == (set([ens1[0], ens1[1]]), set([ens1[0], ens1[1]])))
+        assert (movers[3].ensemble_signature_set
+                == (set([ens1[1], ens1[2]]), set([ens1[1], ens1[2]])))
 
 class TestAllSetRepExStrategy(MoveStrategyTestSetup):
     def test_make_movers(self):
         strategy = AllSetRepExStrategy()
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 6)
+        assert len(movers) == 6
         ens0 = self.network.sampling_transitions[0].ensembles
         ens1 = self.network.sampling_transitions[1].ensembles
 
@@ -267,7 +265,7 @@ def test_make_movers(self):
         ]
         for sig in expected_signatures:
             set_sig = (set(sig[0]), set(sig[1]))
-            assert_in(set_sig, signatures)
+            assert set_sig in signatures
 
 class TestSelectedPairsRepExStrategy(MoveStrategyTestSetup):
     def test_make_movers(self):
@@ -276,18 +274,18 @@ def test_make_movers(self):
         strategy = SelectedPairsRepExStrategy(ensembles=[ens00, ens02])
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 1)
-        assert_equal(movers[0].ensemble_signature_set,
-                     ({ ens00, ens02 }, ({ ens00, ens02 })))
+        assert len(movers) == 1
+        assert (movers[0].ensemble_signature_set
+                == ({ ens00, ens02 }, ({ ens00, ens02 })))
 
-    @raises(RuntimeError)
     def test_init_ensembles_none(self):
-        strategy = SelectedPairsRepExStrategy()
+        with pytest.raises(RuntimeError):
+            strategy = SelectedPairsRepExStrategy()
 
-    @raises(RuntimeError)
     def test_init_ensembles_triplet(self):
         ensembles = self.network.sampling_transitions[0].ensembles
-        strategy = SelectedPairsRepExStrategy(ensembles=ensembles)
+        with pytest.raises(RuntimeError):
+            strategy = SelectedPairsRepExStrategy(ensembles=ensembles)
 
     def test_make_movers_multiple_pairs(self):
         ens00 = self.network.sampling_transitions[0].ensembles[0]
@@ -298,13 +296,13 @@ def test_make_movers_multiple_pairs(self):
                                                          [ens01, ens02]])
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 3)
-        assert_equal(movers[0].ensemble_signature_set,
-                     ({ens00, ens01}, {ens00, ens01}))
-        assert_equal(movers[1].ensemble_signature_set,
-                     ({ens00, ens02}, {ens00, ens02}))
-        assert_equal(movers[2].ensemble_signature_set,
-                     ({ens01, ens02}, {ens01, ens02}))
+        assert len(movers) == 3
+        assert (movers[0].ensemble_signature_set
+                == ({ens00, ens01}, {ens00, ens01}))
+        assert (movers[1].ensemble_signature_set
+                == ({ens00, ens02}, {ens00, ens02}))
+        assert (movers[2].ensemble_signature_set
+                == ({ens01, ens02}, {ens01, ens02}))
 
 class TestReplicaExchangeStrategy(MoveStrategyTestSetup):
     def test_make_movers(self):
@@ -312,36 +310,36 @@ def test_make_movers(self):
         scheme = MoveScheme(self.network)
         scheme.apply_strategy(NearestNeighborRepExStrategy())
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 4)
+        assert len(movers) == 4
 
     def test_swap_to_hop_to_swap(self):
         scheme = DefaultScheme(self.network)
         root = scheme.move_decision_tree()
-        assert_equal(len(scheme.movers['repex']), 6)
+        assert len(scheme.movers['repex']) == 6
         old_movers = scheme.movers['repex']
         scheme.append(EnsembleHopStrategy(), force=True)
         root = scheme.move_decision_tree(rebuild=True)
-        assert_equal(len(scheme.movers['repex']), 12)
+        assert len(scheme.movers['repex']) == 12
         scheme.append(ReplicaExchangeStrategy(), force=True)
         root = scheme.move_decision_tree(rebuild=True)
-        assert_equal(len(scheme.movers['repex']), 6)
+        assert len(scheme.movers['repex']) == 6
         new_movers = scheme.movers['repex']
-        assert_not_equal(old_movers, new_movers)
+        assert old_movers != new_movers
         old_sigs = [m.ensemble_signature_set for m in old_movers]
         new_sigs = [m.ensemble_signature_set for m in new_movers]
         for old in old_sigs:
-            assert_in(old, new_sigs)
+            assert old in new_sigs
 
-    @raises(RuntimeError)
     def test_detailed_balance_partners(self):
         scheme = DefaultScheme(self.network)
         scheme.append(EnsembleHopStrategy(), force=True)
         root = scheme.move_decision_tree()
-        assert_equal(len(scheme.movers['repex']), 12)
+        assert len(scheme.movers['repex']) == 12
         scheme.movers['repex'].pop()
-        assert_equal(len(scheme.movers['repex']), 11)
+        assert len(scheme.movers['repex']) == 11
         strategy = ReplicaExchangeStrategy()
-        strategy.make_movers(scheme)
+        with pytest.raises(RuntimeError):
+            strategy.make_movers(scheme)
 
 
 class TestEnsembleHopStrategy(MoveStrategyTestSetup):
@@ -351,30 +349,29 @@ def test_make_movers(self):
         scheme.apply_strategy(NearestNeighborRepExStrategy())
         movers = strategy.make_movers(scheme)
         # defaults to 4 repex movers, so
-        assert_equal(len(movers), 8)
+        assert len(movers) == 8
 
         # set up the swap pairs
         swap_pairs = []
         for trans in self.network.sampling_transitions:
             swap_pairs.extend([[trans.ensembles[i], trans.ensembles[i+1]]
                                for i in range(len(trans.ensembles)-1)])
-        assert_equal(len(swap_pairs), 4)
+        assert len(swap_pairs) == 4
 
         # check that each swap pair has a hop
         mover_sigs = [m.ensemble_signature for m in movers]
         for pair in swap_pairs:
             sig1 = ((pair[0],),(pair[1],))
             sig2 = ((pair[1],),(pair[0],))
-            assert_in(sig1, mover_sigs)
-            assert_in(sig2, mover_sigs)
+            assert sig1 in mover_sigs
+            assert sig2 in mover_sigs
 
         scheme.movers['repex'] = movers
         newmovers = strategy.make_movers(scheme)
-        assert_equal(len(newmovers), 8)
+        assert len(newmovers) == 8
         for mover in newmovers:
-            assert_in(mover.ensemble_signature, mover_sigs)
+            assert mover.ensemble_signature in mover_sigs
 
-    @raises(RuntimeError)
     def test_different_number_input_output_ensembles(self):
         ens0 = self.network.sampling_ensembles[0]
         ens1 = self.network.sampling_ensembles[1]
@@ -383,14 +380,14 @@ def test_different_number_input_output_ensembles(self):
             input_ensembles=[ens0, ens1, ens2],
             output_ensembles=[ens0, ens1]
         )
-        assert_equal(weird_mover.ensemble_signature,
-                     ((ens0,ens1,ens2),(ens0,ens1)))
+        assert (weird_mover.ensemble_signature
+                == ((ens0,ens1,ens2),(ens0,ens1)))
         scheme = MoveScheme(self.network)
         scheme.movers['weird'] = [weird_mover]
         strategy = EnsembleHopStrategy(group='weird')
-        strategy.make_movers(scheme)
+        with pytest.raises(RuntimeError):
+            strategy.make_movers(scheme)
 
-    @raises(RuntimeError)
     def test_wrong_number_ensembles_in_signature(self):
         ens0 = self.network.sampling_ensembles[0]
         ens1 = self.network.sampling_ensembles[1]
@@ -399,14 +396,14 @@ def test_wrong_number_ensembles_in_signature(self):
             input_ensembles=[ens0, ens1, ens2],
             output_ensembles=[ens0, ens1, ens2]
         )
-        assert_equal(weird_mover.ensemble_signature,
-                     ((ens0,ens1,ens2),(ens0,ens1,ens2)))
+        assert (weird_mover.ensemble_signature
+                == ((ens0,ens1,ens2),(ens0,ens1,ens2)))
         scheme = MoveScheme(self.network)
         scheme.movers['weird'] = [weird_mover]
         strategy = EnsembleHopStrategy(group='weird')
-        strategy.make_movers(scheme)
+        with pytest.raises(RuntimeError):
+            strategy.make_movers(scheme)
 
-    @raises(RuntimeError)
     def test_not_replica_exchange_signature(self):
         ens0 = self.network.sampling_ensembles[0]
         ens1 = self.network.sampling_ensembles[1]
@@ -415,12 +412,12 @@ def test_not_replica_exchange_signature(self):
             input_ensembles=[ens0, ens1],
             output_ensembles=[ens1, ens2]
         )
-        assert_equal(weird_mover.ensemble_signature,
-                     ((ens0,ens1),(ens1,ens2)))
+        assert weird_mover.ensemble_signature == ((ens0,ens1),(ens1,ens2))
         scheme = MoveScheme(self.network)
         scheme.movers['weird'] = [weird_mover]
         strategy = EnsembleHopStrategy(group='weird')
-        strategy.make_movers(scheme)
+        with pytest.raises(RuntimeError):
+            strategy.make_movers(scheme)
 
     def test_replace_nofrom(self):
         # this is the default behavior
@@ -429,7 +426,7 @@ def test_replace_nofrom(self):
         scheme.append(EnsembleHopStrategy(replace=True, from_group=None))
         scheme.build_move_decision_tree()
         # 4 normal repex + 2 ms-outer repex = 6 repex * 2 hop/repex = 12
-        assert_equal(len(scheme.movers['repex']), 12)
+        assert len(scheme.movers['repex']) == 12
 
     def test_noreplace_from(self):
         # if replace is False and from_group is given, we end up with two
@@ -440,8 +437,8 @@ def test_noreplace_from(self):
                                           group='hop',
                                           from_group='repex'))
         scheme.build_move_decision_tree()
-        assert_equal(len(scheme.movers['repex']), 6)
-        assert_equal(len(scheme.movers['hop']), 12)
+        assert len(scheme.movers['repex']) == 6
+        assert len(scheme.movers['hop']) == 12
 
     def test_replace_from(self):
         # if replace is True and we have a different from_group, we should
@@ -452,8 +449,8 @@ def test_replace_from(self):
                                           group='hop',
                                           from_group='repex'))
         scheme.build_move_decision_tree()
-        assert_equal(len(scheme.movers['hop']), 12)
-        assert_not_in("repex", list(scheme.movers.keys()))
+        assert len(scheme.movers['hop']) == 12
+        assert "repex" not in list(scheme.movers.keys())
 
     def test_noreplace_nofrom(self):
         # if replace==False and the from_group is not given, we should
@@ -462,7 +459,7 @@ def test_noreplace_nofrom(self):
         scheme.movers ={}
         scheme.append(EnsembleHopStrategy(replace=False, from_group=None))
         scheme.build_move_decision_tree()
-        assert_equal(len(scheme.movers['repex']), 18)
+        assert len(scheme.movers['repex']) == 18
 
 
 class TestPathReversalStrategy(MoveStrategyTestSetup):
@@ -470,9 +467,9 @@ def test_make_movers(self):
         strategy = PathReversalStrategy()
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 6)
+        assert len(movers) == 6
         for m in movers:
-            assert_equal(type(m), paths.PathReversalMover)
+            assert type(m) == paths.PathReversalMover
 
 
 class TestMinusMoveStrategy(MoveStrategyTestSetup):
@@ -480,10 +477,10 @@ def test_get_ensembles(self):
         strategy = MinusMoveStrategy()
         scheme = MoveScheme(self.network)
         ensembles = strategy.get_ensembles(scheme, None)
-        assert_equal(len(ensembles), 2)
+        assert len(ensembles) == 2
         for ens_group in ensembles:
-            assert_equal(len(ens_group), 1)
-        assert_not_equal(ensembles[0][0].state_vol, ensembles[1][0].state_vol)
+            assert len(ens_group) == 1
+        assert ensembles[0][0].state_vol != ensembles[1][0].state_vol
 
     def test_get_ensembles_multiple_minus(self):
         strategy = MinusMoveStrategy()
@@ -498,23 +495,23 @@ def test_get_ensembles_multiple_minus(self):
         self.network.special_ensembles['minus'][extra_minus] = [innerA, innerB]
         scheme = MoveScheme(self.network)
         ensembles = strategy.get_ensembles(scheme, None)
-        assert_equal(len(ensembles), 2)
-        assert_equal({ len(ensembles[0]), len(ensembles[1]) }, { 1, 2 })
+        assert len(ensembles) == 2
+        assert { len(ensembles[0]), len(ensembles[1]) } == { 1, 2 }
 
     def test_get_ensembles_fixed_ensembles(self):
         strategy = MinusMoveStrategy()
         minusA = list(self.network.special_ensembles['minus'].keys())[0]
         scheme = MoveScheme(self.network)
         ensembles = strategy.get_ensembles(scheme, minusA)
-        assert_equal(len(ensembles), 1)
-        assert_equal(len(ensembles[0]), 1)
-        assert_equal(ensembles[0][0], minusA)
+        assert len(ensembles) == 1
+        assert len(ensembles[0]) == 1
+        assert ensembles[0][0] == minusA
 
     def test_make_movers(self):
         strategy = MinusMoveStrategy()
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 2)
+        assert len(movers) == 2
 
         minuses = self.network.special_ensembles['minus']
         ens_minusA = list(minuses.keys())[0]
@@ -526,28 +523,26 @@ def test_make_movers(self):
         all_ens_sigs = [m.ensemble_signature_set for m in movers]
 
         # check the signatures
-        assert_not_equal(sig_A, sig_B)
-        assert_in(tuple([sig_A, sig_A]), all_ens_sigs)
-        assert_in(tuple([sig_B, sig_B]), all_ens_sigs)
+        assert sig_A != sig_B
+        assert tuple([sig_A, sig_A]) in all_ens_sigs
+        assert tuple([sig_B, sig_B]) in all_ens_sigs
 
         # check that these are inner ensembles
         inners = [t.ensembles[0] for t in self.network.sampling_transitions]
         for inner in ens_innerA + ens_innerB:
-            assert_in(inner, inners)
+            assert inner in inners
 
         # check that we've got the right inner for the right state
         stateA_inner = self.network.from_state[ens_minusA.state_vol].ensembles[0]
-        assert_equal([stateA_inner], ens_innerA)
+        assert [stateA_inner] == ens_innerA
         stateB_inner = self.network.from_state[ens_minusB.state_vol].ensembles[0]
-        assert_equal([stateB_inner], ens_innerB)
+        assert [stateB_inner] == ens_innerB
 
         # check that we've got minus ensembles
         for mover in movers:
-            assert_in(mover.minus_ensemble, self.network.minus_ensembles)
-            assert_equal(
-                isinstance(mover.minus_ensemble, paths.MinusInterfaceEnsemble),
-                True
-            )
+            assert mover.minus_ensemble in self.network.minus_ensembles
+            assert isinstance(mover.minus_ensemble,
+                              paths.MinusInterfaceEnsemble)
 
 
 class TestSingleReplicaMinusMoveStrategy(MoveStrategyTestSetup):
@@ -555,7 +550,7 @@ def test_make_movers(self):
         strategy = SingleReplicaMinusMoveStrategy()
         scheme = MoveScheme(self.network)
         movers = strategy.make_movers(scheme)
-        assert_equal(len(movers), 2)
+        assert len(movers) == 2
 
         minuses = self.network.special_ensembles['minus']
         ens_minusA = list(minuses.keys())[0]
@@ -603,12 +598,12 @@ def test_choice_probability(self):
         # norm = 3*1.0 + 2*0.5 = 4.0
         # each shooting prob: 0.25
         # each repex prob: 0.125
-        assert_equal(len(choice_prob), len(sum(list(scheme.movers.values()), [])))
+        assert len(choice_prob) == len(sum(list(scheme.movers.values()), []))
         for m in list(choice_prob.keys()):
             if m in scheme.movers['shooting']:
-                assert_equal(choice_prob[m], 0.25)
+                assert choice_prob[m] == 0.25
             elif m in scheme.movers['repex']:
-                assert_equal(choice_prob[m], 0.125)
+                assert choice_prob[m] == 0.125
             else:
                 raise RuntimeError("Unknown mover "+repr(m))
 
@@ -625,15 +620,14 @@ def test_choice_probability(self):
         for m in list(choice_prob.keys()):
             if m in scheme.movers['shooting']:
                    if m.ensemble_signature == ens0_sig:
-                       assert_equal(choice_prob[m], 0.4)
+                       assert choice_prob[m] == 0.4
                    else:
-                       assert_equal(choice_prob[m], 0.2)
+                       assert choice_prob[m] == 0.2
             elif m in scheme.movers['repex']:
-                assert_equal(choice_prob[m], 0.1)
+                assert choice_prob[m] == 0.1
             else:
                 raise RuntimeError("Unknown mover "+repr(m))
 
-    @raises(KeyError)
     def test_choice_probability_bad_group_weights(self):
         scheme = MoveScheme(self.network)
         ens0 = self.network.sampling_transitions[0].ensembles[0]
@@ -656,9 +650,10 @@ def test_choice_probability_bad_group_weights(self):
         for groupname in list(scheme.movers.keys()):
             for mover in scheme.movers[groupname]:
                 mover_weights[(groupname, mover.ensemble_signature)] = 1.0
-        assert_equal(len(mover_weights), 5)
-        choice_prob = strategy.choice_probability(scheme, group_weights,
-                                                  mover_weights)
+        assert len(mover_weights) == 5
+        with pytest.raises(KeyError):
+            choice_prob = strategy.choice_probability(scheme, group_weights,
+                                                      mover_weights)
 
     def test_weights_from_choice_probability(self):
         scheme = self.scheme_setup_shooting_repex()
@@ -679,8 +674,8 @@ def test_weights_from_choice_probability(self):
             scheme, choice_prob
         )
 
-        assert_equal(group_weights, group_w)
-        assert_equal(mover_weights, mover_w)
+        assert group_weights == group_w
+        assert mover_weights == mover_w
         #TODO: run more thorough tests of this
 
     def test_chooser_root_weights(self):
@@ -707,7 +702,7 @@ def test_chooser_root_weights(self):
                 mover_weights[(groupname, mover.ensemble_signature)] = 1.0
 
         w = strategy.chooser_root_weights(scheme, group_weights, mover_weights)
-        assert_equal(w, {'shooting' : 3.0, 'repex' : 1.0})
+        assert w == {'shooting' : 3.0, 'repex' : 1.0}
 
     def test_chooser_mover_weights(self):
         scheme = self.scheme_setup_shooting_repex()
@@ -726,7 +721,7 @@ def test_chooser_mover_weights(self):
         for g in scheme.movers:
             expected_w = {m : mover_weights[m_sig[m]] for m in scheme.movers[g]}
             w = strategy.chooser_mover_weights(scheme, g, mover_weights)
-            assert_equal(w, expected_w)
+            assert w == expected_w
 
 
     def test_make_movers(self):
@@ -757,39 +752,39 @@ def test_make_movers(self):
         strategy = OrganizeByMoveGroupStrategy()
         root = strategy.make_movers(scheme)
 
-        assert_equal(len(root.movers), 4)
+        assert len(root.movers) == 4
         names = ['ShootingChooser', 'RepexChooser', 'PathreversalChooser',
                  'MinusChooser']
         name_dict = {root.movers[i].name : i for i in range(len(root.movers))}
         for name in names:
-            assert_in(name, list(name_dict.keys()))
+            assert name in list(name_dict.keys())
 
         name = 'ShootingChooser'
         weight = root.weights[name_dict[name]]
         chooser = root.movers[name_dict[name]]
-        assert_equal(type(chooser), paths.RandomChoiceMover)
-        assert_equal(weight, 3.0)
-        assert_equal(len(chooser.movers), 3)
+        assert type(chooser) == paths.RandomChoiceMover
+        assert weight == 3.0
+        assert len(chooser.movers) == 3
         for w in chooser.weights:
-            assert_equal(w, 1.0)
+            assert w == 1.0
 
         name = 'RepexChooser'
         weight = root.weights[name_dict[name]]
         chooser = root.movers[name_dict[name]]
-        assert_equal(type(chooser), paths.RandomChoiceMover)
-        assert_equal(weight, 1.0)
-        assert_equal(len(chooser.movers), 2)
+        assert type(chooser) == paths.RandomChoiceMover
+        assert weight == 1.0
+        assert len(chooser.movers) == 2
         for w in chooser.weights:
-            assert_equal(w, 1.0)
+            assert w == 1.0
 
         name = 'MinusChooser'
         weight = root.weights[name_dict[name]]
         chooser = root.movers[name_dict[name]]
-        assert_equal(type(chooser), paths.RandomChoiceMover)
-        assert_equal(len(chooser.movers), 1)
-        assert_equal(weight, 0.2)
+        assert type(chooser) == paths.RandomChoiceMover
+        assert len(chooser.movers) == 1
+        assert weight == 0.2
         for w in chooser.weights:
-            assert_equal(w, 1.0)
+            assert w == 1.0
 
     def test_make_movers_unknown_group(self):
         scheme = MoveScheme(self.network)
@@ -809,11 +804,11 @@ def test_make_movers_unknown_group(self):
         name = 'BlahblahChooser'
         weight = root.weights[name_dict[name]]
         chooser = root.movers[name_dict[name]]
-        assert_equal(type(chooser), paths.RandomChoiceMover)
-        assert_equal(weight, 2.0)
-        assert_equal(len(chooser.movers), 2)
+        assert type(chooser) == paths.RandomChoiceMover
+        assert weight == 2.0
+        assert len(chooser.movers) == 2
         for w in chooser.weights:
-            assert_equal(w, 1.0)
+            assert w == 1.0
 
     def test_make_movers_custom_group(self):
         scheme = MoveScheme(self.network)
@@ -834,11 +829,11 @@ def test_make_movers_custom_group(self):
         name = 'BlahblahblahChooser'
         weight = root.weights[name_dict[name]]
         chooser = root.movers[name_dict[name]]
-        assert_equal(type(chooser), paths.RandomChoiceMover)
-        assert_equal(weight, 4.0)
-        assert_equal(len(chooser.movers), 2)
+        assert type(chooser) == paths.RandomChoiceMover
+        assert weight == 4.0
+        assert len(chooser.movers) == 2
         for w in chooser.weights:
-            assert_equal(w, 1.0)
+            assert w == 1.0
 
     def test_get_weights_scheme_all_unset(self):
         strategy = OrganizeByMoveGroupStrategy()
@@ -847,49 +842,49 @@ def test_get_weights_scheme_all_unset(self):
         scheme.append(NearestNeighborRepExStrategy())
         scheme.append(OneWayShootingStrategy())
         root = scheme.move_decision_tree()
-        assert_equal(len(scheme.movers), 2)
+        assert len(scheme.movers) == 2
         all_movers = scheme.movers['shooting'] + scheme.movers['repex']
         all_movers_sigs = [m.ensemble_signature for m in all_movers]
-        assert_equal(strategy.group_weights, {})
-        assert_equal(strategy.mover_weights, {})
+        assert strategy.group_weights == {}
+        assert strategy.mover_weights == {}
 
         (group_weights, mover_weights) = strategy.get_weights(
             scheme=scheme,
             sorted_movers=scheme.movers
         )
-        assert_equal(group_weights, {'shooting' : 1.0, 'repex' : 0.5})
+        assert group_weights == {'shooting' : 1.0, 'repex' : 0.5}
 
         # check that the number of sigs in a each group matches the number
         # of movers in that group
         for group in list(group_weights.keys()):
             mover_sigs = [sig for sig in list(mover_weights.keys())
                           if sig[0]==group]
-            assert_equal(len(mover_sigs), len(scheme.movers[group]))
+            assert len(mover_sigs) == len(scheme.movers[group])
 
         for sig in list(mover_weights.keys()):
-            assert_equal(mover_weights[sig], 1.0)
-            assert_in(sig[1], all_movers_sigs)
+            assert mover_weights[sig] == 1.0
+            assert sig[1] in all_movers_sigs
 
         # check that we can reuse these in a different scheme
         scheme2 = MoveScheme(self.network)
         scheme2.append(OneWayShootingStrategy())
         root = scheme2.move_decision_tree()
-        assert_equal(len(scheme2.movers), 1)
+        assert len(scheme2.movers) == 1
 
         (group_weights, mover_weights) = strategy.get_weights(
             scheme=scheme2,
             sorted_movers=scheme2.movers
         )
-        assert_equal(group_weights, {'shooting' : 1.0})
+        assert group_weights == {'shooting' : 1.0}
         for sig in mover_weights:
-            assert_equal(mover_weights[sig], 1.0)
-            assert_in(sig[1], [m.ensemble_signature
-                               for m in scheme2.movers[sig[0]]])
+            assert mover_weights[sig] == 1.0
+            assert sig[1] in [m.ensemble_signature
+                              for m in scheme2.movers[sig[0]]]
 
         for group in list(scheme2.movers.keys()):
             mover_sigs = [sig for sig in list(mover_weights.keys())
                           if sig[0]==group]
-            assert_equal(len(mover_sigs), len(scheme2.movers[group]))
+            assert len(mover_sigs) == len(scheme2.movers[group])
 
     def test_get_weights_both_internal_weights_set(self):
         strategy = OrganizeByMoveGroupStrategy()
@@ -917,7 +912,7 @@ def test_get_weights_both_internal_weights_set(self):
         )
         root = scheme.move_decision_tree(rebuild=True)
 
-        assert_equal(group_weights, {'shooting' : 1.0, 'repex' : 3.0})
+        assert group_weights == {'shooting' : 1.0, 'repex' : 3.0}
         expected_mover_weights = {}
         for group in scheme.movers:
             for mover in scheme.movers[group]:
@@ -929,21 +924,21 @@ def test_get_weights_both_internal_weights_set(self):
                 else:
                     expected_mover_weights[(group,sig)] = 1.0
 
-        assert_equal(mover_weights, expected_mover_weights)
+        assert mover_weights == expected_mover_weights
 
         new_choice_probability = scheme.choice_probability
         new_repex_chooser = [m for m in root if m.name=="RepexChooser"][0]
         repex_chooser_idx = root.movers.index(new_repex_chooser)
-        assert_equal(root.weights[repex_chooser_idx],
-                     3.0*len(new_repex_chooser.movers))
+        assert (root.weights[repex_chooser_idx]
+                == 3.0*len(new_repex_chooser.movers))
 
         new_shoot_chooser = [m for m in root if m.name=="ShootingChooser"][0]
         new_shooter_ensA = [m for m in scheme.movers['shooting']
                             if m.ensemble_signature == ensA_sig][0]
         shooter_ensA_idx = new_shoot_chooser.movers.index(new_shooter_ensA)
-        assert_equal(new_shoot_chooser.weights[shooter_ensA_idx], 2.0)
+        assert new_shoot_chooser.weights[shooter_ensA_idx] == 2.0
 
-        assert_not_equal(new_choice_probability, old_choice_probability)
+        assert new_choice_probability != old_choice_probability
 
     def test_get_weights_group_weights_set(self):
         strategy = OrganizeByMoveGroupStrategy()
@@ -965,19 +960,19 @@ def test_get_weights_group_weights_set(self):
         strategy.group_weights['shooting'] = 2.0
         root = scheme.move_decision_tree(rebuild=True)
 
-        assert_equal(strategy.group_weights, {'shooting' : 2.0, 'repex' : 0.5})
+        assert strategy.group_weights == {'shooting' : 2.0, 'repex' : 0.5}
 
         (group_weights, mover_weights) = strategy.get_weights(
             scheme=scheme,
             sorted_movers=scheme.movers,
             sort_weights_override=strategy.group_weights
         )
-        assert_equal(group_weights, {'shooting' : 2.0, 'repex' : 0.5})
+        assert group_weights == {'shooting' : 2.0, 'repex' : 0.5}
         # everything within the group should have the same mover_weight
         for group in scheme.movers:
             group_sigs = [s for s in mover_weights if s[0]==group]
             for sig in group_sigs:
-                assert_equal(mover_weights[sig], mover_weights[group_sigs[0]])
+                assert mover_weights[sig] == mover_weights[group_sigs[0]]
 
         choice_prob = strategy.choice_probability(
             scheme, group_weights, mover_weights
@@ -1002,7 +997,7 @@ def test_get_weights_mover_weights_set(self):
             sorted_movers=scheme.movers,
             sort_weights_override=strategy.group_weights
         )
-        assert_equal(group_weights, {'shooting' : 1.0, 'repex' : 3.0})
+        assert group_weights == {'shooting' : 1.0, 'repex' : 3.0}
 
         ensA = self.network.sampling_transitions[0].ensembles[0]
         ensA_sig = ((ensA,),(ensA,))
@@ -1018,9 +1013,9 @@ def test_get_weights_mover_weights_set(self):
 
         for sig in mover_weights:
             if sig == ('shooting',ensA_sig):
-                assert_equal(mover_weights[sig], 2.0)
+                assert mover_weights[sig] == 2.0
             elif sig[0] == 'shooting':
-                assert_equal(mover_weights[sig], 1.0)
+                assert mover_weights[sig] == 1.0
 
         assert_almost_equal(group_weights['shooting'], 1.0)
         assert_almost_equal(group_weights['repex'], 3.0)
@@ -1075,12 +1070,12 @@ def test_get_weights_internal_unset_choice_prob_set(self):
         #print new_choice_prob
         for (old, new) in zip(list(old_mover_weights.keys()), list(mover_weights.keys())):
             try:
-                assert_equal(old_mover_weights[old], mover_weights[new])
+                assert old_mover_weights[old] == mover_weights[new]
             except AssertionError:
                 print(old_mover_weights[old])
                 print(mover_weights[new])
                 raise
-        assert_equal(old_mover_weights, mover_weights)
+        assert old_mover_weights == mover_weights
 
     def test_get_weights_mover_weights_set_no_shooting(self):
         # follows test_get_weights_mover_weights_set, replacing shooting
@@ -1098,7 +1093,7 @@ def test_get_weights_mover_weights_set_no_shooting(self):
             sorted_movers=scheme.movers,
             sort_weights_override=strategy.group_weights
         )
-        assert_equal(group_weights, {'pathreversal' : 1.0, 'repex' : 3.0})
+        assert group_weights == {'pathreversal' : 1.0, 'repex' : 3.0}
         ensA = self.network.sampling_transitions[0].ensembles[0]
         ensA_sig = ((ensA,),(ensA,))
         strategy.group_weights = {}
@@ -1114,9 +1109,9 @@ def test_get_weights_mover_weights_set_no_shooting(self):
             weight_sigA = mover_weights[('pathreversal',ensA_sig)]
             ratio = old_div(mover_weights[sig], weight_sigA)
             if sig == ('pathreversal',ensA_sig):
-                assert_equal(ratio, 1.0)
+                assert ratio == 1.0
             else:
-                assert_equal(ratio, 0.5)
+                assert ratio == 0.5
 
         assert_almost_equal(group_weights['pathreversal'], 1.0)
         assert_almost_equal(group_weights['repex'], 3.0)
@@ -1226,7 +1221,7 @@ def test_choice_probability(self):
             ('pathreversal', sig1) : old_div(1.0,18.0),
             ('pathreversal', sig2) : old_div(2.0,27.0)
         }
-        assert_equal(set(expected.keys()), set(found.keys()))
+        assert set(expected.keys()) == set(found.keys())
         for k in list(expected.keys()):
             assert_almost_equal(expected[k], found[k])
 
@@ -1245,14 +1240,14 @@ def test_chooser_mover_weights(self):
             chooser_mweights = strategy.chooser_mover_weights(scheme, ens,
                                                               mover_weights)
             for mover in chooser_mweights:
-                assert_in(ens, mover.ensemble_signature[0])
+                assert ens in mover.ensemble_signature[0]
 
             if ens in [ens0, ens1]:
-                assert_equal(len(chooser_mweights), 4)
+                assert len(chooser_mweights) == 4
             elif ens is minus:
-                assert_equal(len(chooser_mweights), 1)
+                assert len(chooser_mweights) == 1
             elif ens is ens2:
-                assert_equal(len(chooser_mweights), 3)
+                assert len(chooser_mweights) == 3
         # that test feels a little minimal, but I guess it does the job
 
     def test_default_weights(self):
@@ -1265,8 +1260,8 @@ def test_default_weights(self):
 
         (ensemble_weights, mover_weights)= strategy.default_weights(scheme)
 
-        assert_equal(ensemble_weights,
-                     {e : 1.0 for e in [ens0, ens1, ens2, minus]})
+        assert ensemble_weights == {e : 1.0
+                                    for e in [ens0, ens1, ens2, minus]}
 
         # get the correct order on repex and minus signatures for testing
         double_sigs = [m.ensemble_signature
@@ -1295,11 +1290,11 @@ def test_default_weights(self):
             ('minus', minus_sig, ens0),
         ]
 
-        assert_equal(len(mover_ens_sigs), len(list(mover_weights.keys())))
-        assert_equal(set(mover_weights.keys()), set(mover_ens_sigs))
+        assert len(mover_ens_sigs) == len(list(mover_weights.keys()))
+        assert set(mover_weights.keys()) == set(mover_ens_sigs)
 
         expected = {s : 1.0 for s in mover_ens_sigs}
-        assert_equal(expected, mover_weights)
+        assert expected == mover_weights
 
     def test_weights_from_choice_probability(self):
         scheme = self.scheme
@@ -1343,10 +1338,10 @@ def test_make_movers(self):
 
         choosers = root.movers
         chooser_weights = root.weights
-        assert_equal(list(chooser_weights), [1.0]*4)
+        assert list(chooser_weights) == [1.0]*4
         for (mover, w) in zip(choosers, chooser_weights):
             n_moves = len(mover.movers)
-            assert_equal(mover.weights, [1.0]*n_moves)
+            assert mover.weights == [1.0]*n_moves
 
 
     def test_make_mover_rebuild_choice_probability(self):
@@ -1412,16 +1407,16 @@ def test_chooser_mover_weights(self):
             chooser_mweights = strategy.chooser_mover_weights(scheme, ens,
                                                               mover_weights)
             if ens in [ens0, ens1]:
-                assert_equal(len(chooser_mweights), 5)
+                assert len(chooser_mweights) == 5
             elif ens is minus:
-                assert_equal(len(chooser_mweights), 2)
+                assert len(chooser_mweights) == 2
             elif ens is ens2:
-                assert_equal(len(chooser_mweights), 4)
+                assert len(chooser_mweights) == 4
 
             real_movers = [m for m in list(chooser_mweights.keys())
                            if m != strategy.null_mover]
             for m in real_movers:
-                assert_equal(scheme.choice_probability[m], chooser_mweights[m])
+                assert scheme.choice_probability[m] == chooser_mweights[m]
             assert_almost_equal(sum(chooser_mweights.values()), 1.0)
 
     def test_make_movers(self):
@@ -1429,7 +1424,7 @@ def test_make_movers(self):
         strategy = self.StrategyClass()
         root = strategy.make_movers(scheme)
 
-        assert_equal(len(root.movers), 4)
+        assert len(root.movers) == 4
 
         for mover in list(scheme.choice_probability.keys()):
             assert_almost_equal(
diff --git a/openpathsampling/tests/test_ms_outer_interface.py b/openpathsampling/tests/test_ms_outer_interface.py
index 026a32120..7c9af2ed2 100644
--- a/openpathsampling/tests/test_ms_outer_interface.py
+++ b/openpathsampling/tests/test_ms_outer_interface.py
@@ -1,8 +1,5 @@
 from __future__ import absolute_import
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises)
-from nose.plugins.skip import Skip, SkipTest
 from .test_helpers import (
     true_func, assert_equal_array_array, make_1d_traj, data_filename,
     assert_items_equal
@@ -62,37 +59,38 @@ def test_initialization(self):
         by_lambda = self.ms_outer
         explicit = self.ms_outer_explicit
         for iface_set in explicit.interface_sets:
-            assert_equal(by_lambda.volume_for_interface_set(iface_set),
-                         explicit.volume_for_interface_set(iface_set))
-            assert_equal(by_lambda.lambda_for_interface_set(iface_set),
-                         explicit.lambda_for_interface_set(iface_set))
+            assert (by_lambda.volume_for_interface_set(iface_set)
+                    == explicit.volume_for_interface_set(iface_set))
+            assert (by_lambda.lambda_for_interface_set(iface_set)
+                    == explicit.lambda_for_interface_set(iface_set))
 
-        assert_equal(len(explicit.volumes), len(by_lambda.volumes))
-        assert_equal(len(explicit.lambdas), len(by_lambda.lambdas))
+        assert len(explicit.volumes) == len(by_lambda.volumes)
+        assert len(explicit.lambdas) == len(by_lambda.lambdas)
         assert_items_equal(set(explicit.interface_sets),
                            set(by_lambda.interface_sets))
 
 
     def test_volume_for_interface_set(self):
-        assert_equal(
-            self.ms_outer.volume_for_interface_set(self.interfaces_inc),
-            self.volumes[0]
+        assert (
+            self.ms_outer.volume_for_interface_set(self.interfaces_inc)
+            == self.volumes[0]
         )
-        assert_equal(
-            self.ms_outer.volume_for_interface_set(self.interfaces_dec),
-            self.volumes[1]
+        assert (
+            self.ms_outer.volume_for_interface_set(self.interfaces_dec)
+            == self.volumes[1]
         )
 
     def test_lambda_for_interface_set(self):
-        assert_equal(
-            self.ms_outer.lambda_for_interface_set(self.interfaces_inc),
-            0.5
+        assert (
+            self.ms_outer.lambda_for_interface_set(self.interfaces_inc)
+            == 0.5
         )
-        assert_equal(
-            self.ms_outer.lambda_for_interface_set(self.interfaces_dec),
-            0.4
+        assert (
+            self.ms_outer.lambda_for_interface_set(self.interfaces_dec)
+            == 0.4
         )
 
+
     def test_relevant_transitions(self):
         extra_set = paths.VolumeInterfaceSet(self.cv_inc, 0.0, [0.2, 0.3])
         extra = paths.TISTransition(self.stateA, self.stateB, extra_set,
@@ -101,8 +99,8 @@ def test_relevant_transitions(self):
         # TODO: switch once network is working
         relevant = self.post_network.relevant_transitions(transitions)
         #relevant = self.ms_outer.relevant_transitions(transitions)
-        assert_equal(len(relevant), 2)
-        assert_equal(set(self.network.sampling_transitions), set(relevant))
+        assert len(relevant) == 2
+        assert set(self.network.sampling_transitions) == set(relevant)
 
     def test_make_ensemble(self):
         transitions = self.network.sampling_transitions
@@ -115,12 +113,12 @@ def test_make_ensemble(self):
         test_BXB = make_1d_traj([1.1, 0.5, 1.2])
         test_AXB = make_1d_traj([-0.1, 0.6, 1.1])
         test_BXA = make_1d_traj([1.1, 0.5, -0.1])
-        assert_equal(ensemble(test_AA), False)
-        assert_equal(ensemble(test_AXA), True)
-        assert_equal(ensemble(test_BB), False)
-        assert_equal(ensemble(test_BXB), True)
-        assert_equal(ensemble(test_BXA), True)
-        assert_equal(ensemble(test_AXB), True)
+        assert ensemble(test_AA) is False
+        assert ensemble(test_AXA) is True
+        assert ensemble(test_BB) is False
+        assert ensemble(test_BXB) is True
+        assert ensemble(test_BXA) is True
+        assert ensemble(test_AXB) is True
 
     def test_make_ensemble_with_forbidden(self):
         forbidden = paths.CVDefinedVolume(self.cv_inc, 0.55, 0.65)
@@ -138,13 +136,13 @@ def test_make_ensemble_with_forbidden(self):
         test_AFB = make_1d_traj([-0.1, 0.6, 1.1])
         test_BXA = make_1d_traj([1.1, 0.5, -0.1])
         test_BFA = make_1d_traj([1.1, 0.6, -0.1])
-        assert_equal(ensemble(test_AA), False)
-        assert_equal(ensemble(test_AXA), True)
-        assert_equal(ensemble(test_BB), False)
-        assert_equal(ensemble(test_BXB), True)
-        assert_equal(ensemble(test_BXA), True)
-        assert_equal(ensemble(test_AXB), True)
-        assert_equal(ensemble(test_AFA), False)
-        assert_equal(ensemble(test_BFB), False)
-        assert_equal(ensemble(test_AFB), False)
-        assert_equal(ensemble(test_BFA), False)
+        assert ensemble(test_AA) is False
+        assert ensemble(test_AXA) is True
+        assert ensemble(test_BB) is False
+        assert ensemble(test_BXB) is True
+        assert ensemble(test_BXA) is True
+        assert ensemble(test_AXB) is True
+        assert ensemble(test_AFA) is False
+        assert ensemble(test_BFB) is False
+        assert ensemble(test_AFB) is False
+        assert ensemble(test_BFA) is False
diff --git a/openpathsampling/tests/test_network.py b/openpathsampling/tests/test_network.py
index 32810e999..0b26adabf 100644
--- a/openpathsampling/tests/test_network.py
+++ b/openpathsampling/tests/test_network.py
@@ -3,9 +3,6 @@
 from builtins import object
 import numpy as np
 
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises)
-from nose.plugins.skip import Skip, SkipTest
 from .test_helpers import (
     true_func, assert_equal_array_array, make_1d_traj, data_filename
 )
@@ -124,37 +121,37 @@ def test_set_fluxes(self):
             myflux = {self.stateA: 2.0,
                       self.stateB: 4.0,
                       self.stateC: 5.0}[trans[0]]
-            assert_equal(self.mstis.transitions[trans]._flux, myflux)
+            assert self.mstis.transitions[trans]._flux == myflux
 
     def test_all_states(self):
-        assert_equal(set(self.mstis.all_states),
-                     set([self.stateA, self.stateB, self.stateC]))
+        assert (set(self.mstis.all_states)
+                == set([self.stateA, self.stateB, self.stateC]))
 
     def test_trajectories(self):
         # TODO; make this test fully comprehensive? (loop over all
         # possibilities?)
         ensA0 = self.mstis.from_state[self.stateA].ensembles[0]
         ensAm = self.mstis.from_state[self.stateA].ensembles[-1]
-        assert_equal(ensA0(self.traj['AA']), True)
-        assert_equal(ensAm(self.traj['AA']), False)
-        assert_equal(ensAm(self.traj['AB']), True)
+        assert ensA0(self.traj['AA'])
+        assert not ensAm(self.traj['AA'])
+        assert ensAm(self.traj['AB'])
         ensB0 = self.mstis.from_state[self.stateB].ensembles[0]
-        assert_equal(ensB0(self.traj['AB']), False)
-        assert_equal(ensB0(self.traj['BA']), True)
-        assert_equal(ensB0(self.traj['BB']), True)
-        assert_equal(ensB0(self.traj['BC']), True)
-        assert_equal(ensB0(self.traj['AC']), False)
+        assert not ensB0(self.traj['AB'])
+        assert ensB0(self.traj['BA'])
+        assert ensB0(self.traj['BB'])
+        assert ensB0(self.traj['BC'])
+        assert not ensB0(self.traj['AC'])
         ensC0 = self.mstis.from_state[self.stateC].ensembles[0]
-        assert_equal(ensC0(self.traj['CC']), True)
-        assert_equal(ensC0(self.traj['CB']), True)
-        assert_equal(ensC0(self.traj['CA']), True)
-        assert_equal(ensC0(self.traj['BC']), False)
-        assert_equal(ensC0(self.traj['AC']), False)
-        assert_equal(ensC0(self.traj['BB']), False)
+        assert ensC0(self.traj['CC'])
+        assert ensC0(self.traj['CB'])
+        assert ensC0(self.traj['CA'])
+        assert not ensC0(self.traj['BC'])
+        assert not ensC0(self.traj['AC'])
+        assert not ensC0(self.traj['BB'])
 
     def test_ms_outers(self):
         for traj_label in ['AB', 'BA', 'AC', 'CA', 'BC', 'CB']:
-            assert_equal(self.mstis.ms_outers[0](self.traj[traj_label]), True)
+            assert self.mstis.ms_outers[0](self.traj[traj_label])
 
     def test_minus_ensembles(self):
         good_traj_seq = [-0.51, -0.49, -0.40, -0.52, -0.48, -0.51]  # AXXAXA
@@ -169,50 +166,49 @@ def test_minus_ensembles(self):
         good_minus_traj = make_1d_traj(good_traj_seq)
         bad_minus_traj = make_1d_traj(bad_traj_seq)
         # test that the call works
-        assert_equal(minus_A(good_minus_traj), True)
-        assert_equal(minus_A(bad_minus_traj), False)
+        assert minus_A(good_minus_traj)
+        assert not minus_A(bad_minus_traj)
         # test that the can_append works for the good traj
         good_building_traj = paths.Trajectory([])
         for (i, snap) in enumerate(good_minus_traj):
             good_building_traj.append(snap)
             if not minus_A.can_append(good_building_traj, trusted=True):
                 break
-        assert_equal(len(good_building_traj), len(good_minus_traj))
+        assert len(good_building_traj) == len(good_minus_traj)
         # test that the can_append works for the bad traj
         bad_building_traj = paths.Trajectory([])
         for (i, snap) in enumerate(bad_minus_traj):
             bad_building_traj.append(snap)
             if not minus_A.can_append(bad_building_traj, trusted=True):
                 break
-        assert_equal(len(bad_building_traj), 3)
+        assert len(bad_building_traj) == 3
 
     def test_sampling_ensembles(self):
-        assert_equal(len(self.mstis.from_state[self.stateA].ensembles), 2)
-        assert_equal(len(self.mstis.from_state[self.stateB].ensembles), 2)
-        assert_equal(len(self.mstis.from_state[self.stateC].ensembles), 2)
+        assert len(self.mstis.from_state[self.stateA].ensembles) == 2
+        assert len(self.mstis.from_state[self.stateB].ensembles) == 2
+        assert len(self.mstis.from_state[self.stateC].ensembles) == 2
 
         # test that .sampling_ensembles is as expected
-        assert_equal(len(self.mstis.sampling_ensembles), 6)
+        assert len(self.mstis.sampling_ensembles) == 6
         all_sampling_ens = sum(
             [self.mstis.from_state[state].ensembles
              for state in [self.stateA, self.stateB, self.stateC]],
             []
         )
-        assert_equal(set(self.mstis.sampling_ensembles),
-                     set(all_sampling_ens))
+        assert set(self.mstis.sampling_ensembles) == set(all_sampling_ens)
 
         # test that sampling ensembles has cv_max set
-        assert_equal(len(paths.InterfaceSet._cv_max_dict), 1)
+        assert len(paths.InterfaceSet._cv_max_dict) == 1
         cv_max = list(paths.InterfaceSet._cv_max_dict.values())[0]
         for transition in self.mstis.sampling_transitions:
-            assert_equal(transition.interfaces.cv_max, cv_max)
+            assert transition.interfaces.cv_max == cv_max
         for ens in self.mstis.sampling_ensembles:
-            assert_equal(ens.cv_max, cv_max)
+            assert ens.cv_max == cv_max
 
     def test_autonaming(self):
-        assert_equal(self.stateA.name, "A")
-        assert_equal(self.stateB.name, "B")
-        assert_equal(self.stateC.name, "C")
+        assert self.stateA.name == "A"
+        assert self.stateB.name == "B"
+        assert self.stateC.name == "C"
 
         # check that (1) given names stay unchanged; (2) code knows to skip
         # over any default names that have been assigned (i.e., it renames
@@ -235,9 +231,9 @@ def test_autonaming(self):
             (self.stateB, ifacesB),
             (self.stateC, ifacesC)
         ])
-        assert_equal(self.stateA.name, "B")
-        assert_equal(self.stateB.name, "A")
-        assert_equal(self.stateC.name, "C")
+        assert self.stateA.name == "B"
+        assert self.stateB.name == "A"
+        assert self.stateC.name == "C"
 
 
 class TestMISTISNetwork(TestMultipleStateTIS):
@@ -260,36 +256,35 @@ def setup_method(self):
         )
 
     def test_initialization(self):
-        assert_equal(len(self.mistis.sampling_transitions), 3)
-        assert_equal(len(self.mistis.input_transitions), 3)
-        assert_equal(len(self.mistis.transitions), 3)
+        assert len(self.mistis.sampling_transitions) == 3
+        assert len(self.mistis.input_transitions) == 3
+        assert len(self.mistis.transitions) == 3
         transitions = self.mistis.transitions
-        assert_equal(len(transitions[self.stateA, self.stateB].ensembles), 2)
-        assert_equal(len(transitions[self.stateB, self.stateA].ensembles), 2)
-        assert_equal(len(transitions[self.stateA, self.stateC].ensembles), 3)
+        assert len(transitions[self.stateA, self.stateB].ensembles) == 2
+        assert len(transitions[self.stateB, self.stateA].ensembles) == 2
+        assert len(transitions[self.stateA, self.stateC].ensembles) == 3
         # TODO: add more checks here
 
     def test_sampling_ensembles(self):
-        assert_equal(len(self.mistis.sampling_ensembles), 7)
+        assert len(self.mistis.sampling_ensembles) == 7
         all_sampling_ens = sum(
             [t.ensembles for t in self.mistis.sampling_transitions], []
         )
-        assert_equal(set(self.mistis.sampling_ensembles),
-                     set(all_sampling_ens))
+        assert set(self.mistis.sampling_ensembles) == set(all_sampling_ens)
         # test that sampling ensembles has cv_max set
-        assert_equal(len(paths.InterfaceSet._cv_max_dict), 1)
+        assert len(paths.InterfaceSet._cv_max_dict) == 1
         cv_max = list(paths.InterfaceSet._cv_max_dict.values())[0]
         for transition in self.mistis.sampling_transitions:
-            assert_equal(transition.interfaces.cv_max, cv_max)
+            assert transition.interfaces.cv_max == cv_max
         for ens in self.mistis.sampling_ensembles:
-            assert_equal(ens.cv_max, cv_max)
+            assert ens.cv_max == cv_max
 
     def test_ms_outers(self):
         ms_outer_ens = self.mistis.ms_outers[0]
         for traj_label in ['AB', 'BA']:
-            assert_equal(ms_outer_ens(self.traj[traj_label]), True)
+            assert ms_outer_ens(self.traj[traj_label])
         for traj_label in ['CB', 'CA']:
-            assert_equal(ms_outer_ens(self.traj[traj_label]), False)
+            assert not ms_outer_ens(self.traj[traj_label])
 
     def test_minus_ensembles(self):
         good_traj_seq = [-0.51, -0.49, -0.40, -0.52, -0.48, -0.51]  # AXXAXA
@@ -314,37 +309,37 @@ def test_set_fluxes(self):
         self.mistis.set_fluxes(flux_dict)
         for (A, B) in self.mistis.transitions:
             if A == self.stateA:
-                assert_equal(self.mistis.transitions[(A, B)]._flux, 2.0)
+                assert self.mistis.transitions[(A, B)]._flux == 2.0
             elif A == self.stateB:
-                assert_equal(self.mistis.transitions[(A, B)]._flux, 4.0)
+                assert self.mistis.transitions[(A, B)]._flux == 4.0
 
     def test_trajectories_nonstrict(self):
         fromA = [trans for trans in self.mistis.sampling_transitions
                  if trans.stateA == self.stateA]
         fromB = [trans for trans in self.mistis.sampling_transitions
                  if trans.stateA == self.stateB]
-        assert_equal(len(fromA), 2)
-        assert_equal(len(fromB), 1)
+        assert len(fromA) == 2
+        assert len(fromB) == 1
         fromA_0 = fromA[0].ensembles[0]
         fromA_1 = fromA[1].ensembles[0]
         fromB_0 = fromB[0].ensembles[0]
-        assert_equal(fromA_0(self.traj['AA']), True)
-        assert_equal(fromA_0(self.traj['AB']), True)
-        assert_equal(fromA_0(self.traj['AC']), True)
-        assert_equal(fromA_0(self.traj['BB']), False)
-        assert_equal(fromA_0(self.traj['CB']), False)
-        assert_equal(fromA_0(self.traj['ABC']), False)
-        assert_equal(fromA_1(self.traj['AA']), True)
-        assert_equal(fromA_1(self.traj['AB']), True)
-        assert_equal(fromA_1(self.traj['AC']), True)
-        assert_equal(fromA_1(self.traj['CB']), False)
-        assert_equal(fromA_1(self.traj['CB']), False)
-        assert_equal(fromA_1(self.traj['ABC']), False)
-        assert_equal(fromB_0(self.traj['BA']), True)
-        assert_equal(fromB_0(self.traj['BB']), True)
-        assert_equal(fromB_0(self.traj['BB']), True)
-        assert_equal(fromB_0(self.traj['AB']), False)
-        assert_equal(fromB_0(self.traj['CB']), False)
+        assert fromA_0(self.traj['AA'])
+        assert fromA_0(self.traj['AB'])
+        assert fromA_0(self.traj['AC'])
+        assert not fromA_0(self.traj['BB'])
+        assert not fromA_0(self.traj['CB'])
+        assert not fromA_0(self.traj['ABC'])
+        assert fromA_1(self.traj['AA'])
+        assert fromA_1(self.traj['AB'])
+        assert fromA_1(self.traj['AC'])
+        assert not fromA_1(self.traj['CB'])
+        assert not fromA_1(self.traj['CB'])
+        assert not fromA_1(self.traj['ABC'])
+        assert fromB_0(self.traj['BA'])
+        assert fromB_0(self.traj['BB'])
+        assert fromB_0(self.traj['BB'])
+        assert not fromB_0(self.traj['AB'])
+        assert not fromB_0(self.traj['CB'])
 
     def test_trajectories_strict(self):
         strict = MISTISNetwork([
@@ -364,23 +359,23 @@ def test_trajectories_strict(self):
         ensAB = transAB.ensembles[0]
         ensAC = transAC.ensembles[0]
         ensBA = transBA.ensembles[0]
-        assert_equal(ensAB(self.traj['AA']), True)
-        assert_equal(ensAB(self.traj['AB']), True)
-        assert_equal(ensAB(self.traj['AC']), False)
-        assert_equal(ensAB(self.traj['BB']), False)
-        assert_equal(ensAB(self.traj['BC']), False)
-        assert_equal(ensAB(self.traj['ABC']), False)
-        assert_equal(ensAC(self.traj['AA']), True)
-        assert_equal(ensAC(self.traj['AC']), True)
-        assert_equal(ensAC(self.traj['AB']), False)
-        assert_equal(ensAC(self.traj['BB']), False)
-        assert_equal(ensAC(self.traj['BC']), False)
-        assert_equal(ensAC(self.traj['ABC']), False)
-        assert_equal(ensBA(self.traj['BB']), True)
-        assert_equal(ensBA(self.traj['BA']), True)
-        assert_equal(ensBA(self.traj['BC']), False)
-        assert_equal(ensBA(self.traj['AB']), False)
-        assert_equal(ensBA(self.traj['AC']), False)
+        assert ensAB(self.traj['AA'])
+        assert ensAB(self.traj['AB'])
+        assert not ensAB(self.traj['AC'])
+        assert not ensAB(self.traj['BB'])
+        assert not ensAB(self.traj['BC'])
+        assert not ensAB(self.traj['ABC'])
+        assert ensAC(self.traj['AA'])
+        assert ensAC(self.traj['AC'])
+        assert not ensAC(self.traj['AB'])
+        assert not ensAC(self.traj['BB'])
+        assert not ensAC(self.traj['BC'])
+        assert not ensAC(self.traj['ABC'])
+        assert ensBA(self.traj['BB'])
+        assert ensBA(self.traj['BA'])
+        assert not ensBA(self.traj['BC'])
+        assert not ensBA(self.traj['AB'])
+        assert not ensBA(self.traj['AC'])
 
     def test_storage(self):
         import os
@@ -397,9 +392,9 @@ def test_storage(self):
 
         storage_r = paths.AnalysisStorage(fname)
         reloaded = storage_r.networks[0]
-        assert_equal(reloaded.strict_sampling, False)
-        assert_equal(reloaded.sampling_transitions[0].ensembles[0],
-                     self.mistis.sampling_transitions[0].ensembles[0])
+        assert not reloaded.strict_sampling
+        assert (reloaded.sampling_transitions[0].ensembles[0]
+                == self.mistis.sampling_transitions[0].ensembles[0])
 
         storage_w.close()
         storage_r.close()
@@ -471,29 +466,28 @@ def network3c(self):
 
     def test_initialization_2state(self):
         network2a = self.network2a
-        assert_equal(len(network2a.sampling_transitions), 1)
-        assert_equal(len(network2a.transitions), 1)
+        assert len(network2a.sampling_transitions) == 1
+        assert len(network2a.transitions) == 1
         network2b = self.network2b
-        assert_equal(len(network2b.sampling_transitions), 1)
-        assert_equal(len(network2b.transitions), 1)
+        assert len(network2b.sampling_transitions) == 1
+        assert len(network2b.transitions) == 1
         network2c = self.network2c
-        assert_equal(len(network2c.sampling_transitions), 1)
-        assert_equal(len(network2c.transitions), 1)
-        assert_equal(set(network2a.all_states), set(network2b.all_states))
-        assert_equal(set(network2b.all_states), set(network2c.all_states))
-        assert_equal(set(network2a.all_states),
-                     set([self.stateA, self.stateB]))
+        assert len(network2c.sampling_transitions) == 1
+        assert len(network2c.transitions) == 1
+        assert set(network2a.all_states) == set(network2b.all_states)
+        assert set(network2b.all_states) == set(network2c.all_states)
+        assert set(network2a.all_states) == set([self.stateA, self.stateB])
 
     def test_initialization_3state(self):
         network3a = self.network3a
-        assert_equal(len(network3a.sampling_transitions), 1)
-        assert_equal(len(network3a.transitions), 6)
+        assert len(network3a.sampling_transitions) == 1
+        assert len(network3a.transitions) == 6
         network3b = self.network3b
-        assert_equal(len(network3b.sampling_transitions), 1)
-        assert_equal(len(network3b.transitions), 6)
+        assert len(network3b.sampling_transitions) == 1
+        assert len(network3b.transitions) == 6
         network3c = self.network3c
-        assert_equal(len(network3c.sampling_transitions), 1)
-        assert_equal(len(network3c.transitions), 6)
+        assert len(network3c.sampling_transitions) == 1
+        assert len(network3c.transitions) == 6
 
     def test_storage(self):
         import os
@@ -511,8 +505,8 @@ def test_storage(self):
         network_a = self.NetworkType(initial_states=states,
                                      final_states=states,
                                      **self.std_kwargs)
-        assert_equal(len(network_a.sampling_transitions), 1)
-        assert_equal(len(network_a.transitions), 6)
+        assert len(network_a.sampling_transitions) == 1
+        assert len(network_a.transitions) == 6
         storage_w = paths.storage.Storage(fname, "w")
         storage_w.snapshots.save(self.template)
         storage_w.save(network_a)
@@ -520,8 +514,8 @@ def test_storage(self):
 
         storage_r = paths.storage.AnalysisStorage(fname)
         network_b = storage_r.networks[0]
-        assert_equal(len(network_b.sampling_transitions), 1)
-        assert_equal(len(network_b.transitions), 6)
+        assert len(network_b.sampling_transitions) == 1
+        assert len(network_b.transitions) == 6
 
         if os.path.isfile(fname):
             os.remove(fname)
@@ -530,48 +524,48 @@ def test_allow_self_transitions_false(self):
         network = self.NetworkType.from_states_all_to_all(
             self.states, allow_self_transitions=False, **self.std_kwargs
         )
-        assert_equal(len(network.sampling_ensembles), 1)
+        assert len(network.sampling_ensembles) == 1
         ensemble = network.sampling_ensembles[0]
-        assert_equal(ensemble(self.traj['AA']), False)
-        assert_equal(ensemble(self.traj['AB']), True)
-        assert_equal(ensemble(self.traj['BA']), True)
-        assert_equal(ensemble(self.traj['BC']), True)
-        assert_equal(ensemble(self.traj['CA']), True)
-        assert_equal(ensemble(self.traj['BB']), False)
-        assert_equal(ensemble(self.traj['CC']), False)
+        assert not ensemble(self.traj['AA'])
+        assert ensemble(self.traj['AB'])
+        assert ensemble(self.traj['BA'])
+        assert ensemble(self.traj['BC'])
+        assert ensemble(self.traj['CA'])
+        assert not ensemble(self.traj['BB'])
+        assert not ensemble(self.traj['CC'])
 
     def test_allow_self_transitions_true(self):
         network = self.NetworkType.from_states_all_to_all(
             self.states, allow_self_transitions=True, **self.std_kwargs
         )
-        assert_equal(len(network.sampling_ensembles), 1)
+        assert len(network.sampling_ensembles) == 1
         ensemble = network.sampling_ensembles[0]
-        assert_equal(ensemble(self.traj['AA']), True)
-        assert_equal(ensemble(self.traj['AB']), True)
-        assert_equal(ensemble(self.traj['BA']), True)
-        assert_equal(ensemble(self.traj['BC']), True)
-        assert_equal(ensemble(self.traj['CA']), True)
-        assert_equal(ensemble(self.traj['BB']), True)
-        assert_equal(ensemble(self.traj['CC']), True)
+        assert ensemble(self.traj['AA'])
+        assert ensemble(self.traj['AB'])
+        assert ensemble(self.traj['BA'])
+        assert ensemble(self.traj['BC'])
+        assert ensemble(self.traj['CA'])
+        assert ensemble(self.traj['BB'])
+        assert ensemble(self.traj['CC'])
 
     def test_allow_self_transitions_false_ABX(self):
         network = self.NetworkType.from_states_all_to_all(
             self.states, allow_self_transitions=False, **self.std_kwargs
         )
-        assert_equal(len(network.sampling_ensembles), 1)
+        assert len(network.sampling_ensembles) == 1
         ensemble = network.sampling_ensembles[0]
-        assert_equal(ensemble(self.traj['AB0']), False)
-        assert_equal(ensemble(self.traj['ABA']), False)
+        assert not ensemble(self.traj['AB0'])
+        assert not ensemble(self.traj['ABA'])
 
     def test_allow_self_transitions_true_ABX(self):
         # special case that differs between fixed and flexible
         network = self.NetworkType.from_states_all_to_all(
             self.states, allow_self_transitions=True, **self.std_kwargs
         )
-        assert_equal(len(network.sampling_ensembles), 1)
+        assert len(network.sampling_ensembles) == 1
         ensemble = network.sampling_ensembles[0]
-        assert_equal(ensemble(self.traj['AB0']), False)
-        assert_equal(ensemble(self.traj['ABA']), False)
+        assert not ensemble(self.traj['AB0'])
+        assert not ensemble(self.traj['ABA'])
 
 
 class TestFixedLengthTPSNetwork(TestTPSNetwork):
@@ -581,14 +575,14 @@ class TestFixedLengthTPSNetwork(TestTPSNetwork):
     def test_lengths(self):
         for network in [self.network2a, self.network2b, self.network2c,
                         self.network3a, self.network3b, self.network3c]:
-            assert_equal(network.sampling_transitions[0].length, 4)
-            assert_equal(list(network.transitions.values())[0].length, 4)
+            assert network.sampling_transitions[0].length == 4
+            assert list(network.transitions.values())[0].length == 4
 
     def test_allow_self_transitions_true_ABX(self):
         network = self.NetworkType.from_states_all_to_all(
             self.states, allow_self_transitions=True, **self.std_kwargs
         )
-        assert_equal(len(network.sampling_ensembles), 1)
+        assert len(network.sampling_ensembles) == 1
         ensemble = network.sampling_ensembles[0]
-        assert_equal(ensemble(self.traj['AB0']), False)
-        assert_equal(ensemble(self.traj['ABA']), True)
+        assert not ensemble(self.traj['AB0'])
+        assert ensemble(self.traj['ABA'])
diff --git a/openpathsampling/tests/test_openmm_engine.py b/openpathsampling/tests/test_openmm_engine.py
index 407534f9d..177594779 100644
--- a/openpathsampling/tests/test_openmm_engine.py
+++ b/openpathsampling/tests/test_openmm_engine.py
@@ -9,8 +9,6 @@
 from builtins import object
 from past.utils import old_div
 import numpy as np
-from nose.tools import (assert_equal)
-from nose.plugins.skip import SkipTest
 
 from openpathsampling.integration_tools import openmm as mm
 
@@ -40,7 +38,7 @@
 def setup_module():
     global topology, template, system, nan_causing_template
     if not (u and mm and app and md):
-        raise SkipTest
+        pytest.skip("Missing requirements")
     template = peng.snapshot_from_pdb(data_filename("ala_small_traj.pdb"))
     topology = peng.to_openmm_topology(template)
 
@@ -106,8 +104,8 @@ def teardown_method(self):
         pass
 
     def test_sanity(self):
-        assert_equal(self.engine.n_steps_per_frame, 2)
-        assert_equal(self.engine.n_frames_max, 5)
+        assert self.engine.n_steps_per_frame == 2
+        assert self.engine.n_frames_max == 5
         # TODO: add more sanity checks
         pass  # not quite a SkipTest, but a reminder to add more
 
@@ -161,8 +159,8 @@ def test_generate_next_frame(self):
         new_pos = old_div(new_snap.coordinates, u.nanometers)
         old_vel = old_div(snap0.velocities, (old_div(u.nanometers, u.picoseconds)))
         new_vel = old_div(new_snap.velocities, (old_div(u.nanometers, u.picoseconds)))
-        assert_equal(old_pos.shape, new_pos.shape)
-        assert_equal(old_vel.shape, new_vel.shape)
+        assert old_pos.shape == new_pos.shape
+        assert old_vel.shape == new_vel.shape
         assert_not_equal_array_array(old_pos, new_pos)
         assert_not_equal_array_array(old_vel, new_vel)
 
@@ -171,12 +169,12 @@ def test_generate(self):
             _ = self.engine.generate(self.engine.current_snapshot, [true_func])
         except dyn.EngineMaxLengthError as e:
             traj = e.last_trajectory
-            assert_equal(len(traj), self.engine.n_frames_max)
+            assert len(traj) == self.engine.n_frames_max
         else:
             raise RuntimeError('Did not have correct MaxLengthError')
 
     def test_snapshot_timestep(self):
-        assert_equal(self.engine.snapshot_timestep, 4 * u.femtoseconds)
+        assert self.engine.snapshot_timestep == 4 * u.femtoseconds
 
     @raises_with_message_like(paths.engines.EngineMaxLengthError,
                               "Hit maximal length")
@@ -224,15 +222,15 @@ def test_nan_rejected(self):
         change = mover.move(init_samp)
 
         assert (isinstance(change, paths.RejectedNaNSampleMoveChange))
-        assert_equal(change.details.rejection_reason, 'nan')
+        assert change.details.rejection_reason == 'nan'
         # since we shoot, we start with a shorter trajectory
         assert(len(change.samples[0].trajectory) < len(init_traj))
 
         newsamp = init_samp.apply_samples(change)
-        assert_equal(len(newsamp), 1)
+        assert len(newsamp) == 1
 
         # make sure there is no change!
-        assert_equal(init_samp[0].trajectory, init_traj)
+        assert init_samp[0].trajectory == init_traj
 
     def test_max_length_rejected(self):
         stateA = paths.EmptyVolume()  # will run indefinitely
@@ -256,15 +254,14 @@ def test_max_length_rejected(self):
         change = mover.move(init_samp)
 
         assert(isinstance(change, paths.RejectedMaxLengthSampleMoveChange))
-        assert_equal(change.details.rejection_reason, 'max_length')
-        assert_equal(
-            len(change.samples[0].trajectory), self.engine.n_frames_max)
+        assert change.details.rejection_reason == 'max_length'
+        assert len(change.samples[0].trajectory) == self.engine.n_frames_max
 
         newsamp = init_samp.apply_samples(change)
-        assert_equal(len(newsamp), 1)
+        assert len(newsamp) == 1
 
         # make sure there is no change!
-        assert_equal(init_samp[0].trajectory, init_traj)
+        assert init_samp[0].trajectory == init_traj
 
     @pytest.mark.parametrize('has_constraints', [True, False])
     def test_has_constraints(self, has_constraints):
diff --git a/openpathsampling/tests/test_openmm_snapshot.py b/openpathsampling/tests/test_openmm_snapshot.py
index 48b62c1ef..1afae80fc 100644
--- a/openpathsampling/tests/test_openmm_snapshot.py
+++ b/openpathsampling/tests/test_openmm_snapshot.py
@@ -3,9 +3,6 @@
 from builtins import object
 import openpathsampling.engines.openmm as omm_engine
 import openpathsampling as paths
-from nose.tools import (assert_equal, assert_almost_equal, assert_not_equal,
-                        assert_is_not, assert_is)
-from nose.plugins.skip import SkipTest
 from .test_helpers import data_filename, assert_close_unit, u
 
 import pytest
@@ -28,10 +25,10 @@
 class TestOpenMMSnapshot(object):
     def setup_method(self):
         if not openmm:
-            raise SkipTest("OpenMM not installed")
+            pytest.skip("OpenMM not installed")
         if not omt:
-            raise SkipTest("OpenMMTools not installed; required for OpenMM "
-                           "tests.")
+            pytest.skip("OpenMMTools not installed; required for OpenMM "
+                        "tests.")
         self.test_system = omt.testsystems.AlanineDipeptideVacuum()
         self.template = omm_engine.snapshot_from_testsystem(self.test_system)
         self.engine = omm_engine.Engine(
@@ -49,7 +46,7 @@ def setup_method(self):
 
     def test_masses_from_file(self):
         masses = self.template.masses
-        assert_equal(len(masses), self.n_atoms)
+        assert len(masses) == self.n_atoms
 
     def test_masses_from_simulation(self):
         assert len(self.test_snap.masses) == self.n_atoms
@@ -86,19 +83,19 @@ def test_instantaneous_temperature_changes(self):
                                           [lambda t, foo: len(t) < 4])
         temp_1 = trajectory[1].instantaneous_temperature
         temp_2 = trajectory[2].instantaneous_temperature
-        assert_not_equal(temp_1, temp_2)
+        assert temp_1 != temp_2
 
     def test_mdtraj_trajectory(self):
         snap_1 = omm_engine.snapshot_from_testsystem(self.test_system,
                                                      periodic=False)
-        assert_is(snap_1.box_vectors, None)
+        assert snap_1.box_vectors is None
         traj_1 = snap_1.md
-        assert_equal(len(traj_1), 1)
-        assert_is_not(traj_1.xyz, None)
-        assert_is(traj_1.unitcell_vectors, None)
+        assert len(traj_1) == 1
+        assert traj_1.xyz is not None
+        assert traj_1.unitcell_vectors is None
 
         snap_2 = self.test_snap
         traj_2 = snap_2.md
-        assert_equal(len(traj_2), 1)
-        assert_is_not(traj_2.xyz, None)
-        assert_is_not(traj_2.unitcell_vectors, None)
+        assert len(traj_2) == 1
+        assert traj_2.xyz is not None
+        assert traj_2.unitcell_vectors is not None
diff --git a/openpathsampling/tests/test_part_in_b_tps.py b/openpathsampling/tests/test_part_in_b_tps.py
index 0462e6f50..9d918008d 100644
--- a/openpathsampling/tests/test_part_in_b_tps.py
+++ b/openpathsampling/tests/test_part_in_b_tps.py
@@ -1,6 +1,4 @@
 from __future__ import absolute_import
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises)
 import logging
 from openpathsampling.high_level.part_in_b_tps import *
 from .test_network import TestFixedLengthTPSNetwork
@@ -17,16 +15,16 @@ def test_allow_self_transitions_false_ABX(self):
         network = self.NetworkType.from_states_all_to_all(
             self.states, allow_self_transitions=False, **self.std_kwargs
         )
-        assert_equal(len(network.sampling_ensembles), 1)
+        assert len(network.sampling_ensembles) == 1
         ensemble = network.sampling_ensembles[0]
-        assert_equal(ensemble(self.traj['AB0']), True)
-        assert_equal(ensemble(self.traj['ABA']), True)
+        assert ensemble(self.traj['AB0'])
+        assert ensemble(self.traj['ABA'])
 
     def test_allow_self_transitions_true_ABX(self):
         network = self.NetworkType.from_states_all_to_all(
             self.states, allow_self_transitions=True, **self.std_kwargs
         )
-        assert_equal(len(network.sampling_ensembles), 1)
+        assert len(network.sampling_ensembles) == 1
         ensemble = network.sampling_ensembles[0]
-        assert_equal(ensemble(self.traj['AB0']), True)
-        assert_equal(ensemble(self.traj['ABA']), True)
+        assert ensemble(self.traj['AB0'])
+        assert ensemble(self.traj['ABA'])
diff --git a/openpathsampling/tests/test_path_histogram.py b/openpathsampling/tests/test_path_histogram.py
index 1b3400f0d..39c27cfb1 100644
--- a/openpathsampling/tests/test_path_histogram.py
+++ b/openpathsampling/tests/test_path_histogram.py
@@ -6,9 +6,6 @@
 
 import pytest
 
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal,
-                        raises)
-from nose.plugins.skip import Skip, SkipTest
 from .test_helpers import (
     true_func, assert_equal_array_array, make_1d_traj, data_filename,
     assert_items_almost_equal
@@ -67,9 +64,9 @@ def test_same_cell(self):
                              bin_widths=(0.5, 0.5),
                              interpolate=self.Interpolator, per_traj=False)
         hist.add_trajectory(traj)
-        assert_equal(len(list(hist._histogram.keys())), 2)
-        assert_equal(hist._histogram[(0,0)], 3)
-        assert_equal(hist._histogram[(0,1)], 1)
+        assert len(list(hist._histogram.keys())) == 2
+        assert hist._histogram[(0,0)] == 3
+        assert hist._histogram[(0,1)] == 1
 
 
 class TestPathHistogramNoInterpolate(PathHistogramTester):
@@ -154,13 +151,13 @@ def test_add_with_weight(self):
         for val in [(0,1), (0,2), (0,3), (1,2), (1,3), (1,4), (2,1), (2,3),
                     (2,4), (2,5), (3,1), (3,2), (3,4), (3,5), (3,6), (4,5),
                     (4,6)]:
-            assert_equal(hist._histogram[val], 1.0)
+            assert hist._histogram[val] == 1.0
         for val in [(2,2), (4,4)]:
-            assert_equal(hist._histogram[val], 2.0)
+            assert hist._histogram[val] == 2.0
         for val in [(0,0), (1,1), (3,3)]:
-            assert_equal(hist._histogram[val], 3.0)
+            assert hist._histogram[val] == 3.0
         for val in [(0,4), (0,5), (0.6), (0,7), (-1,0)]:
-            assert_equal(hist._histogram[val], 0.0)
+            assert hist._histogram[val] == 0.0
 
     def test_add_data_to_histograms(self):
         hist = PathHistogram(left_bin_edges=(0.0, 0.0),
@@ -172,13 +169,13 @@ def test_add_data_to_histograms(self):
         for val in [(0,1), (0,2), (0,3), (1,2), (1,3), (1,4), (2,1), (2,3),
                     (2,4), (2,5), (3,1), (3,2), (3,4), (3,5), (3,6), (4,5),
                     (4,6)]:
-            assert_equal(counter[val], 1.0)
+            assert counter[val] == 1.0
         for val in [(2,2), (4,4)]:
-            assert_equal(counter[val], 2.0)
+            assert counter[val] == 2.0
         for val in [(0,0), (1,1), (3,3)]:
-            assert_equal(counter[val], 3.0)
+            assert counter[val] == 3.0
         for val in [(0,4), (0,5), (0.6), (0,7), (-1,0)]:
-            assert_equal(counter[val], 0.0)
+            assert counter[val] == 0.0
 
     def test_add_data_to_histograms_no_weight(self):
         hist = PathHistogram(left_bin_edges=(0.0, 0.0),
@@ -189,13 +186,13 @@ def test_add_data_to_histograms_no_weight(self):
         for val in [(0,1), (0,2), (0,3), (1,2), (1,3), (1,4), (2,1), (2,3),
                     (2,4), (2,5), (3,1), (3,2), (3,4), (3,5), (3,6), (4,5),
                     (4,6)]:
-            assert_equal(counter[val], 1.0)
+            assert counter[val] == 1.0
         for val in [(2,2), (4,4)]:
-            assert_equal(counter[val], 1.0)
+            assert counter[val] == 1.0
         for val in [(0,0), (1,1), (3,3)]:
-            assert_equal(counter[val], 2.0)
+            assert counter[val] == 2.0
         for val in [(0,4), (0,5), (0.6), (0,7), (-1,0)]:
-            assert_equal(counter[val], 0.0)
+            assert counter[val] == 0.0
 
 
 class TestPathDensityHistogram(object):
@@ -225,35 +222,35 @@ def test_histogram_no_weights(self):
         hist = PathDensityHistogram(self.cvs, self.left_bin_edges,
                                     self.bin_widths)
         counter = hist.histogram([self.traj1, self.traj2])
-        assert_equal(len(counter), 5)
+        assert len(counter) == 5
         for bin_label in [(0,0,0), (2,0,0), (1,0,0), (2,1,1)]:
-            assert_equal(counter[bin_label], 1.0)
-        assert_equal(counter[(2,1,0)], 2.0)
+            assert counter[bin_label] == 1.0
+        assert counter[(2,1,0)] == 2.0
         for bin_label in [(1,1,1), (2,2,2), (-1,0,0), (0,-1,0)]:
-            assert_equal(counter[bin_label], 0.0)
+            assert counter[bin_label] == 0.0
 
     def test_histogram_with_weights(self):
         hist = PathDensityHistogram(self.cvs, self.left_bin_edges,
                                     self.bin_widths)
         counter = hist.histogram([self.traj1, self.traj2],
                                  weights=[1.0, 2.0])
-        assert_equal(len(counter), 5)
+        assert len(counter) == 5
         for bin_label in [(0,0,0), (2,0,0), (1,0,0)]:
-            assert_equal(counter[bin_label], 1.0)
-        assert_equal(counter[(2,1,1)], 2.0)
-        assert_equal(counter[(2,1,0)], 3.0)
+            assert counter[bin_label] == 1.0
+        assert counter[(2,1,1)] == 2.0
+        assert counter[(2,1,0)] == 3.0
         for bin_label in [(1,1,1), (2,2,2), (-1,0,0), (0,-1,0)]:
-            assert_equal(counter[bin_label], 0.0)
+            assert counter[bin_label] == 0.0
 
     def test_histogram_single_traj(self):
         hist = PathDensityHistogram(self.cvs, self.left_bin_edges,
                                     self.bin_widths)
         counter = hist.histogram(self.traj1)
-        assert_equal(len(counter), 4)
+        assert len(counter) == 4
         for bin_label in [(0,0,0), (2,0,0), (1,0,0), (2,1,0)]:
-            assert_equal(counter[bin_label], 1.0)
+            assert counter[bin_label] == 1.0
         for bin_label in [(1,1,1), (2,2,2), (-1,0,0), (0,-1,0)]:
-            assert_equal(counter[bin_label], 0.0)
+            assert counter[bin_label] == 0.0
 
     def test_map_to_float_bins_trajectory(self):
         hist = PathDensityHistogram(self.cvs, self.left_bin_edges,
diff --git a/openpathsampling/tests/test_pathsimulator.py b/openpathsampling/tests/test_pathsimulator.py
index a7cbd242c..1721d0503 100644
--- a/openpathsampling/tests/test_pathsimulator.py
+++ b/openpathsampling/tests/test_pathsimulator.py
@@ -4,12 +4,12 @@
 from builtins import range
 from past.utils import old_div
 from builtins import object
+
+import pytest
 from .test_helpers import (raises_with_message_like, data_filename,
                            CalvinistDynamics, make_1d_traj,
                            assert_items_equal)
-from nose.tools import (assert_equal, assert_not_equal, raises,
-                        assert_almost_equal, assert_true, assert_greater)
-# from nose.plugins.skip import SkipTest
+from numpy.testing import assert_almost_equal
 
 from openpathsampling.pathsimulators import *
 import openpathsampling as paths
@@ -65,7 +65,6 @@ def setup_method(self):
             snapshot=self.snapA
         )
 
-    @raises(RuntimeError)
     def test_initial_max_length(self):
         engine = CalvinistDynamics([-0.5, -0.4, -0.3, -0.2, -0.1, 0.1, -0.1])
         bootstrap_AB_maxlength = paths.FullBootstrapping(
@@ -75,16 +74,17 @@ def test_initial_max_length(self):
             engine=engine
         )
         bootstrap_AB_maxlength.output_stream = open(os.devnull, "w")
-        bootstrap_AB_maxlength.run(build_attempts=1)
+        with pytest.raises(RuntimeError):
+            bootstrap_AB_maxlength.run(build_attempts=1)
 
     def test_first_traj_ensemble(self):
         traj_starts_in = make_1d_traj([-0.2, -0.1, 0.1, -0.1])
         traj_starts_out = make_1d_traj([0.1, -0.1, 0.1, -0.1])
         traj_not_good = make_1d_traj([0.1, -0.1, 0.1])
         first_traj_ens = self.noforbid_noextra_AB.first_traj_ensemble
-        assert_equal(first_traj_ens(traj_starts_in), True)
-        assert_equal(first_traj_ens(traj_starts_out), True)
-        assert_equal(first_traj_ens(traj_not_good), False)
+        assert first_traj_ens(traj_starts_in)
+        assert first_traj_ens(traj_starts_out)
+        assert not first_traj_ens(traj_not_good)
 
     def test_sampling_ensembles(self):
         traj1 = make_1d_traj([-0.2, -0.1, 0.1, -0.1])
@@ -92,16 +92,16 @@ def test_sampling_ensembles(self):
         traj3 = make_1d_traj([-0.1, 0.1, 0.3, -0.1])
         traj4 = make_1d_traj([0.1, 0.3, 0.1])
         all_ensembles = self.noforbid_noextra_AB.all_ensembles
-        assert_equal(len(all_ensembles), 3)
+        assert len(all_ensembles) == 3
         for ens in all_ensembles:
-            assert_equal(ens(traj1), False)
-            assert_equal(ens(traj4), False)
-        assert_equal(all_ensembles[0](traj2), True)
-        assert_equal(all_ensembles[0](traj3), True)
-        assert_equal(all_ensembles[1](traj2), False)
-        assert_equal(all_ensembles[1](traj3), True)
-        assert_equal(all_ensembles[2](traj2), False)
-        assert_equal(all_ensembles[2](traj3), False)
+            assert not ens(traj1)
+            assert not ens(traj4)
+        assert all_ensembles[0](traj2)
+        assert all_ensembles[0](traj3)
+        assert not all_ensembles[1](traj2)
+        assert all_ensembles[1](traj3)
+        assert not all_ensembles[2](traj2)
+        assert not all_ensembles[2](traj3)
 
     def test_run_already_satisfied(self):
         engine = CalvinistDynamics([-0.5, 0.8, -0.1])
@@ -112,7 +112,7 @@ def test_run_already_satisfied(self):
         )
         bootstrap.output_stream = open(os.devnull, "w")
         gs = bootstrap.run()
-        assert_equal(len(gs), 3)
+        assert len(gs) == 3
 
     def test_run_extra_interfaces(self):
         engine = CalvinistDynamics([-0.5, 0.8, -0.1])
@@ -124,7 +124,7 @@ def test_run_extra_interfaces(self):
         )
         bootstrap.output_stream = open(os.devnull, "w")
         gs = bootstrap.run()
-        assert_equal(len(gs), 4)
+        assert len(gs) == 4
 
     def test_run_forbidden_states(self):
         engine = CalvinistDynamics([-0.5, 0.3, 3.2, -0.1, 0.8, -0.1])
@@ -136,7 +136,7 @@ def test_run_forbidden_states(self):
         )
         bootstrap1.output_stream = open(os.devnull, "w")
         gs1 = bootstrap1.run()
-        assert_equal(len(gs1), 3)
+        assert len(gs1) == 3
         assert_items_equal(self.cv(gs1[0]), [-0.5, 0.3, 3.2, -0.1])
         # now with setting forbidden_states
         bootstrap2 = FullBootstrapping(
@@ -152,7 +152,6 @@ def test_run_forbidden_states(self):
         except RuntimeError:
             pass
 
-    @raises(RuntimeError)
     def test_too_much_bootstrapping(self):
         engine = CalvinistDynamics([-0.5, 0.2, -0.1])
         bootstrap = FullBootstrapping(
@@ -161,7 +160,8 @@ def test_too_much_bootstrapping(self):
             engine=engine,
         )
         bootstrap.output_stream = open(os.devnull, "w")
-        bootstrap.run(max_ensemble_rounds=1)
+        with pytest.raises(RuntimeError):
+            bootstrap.run(max_ensemble_rounds=1)
 
 
 class TestShootFromSnapshotsSimulation(object):
@@ -215,20 +215,20 @@ def test_run_arbitrary_ensemble(self):
         self.storage.close()
         analysis = paths.Storage(self.filename, 'r')
         sim = analysis.pathsimulators[0]
-        assert_equal(len(analysis.steps), 10)
+        assert len(analysis.steps) == 10
         length_to_submover = {5: [], 3: []}
         for step in analysis.steps:
             step.active.sanity_check()
-            assert_equal(len(step.active), 1)
+            assert len(step.active) == 1
             active_sample = step.active[0]
             change = step.change
-            assert_equal(change.mover, sim.mover)
+            assert change.mover == sim.mover
             # KeyError here indicates problem with lengths generated
             length_to_submover[len(active_sample)] += change.subchange.mover
 
         for k in length_to_submover:
             # allow 0 or 1  because maybe we made no trials with submover
-            assert_true(len(set(length_to_submover[k])) <= 1)
+            assert len(set(length_to_submover[k])) <= 1
 
 
 class TestCommittorSimulation(object):
@@ -276,8 +276,8 @@ def teardown_method(self):
 
     def test_initialization(self):
         sim = self.simulation  # convenience
-        assert_equal(len(sim.initial_snapshots), 1)
-        assert_true(isinstance(sim.mover, paths.RandomChoiceMover))
+        assert len(sim.initial_snapshots) == 1
+        assert isinstance(sim.mover, paths.RandomChoiceMover)
 
     def test_storage(self):
         self.storage.tag['simulation'] = self.simulation
@@ -295,31 +295,31 @@ def test_storage(self):
 
     def test_committor_run(self):
         self.simulation.run(n_per_snapshot=20)
-        assert_equal(len(self.simulation.storage.steps), 20)
+        assert len(self.simulation.storage.steps) == 20
         counts = {'fwd': 0, 'bkwd': 0}
         for step in self.simulation.storage.steps:
             step.active.sanity_check()  # traj is in ensemble
             traj = step.active[0].trajectory
             traj_str = traj.summarize_by_volumes_str(self.state_labels)
             if traj_str == "None-Right":
-                assert_equal(step.change.canonical.mover,
-                             self.simulation.forward_mover)
-                assert_equal(step.active[0].ensemble,
-                             self.simulation.forward_ensemble)
+                assert (step.change.canonical.mover
+                        == self.simulation.forward_mover)
+                assert (step.active[0].ensemble
+                        == self.simulation.forward_ensemble)
                 counts['fwd'] += 1
             elif traj_str == "Left-None":
-                assert_equal(step.change.canonical.mover,
-                             self.simulation.backward_mover)
-                assert_equal(step.active[0].ensemble,
-                             self.simulation.backward_ensemble)
+                assert (step.change.canonical.mover
+                        == self.simulation.backward_mover)
+                assert (step.active[0].ensemble
+                        == self.simulation.backward_ensemble)
                 counts['bkwd'] += 1
             else:
                 raise AssertionError(
                     str(traj_str) + "is neither 'None-Right' nor 'Left-None'"
                 )
-        assert_true(counts['fwd'] > 0)
-        assert_true(counts['bkwd'] > 0)
-        assert_equal(counts['fwd'] + counts['bkwd'], 20)
+        assert counts['fwd'] > 0
+        assert counts['bkwd'] > 0
+        assert counts['fwd'] + counts['bkwd'] == 20
 
     def test_forward_only_committor(self):
         sim = CommittorSimulation(storage=self.storage,
@@ -330,17 +330,14 @@ def test_forward_only_committor(self):
                                   direction=1)
         sim.output_stream = open(os.devnull, 'w')
         sim.run(n_per_snapshot=10)
-        assert_equal(len(sim.storage.steps), 10)
+        assert len(sim.storage.steps) == 10
         for step in self.simulation.storage.steps:
             s = step.active[0]
             step.active.sanity_check()  # traj is in ensemble
-            assert_equal(
-                s.trajectory.summarize_by_volumes_str(self.state_labels),
-                "None-Right"
-            )
-            assert_equal(s.ensemble, sim.forward_ensemble)
-            assert_equal(step.change.canonical.mover,
-                         sim.forward_mover)
+            assert (s.trajectory.summarize_by_volumes_str(self.state_labels)
+                    == "None-Right")
+            assert s.ensemble == sim.forward_ensemble
+            assert step.change.canonical.mover == sim.forward_mover
 
     def test_backward_only_committor(self):
         sim = CommittorSimulation(storage=self.storage,
@@ -351,17 +348,14 @@ def test_backward_only_committor(self):
                                   direction=-1)
         sim.output_stream = open(os.devnull, 'w')
         sim.run(n_per_snapshot=10)
-        assert_equal(len(sim.storage.steps), 10)
+        assert len(sim.storage.steps) == 10
         for step in self.simulation.storage.steps:
             s = step.active[0]
             step.active.sanity_check()  # traj is in ensemble
-            assert_equal(
-                s.trajectory.summarize_by_volumes_str(self.state_labels),
-                "Left-None"
-            )
-            assert_equal(s.ensemble, sim.backward_ensemble)
-            assert_equal(step.change.canonical.mover,
-                         sim.backward_mover)
+            assert (s.trajectory.summarize_by_volumes_str(self.state_labels)
+                    == "Left-None")
+            assert s.ensemble == sim.backward_ensemble
+            assert step.change.canonical.mover == sim.backward_mover
 
     def test_multiple_initial_snapshots(self):
         snap1 = toys.Snapshot(coordinates=np.array([[0.1]]),
@@ -374,7 +368,7 @@ def test_multiple_initial_snapshots(self):
                                   initial_snapshots=[self.snap0, snap1])
         sim.output_stream = open(os.devnull, 'w')
         sim.run(10)
-        assert_equal(len(self.storage.steps), 20)
+        assert len(self.storage.steps) == 20
         snap0_coords = self.snap0.coordinates.tolist()
         snap1_coords = snap1.coordinates.tolist()
         count = {self.snap0: 0, snap1: 0}
@@ -388,7 +382,7 @@ def test_multiple_initial_snapshots(self):
                 msg = "Shooting snapshot matches neither test snapshot"
                 raise AssertionError(msg)
             count[mysnap] += 1
-        assert_equal(count, {self.snap0: 10, snap1: 10})
+        assert count == {self.snap0: 10, snap1: 10}
 
     def test_randomized_committor(self):
         # this shows that we get both states even with forward-only
@@ -402,7 +396,7 @@ def test_randomized_committor(self):
                                   direction=1)
         sim.output_stream = open(os.devnull, 'w')
         sim.run(50)
-        assert_equal(len(sim.storage.steps), 50)
+        assert len(sim.storage.steps) == 50
         counts = {'None-Right': 0,
                   'Left-None': 0,
                   'None-Left': 0,
@@ -417,11 +411,11 @@ def test_randomized_committor(self):
                 msg = "Got trajectory described as '{0}', length {1}"
                 # this might be okay if it is 'None', length 100000
                 raise AssertionError(msg.format(traj_str, len(traj)))
-        assert_equal(counts['Left-None'], 0)
-        assert_equal(counts['Right-None'], 0)
-        assert_true(counts['None-Left'] > 0)
-        assert_true(counts['None-Right'] > 0)
-        assert_equal(sum(counts.values()), 50)
+        assert counts['Left-None'] == 0
+        assert counts['Right-None'] == 0
+        assert counts['None-Left'] > 0
+        assert counts['None-Right'] > 0
+        assert sum(counts.values()) == 50
 
 
 class TestReactiveFluxSimulation(object):
@@ -491,58 +485,52 @@ def teardown_method(self):
 
     def test_initialization(self):
         sim = self.simulation
-        assert_equal(len(sim.initial_snapshots), 3)
-        assert_true(isinstance(sim.mover, paths.ConditionalSequentialMover))
+        assert len(sim.initial_snapshots) == 3
+        assert isinstance(sim.mover, paths.ConditionalSequentialMover)
 
     def test_simulation_run(self):
         self.simulation.run(n_per_snapshot=1)
-        assert_equal(len(self.simulation.storage.steps), 3)
+        assert len(self.simulation.storage.steps) == 3
 
         # snapshot 0, fails at backward shot (falls back to dividing surface)
         step = self.simulation.storage.steps[0]
         # last mover should be backward_mover of simulation
-        assert_equal(step.change.canonical.mover,
-                     self.simulation.backward_mover)
+        assert step.change.canonical.mover == self.simulation.backward_mover
         # active ensemble should be starting ensemble
-        assert_equal(step.active[0].ensemble,
-                     self.simulation.starting_ensemble)
+        assert step.active[0].ensemble == self.simulation.starting_ensemble
         # analyze trajectory, last step should be in 'None', the rest in 'ToA'
         traj = step.change.trials[0].trajectory
         traj_summary = traj.summarize_by_volumes(self.state_labels)
-        assert_equal(traj_summary[0], ('None', 1))
-        assert_equal(traj_summary[1][0], 'ToA')
-        assert_greater(traj_summary[1][1], 1)
+        assert traj_summary[0] == ('None', 1)
+        assert traj_summary[1][0] == 'ToA'
+        assert traj_summary[1][1] > 1
 
         # snapshot 1, fails at backward shot (wrong direction)
         step = self.simulation.storage.steps[1]
         # last mover should be backward_mover of simulation
-        assert_equal(step.change.canonical.mover,
-                     self.simulation.backward_mover)
+        assert step.change.canonical.mover == self.simulation.backward_mover
         # active ensemble should be starting ensemble
-        assert_equal(step.active[0].ensemble,
-                     self.simulation.starting_ensemble)
+        assert step.active[0].ensemble == self.simulation.starting_ensemble
         # analyze trajectory, backwards trajectory reaches immediately 'None'
         traj = step.change.trials[0].trajectory
         traj_summary = traj.summarize_by_volumes(self.state_labels)
-        assert_equal(traj_summary[0], ('None', 2))
+        assert traj_summary[0] == ('None', 2)
 
         # snapshot 2, is accepted
         step = self.simulation.storage.steps[2]
         # last mover should be forward_mover of simulation
-        assert_equal(step.change.canonical.mover,
-                     self.simulation.forward_mover)
+        assert step.change.canonical.mover == self.simulation.forward_mover
         # active ensemble should not be starting ensemble
-        assert_not_equal(step.active[0].ensemble,
-                     self.simulation.starting_ensemble)
+        assert step.active[0].ensemble != self.simulation.starting_ensemble
         # analyze active trajectory, trajectory should start in 'A', end in 'B'
         traj = step.active[0].trajectory
         traj_summary = traj.summarize_by_volumes(self.state_labels)
-        assert_equal(traj_summary[0], ('A', 1))
-        assert_equal(traj_summary[1][0], 'ToA')
-        assert_greater(traj_summary[1][1], 1)
-        assert_equal(traj_summary[2][0], 'None')
-        assert_greater(traj_summary[2][1], 1)
-        assert_equal(traj_summary[3], ('B', 1))
+        assert traj_summary[0] == ('A', 1)
+        assert traj_summary[1][0] == 'ToA'
+        assert traj_summary[1][1] > 1
+        assert traj_summary[2][0] == 'None'
+        assert traj_summary[2][1] > 1
+        assert traj_summary[3] == ('B', 1)
 
 
 class TestDirectSimulation(object):
@@ -574,17 +562,16 @@ def setup_method(self):
 
     def test_run(self):
         self.sim.run(200)
-        assert_true(len(self.sim.transition_count) > 1)
-        assert_true(len(self.sim.flux_events[self.flux_pairs[0]]) > 1)
+        assert len(self.sim.transition_count) > 1
+        assert len(self.sim.flux_events[self.flux_pairs[0]]) > 1
 
     def test_results(self):
         self.sim.run(200)
         results = self.sim.results
-        assert_equal(len(results), 2)
-        assert_equal(set(results.keys()),
-                     set(['transition_count', 'flux_events']))
-        assert_equal(results['transition_count'], self.sim.transition_count)
-        assert_equal(results['flux_events'], self.sim.flux_events)
+        assert len(results) == 2
+        assert set(results.keys()) == set(['transition_count', 'flux_events'])
+        assert results['transition_count'] == self.sim.transition_count
+        assert results['flux_events'] == self.sim.flux_events
 
     def test_load_results(self):
         left_interface = paths.CVDefinedVolume(self.cv, -0.3, float("inf"))
@@ -600,8 +587,8 @@ def test_load_results(self):
         results = {'transition_count': fake_transition_count,
                    'flux_events': fake_flux_events}
         self.sim.load_results(results)
-        assert_equal(self.sim.transition_count, fake_transition_count)
-        assert_equal(self.sim.flux_events, fake_flux_events)
+        assert self.sim.transition_count == fake_transition_count
+        assert self.sim.flux_events == fake_flux_events
 
     def test_transitions(self):
         # set fake data
@@ -609,16 +596,14 @@ def test_transitions(self):
             (self.center, 1), (self.outside, 4), (self.center, 7),
             (self.extra, 10), (self.center, 12), (self.outside, 14)
         ]
-        assert_equal(self.sim.n_transitions,
-                     {(self.center, self.outside): 2,
-                      (self.outside, self.center): 1,
-                      (self.center, self.extra): 1,
-                      (self.extra, self.center): 1})
-        assert_equal(self.sim.transitions,
-                     {(self.center, self.outside): [3, 2],
-                      (self.outside, self.center): [3],
-                      (self.center, self.extra): [3],
-                      (self.extra, self.center): [2]})
+        assert self.sim.n_transitions == {(self.center, self.outside): 2,
+                                          (self.outside, self.center): 1,
+                                          (self.center, self.extra): 1,
+                                          (self.extra, self.center): 1}
+        assert self.sim.transitions == {(self.center, self.outside): [3, 2],
+                                        (self.outside, self.center): [3],
+                                        (self.center, self.extra): [3],
+                                        (self.extra, self.center): [2]}
 
     def test_rate_matrix(self):
         self.sim.states += [self.extra]
@@ -644,7 +629,7 @@ def test_rate_matrix(self):
         for i in range(len(self.sim.states)):
             for j in range(len(self.sim.states)):
                 if np.isnan(test_matrix[i][j]):
-                    assert_true(np.isnan(rate_matrix[i][j]))
+                    assert np.isnan(rate_matrix[i][j])
                 else:
                     assert_almost_equal(rate_matrix[i][j],
                                         test_matrix[i][j])
@@ -665,7 +650,7 @@ def test_fluxes(self):
         sim.flux_events = fake_flux_events
         n_flux_events = {(self.center, right_interface): 3,
                          (self.center, left_interface): 2}
-        assert_equal(sim.n_flux_events, n_flux_events)
+        assert sim.n_flux_events == n_flux_events
         time_step = sim.engine.snapshot_timestep
         expected_fluxes = {(self.center, right_interface):
                            1.0 / (((15-3) + (23-15) + (48-23))/3.0) / time_step,
@@ -730,11 +715,11 @@ def test_multiple_cv_flux(self):
             (state, alpha): [(4, 2), (6, 4), (22, 19)],
             (state, beta): [(9, 6), (12, 9), (22, 17)]
         }
-        assert_equal(len(sim.flux_events), 2)
-        assert_equal(sim.flux_events[(state, alpha)],
-                     expected_flux_events[(state, alpha)])
-        assert_equal(sim.flux_events[(state, beta)],
-                     expected_flux_events[(state, beta)])
+        assert len(sim.flux_events) == 2
+        assert (sim.flux_events[(state, alpha)]
+                == expected_flux_events[(state, alpha)])
+        assert (sim.flux_events[(state, beta)]
+                == expected_flux_events[(state, beta)])
 
     def test_simple_flux(self):
         state = self.center
@@ -754,9 +739,9 @@ def test_simple_flux(self):
                                initial_snapshot=init[0])
         sim.run(len(predetermined) - 1)
         expected_flux_events = {(state, interface): [(10, 2)]}
-        assert_equal(len(sim.flux_events), 1)
-        assert_equal(sim.flux_events[(state, interface)],
-                     expected_flux_events[(state, interface)])
+        assert len(sim.flux_events) == 1
+        assert (sim.flux_events[(state, interface)]
+                == expected_flux_events[(state, interface)])
 
     def test_sim_with_storage(self):
         tmpfile = data_filename("direct_sim_test.nc")
@@ -772,9 +757,9 @@ def test_sim_with_storage(self):
         sim.run(200)
         storage.close()
         read_store = paths.AnalysisStorage(tmpfile)
-        assert_equal(len(read_store.trajectories), 1)
+        assert len(read_store.trajectories) == 1
         traj = read_store.trajectories[0]
-        assert_equal(len(traj), 201)
+        assert len(traj) == 201
         read_store.close()
         os.remove(tmpfile)
 
diff --git a/openpathsampling/tests/test_range_logic.py b/openpathsampling/tests/test_range_logic.py
index 2a1a59a03..f1d0afec1 100644
--- a/openpathsampling/tests/test_range_logic.py
+++ b/openpathsampling/tests/test_range_logic.py
@@ -1,86 +1,84 @@
 
 from builtins import object
-from nose.tools import assert_equal, assert_not_equal, raises
-from nose.plugins.skip import Skip, SkipTest
 from openpathsampling.range_logic import *
 
 class TestRangeLogic(object):
     def test_range_and(self):
-        assert_equal(range_and(1, 3, 2, 4), [(2, 3)])
-        assert_equal(range_and(2, 4, 1, 3), [(2, 3)])
-        assert_equal(range_and(1, 2, 3, 4), None)
-        assert_equal(range_and(3, 4, 1, 2), None)
-        assert_equal(range_and(1, 4, 2, 3), [(2, 3)])
-        assert_equal(range_and(2, 3, 1, 4), [(2, 3)])
-        assert_equal(range_and(1, 2, 1, 2), 1)
+        assert range_and(1, 3, 2, 4) == [(2, 3)]
+        assert range_and(2, 4, 1, 3) == [(2, 3)]
+        assert range_and(1, 2, 3, 4) is None
+        assert range_and(3, 4, 1, 2) is None
+        assert range_and(1, 4, 2, 3) == [(2, 3)]
+        assert range_and(2, 3, 1, 4) == [(2, 3)]
+        assert range_and(1, 2, 1, 2) == 1
 
     def test_range_or(self):
-        assert_equal(range_or(1, 3, 2, 4), [(1, 4)])
-        assert_equal(range_or(2, 4, 1, 3), [(1, 4)])
-        assert_equal(range_or(1, 2, 3, 4), [(1, 2), (3, 4)])
-        assert_equal(range_or(3, 4, 1, 2), [(3, 4), (1, 2)])
-        assert_equal(range_or(1, 4, 2, 3), [(1, 4)])
-        assert_equal(range_or(2, 3, 1, 4), [(1, 4)])
-        assert_equal(range_or(1, 2, 1, 2), 1)
+        assert range_or(1, 3, 2, 4) == [(1, 4)]
+        assert range_or(2, 4, 1, 3) == [(1, 4)]
+        assert range_or(1, 2, 3, 4) == [(1, 2), (3, 4)]
+        assert range_or(3, 4, 1, 2) == [(3, 4), (1, 2)]
+        assert range_or(1, 4, 2, 3) == [(1, 4)]
+        assert range_or(2, 3, 1, 4) == [(1, 4)]
+        assert range_or(1, 2, 1, 2) == 1
 
 
     def test_range_sub(self):
-        assert_equal(range_sub(1, 3, 2, 4), [(1, 2)])
-        assert_equal(range_sub(2, 4, 1, 3), [(3, 4)])
-        assert_equal(range_sub(1, 2, 3, 4), 1)
-        assert_equal(range_sub(3, 4, 1, 2), 1)
-        assert_equal(range_sub(1, 4, 2, 3), [(1, 2), (3, 4)])
-        assert_equal(range_sub(2, 3, 1, 4), None)
-        assert_equal(range_sub(1, 2, 1, 2), None)
-        assert_equal(range_sub(0.1, 0.4, 0.1, 0.3), [(0.3, 0.4)])
+        assert range_sub(1, 3, 2, 4) == [(1, 2)]
+        assert range_sub(2, 4, 1, 3) == [(3, 4)]
+        assert range_sub(1, 2, 3, 4) == 1
+        assert range_sub(3, 4, 1, 2) == 1
+        assert range_sub(1, 4, 2, 3) == [(1, 2), (3, 4)]
+        assert range_sub(2, 3, 1, 4) is None
+        assert range_sub(1, 2, 1, 2) is None
+        assert range_sub(0.1, 0.4, 0.1, 0.3) == [(0.3, 0.4)]
 
 
 class TestPeriodicRangeLogic(object):
 
     def test_periodic_order(self):
         # orders without wrapping
-        assert_equal(periodic_ordering(1, 2, 3, 4), [0, 1, 2, 3])
-        assert_equal(periodic_ordering(1, 3, 2, 4), [0, 2, 1, 3])
-        assert_equal(periodic_ordering(4, 3, 2, 1), [0, 3, 2, 1])
-        assert_equal(periodic_ordering(1, 2, 1, 2), [0, 2, 1, 3])
-        assert_equal(periodic_ordering(2, 4, 1, 3), [1, 3, 0, 2])
-        assert_equal(periodic_ordering(1, 2, 4, 3), [1, 2, 0, 3])
+        assert periodic_ordering(1, 2, 3, 4) == [0, 1, 2, 3]
+        assert periodic_ordering(1, 3, 2, 4) == [0, 2, 1, 3]
+        assert periodic_ordering(4, 3, 2, 1) == [0, 3, 2, 1]
+        assert periodic_ordering(1, 2, 1, 2) == [0, 2, 1, 3]
+        assert periodic_ordering(2, 4, 1, 3) == [1, 3, 0, 2]
+        assert periodic_ordering(1, 2, 4, 3) == [1, 2, 0, 3]
 
     def test_periodic_and(self):
-        assert_equal(periodic_range_and(0.1, 0.3, 0.2, 0.4), [(0.2, 0.3)])
-        assert_equal(periodic_range_and(0.2, 0.4, 0.1, 0.3), [(0.2, 0.3)])
-        assert_equal(periodic_range_and(1, 2, 3, 4), None)
-        assert_equal(periodic_range_and(3, 4, 1, 2), None)
-        assert_equal(periodic_range_and(1, 4, 2, 3), [(2, 3)])
-        assert_equal(periodic_range_and(2, 3, 1, 4), [(2, 3)])
-        assert_equal(periodic_range_and(1, 2, 1, 2), 1)
-        assert_equal(periodic_range_and(1, 2, 2, 1), None)
-        assert_equal(periodic_range_and(2, 1, 1, 4), [(2, 4)])
-        assert_equal(periodic_range_and(0.1, 0.4, 0.3, 0.2), 
-                     [(0.1, 0.2), (0.3, 0.4)])
+        assert periodic_range_and(0.1, 0.3, 0.2, 0.4) == [(0.2, 0.3)]
+        assert periodic_range_and(0.2, 0.4, 0.1, 0.3) == [(0.2, 0.3)]
+        assert periodic_range_and(1, 2, 3, 4) is None
+        assert periodic_range_and(3, 4, 1, 2) is None
+        assert periodic_range_and(1, 4, 2, 3) == [(2, 3)]
+        assert periodic_range_and(2, 3, 1, 4) == [(2, 3)]
+        assert periodic_range_and(1, 2, 1, 2) == 1
+        assert periodic_range_and(1, 2, 2, 1) is None
+        assert periodic_range_and(2, 1, 1, 4) == [(2, 4)]
+        assert (periodic_range_and(0.1, 0.4, 0.3, 0.2)
+                == [(0.1, 0.2), (0.3, 0.4)])
 
     def test_periodic_or(self):
-        assert_equal(periodic_range_or(0.1, 0.3, 0.2, 0.4), [(0.1, 0.4)])
-        assert_equal(periodic_range_or(0.2, 0.4, 0.1, 0.3), [(0.1, 0.4)])
-        assert_equal(periodic_range_or(1, 2, 3, 4), [(1, 2), (3, 4)])
-        assert_equal(periodic_range_or(3, 4, 1, 2), [(3, 4), (1, 2)])
-        assert_equal(periodic_range_or(1, 4, 2, 3), [(1, 4)])
-        assert_equal(periodic_range_or(2, 3, 1, 4), [(1, 4)])
-        assert_equal(periodic_range_or(1, 2, 1, 2), 1)
-        assert_equal(periodic_range_or(1, 2, 2, 1), -1)
-        assert_equal(periodic_range_or(0.1, 0.4, 0.3, 0.2), -1)
-        assert_equal(periodic_range_or(2, 1, 1, 4), -1)
+        assert periodic_range_or(0.1, 0.3, 0.2, 0.4) == [(0.1, 0.4)]
+        assert periodic_range_or(0.2, 0.4, 0.1, 0.3) == [(0.1, 0.4)]
+        assert periodic_range_or(1, 2, 3, 4) == [(1, 2), (3, 4)]
+        assert periodic_range_or(3, 4, 1, 2) == [(3, 4), (1, 2)]
+        assert periodic_range_or(1, 4, 2, 3) == [(1, 4)]
+        assert periodic_range_or(2, 3, 1, 4) == [(1, 4)]
+        assert periodic_range_or(1, 2, 1, 2) == 1
+        assert periodic_range_or(1, 2, 2, 1) == -1
+        assert periodic_range_or(0.1, 0.4, 0.3, 0.2) == -1
+        assert periodic_range_or(2, 1, 1, 4) == -1
 
 
     def test_periodic_sub(self):
-        assert_equal(periodic_range_sub(0.1, 0.3, 0.2, 0.4), [(0.1, 0.2)])
-        assert_equal(periodic_range_sub(0.2, 0.4, 0.1, 0.3), [(0.3, 0.4)])
-        assert_equal(periodic_range_sub(1, 2, 3, 4), 1)
-        assert_equal(periodic_range_sub(3, 4, 1, 2), 1)
-        assert_equal(periodic_range_sub(1, 4, 2, 3), [(1, 2), (3, 4)])
-        assert_equal(periodic_range_sub(2, 3, 1, 4), None)
-        assert_equal(periodic_range_sub(1, 2, 1, 2), None)
-        assert_equal(periodic_range_sub(1, 2, 2, 1), 1)
-        assert_equal(periodic_range_sub(2, 1, 1, 4), [(4, 1)])
-        assert_equal(periodic_range_sub(0.1, 0.4, 0.3, 0.2), [(0.2, 0.3)])
-        assert_equal(periodic_range_sub(0.1, 0.4, 0.1, 0.3), [(0.3, 0.4)])
+        assert periodic_range_sub(0.1, 0.3, 0.2, 0.4) == [(0.1, 0.2)]
+        assert periodic_range_sub(0.2, 0.4, 0.1, 0.3) == [(0.3, 0.4)]
+        assert periodic_range_sub(1, 2, 3, 4) == 1
+        assert periodic_range_sub(3, 4, 1, 2) == 1
+        assert periodic_range_sub(1, 4, 2, 3) == [(1, 2), (3, 4)]
+        assert periodic_range_sub(2, 3, 1, 4) is None
+        assert periodic_range_sub(1, 2, 1, 2) is None
+        assert periodic_range_sub(1, 2, 2, 1) == 1
+        assert periodic_range_sub(2, 1, 1, 4) == [(4, 1)]
+        assert periodic_range_sub(0.1, 0.4, 0.3, 0.2) == [(0.2, 0.3)]
+        assert periodic_range_sub(0.1, 0.4, 0.1, 0.3) == [(0.3, 0.4)]
diff --git a/openpathsampling/tests/test_reactive_flux_analysis.py b/openpathsampling/tests/test_reactive_flux_analysis.py
index 007ad5ea5..60d0c7821 100644
--- a/openpathsampling/tests/test_reactive_flux_analysis.py
+++ b/openpathsampling/tests/test_reactive_flux_analysis.py
@@ -4,11 +4,8 @@
 from builtins import range
 from past.utils import old_div
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, raises,
-                        assert_almost_equal, assert_true, assert_in,
-                        assert_raises)
-from nose.plugins.skip import SkipTest
-from numpy.testing import assert_array_almost_equal
+import pytest
+from numpy.testing import assert_array_almost_equal, assert_almost_equal
 from .test_helpers import (make_1d_traj, data_filename, assert_items_equal,
                            assert_same_items)
 
@@ -138,8 +135,8 @@ def teardown_method(self):
         paths.EngineMover.default_engine = None
 
     def gradient(self, snapshot):
-        assert_equal(len(snapshot.xyz), 1)
-        assert_equal(len(snapshot.xyz[0]), 1)
+        assert len(snapshot.xyz) == 1
+        assert len(snapshot.xyz[0]) == 1
         return np.array([[1.0]])
 
     def test_analysis(self):
@@ -149,11 +146,11 @@ def test_analysis(self):
 
         # check wrong analyze_single_step() argument
         empty_list = self.analysis.analyze_single_step(3.1415)
-        assert_equal(empty_list, [])
+        assert empty_list == []
 
         # dictionary with three entries returned (mind: trajectories start from
         # x = -0.001, 0.0, 0.001).
-        assert_equal(len(self.analysis), 3)
+        assert len(self.analysis) == 3
 
         # get total and per-snapshot flux.
         flux, flux_dict = self.analysis.flux()
@@ -162,18 +159,18 @@ def test_analysis(self):
         for snapshot in flux_dict.keys():
             if snapshot.xyz[0][0] == -0.001:
                 assert_almost_equal(flux_dict[snapshot], 4.0 / 3.0)
-                assert_equal(self.analysis[snapshot]["accepted"], 1)
-                assert_equal(self.analysis[snapshot]["rejected"], 2)
+                assert self.analysis[snapshot]["accepted"] == 1
+                assert self.analysis[snapshot]["rejected"] == 2
                 assert_almost_equal(self.analysis[snapshot]["sumflux"], 4.0)
             elif snapshot.xyz[0][0] == 0.0:
                 assert_almost_equal(flux_dict[snapshot], 7.0 / 4.0)
-                assert_equal(self.analysis[snapshot]["accepted"], 2)
-                assert_equal(self.analysis[snapshot]["rejected"], 2)
+                assert self.analysis[snapshot]["accepted"] == 2
+                assert self.analysis[snapshot]["rejected"] == 2
                 assert_almost_equal(self.analysis[snapshot]["sumflux"], 7.0)
             elif snapshot.xyz[0][0] == 0.001:
                 assert_almost_equal(flux_dict[snapshot], 19.0 / 5.0)
-                assert_equal(self.analysis[snapshot]["accepted"], 3)
-                assert_equal(self.analysis[snapshot]["rejected"], 2)
+                assert self.analysis[snapshot]["accepted"] == 3
+                assert self.analysis[snapshot]["rejected"] == 2
                 assert_almost_equal(self.analysis[snapshot]["sumflux"], 19.0)
 
         # check total flux.
@@ -203,13 +200,11 @@ def test_analysis(self):
         # check failure of 3D histogram
         hash3D = lambda snap: (snap.xyz[0][0], snap.xyz[0][0], snap.xyz[0][0])
         bins3D = [-0.0015, 0.0005, 0.0015]
-        assert_raises(RuntimeError,
-                      self.analysis.flux_histogram,
-                      hash3D,
-                      bins3D)
-
-        assert_raises(NotImplementedError, self.analysis.committor)
-        assert_raises(NotImplementedError,
-                      self.analysis.committor_histogram,
-                      hash1D,
-                      bins1D)
+        with pytest.raises(RuntimeError):
+            self.analysis.flux_histogram(hash3D, bins3D)
+
+        with pytest.raises(NotImplementedError):
+            self.analysis.committor()
+
+        with pytest.raises(NotImplementedError):
+            self.analysis.committor_histogram(hash1D, bins1D)
diff --git a/openpathsampling/tests/test_resampling_statistics.py b/openpathsampling/tests/test_resampling_statistics.py
index 7a82f029a..8bac9f588 100644
--- a/openpathsampling/tests/test_resampling_statistics.py
+++ b/openpathsampling/tests/test_resampling_statistics.py
@@ -1,6 +1,5 @@
 import pandas as pd
 from pandas.testing import assert_frame_equal
-from nose.tools import assert_equal
 from .test_helpers import assert_items_equal
 import openpathsampling as paths
 
@@ -91,12 +90,12 @@ def setup_method(self):
 
     def test_default_initialization(self):
         resampler = paths.numerics.BlockResampling(self.samples)
-        assert_equal(resampler.n_total_samples, 100)
-        assert_equal(resampler.n_blocks, 20)
-        assert_equal(resampler.n_per_block, 5)
-        assert_equal(len(resampler.blocks), 20)
-        assert_equal(resampler.n_resampled, 100)
-        assert_equal(resampler.unassigned, [])
+        assert resampler.n_total_samples == 100
+        assert resampler.n_blocks == 20
+        assert resampler.n_per_block == 5
+        assert len(resampler.blocks) == 20
+        assert resampler.n_resampled == 100
+        assert resampler.unassigned == []
         assert_items_equal(resampler.blocks[0], list(range(0, 5)))
         assert_items_equal(resampler.blocks[1], list(range(5, 10)))
         assert_items_equal(resampler.blocks[10], list(range(50, 55)))
@@ -104,34 +103,34 @@ def test_default_initialization(self):
 
     def test_n_blocks_initialization(self):
         resampler = paths.numerics.BlockResampling(self.samples, n_blocks=10)
-        assert_equal(resampler.n_total_samples, 100)
-        assert_equal(resampler.n_blocks, 10)
-        assert_equal(resampler.n_per_block, 10)
-        assert_equal(len(resampler.blocks), 10)
-        assert_equal(resampler.n_resampled, 100)
-        assert_equal(resampler.unassigned, [])
+        assert resampler.n_total_samples == 100
+        assert resampler.n_blocks == 10
+        assert resampler.n_per_block == 10
+        assert len(resampler.blocks) == 10
+        assert resampler.n_resampled == 100
+        assert resampler.unassigned == []
         assert_items_equal(resampler.blocks[0], list(range(0, 10)))
         assert_items_equal(resampler.blocks[1], list(range(10, 20)))
         assert_items_equal(resampler.blocks[5], list(range(50, 60)))
         assert_items_equal(resampler.blocks[-1], list(range(90, 100)))
 
         resampler_2 = paths.numerics.BlockResampling(self.samples, n_blocks=8)
-        assert_equal(resampler_2.n_total_samples, 100)
-        assert_equal(resampler_2.n_blocks, 8)
-        assert_equal(resampler_2.n_per_block, 12)
-        assert_equal(resampler_2.n_resampled, 96)
+        assert resampler_2.n_total_samples == 100
+        assert resampler_2.n_blocks == 8
+        assert resampler_2.n_per_block == 12
+        assert resampler_2.n_resampled == 96
         assert_items_equal(resampler_2.blocks[-1], list(range(84, 96)))
         assert_items_equal(resampler_2.unassigned, list(range(96, 100)))
 
     def test_n_per_block_initialization(self):
         resampler = paths.numerics.BlockResampling(self.samples,
                                                    n_per_block=10)
-        assert_equal(resampler.n_total_samples, 100)
-        assert_equal(resampler.n_blocks, 10)
-        assert_equal(resampler.n_per_block, 10)
-        assert_equal(len(resampler.blocks), 10)
-        assert_equal(resampler.n_resampled, 100)
-        assert_equal(resampler.unassigned, [])
+        assert resampler.n_total_samples == 100
+        assert resampler.n_blocks == 10
+        assert resampler.n_per_block == 10
+        assert len(resampler.blocks) == 10
+        assert resampler.n_resampled == 100
+        assert resampler.unassigned == []
         assert_items_equal(resampler.blocks[0], list(range(0, 10)))
         assert_items_equal(resampler.blocks[1], list(range(10, 20)))
         assert_items_equal(resampler.blocks[5], list(range(50, 60)))
@@ -139,20 +138,20 @@ def test_n_per_block_initialization(self):
 
         resampler_2 = paths.numerics.BlockResampling(self.samples,
                                                      n_per_block=8)
-        assert_equal(resampler_2.n_total_samples, 100)
-        assert_equal(resampler_2.n_blocks, 12)
-        assert_equal(resampler_2.n_resampled, 96)
+        assert resampler_2.n_total_samples == 100
+        assert resampler_2.n_blocks == 12
+        assert resampler_2.n_resampled == 96
         assert_items_equal(resampler_2.blocks[-1], list(range(88, 96)))
         assert_items_equal(resampler_2.unassigned, list(range(96, 100)))
 
     def test_n_blocks_and_n_per_block_initialization(self):
         resampler = paths.numerics.BlockResampling(self.samples, n_blocks=9,
                                                    n_per_block=10)
-        assert_equal(resampler.n_total_samples, 100)
-        assert_equal(resampler.n_blocks, 9)
-        assert_equal(resampler.n_per_block, 10)
-        assert_equal(len(resampler.blocks), 9)
-        assert_equal(resampler.n_resampled, 90)
+        assert resampler.n_total_samples == 100
+        assert resampler.n_blocks == 9
+        assert resampler.n_per_block == 10
+        assert len(resampler.blocks) == 9
+        assert resampler.n_resampled == 90
         assert_items_equal(resampler.unassigned, list(range(90, 100)))
         assert_items_equal(resampler.blocks[0], list(range(0, 10)))
         assert_items_equal(resampler.blocks[1], list(range(10, 20)))
diff --git a/openpathsampling/tests/test_sample.py b/openpathsampling/tests/test_sample.py
index 21a4c4c56..5b98e4f0a 100644
--- a/openpathsampling/tests/test_sample.py
+++ b/openpathsampling/tests/test_sample.py
@@ -4,8 +4,7 @@
 
 from builtins import range
 from builtins import object
-from nose.plugins.skip import SkipTest
-from nose.tools import (assert_equal, raises, assert_true, assert_false)
+import pytest
 from .test_helpers import assert_items_equal, assert_same_items
 
 from openpathsampling.engines.trajectory import Trajectory
@@ -30,8 +29,7 @@ def setup_method(self):
 
     def test_equality(self):
         testset2 = SampleSet([self.s0A, self.s1A, self.s2B])
-        assert_true(self.testset == testset2)
-        assert_false(self.testset != testset2)
+        assert self.testset == testset2
 
     def test_initialization(self):
         self.testset.consistency_check()
@@ -39,24 +37,24 @@ def test_initialization(self):
     def test_iter(self):
         samps = [self.s0A, self.s1A, self.s2B]
         for samp in self.testset:
-            assert_equal(samp in samps, True)
+            assert samp in samps
 
     def test_contains(self):
         samps = [self.s0A, self.s1A, self.s2B]
         for samp in samps:
-            assert_equal(samp in self.testset, True)
+            assert samp in self.testset
 
     def test_len(self):
-        assert_equal(len(self.testset), 3)
+        assert len(self.testset) == 3
 
     def test_getitem_ensemble(self):
-        assert_equal(self.testset[self.ensB], self.s2B)
+        assert self.testset[self.ensB] == self.s2B
         # TODO: add test that we pick at random for ensA
 
     def test_getitem_replica(self):
-        assert_equal(self.testset[0], self.s0A)
-        assert_equal(self.testset[1], self.s1A)
-        assert_equal(self.testset[2], self.s2B)
+        assert self.testset[0] == self.s0A
+        assert self.testset[1] == self.s1A
+        assert self.testset[2] == self.s2B
         # TODO: add test that we pick at random
 
     def test_setitem_ensemble(self):
@@ -65,14 +63,14 @@ def test_setitem_ensemble(self):
         s3C = Sample(replica=3, trajectory=traj3C, ensemble=ensC)
         self.testset[ensC] = s3C
         self.testset.consistency_check()
-        assert_equal(len(self.testset), 4)
+        assert len(self.testset) == 4
 
     def test_setitem_replace_ensemble(self):
         self.testset[self.ensB] = self.s2B_
-        assert_equal(self.s2B in self.testset, False)
-        assert_equal(self.s2B_ in self.testset, True)
-        assert_equal(self.testset[2], self.s2B_)
-        assert_equal(self.testset[self.ensB], self.s2B_)
+        assert self.s2B not in self.testset
+        assert self.s2B_ in self.testset
+        assert self.testset[2] == self.s2B_
+        assert self.testset[self.ensB] == self.s2B_
         # TODO add test that we replace at random
 
     def test_setitem_replica(self):
@@ -81,22 +79,22 @@ def test_setitem_replica(self):
         s3C = Sample(replica=3, trajectory=traj3C, ensemble=ensC)
         self.testset[3] = s3C
         self.testset.consistency_check()
-        assert_equal(len(self.testset), 4)
+        assert len(self.testset) == 4
 
     def test_setitem_replace_replica(self):
         self.testset[2] = self.s2B_
-        assert_equal(self.s2B in self.testset, False)
-        assert_equal(self.s2B_ in self.testset, True)
-        assert_equal(self.testset[2], self.s2B_)
+        assert self.s2B not in self.testset
+        assert self.s2B_ in self.testset
+        assert self.testset[2] == self.s2B_
         # TODO add test that we replace at random
 
-    @raises(SampleKeyError)
     def test_illegal_assign_ensemble(self):
-        self.testset[self.ensA] = self.s2B_
+        with pytest.raises(SampleKeyError):
+            self.testset[self.ensA] = self.s2B_
 
-    @raises(SampleKeyError)
     def test_illegal_assign_replica(self):
-        self.testset[0] = self.s2B_
+        with pytest.raises(SampleKeyError):
+            self.testset[0] = self.s2B_
 
     def test_setitem_itemexists_ensemble(self):
         # exact sample is already there
@@ -106,7 +104,7 @@ def test_setitem_itemexists_ensemble(self):
         for i in range(100):
             self.testset[self.ensA] = self.s0A
             self.testset.consistency_check()
-            assert_equal(len(self.testset), 3)
+            assert len(self.testset) == 3
             assert_items_equal(self.testset, testset2)
 
     def test_setitem_itemexists_replica(self):
@@ -114,14 +112,14 @@ def test_setitem_itemexists_replica(self):
         testset2 = SampleSet([self.s0A, self.s1A, self.s2B, self.s2B_])
         testset[2] = self.s2B
         testset.consistency_check()
-        assert_equal(len(testset), 4)
+        assert len(testset) == 4
         assert_items_equal(testset, testset2)
 
     def test_additem(self):
         testset2 = SampleSet([self.s0A, self.s1A, self.s2B, self.s2B_])
         self.testset.append(self.s2B_)
-        assert_equal(self.s2B_ in self.testset, True)
-        assert_equal(len(self.testset), 4)
+        assert self.s2B_ in self.testset
+        assert len(self.testset) == 4
         self.testset.consistency_check()
         assert_items_equal(self.testset, testset2)
 
@@ -130,41 +128,41 @@ def test_additem_itemexists(self):
         testset2 = SampleSet([self.s0A, self.s1A, self.s2B])
         self.testset.append(self.s2B)
         self.testset.consistency_check()
-        assert_equal(len(self.testset), 3)
+        assert len(self.testset) == 3
         assert_items_equal(self.testset, testset2)
 
     def test_del_sample(self):
         del self.testset[self.s2B]
-        assert_equal(len(self.testset), 2)
-        assert_equal(self.ensB in list(self.testset.ensemble_dict.keys()), False)
-        assert_equal(self.ensA in list(self.testset.ensemble_dict.keys()), True)
-        assert_equal(2 in list(self.testset.replica_dict.keys()), False)
-        assert_equal(0 in list(self.testset.replica_dict.keys()), True)
+        assert len(self.testset) == 2
+        assert self.ensB not in list(self.testset.ensemble_dict.keys())
+        assert self.ensA in list(self.testset.ensemble_dict.keys())
+        assert 2 not in list(self.testset.replica_dict.keys())
+        assert 0 in list(self.testset.replica_dict.keys())
 
     def test_del_ensemble(self):
-        raise SkipTest
+        pytest.skip()
 
     def test_del_replica(self):
-        raise SkipTest
+        pytest.skip()
 
     def test_apply_samples(self):
-        raise SkipTest
+        pytest.skip()
 
     def test_extend(self):
         testset = SampleSet([self.s0A])
         testset.extend([self.s1A])
-        assert_equal(len(testset), 2)
-        assert_equal(self.s1A in testset, True)
+        assert len(testset) == 2
+        assert self.s1A in testset
         testset.consistency_check()
 
         testset.extend(SampleSet([self.s2B]))
-        assert_equal(len(testset), 3)
-        assert_equal(self.s2B in testset, True)
+        assert len(testset) == 3
+        assert self.s2B in testset
         testset.consistency_check()
 
         testset.extend(self.s2B_)
-        assert_equal(len(testset), 4)
-        assert_equal(self.s2B_ in testset, True)
+        assert len(testset) == 4
+        assert self.s2B_ in testset
         testset.consistency_check()
 
     def test_replica_list(self):
@@ -186,33 +184,33 @@ def test_all_from_replica(self):
         self.testset.append(self.s2B_)
         assert_items_equal(self.testset.all_from_replica(2), [self.s2B, self.s2B_])
 
-    @raises(AssertionError)
     def test_consistency_fail_size_ensdict(self):
         del self.testset.ensemble_dict[self.ensB]
-        self.testset.consistency_check()
+        with pytest.raises(AssertionError):
+            self.testset.consistency_check()
 
-    @raises(AssertionError)
     def test_consistency_fail_size_repdict(self):
         del self.testset.replica_dict[0]
-        self.testset.consistency_check()
+        with pytest.raises(AssertionError):
+            self.testset.consistency_check()
 
     def test_consistency_fail_sample_in_ensdict(self):
-        raise SkipTest
+        pytest.skip()
 
     def test_consistency_fail_sample_in_repdict(self):
-        raise SkipTest
+        pytest.skip()
 
     def test_consistency_fail_duplicate_samples(self):
-        raise SkipTest
+        pytest.skip()
 
     def test_sanity(self):
         self.testset.sanity_check()
 
-    @raises(AssertionError)
     def test_sanity_insane(self):
         traj0A = self.s0A.trajectory
         ensB = self.s2B.ensemble
         bad_samp = Sample(replica=0, trajectory=traj0A, ensemble=ensB)
         testset = SampleSet([bad_samp])
-        testset.sanity_check()
+        with pytest.raises(AssertionError):
+            testset.sanity_check()
 
diff --git a/openpathsampling/tests/test_snapshot.py b/openpathsampling/tests/test_snapshot.py
index 98fb1b2b8..b641bb9b7 100644
--- a/openpathsampling/tests/test_snapshot.py
+++ b/openpathsampling/tests/test_snapshot.py
@@ -5,9 +5,6 @@
 import pytest
 
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, assert_is, raises,
-                        assert_true)
-from nose.plugins.skip import Skip, SkipTest
 from numpy.testing import assert_allclose
 from .test_helpers import CallIdentity, raises_with_message_like, assert_close_unit
 
@@ -58,9 +55,9 @@ def test_copy_none(self):
                                     velocities=np.array([[0.0, 0.0, 0.0],
                                                          [0.0, 0.0, 0.0]]))
         new_snap = snap.copy()
-        assert_true(new_snap is not snap)
-        assert_true(new_snap.coordinates is not snap.coordinates)
+        assert new_snap is not snap
+        assert new_snap.coordinates is not snap.coordinates
         assert_allclose(new_snap.coordinates, snap.coordinates)
-        assert_true(new_snap.box_vectors is snap.box_vectors)
-        assert_true(new_snap.box_vectors is None)
-        assert_true(new_snap.engine is snap.engine)
+        assert new_snap.box_vectors is snap.box_vectors
+        assert new_snap.box_vectors is None
+        assert new_snap.engine is snap.engine
diff --git a/openpathsampling/tests/test_storage.py b/openpathsampling/tests/test_storage.py
index 1c1ebbf01..9c0819704 100644
--- a/openpathsampling/tests/test_storage.py
+++ b/openpathsampling/tests/test_storage.py
@@ -10,8 +10,6 @@
 
 import pytest
 
-from nose.tools import (assert_equal)
-
 import openpathsampling as paths
 
 import openpathsampling.engines.openmm as peng
@@ -22,13 +20,12 @@
 from .test_helpers import (data_filename, md, compare_snapshot)
 
 import numpy as np
-from nose.plugins.skip import SkipTest
 
 
 class TestStorage(object):
     def setup_method(self):
         if not md:
-            raise SkipTest("mdtraj not installed")
+            pytest.skip("mdtraj not installed")
         self.mdtraj = md.load(data_filename("ala_small_traj.pdb"))
         _ = pytest.importorskip('simtk.unit')
         self.traj = peng.trajectory_from_mdtraj(
@@ -68,7 +65,7 @@ def test_create_storage(self):
         store.close()
 
     def test_stored_topology(self):
-        raise SkipTest
+        pytest.skip()
         store = Storage(
             filename=self.filename,
             mode='w')
@@ -80,10 +77,8 @@ def test_stored_topology(self):
         # check if path topologies have the same JSON string
         # this also tests the simplifier for topologies
 
-        assert_equal(
-            self.simplifier.to_json(self.template_snapshot.topology),
-            self.simplifier.to_json(loaded_topology)
-        )
+        assert (self.simplifier.to_json(self.template_snapshot.topology)
+                == self.simplifier.to_json(loaded_topology))
 
         store.close()
 
diff --git a/openpathsampling/tests/test_tis_analysis.py b/openpathsampling/tests/test_tis_analysis.py
index 878937cf3..1667b3ba7 100644
--- a/openpathsampling/tests/test_tis_analysis.py
+++ b/openpathsampling/tests/test_tis_analysis.py
@@ -1,7 +1,7 @@
 import itertools
 import random
 import pytest
-from nose.tools import assert_equal, assert_almost_equal, raises
+from numpy.testing import assert_almost_equal
 from .test_helpers import (make_1d_traj, MoverWithSignature, RandomMDEngine,
                            assert_frame_equal, assert_items_equal)
 
@@ -36,10 +36,10 @@ def make_tis_traj_fixed_steps(n_steps, step_size=0.1, reverse=False):
 class TestMultiEnsembleSamplingAnalyzer(object):
     # this only has to check the error generation; everything else gets
     # covered by tests of subclasses
-    @raises(RuntimeError)
     def test_no_ensembles(self):
         histogrammer = MultiEnsembleSamplingAnalyzer()
-        histogrammer.calculate([])
+        with pytest.raises(RuntimeError):
+            histogrammer.calculate([])
 
 
 class TISAnalysisTester(object):
@@ -181,23 +181,19 @@ def _check_network_results(self, network, weighted_trajs):
                    (2, 0): 0, (2, 1): 0, (2, 2): 2, (2, 3): 2}
 
         for ((ens, traj), result) in results.items():
-            assert_equal(
-                weighted_trajs[ensembles_AB[ens]][self.trajs_AB[traj]],
-                result
-            )
-            assert_equal(
-                weighted_trajs[ensembles_BA[ens]][self.trajs_BA[traj]],
-                result
-            )
+            assert (weighted_trajs[ensembles_AB[ens]][self.trajs_AB[traj]]
+                    == result)
+            assert (weighted_trajs[ensembles_BA[ens]][self.trajs_BA[traj]]
+                    == result)
 
     def test_steps_to_weighted_trajectories(self):
-        assert_equal(len(self.mistis_weighted_trajectories),
-                     len(self.mistis.sampling_ensembles))
+        assert (len(self.mistis_weighted_trajectories)
+                == len(self.mistis.sampling_ensembles))
         self._check_network_results(self.mistis,
                                     self.mistis_weighted_trajectories)
 
-        assert_equal(len(self.mstis_weighted_trajectories),
-                     len(self.mstis.sampling_ensembles))
+        assert (len(self.mstis_weighted_trajectories)
+                == len(self.mstis.sampling_ensembles))
         self._check_network_results(self.mstis,
                                     self.mstis_weighted_trajectories)
 
@@ -249,9 +245,9 @@ def test_flux_matrix_pd_None(self):
         for idx in self.indices:
             assert_almost_equal(series[idx], self.expected_series[idx])
 
-    @raises(KeyError)
     def test_flux_matrix_pd_unknown_str(self):
-        flux_matrix_pd(self.fluxes, sort_method="foo")
+        with pytest.raises(KeyError):
+            flux_matrix_pd(self.fluxes, sort_method="foo")
 
 
 class TestDictFlux(TISAnalysisTester):
@@ -271,40 +267,33 @@ def setup_method(self):
         self.flux_method = DictFlux(self.flux_dict)
 
     def test_calculate(self):
-        assert_equal(self.flux_method.calculate(self.mistis_steps),
-                     self.flux_dict)
+        assert self.flux_method.calculate(self.mistis_steps) == self.flux_dict
 
     def test_from_weighted_trajectories(self):
-        assert_equal(
-            self.flux_method.from_weighted_trajectories(self.mistis_steps),
-            self.flux_dict
-        )
+        fd = self.flux_method.from_weighted_trajectories(self.mistis_steps)
+        assert fd == self.flux_dict
 
     def test_intermediates(self):
-        assert_equal(self.flux_method.intermediates(self.mistis_steps), [])
+        assert self.flux_method.intermediates(self.mistis_steps) == []
 
     def test_calculate_from_intermediates(self):
         intermediates = self.flux_method.intermediates(self.mistis_steps)
-        assert_equal(
-            self.flux_method.calculate_from_intermediates(*intermediates),
-            self.flux_dict
-        )
+        fd = self.flux_method.calculate_from_intermediates(*intermediates)
+        assert fd == self.flux_dict
 
     def test_combine_results(self):
         my_result = self.flux_method.calculate(self.mistis_steps)
         same_result = {(self.state_A, self.innermost_interface_A): 1.0,
                        (self.state_B, self.innermost_interface_B): 1.0}
-        assert_equal(
-            self.flux_method.combine_results(my_result, same_result),
-            my_result
-        )
+        res = self.flux_method.combine_results(my_result, same_result)
+        assert res == my_result
 
-    @raises(RuntimeError)
     def test_bad_combine_results(self):
         my_result = self.flux_method.calculate(self.mistis_steps)
         bad_result = {(self.state_A, self.innermost_interface_A): 2.0,
                       (self.state_B, self.innermost_interface_B): 2.0}
-        self.flux_method.combine_results(my_result, bad_result)
+        with pytest.raises(RuntimeError):
+            self.flux_method.combine_results(my_result, bad_result)
 
 
 class TestMinusMoveFlux(TISAnalysisTester):
@@ -345,8 +334,8 @@ def _make_fake_minus_steps(self, scheme, descriptions):
         minus_ensemble_to_mover = {m.minus_ensemble: m
                                    for m in scheme.movers['minus']}
 
-        assert_equal(set(minus_ensemble_to_mover.keys()),
-                     set(network.minus_ensembles))
+        assert (set(minus_ensemble_to_mover.keys())
+                == set(network.minus_ensembles))
         steps = []
         mccycle = 0
         for minus_traj in descriptions:
@@ -354,7 +343,7 @@ def _make_fake_minus_steps(self, scheme, descriptions):
                 replica = -1 - i
                 adjustment = state_adjustment[minus_ensemble.state_vol]
                 traj = make_1d_traj([adjustment(s) for s in minus_traj])
-                assert_equal(minus_ensemble(traj), True)
+                assert minus_ensemble(traj)
                 samp = paths.Sample(trajectory=traj,
                                     ensemble=minus_ensemble,
                                     replica=replica)
@@ -373,14 +362,14 @@ def _make_fake_minus_steps(self, scheme, descriptions):
                                           change=change))
 
                 mccycle += 1
-        assert_equal(len(steps), 4)
+        assert len(steps) == 4
         return steps
 
     def test_get_minus_steps(self):
         all_mistis_steps = self.mistis_steps + self.mistis_minus_steps
         mistis_minus_steps = \
             self.mistis_minus_flux._get_minus_steps(all_mistis_steps)
-        assert_equal(len(mistis_minus_steps), len(self.mistis_minus_steps))
+        assert len(mistis_minus_steps) == len(self.mistis_minus_steps)
         assert_items_equal(mistis_minus_steps, self.mistis_minus_steps)
         # this could be repeated for MSTIS, but why?
 
@@ -399,7 +388,6 @@ def test_calculate(self):
         for flux in mstis_flux.values():  # all values are the same
             assert_almost_equal(flux, expected_flux)
 
-    @raises(ValueError)
     def test_bad_network(self):
         # raises error if more than one transition shares a minus ensemble
         # (flux cannot be calculated with multiple interface set minus move)
@@ -416,7 +404,8 @@ def test_bad_network(self):
         ])
         scheme = paths.DefaultScheme(bad_mistis)
         scheme.build_move_decision_tree()
-        MinusMoveFlux(scheme)
+        with pytest.raises(ValueError):
+            MinusMoveFlux(scheme)
 
 
 class TestPathLengthHistogrammer(TISAnalysisTester):
@@ -433,15 +422,15 @@ def _check_network_results(self, network, hists):
                                                               self.state_A)
         for (key, dct) in results.items():
             hist_dct_AB = hists[ensembles_AB[key]]._histogram
-            assert_equal(dict(hist_dct_AB), dct)
+            assert dict(hist_dct_AB) == dct
             hist_dct_BA = hists[ensembles_BA[key]]._histogram
-            assert_equal(dict(hist_dct_BA), dct)
+            assert dict(hist_dct_BA) == dct
 
     def test_calculate(self):
         default_histogrammer = \
                 PathLengthHistogrammer(self.mistis.sampling_ensembles)
-        assert_equal(default_histogrammer.hist_parameters,
-                     {'bin_width': 5, 'bin_range': (0, 1000)})
+        assert (default_histogrammer.hist_parameters
+                == {'bin_width': 5, 'bin_range': (0, 1000)})
 
         mistis_histogrammer = PathLengthHistogrammer(
             ensembles=self.mistis.sampling_ensembles,
@@ -503,7 +492,6 @@ def test_calculate(self):
         mstis_BA_hists = mstis_BA_histogrammer.calculate(self.mstis_steps)
         self._check_transition_results(mstis_BA, mstis_BA_hists)
 
-    @raises(RuntimeError)
     def test_calculate_no_max_lambda(self):
         mistis_AB = self.mistis.transitions[(self.state_A, self.state_B)]
         modified_transition = paths.TISTransition(
@@ -512,10 +500,11 @@ def test_calculate_no_max_lambda(self):
             interfaces=mistis_AB.interfaces.volumes,
             orderparameter=mistis_AB.orderparameter
         )
-        FullHistogramMaxLambdas(
-            transition=modified_transition,
-            hist_parameters={'bin_width': 0.1, 'bin_range': (-0.1, 1.1)}
-        )
+        with pytest.raises(RuntimeError):
+            FullHistogramMaxLambdas(
+                transition=modified_transition,
+                hist_parameters={'bin_width': 0.1, 'bin_range': (-0.1, 1.1)}
+            )
 
 
 class TestConditionalTransitionProbability(TISAnalysisTester):
@@ -532,17 +521,17 @@ def _check_network_results(self, network, ctp_results):
             dct_AB = ctp_results[ensembles_AB[ens_num]]
             result = results[ens_num]
             if result != 0.0:
-                assert_equal(dct_AB[self.state_B], result)
+                assert dct_AB[self.state_B] == result
             if result != 1.0:
-                assert_equal(dct_AB[self.state_A], 1.0-result)
+                assert dct_AB[self.state_A] == 1.0 - result
 
         for ens_num in range(len(ensembles_BA)):
             dct_BA = ctp_results[ensembles_BA[ens_num]]
             result = results[ens_num]
             if result != 0.0:
-                assert_equal(dct_BA[self.state_A], result)
+                assert dct_BA[self.state_A] == result
             if result != 1.0:
-                assert_equal(dct_BA[self.state_B], 1.0-result)
+                assert dct_BA[self.state_B] == 1.0 - result
 
     def test_calculate(self):
         mistis_ctp_calc = ConditionalTransitionProbability(
@@ -690,46 +679,38 @@ def setup_method(self):
         )
 
     def test_iter(self):
-        assert_equal(set(pair for pair in self.mistis_transition_dict),
-                     set(pair for pair in self.mstis_transition_dict))
+        assert (set(pair for pair in self.mistis_transition_dict)
+                == set(pair for pair in self.mstis_transition_dict))
 
     def test_get_by_pair(self):
-        assert_equal(
-            self.mstis_transition_dict[(self.state_A, self.state_B)], 1
-        )
-        assert_equal(
-            self.mstis_transition_dict[(self.state_A, self.state_B)],
-            self.mistis_transition_dict[(self.state_A, self.state_B)]
-        )
-        assert_equal(
-            self.mstis_transition_dict[(self.state_B, self.state_A)], 2
-        )
-        assert_equal(
-            self.mstis_transition_dict[(self.state_B, self.state_A)],
-            self.mistis_transition_dict[(self.state_B, self.state_A)]
-        )
+        assert self.mstis_transition_dict[(self.state_A, self.state_B)] == 1
+        assert (self.mstis_transition_dict[(self.state_A, self.state_B)]
+                == self.mistis_transition_dict[(self.state_A, self.state_B)])
+        assert self.mstis_transition_dict[(self.state_B, self.state_A)] == 2
+        assert (self.mstis_transition_dict[(self.state_B, self.state_A)]
+                == self.mistis_transition_dict[(self.state_B, self.state_A)])
 
-    @raises(KeyError)
     def test_get_bad_pair(self):
-        self.mistis_transition_dict[(self.state_A, self.state_A)]
+        with pytest.raises(KeyError):
+            self.mistis_transition_dict[(self.state_A, self.state_A)]
 
     def test_get_by_transition(self):
         mistis_AB = self.mistis.transitions[(self.state_A, self.state_B)]
         mstis_AB = self.mstis.transitions[(self.state_A, self.state_B)]
-        assert_equal(self.mistis_transition_dict[mistis_AB], 1)
-        assert_equal(self.mistis_transition_dict[mistis_AB],
-                     self.mstis_transition_dict[mstis_AB])
+        assert self.mistis_transition_dict[mistis_AB] == 1
+        assert (self.mistis_transition_dict[mistis_AB]
+                == self.mstis_transition_dict[mstis_AB])
 
     def test_get_by_sampling_transition(self):
         from_A = self.mstis.from_state[self.state_A]
         from_B = self.mstis.from_state[self.state_B]
-        assert_equal(self.mstis_transition_dict[from_A], 1)
-        assert_equal(self.mstis_transition_dict[from_B], 2)
+        assert self.mstis_transition_dict[from_A] == 1
+        assert self.mstis_transition_dict[from_B] == 2
 
-    @raises(KeyError)
     def test_bad_get_sampling_transition(self):
         sampling_trans = self.mistis.sampling_transitions[0]
-        self.mistis_transition_dict[sampling_trans]
+        with pytest.raises(KeyError):
+            self.mistis_transition_dict[sampling_trans]
 
     def test_to_pandas(self):
         result = [[float("nan"), 1], [2, float("nan")]]
@@ -785,31 +766,29 @@ def setup_method(self):
     def test_bad_access_cached_results(self):
         no_results = self._make_tis_analysis(self.mistis)
         _ = self.mistis_analysis._access_cached_result('rate')
-        # use a try/except here instead of @raises so that we also test that
-        # the calculated version (previous line) works as expected
-        try:
+        with pytest.raises(AttributeError):
             no_results._access_cached_result('rate')
-        except AttributeError:
-            pass  # this is the expected test result
 
     def test_flux_matrix(self):
-        assert_equal(self.mistis_analysis.flux_matrix,
-                     {(t.stateA, t.interfaces[0]): 0.1
-                      for t in self.mistis.sampling_transitions})
-        assert_equal(self.mstis_analysis.flux_matrix,
-                     {(t.stateA, t.interfaces[0]): 0.1
-                      for t in self.mstis.sampling_transitions})
+        assert self.mistis_analysis.flux_matrix== {
+            (t.stateA, t.interfaces[0]): 0.1
+            for t in self.mistis.sampling_transitions
+        }
+        assert self.mstis_analysis.flux_matrix == {
+            (t.stateA, t.interfaces[0]): 0.1
+            for t in self.mstis.sampling_transitions
+        }
 
     def test_flux(self):
         for transition in self.mistis.sampling_transitions:
             state = transition.stateA
             innermost = transition.interfaces[0]
-            assert_equal(self.mistis_analysis.flux(state, innermost), 0.1)
+            assert self.mistis_analysis.flux(state, innermost) == 0.1
 
         for transition in self.mstis.sampling_transitions:
             state = transition.stateA
             innermost = transition.interfaces[0]
-            assert_equal(self.mstis_analysis.flux(state, innermost), 0.1)
+            assert self.mstis_analysis.flux(state, innermost) == 0.1
 
     def test_flux_through_state(self):
         flux_dict = {(t.stateA, t.interfaces[0]): 0.1
@@ -838,21 +817,21 @@ def test_flux_through_state(self):
         )
         tis.calculate(self.mistis_steps)
         trans_AB = self.mistis.transitions[(self.state_A, self.state_B)]
-        assert_equal(tis.flux(self.state_A, trans_AB.interfaces[0]), 0.1)
-        assert_equal(tis.flux(self.state_A), 0.5)
+        assert tis.flux(self.state_A, trans_AB.interfaces[0]) == 0.1
+        assert tis.flux(self.state_A) == 0.5
 
     def test_state_fluxes(self):
         for transition in self.mistis.sampling_transitions:
             state = transition.stateA
             innermost = transition.interfaces[0]
-            assert_equal(self.mistis_analysis.state_fluxes(state),
-                         {(state, innermost): 0.1})
+            assert (self.mistis_analysis.state_fluxes(state)
+                    == {(state, innermost): 0.1})
 
         for transition in self.mstis.sampling_transitions:
             state = transition.stateA
             innermost = transition.interfaces[0]
-            assert_equal(self.mstis_analysis.state_fluxes(state),
-                         {(state, innermost): 0.1})
+            assert (self.mstis_analysis.state_fluxes(state)
+                    == {(state, innermost): 0.1})
 
     def test_transition_probability_matrix(self):
         pairs = [(self.state_A, self.state_B), (self.state_B, self.state_A)]
@@ -951,23 +930,23 @@ def test_conditional_transition_probability(self):
                                        index=mistis_interfaces,
                                        columns=states)
         mistis_ctp = self.mistis_analysis.conditional_transition_probability
-        assert_equal(set(states), set(mistis_ctp.columns))
-        assert_equal(set(mistis_interfaces), set(mistis_ctp.index))
+        assert set(states) == set(mistis_ctp.columns)
+        assert set(mistis_interfaces) == set(mistis_ctp.index)
         for iface in mistis_interfaces:
             for state in states:
-                assert_equal(expected_mistis.loc[(iface, state)],
-                             mistis_ctp.loc[(iface, state)])
+                assert (expected_mistis.loc[(iface, state)]
+                        == mistis_ctp.loc[(iface, state)])
 
         expected_mstis = pd.DataFrame(data=expected_data,
                                       index=mstis_interfaces,
                                       columns=states)
         mstis_ctp = self.mstis_analysis.conditional_transition_probability
-        assert_equal(set(states), set(mstis_ctp.columns))
-        assert_equal(set(mstis_interfaces), set(mstis_ctp.index))
+        assert set(states) == set(mstis_ctp.columns)
+        assert set(mstis_interfaces) == set(mstis_ctp.index)
         for iface in mstis_interfaces:
             for state in states:
-                assert_equal(expected_mstis.loc[(iface, state)],
-                             mstis_ctp.loc[(iface, state)])
+                assert (expected_mstis.loc[(iface, state)]
+                        == mstis_ctp.loc[(iface, state)])
 
     def test_total_crossing_probability(self):
         results = {0.0: 1.0, 0.1: 0.5, 0.2: 0.25, 0.3: 0.125,
@@ -985,24 +964,24 @@ def test_total_crossing_probability(self):
             for x in results:
                 assert_almost_equal(results[x], tcp(x))
 
-    @raises(TypeError)
     def test_bad_no_flux(self):
         network = self.mistis
-        StandardTISAnalysis(
-            network=network,
-            max_lambda_calcs={t: {'bin_width': 0.1,
-                                  'bin_range': (-0.1, 1.1)}
-                              for t in network.sampling_transitions}
-        )
+        with pytest.raises(TypeError):
+            StandardTISAnalysis(
+                network=network,
+                max_lambda_calcs={t: {'bin_width': 0.1,
+                                      'bin_range': (-0.1, 1.1)}
+                                  for t in network.sampling_transitions}
+            )
 
-    @raises(RuntimeError)
     def test_bad_max_lambda_calcs(self):
         network = self.mistis
-        StandardTISAnalysis(
-            network=network,
-            flux_method=DictFlux({(t.stateA, t.interfaces[0]): 0.1
-                                  for t in network.sampling_transitions})
-        )
+        with pytest.raises(RuntimeError):
+            StandardTISAnalysis(
+                network=network,
+                flux_method=DictFlux({(t.stateA, t.interfaces[0]): 0.1
+                                      for t in network.sampling_transitions})
+            )
 
     def test_init_ensemble_histogrammer_max_lambda(self):
         network = self.mistis
@@ -1052,7 +1031,7 @@ def test_with_minus_move_flux(self):
 
             for seq in [seq_1, seq_2]:
                 traj = make_1d_traj(seq)
-                assert_equal(minus_ens(traj), True)
+                assert minus_ens(traj)
                 samp = paths.Sample(trajectory=traj,
                                     ensemble=minus_ens,
                                     replica=replica[state])
diff --git a/openpathsampling/tests/test_tools.py b/openpathsampling/tests/test_tools.py
index 8932b474e..b39e77aab 100644
--- a/openpathsampling/tests/test_tools.py
+++ b/openpathsampling/tests/test_tools.py
@@ -1,5 +1,4 @@
 import pytest
-from nose.tools import assert_equal
 from openpathsampling.tools import *
 
 import tempfile
@@ -15,42 +14,35 @@
 
 def test_pretty_print_seconds():
     # test the basics with full reporting
-    assert_equal(pretty_print_seconds(93784),
-                 "1 day 2 hours 3 minutes 4 seconds")
-    assert_equal(pretty_print_seconds(179990),
-                 "2 days 1 hour 59 minutes 50 seconds")
-    assert_equal(pretty_print_seconds(31),
-                 "31 seconds")
+    assert pretty_print_seconds(93784) == "1 day 2 hours 3 minutes 4 seconds"
+    assert (pretty_print_seconds(179990)
+            == "2 days 1 hour 59 minutes 50 seconds")
+    assert pretty_print_seconds(31) == "31 seconds"
 
     # test positive n_labels (including testing rounding)
-    assert_equal(pretty_print_seconds(93784, n_labels=2),
-                 "1 day 2 hours")
-    assert_equal(pretty_print_seconds(179990, n_labels=2),
-                 "2 days 2 hours")
-    assert_equal(pretty_print_seconds(179990, n_labels=3),
-                 "2 days 2 hours 0 minutes")
-    assert_equal(pretty_print_seconds(31, n_labels=2),
-                 "31 seconds")
+    assert pretty_print_seconds(93784, n_labels=2) == "1 day 2 hours"
+    assert pretty_print_seconds(179990, n_labels=2) == "2 days 2 hours"
+    assert (pretty_print_seconds(179990, n_labels=3)
+            == "2 days 2 hours 0 minutes")
+    assert pretty_print_seconds(31, n_labels=2) == "31 seconds"
 
     # test negative n_labels
-    assert_equal(pretty_print_seconds(93784, n_labels=-1),
-                 "1.09 days")
-    assert_equal(pretty_print_seconds(93784, n_labels=-2),
-                 "1 day 2.05 hours")
-    assert_equal(pretty_print_seconds(31, n_labels=-2),
-                 "31 seconds")
+    assert pretty_print_seconds(93784, n_labels=-1) == "1.09 days"
+    assert pretty_print_seconds(93784, n_labels=-2) == "1 day 2.05 hours"
+    assert pretty_print_seconds(31, n_labels=-2) == "31 seconds"
 
     # test separators
-    assert_equal(pretty_print_seconds(93784, separator=", "),
-                 "1 day, 2 hours, 3 minutes, 4 seconds")
+    assert (pretty_print_seconds(93784, separator=", ")
+            == "1 day, 2 hours, 3 minutes, 4 seconds")
 
 def test_progress_string():
-    assert_equal(progress_string(0, 100, 10),
-                 "Starting simulation...\nWorking on first step\n")
-    assert_equal(progress_string(1, 11, 9378.4),
-                 "Running for 2 hours 36 minutes 18 seconds - "
-                 + "9378.40 seconds per step\n"
-                 + "Estimated time remaining: 1 day 2.05 hours\n")
+    assert (progress_string(0, 100, 10)
+            == "Starting simulation...\nWorking on first step\n")
+    assert progress_string(1, 11, 9378.4) == (
+        "Running for 2 hours 36 minutes 18 seconds - "
+        + "9378.40 seconds per step\n"
+        + "Estimated time remaining: 1 day 2.05 hours\n"
+    )
 
 
 def test_ensure_file_dne():
diff --git a/openpathsampling/tests/test_toy_dynamics.py b/openpathsampling/tests/test_toy_dynamics.py
index 583ef75c9..5eab1fbf5 100644
--- a/openpathsampling/tests/test_toy_dynamics.py
+++ b/openpathsampling/tests/test_toy_dynamics.py
@@ -9,9 +9,8 @@
 from builtins import object
 import os
 
-from nose.tools import (assert_equal, assert_not_equal, assert_almost_equal)
-
-from nose.plugins.skip import SkipTest
+import pytest
+from numpy.testing import assert_almost_equal
 
 import openpathsampling as paths
 import openpathsampling.engines.toy as toy
@@ -108,7 +107,7 @@ def test_V(self):
         assert_almost_equal(linear.V(self), 2.0375)
 
     def test_dVdx(self):
-        assert_equal(linear.dVdx(self), [1.5, 0.75])
+        assert linear.dVdx(self) == [1.5, 0.75]
 
 
 class TestDoubleWell(object):
@@ -161,7 +160,7 @@ def test_kinetic_energy(self):
 
 class Test_convert_fcn(object):
     def test_convert_to_3Ndim(self):
-        raise SkipTest
+        pytest.skip()
 
         assert_equal_array_array(toy.convert_to_3Ndim([1.0, 2.0]),
                                  np.array([[1.0, 2.0, 0.0]]))
@@ -203,10 +202,10 @@ def teardown_method(self):
     def test_sanity(self):
         assert_items_equal(self.sim._mass, sys_mass)
         assert_items_equal(self.sim._minv, [old_div(1.0,m_i) for m_i in sys_mass])
-        assert_equal(self.sim.n_steps_per_frame, 10)
+        assert self.sim.n_steps_per_frame == 10
 
     def test_snapshot_timestep(self):
-        assert_equal(self.sim.snapshot_timestep, 0.02)
+        assert self.sim.snapshot_timestep == 0.02
 
     def test_snapshot_get(self):
         snapshot = self.sim.current_snapshot
@@ -239,7 +238,7 @@ def test_generate(self):
             traj = self.sim.generate(self.sim.current_snapshot, [true_func])
         except paths.engines.EngineMaxLengthError as e:
             traj = e.last_trajectory
-            assert_equal(len(traj), self.sim.n_frames_max)
+            assert len(traj) == self.sim.n_frames_max
         else:
             raise RuntimeError('Did not raise MaxLength Error')
 
@@ -250,13 +249,13 @@ def test_generate_n_frames(self):
         traj1 = self.sim.generate(self.sim.current_snapshot, [ens.can_append])
         self.sim.current_snapshot = orig
         traj2 = [orig] + self.sim.generate_n_frames(3)
-        assert_equal(len(traj1), len(traj2))
+        assert len(traj1) == len(traj2)
         for (s1, s2) in zip(traj1, traj2):
             # snapshots are not the same object
-            assert_not_equal(s1, s2)
+            assert s1 != s2
             # however, they have the same values stored in them
-            assert_equal(len(s1.coordinates), 1)
-            assert_equal(len(s1.coordinates[0]), 2)
+            assert len(s1.coordinates) == 1
+            assert len(s1.coordinates[0]) == 2
             assert_items_equal(s1.coordinates[0], s2.coordinates[0])
             assert_items_equal(s1.velocities[0], s2.velocities[0])
 
@@ -305,8 +304,8 @@ def test_momentum_update(self):
         # velocities = init_vel - pes.dVdx(init_pos)/m*dt
         #            = [0.6, 0.5] - [1.5, 0.75]/[1.5, 1.5] * 0.002
         #            = [0.598, 0.499]
-        assert_equal(self.sim.velocities[0], 0.598)
-        assert_equal(self.sim.velocities[1], 0.499)
+        assert self.sim.velocities[0] == 0.598
+        assert self.sim.velocities[1] == 0.499
 
     def test_position_update(self):
         self.sim.integ._position_update(self.sim, 0.002)
@@ -357,14 +356,14 @@ def setup_method(self):
     def test_OU_update(self):
         # we can't actually test for correct values, but we *can* test that
         # some things *don't* happen
-        assert_equal(self.sim.velocities[0], init_vel[0])
-        assert_equal(self.sim.velocities[1], init_vel[1])
+        assert self.sim.velocities[0] == init_vel[0]
+        assert self.sim.velocities[1] == init_vel[1]
         self.sim.integ._OU_update(self.sim, 0.002)
-        assert_not_equal(self.sim.velocities[0], init_vel[0])
-        assert_not_equal(self.sim.velocities[1], init_vel[1])
+        assert self.sim.velocities[0] != init_vel[0]
+        assert self.sim.velocities[1] != init_vel[1]
         # tests that the same random number wasn't used for both:
-        assert_not_equal(self.sim.velocities[0] - init_vel[0],
-                         self.sim.velocities[1] - init_vel[1])
+        assert (self.sim.velocities[0] - init_vel[0]
+                != self.sim.velocities[1] - init_vel[1])
 
     def test_step(self):
         self.sim.generate_next_frame()
diff --git a/openpathsampling/tests/test_toy_features.py b/openpathsampling/tests/test_toy_features.py
index 7f952dda6..2e8f1afb5 100644
--- a/openpathsampling/tests/test_toy_features.py
+++ b/openpathsampling/tests/test_toy_features.py
@@ -2,8 +2,7 @@
 import openpathsampling.engines.toy as toys
 import numpy as np
 
-from nose.tools import assert_equal, assert_almost_equal
-from nose.plugins.skip import SkipTest
+from numpy.testing import assert_almost_equal
 import logging
 
 logging.getLogger('openpathsampling.initialization').setLevel(logging.CRITICAL)
@@ -37,8 +36,8 @@ def setup_method(self):
                                      engine=engine_6D)
 
     def test_n_degrees_of_freedom(self):
-        assert_equal(self.snap_2D.n_degrees_of_freedom, 2)
-        assert_equal(self.snap_6D.n_degrees_of_freedom, 6)
+        assert self.snap_2D.n_degrees_of_freedom == 2
+        assert self.snap_6D.n_degrees_of_freedom == 6
 
     def test_instantaneous_temperature(self):
         # KE = 0.5 * (1.0*2.0**2 + 1.0*4.0**2) = 10.0
diff --git a/openpathsampling/tests/test_trajectory.py b/openpathsampling/tests/test_trajectory.py
index 5c32c527b..86f7f9b63 100644
--- a/openpathsampling/tests/test_trajectory.py
+++ b/openpathsampling/tests/test_trajectory.py
@@ -2,14 +2,9 @@
 from builtins import object
 import logging
 
-from nose.tools import (
-    assert_equal, assert_not_equal, raises
-)
-from nose.plugins.skip import SkipTest
 from .test_helpers import (CallIdentity, prepend_exception_message,
                            make_1d_traj, assert_items_equal)
 
-
 import openpathsampling as paths
 from .test_helpers import make_1d_traj
 
@@ -119,22 +114,22 @@ def test_subtrajectory_indices(self):
         subtrajectoriesABA = ensemble_ABA.split(trajectory)
 
         # make sure we have the trajectories we expect
-        assert_equal(len(subtrajectoriesA), 3)
-        assert_equal(len(subtrajectoriesB), 2)
-        assert_equal(len(subtrajectoriesABA), 1)
+        assert len(subtrajectoriesA) == 3
+        assert len(subtrajectoriesB) == 2
+        assert len(subtrajectoriesABA) == 1
         # the following assertions check that the subtrajectories are the
         # ones that we expect; the numbers here are linked to the indices
         # we'll test next
-        assert_equal(subtrajectoriesA[0], trajectory[0:2])
-        assert_equal(subtrajectoriesA[1], trajectory[3:4])
-        assert_equal(subtrajectoriesA[2], trajectory[11:13])
-        assert_equal(subtrajectoriesB[0], trajectory[5:7])
-        assert_equal(subtrajectoriesB[1], trajectory[8:9])
-        assert_equal(subtrajectoriesABA[0], trajectory[3:12])
+        assert subtrajectoriesA[0] == trajectory[0:2]
+        assert subtrajectoriesA[1] == trajectory[3:4]
+        assert subtrajectoriesA[2] == trajectory[11:13]
+        assert subtrajectoriesB[0] == trajectory[5:7]
+        assert subtrajectoriesB[1] == trajectory[8:9]
+        assert subtrajectoriesABA[0] == trajectory[3:12]
         # now we run the subtrajectory_indices function and test it
         indicesA = trajectory.subtrajectory_indices(subtrajectoriesA)
         indicesB = trajectory.subtrajectory_indices(subtrajectoriesB)
         indicesABA = trajectory.subtrajectory_indices(subtrajectoriesABA)
-        assert_equal(indicesA, [[0, 1], [3], [11, 12]])
-        assert_equal(indicesB, [[5, 6], [8]])
-        assert_equal(indicesABA, [[3, 4, 5, 6, 7, 8, 9, 10, 11]])
+        assert indicesA == [[0, 1], [3], [11, 12]]
+        assert indicesB == [[5, 6], [8]]
+        assert indicesABA == [[3, 4, 5, 6, 7, 8, 9, 10, 11]]
diff --git a/openpathsampling/tests/test_trajectory_transition_analysis.py b/openpathsampling/tests/test_trajectory_transition_analysis.py
index b573f1140..ebaf82a4d 100644
--- a/openpathsampling/tests/test_trajectory_transition_analysis.py
+++ b/openpathsampling/tests/test_trajectory_transition_analysis.py
@@ -3,9 +3,9 @@
 from builtins import zip
 from past.utils import old_div
 from builtins import object
-from nose.tools import (assert_equal, assert_not_equal, raises,
-                        assert_almost_equal)
-from nose.plugins.skip import SkipTest
+
+import pytest
+from numpy.testing import assert_almost_equal
 from .test_helpers import make_1d_traj
 
 import openpathsampling as paths
@@ -36,20 +36,20 @@ def setup_method(self):
                                                           dt=0.5)
 
     def test_list_behavior(self):
-        assert_equal(len(self.container), 3)
-        assert_equal(self.container[0], self.segments[0])
+        assert len(self.container) == 3
+        assert self.container[0] == self.segments[0]
         for (truth, beauty) in zip(self.container, self.segments):
-            assert_equal(truth, beauty)
-        assert_equal(self.segments[0] in self.container, True)
+            assert truth == beauty
+        assert self.segments[0] in self.container
 
-    @raises(TypeError)
     def test_segments_setitem_fails(self):
-        self.container[0] = self.trajectory
+        with pytest.raises(TypeError):
+            self.container[0] = self.trajectory
 
     def test_segments(self):
-        assert_equal(self.container[0], self.trajectory[0:2])
-        assert_equal(self.container[1], self.trajectory[6:8])
-        assert_equal(self.container[2], self.trajectory[9:12])
+        assert self.container[0] == self.trajectory[0:2]
+        assert self.container[1] == self.trajectory[6:8]
+        assert self.container[2] == self.trajectory[9:12]
 
     def test_from_trajectory_and_indices(self):
         container = \
@@ -58,39 +58,39 @@ def test_from_trajectory_and_indices(self):
                 indices=[(0, 2), (6, 8), (9, 12)],
                 dt=0.5
             )
-        assert_equal(container[0], self.trajectory[0:2])
-        assert_equal(container[1], self.trajectory[6:8])
-        assert_equal(container[2], self.trajectory[9:12])
+        assert container[0] == self.trajectory[0:2]
+        assert container[1] == self.trajectory[6:8]
+        assert container[2] == self.trajectory[9:12]
 
     def test_n_frames(self):
-        assert_equal(self.container.n_frames.tolist(), [2, 2, 3])
+        assert self.container.n_frames.tolist() == [2, 2, 3]
 
     def test_times(self):
-        assert_equal(self.container.times.tolist(), [1.0, 1.0, 1.5])
+        assert self.container.times.tolist() == [1.0, 1.0, 1.5]
 
-    @raises(RuntimeError)
     def test_times_without_dt(self):
         bad_container = paths.TrajectorySegmentContainer(self.segments)
-        bad_container.times
+        with pytest.raises(RuntimeError):
+            bad_container.times
 
     def test_add(self):
         ens_B = paths.AllInXEnsemble(self.vol3)
         segs_B = ens_B.split(self.trajectory)
         container_B = paths.TrajectorySegmentContainer(segs_B, dt=0.5)
-        assert_equal(len(container_B), 2)
+        assert len(container_B) == 2
         test_container = self.container + container_B
-        assert_equal(len(test_container), 5)
+        assert len(test_container) == 5
         for seg in self.container:
-            assert_equal(seg in test_container, True)
+            assert seg in test_container
         for seg in container_B:
-            assert_equal(seg in test_container, True)
+            assert seg in test_container
 
-    @raises(RuntimeError)
     def test_add_different_dt(self):
         ens_B = paths.AllInXEnsemble(self.vol3)
         segs_B = ens_B.split(self.trajectory)
         container_B = paths.TrajectorySegmentContainer(segs_B)
-        test_container = self.container + container_B
+        with pytest.raises(RuntimeError):
+            test_container = self.container + container_B
 
     def test_iadd(self):
         ens_B = paths.AllInXEnsemble(self.vol3)
@@ -98,8 +98,8 @@ def test_iadd(self):
         container_B = paths.TrajectorySegmentContainer(segs_B)
         container_B_id = id(container_B)
         container_B += self.container
-        assert_equal(len(container_B), 5)
-        assert_equal(container_B_id, id(container_B))
+        assert len(container_B) == 5
+        assert container_B_id == id(container_B)
 
 
 class TestTrajectoryTransitionAnalysis(object):
@@ -141,18 +141,18 @@ def _make_traj(self, traj_str):
     def test_analyze_continuous_time(self):
         resultA = self.analyzer.analyze_continuous_time(self.trajectory,
                                                         self.stateA)
-        assert_equal(resultA.n_frames.tolist(), [3, 1, 1, 1, 1, 1, 1])
+        assert resultA.n_frames.tolist() == [3, 1, 1, 1, 1, 1, 1]
         resultB = self.analyzer.analyze_continuous_time(self.trajectory,
                                                         self.stateB)
-        assert_equal(resultB.n_frames.tolist(), [1, 1, 1, 5])
+        assert resultB.n_frames.tolist() == [1, 1, 1, 5]
         assert_almost_equal(resultA.times.mean(), 9.0/7.0*0.1)
         assert_almost_equal(resultB.times.mean(), 8.0/4.0*0.1)
 
     def test_analyze_lifetime(self):
         resA = self.analyzer.analyze_lifetime(self.trajectory, self.stateA)
         resB = self.analyzer.analyze_lifetime(self.trajectory, self.stateB)
-        assert_equal(resA.n_frames.tolist(), [3, 1, 2])  # A->B
-        assert_equal(resB.n_frames.tolist(), [2, 1, 1, 11])  # B->A
+        assert resA.n_frames.tolist() == [3, 1, 2]  # A->B
+        assert resB.n_frames.tolist() == [2, 1, 1, 11]  # B->A
         assert_almost_equal(resA.times.mean(), 6.0/3.0*0.1)
         assert_almost_equal(resB.times.mean(), 15.0/4.0*0.1)
 
@@ -163,10 +163,10 @@ def test_analyze_transition_duration(self):
         resBA = self.analyzer.analyze_transition_duration(self.trajectory,
                                                           self.stateB,
                                                           self.stateA)
-        assert_equal(resAB.n_frames.tolist(), [2, 0, 0, 1])
-        assert_equal(resBA.n_frames.tolist(), [1, 0, 0, 6])
-        assert_equal(resAB.times.mean(), 3.0/4.0*0.1)
-        assert_equal(resBA.times.mean(), 7.0/4.0*0.1)
+        assert resAB.n_frames.tolist() == [2, 0, 0, 1]
+        assert resBA.n_frames.tolist() == [1, 0, 0, 6]
+        assert resAB.times.mean() == 3.0/4.0*0.1
+        assert resBA.times.mean() == 7.0/4.0*0.1
 
     def test_analyze_flux(self):
         # A: [{out: 1, in: 1}
@@ -178,34 +178,32 @@ def test_analyze_flux(self):
         core_traj = self._make_traj(flux_core_test_str)
         flux_segs_A = self.analyzer.analyze_flux(core_traj, self.stateA)
         # flux_segs_A = self.analyzer.flux_segments[self.stateA]
-        assert_equal(len(flux_segs_A['in']), 4)
-        assert_equal(flux_segs_A['in'][0], core_traj[2:3])
-        assert_equal(flux_segs_A['in'][1], core_traj[4:7])
-        assert_equal(flux_segs_A['in'][2], core_traj[9:10])
-        assert_equal(flux_segs_A['in'][3], core_traj[13:15])
-
-        assert_equal(len(flux_segs_A['out']), 4)
-        assert_equal(flux_segs_A['out'][0], core_traj[1:2])
-        assert_equal(flux_segs_A['out'][1], core_traj[3:4])
-        assert_equal(flux_segs_A['out'][2], core_traj[7:9])
-        assert_equal(flux_segs_A['out'][3], core_traj[15:17])
+        assert len(flux_segs_A['in']) == 4
+        assert flux_segs_A['in'][0] == core_traj[2:3]
+        assert flux_segs_A['in'][1] == core_traj[4:7]
+        assert flux_segs_A['in'][2] == core_traj[9:10]
+        assert flux_segs_A['in'][3] == core_traj[13:15]
+
+        assert len(flux_segs_A['out']) == 4
+        assert flux_segs_A['out'][0] == core_traj[1:2]
+        assert flux_segs_A['out'][1] == core_traj[3:4]
+        assert flux_segs_A['out'][2] == core_traj[7:9]
+        assert flux_segs_A['out'][3] == core_traj[15:17]
 
     def test_analyze_flux_with_interface(self):
         flux_iface_traj_str = "aixixaiaxiixiaxaixbxbixiaaixiai"
         # frame numbers        0    5    0    5    0    5    0
         # in (I) or out (O)      OOOIIIOOOOOIOII       IIIOO
-        assert_equal(len(flux_iface_traj_str), 31) # check I counted correctly
+        assert len(flux_iface_traj_str) == 31 # check I counted correctly
         flux_traj = self._make_traj(flux_iface_traj_str)
         self.analyzer.reset_analysis()
         flux_segs_A = self.analyzer.analyze_flux(flux_traj, self.stateA,
                                                  self.interfaceA0)
         # flux_segs_A = self.analyzer.flux_segments[self.stateA]
-        assert_equal(flux_segs_A['in'][:],
-                     [flux_traj[5:8], flux_traj[13:14], flux_traj[15:17],
-                      flux_traj[24:27]])
-        assert_equal(flux_segs_A['out'][:],
-                     [flux_traj[2:5], flux_traj[8:13], flux_traj[14:15],
-                      flux_traj[27:29]])
+        assert flux_segs_A['in'][:] == [flux_traj[5:8], flux_traj[13:14],
+                                        flux_traj[15:17], flux_traj[24:27]]
+        assert flux_segs_A['out'][:] == [flux_traj[2:5], flux_traj[8:13],
+                                         flux_traj[14:15], flux_traj[27:29]]
 
     def test_minus_flux(self):
         flux_iface_traj_str = "axxxaaaxxxa"
@@ -213,9 +211,8 @@ def test_minus_flux(self):
         self.analyzer.reset_analysis()
         flux_segs_A = self.analyzer.analyze_flux(flux_traj, self.stateA,
                                                  self.interfaceA0)
-        assert_equal(flux_segs_A['in'][:], [flux_traj[4:7]])
-        assert_equal(flux_segs_A['out'][:],
-                     [flux_traj[1:4], flux_traj[7:10]])
+        assert flux_segs_A['in'][:] == [flux_traj[4:7]]
+        assert flux_segs_A['out'][:] == [flux_traj[1:4], flux_traj[7:10]]
 
     def test_flux(self):
         flux_iface_traj_str = "aixixaiaxiixiaxaixbxbixiaaixiai"
@@ -230,14 +227,14 @@ def test_flux(self):
         assert_almost_equal(flux, old_div(1.0, (average_out + average_in)))
         self.analyzer.dt = None
 
-    @raises(RuntimeError)
     def test_flux_no_dt(self):
         analyzer = paths.TrajectoryTransitionAnalysis(self.transition)
         flux_iface_traj_str = "aixixaiaxiixiaxaixbxbixiaaixiai"
         flux_traj = self._make_traj(flux_iface_traj_str)
-        flux = analyzer.flux(trajectories=[flux_traj],
-                             state=self.stateA,
-                             interface=self.interfaceA0)
+        with pytest.raises(RuntimeError):
+            flux = analyzer.flux(trajectories=[flux_traj],
+                                 state=self.stateA,
+                                 interface=self.interfaceA0)
 
     def test_analyze(self):
         # only test that it runs -- correctness testing in the others
@@ -251,17 +248,17 @@ def test_analyze(self):
 
         self.analyzer.reset_analysis()
         self.analyzer.analyze([self.trajectory])
-        assert_equal(cont_frames[self.stateA].tolist(),
-                     self.analyzer.continuous_frames[self.stateA].tolist())
-        assert_equal(life_frames[self.stateA].tolist(),
-                     self.analyzer.lifetime_frames[self.stateA].tolist())
+        assert (cont_frames[self.stateA].tolist()
+                == self.analyzer.continuous_frames[self.stateA].tolist())
+        assert (life_frames[self.stateA].tolist()
+                == self.analyzer.lifetime_frames[self.stateA].tolist())
         A2B = (self.stateA, self.stateB)
-        assert_equal(trans_frames[A2B].tolist(),
-                     self.analyzer.transition_duration_frames[A2B].tolist())
-        assert_equal(cont_times[self.stateA].mean(),
-                     self.analyzer.continuous_times[self.stateA].mean())
-        assert_equal(life_times[self.stateA].mean(),
-                     self.analyzer.lifetimes[self.stateA].mean())
-        assert_equal(trans_times[A2B].mean(),
-                     self.analyzer.transition_duration[A2B].mean())
+        assert (trans_frames[A2B].tolist()
+                == self.analyzer.transition_duration_frames[A2B].tolist())
+        assert (cont_times[self.stateA].mean()
+                == self.analyzer.continuous_times[self.stateA].mean())
+        assert (life_times[self.stateA].mean()
+                == self.analyzer.lifetimes[self.stateA].mean())
+        assert (trans_times[A2B].mean()
+                == self.analyzer.transition_duration[A2B].mean())
 
diff --git a/openpathsampling/tests/test_transitions.py b/openpathsampling/tests/test_transitions.py
index eed653d85..5f75dcff4 100644
--- a/openpathsampling/tests/test_transitions.py
+++ b/openpathsampling/tests/test_transitions.py
@@ -1,7 +1,5 @@
 from __future__ import absolute_import
 from builtins import object
-from nose.tools import assert_equal, assert_not_equal, raises
-from nose.plugins.skip import SkipTest
 from .test_helpers import (
     CallIdentity, prepend_exception_message, make_1d_traj, data_filename,
     assert_items_equal
@@ -48,12 +46,12 @@ def _make_traj(self, string):
         return make_1d_traj(coordinates=pretraj, velocities=[1.0]*len(pretraj))
 
     def test_init(self):
-        assert_equal(len(self.transition.ensembles), 1)
-        assert_equal(self.transition.length, 4)
-        assert_equal(self.transition.ensembles[0](self.good_traj), True)
-        assert_equal(self.transition.ensembles[0](self.short_traj), False)
-        assert_equal(self.transition.ensembles[0](self.long_traj), False)
-        assert_equal(self.transition.ensembles[0](self.bad_states_traj), False)
+        assert len(self.transition.ensembles) == 1
+        assert self.transition.length == 4
+        assert self.transition.ensembles[0](self.good_traj)
+        assert not self.transition.ensembles[0](self.short_traj)
+        assert not self.transition.ensembles[0](self.long_traj)
+        assert not self.transition.ensembles[0](self.bad_states_traj)
 
     def test_storage(self):
         import os
@@ -64,12 +62,12 @@ def test_storage(self):
         storage.snapshots.save(self.good_traj[0])
 
         storage.save(self.transition)
-        assert_equal(len(storage.transitions), 1)
+        assert len(storage.transitions) == 1
         storage.sync_all()
 
         storage_r = paths.storage.AnalysisStorage(filename)
         reloaded = storage_r.transitions[0]
-        assert_equal(self.transition.ensembles[0], reloaded.ensembles[0])
+        assert self.transition.ensembles[0] == reloaded.ensembles[0]
 
         if os.path.isfile(filename):
             os.remove(filename)
@@ -106,38 +104,38 @@ def _make_traj(self, string):
 
     def test_normal_minus(self):
         minus = paths.MinusInterfaceEnsemble(self.stateA, self.stateA)
-        assert_equal(minus_sides_summary(self.traj_axaxa, minus),
-                     {"in" : [5], "out" : [4]})
-        assert_not_equal(minus_sides_summary(self.traj_axaxa, minus),
-                         {"in" : [5], "out" : [3]})
-        assert_equal(minus_sides_summary(self.traj_aixiaixia, minus),
-                     {"in" : [5], "out" : [6] })
-        assert_equal(minus_sides_summary(self.traj_aixixiaxia, minus),
-                     {"in" : [5], "out" : [10] })
+        assert (minus_sides_summary(self.traj_axaxa, minus)
+                == {"in" : [5], "out" : [4]})
+        assert (minus_sides_summary(self.traj_axaxa, minus)
+                != {"in" : [5], "out" : [3]})
+        assert (minus_sides_summary(self.traj_aixiaixia, minus)
+                == {"in" : [5], "out" : [6] })
+        assert (minus_sides_summary(self.traj_aixixiaxia, minus)
+                == {"in" : [5], "out" : [10] })
 
     def test_minus_with_interstitial(self):
         minus = paths.MinusInterfaceEnsemble(self.stateA, self.innermost)
-        assert_equal(minus_sides_summary(self.traj_axaxa, minus),
-                     {"in" : [5], "out" : [4]})
-        assert_equal(minus_sides_summary(self.traj_aixiaixia, minus),
-                     {"in" : [6], "out" : [4] })
-        assert_equal(minus_sides_summary(self.traj_aixixiaxia, minus),
-                     {"in" : [5], "out" : [8] })
+        assert (minus_sides_summary(self.traj_axaxa, minus)
+                == {"in" : [5], "out" : [4]})
+        assert (minus_sides_summary(self.traj_aixiaixia, minus)
+                == {"in" : [6], "out" : [4] })
+        assert (minus_sides_summary(self.traj_aixixiaxia, minus)
+                == {"in" : [5], "out" : [8] })
 
     def test_minus_with_multiple_excursion(self):
         minus = paths.MinusInterfaceEnsemble(self.stateA, self.stateA,
                                              n_l=4)
-        assert_equal(minus_sides_summary(self.traj_axaxaxaxa, minus),
-                     {"in" : [2, 3, 4], "out" : [1, 2, 3]})
-        assert_equal(minus_sides_summary(self.traj_aixixiaixaxiaixia, minus),
-                     {"in" : [2, 1, 3], "out" : [7, 4, 3]})
+        assert (minus_sides_summary(self.traj_axaxaxaxa, minus)
+                == {"in" : [2, 3, 4], "out" : [1, 2, 3]})
+        assert (minus_sides_summary(self.traj_aixixiaixaxiaixia, minus)
+                == {"in" : [2, 1, 3], "out" : [7, 4, 3]})
 
     def test_minus_with_interstitial_and_multiple_excursion(self):
         minus = paths.MinusInterfaceEnsemble(self.stateA, self.innermost, n_l=4)
-        assert_equal(minus_sides_summary(self.traj_axaxaxaxa, minus),
-                     {"in" : [2, 3, 4], "out" : [1, 2, 3]})
-        assert_equal(minus_sides_summary(self.traj_aixixiaixaxiaixia, minus),
-                     {"in" : [4, 1, 5], "out" : [6, 2, 3]})
-        assert_not_equal(minus_sides_summary(self.traj_aixixiaixaxiaixia, minus),
-                     {"in" : [1, 4, 5], "out" : [6, 2, 3]})
+        assert (minus_sides_summary(self.traj_axaxaxaxa, minus)
+                == {"in" : [2, 3, 4], "out" : [1, 2, 3]})
+        assert (minus_sides_summary(self.traj_aixixiaixaxiaixia, minus)
+                == {"in" : [4, 1, 5], "out" : [6, 2, 3]})
+        assert (minus_sides_summary(self.traj_aixixiaixaxiaixia, minus)
+                != {"in" : [1, 4, 5], "out" : [6, 2, 3]})
 
diff --git a/openpathsampling/tests/test_wham.py b/openpathsampling/tests/test_wham.py
index 1ed2a6212..aba2ae602 100644
--- a/openpathsampling/tests/test_wham.py
+++ b/openpathsampling/tests/test_wham.py
@@ -1,10 +1,8 @@
 from __future__ import division
 from __future__ import absolute_import
 from builtins import object
+import pytest
 from past.utils import old_div
-from nose.tools import (assert_equal, assert_not_equal, raises,
-                        assert_almost_equal)
-from nose.plugins.skip import SkipTest
 from .test_helpers import assert_items_almost_equal, assert_items_equal
 
 import pandas as pd
@@ -161,7 +159,6 @@ def test_wham_bam_histogram(self):
         wham_hist = self.wham.wham_bam_histogram(self.input_df)
         np.testing.assert_allclose(wham_hist.values, self.exact)
 
-    @raises(RuntimeError)
     def test_check_overlaps_no_overlap_with_first(self):
         bad_data = np.array([[1.0, 0.0, 0.0],
                              [0.5, 0.0, 0.0],
@@ -171,9 +168,9 @@ def test_check_overlaps_no_overlap_with_first(self):
         bad_df = pd.DataFrame(data=bad_data,
                               index=self.index[0:5],
                               columns=self.columns)
-        self.wham.check_cleaned_overlaps(bad_df)
+        with pytest.raises(RuntimeError):
+            self.wham.check_cleaned_overlaps(bad_df)
 
-    @raises(RuntimeError)
     def test_check_overlaps_no_overlap_with_final(self):
         bad_data = np.array([[1.0, 0.0, 0.0],
                              [0.5, 0.0, 0.0],
@@ -184,9 +181,9 @@ def test_check_overlaps_no_overlap_with_final(self):
         bad_df = pd.DataFrame(data=bad_data,
                               index=self.index[0:6],
                               columns=self.columns)
-        self.wham.check_cleaned_overlaps(bad_df)
+        with pytest.raises(RuntimeError):
+            self.wham.check_cleaned_overlaps(bad_df)
 
-    @raises(RuntimeError)
     def test_check_overlaps_no_overlap_in_middle(self):
         bad_data = np.array([[1.0, 0.0, 0.0, 0.0],
                              [0.5, 1.0, 0.0, 0.0],
@@ -197,4 +194,5 @@ def test_check_overlaps_no_overlap_in_middle(self):
         bad_df = pd.DataFrame(data=bad_data,
                               index=self.index[0:6],
                               columns=self.columns + ['Interface 4'])
-        self.wham.check_cleaned_overlaps(bad_df)
+        with pytest.raises(RuntimeError):
+            self.wham.check_cleaned_overlaps(bad_df)