Repository: dfki-ric/movement_primitives (language: python)

Issue:
Not able to run the tests
I am trying to run the tests. I have installed the repo using:

1. Cloning the repo
2. Running python3 -m pip install -e ".[all]" 

I also install tests dependencies using:

1. python3 -m pip install -e ".[test]"


When I run the test command highlighted in the README, I get the following error: 


gautamsharma@MacBook-Pro-3 movement_primitives % python3 -m nose test
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/opt/homebrew/lib/python3.11/site-packages/nose/__main__.py", line 8, in <module>
    run_exit()
  File "/opt/homebrew/lib/python3.11/site-packages/nose/core.py", line 118, in __init__
    unittest.TestProgram.__init__(
  File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/unittest/main.py", line 101, in __init__
    self.parseArgs(argv)
  File "/opt/homebrew/lib/python3.11/site-packages/nose/core.py", line 179, in parseArgs
    self.createTests()
  File "/opt/homebrew/lib/python3.11/site-packages/nose/core.py", line 193, in createTests
    self.test = self.testLoader.loadTestsFromNames(self.testNames)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/nose/loader.py", line 481, in loadTestsFromNames
    return unittest.TestLoader.loadTestsFromNames(self, names, module)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/unittest/loader.py", line 220, in loadTestsFromNames
    suites = [self.loadTestsFromName(name, module) for name in names]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/unittest/loader.py", line 220, in <listcomp>
    suites = [self.loadTestsFromName(name, module) for name in names]
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/nose/loader.py", line 454, in loadTestsFromName
    return LazySuite(
           ^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/nose/suite.py", line 53, in __init__
    super(LazySuite, self).__init__()
  File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/unittest/suite.py", line 22, in __init__
    self._tests = []
    ^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/nose/suite.py", line 106, in _set_tests
    if isinstance(tests, collections.Callable) and not is_suite:
                         ^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'collections' has no attribute 'Callable'


My system info as follows:

gautamsharma@MacBook-Pro-3 movement_primitives % system_profiler SPHardwareDataType                                   
**Hardware:

    Hardware Overview:

      Model Name: MacBook Pro
      Model Identifier: MacBookPro18,3
      Model Number: MKGQ3LL/A
      Chip: Apple M1 Pro
      Total Number of Cores: 10 (8 performance and 2 efficiency)
      Memory: 16 GB
      System Firmware Version: 10151.81.1
      OS Loader Version: 10151.81.1
      Serial Number (system): M2J4FMXJJM
      Hardware UUID: 9E39F940-63A8-50ED-AC31-7FB37BB65822
      Provisioning UDID: 00006000-001A21C91121801E
      Activation Lock Status: Enabled**



Discussion / hints:
Thanks for reporting. It seems like nosetest is broken in Python 3.11. We will have to switch to pytest.

Fix patch:
diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml
index 632133c..1d29bed 100644
--- a/.github/workflows/python-package.yml
+++ b/.github/workflows/python-package.yml
@@ -8,7 +8,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: [3.7, 3.8]
+        python-version: ["3.7", "3.8", "3.11"]
 
     steps:
       - uses: actions/checkout@v2
@@ -19,8 +19,7 @@ jobs:
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip
-          pip install cython numpy
-          pip install -e .[all] flake8 nose coverage
+          pip install -e .[all,test] flake8
       - name: Lint with flake8
         run: |
           # stop the build if there are Python syntax errors or undefined names
@@ -29,6 +28,6 @@ jobs:
           flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
       - name: Test with pytest
         run: |
-          NUMBA_DISABLE_JIT=1 MPLBACKEND=Agg nosetests -sv test/ --with-coverage
+          NUMBA_DISABLE_JIT=1 MPLBACKEND=Agg pytest
       - name: Codecov
         uses: codecov/codecov-action@v1.3.2
diff --git a/README.md b/README.md
index 400342f..033a4ed 100644
--- a/README.md
+++ b/README.md
@@ -263,9 +263,10 @@ python -m pip install -e .[test]
 ```
 
 The tests are located in the folder `test/` and can be executed with:
-`python -m nose test`
+`python -m pytest`
 
-This command searches for all files with `test` and executes the functions with `test_*`.
+This command searches for all files with `test` and executes the functions
+with `test_*`. You will find a test coverage report at `htmlcov/index.html`.
 
 ## Contributing
 
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 344ebbc..0ba4d9e 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -2,8 +2,8 @@ FROM continuumio/miniconda3:latest
 
 RUN apt update && apt -y install libusb-1.0-0 libgl1-mesa-glx build-essential
 RUN conda install python=3.8.11  # later versions are not compatible to Open3D 0.13
-RUN conda install cython numpy scipy matplotlib pandas pyyaml numba sphinx numpydoc pdoc3 nose coverage
-RUN pip install gmr pytransform3d[all] tqdm sphinx-gallery sphinx-bootstrap-theme
+RUN conda install cython numpy scipy matplotlib pandas pyyaml numba sphinx numpydoc pytest pytest-cov
+RUN pip install pytransform3d[all,doc]
 
 # docker build . -t conda_py38
 # docker tag conda_py38 af01/conda_py38
diff --git a/setup.cfg b/setup.cfg
index dcec879..8282fc9 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,4 +5,6 @@ with-coverage=true
 cover-html=true
 
 [tool:pytest]
-addopts=--cov-config=.coveragerc --cov=movement_primitives --cov-report html
\ No newline at end of file
+addopts=--cov-config=.coveragerc --cov=movement_primitives --cov-report html
+testpaths =
+    test
\ No newline at end of file
diff --git a/setup.py b/setup.py
index b46ccaa..4f2506f 100644
--- a/setup.py
+++ b/setup.py
@@ -27,7 +27,7 @@
                     "open3d", "tqdm", "gmr", "PyYAML", "numba", "pybullet"],
             "doc": ["sphinx", "sphinx-bootstrap-theme", "numpydoc",
                     "myst-parser"],
-            "test": ["nose", "coverage"]
+            "test": ["pytest", "pytest-cov"]
         }
     )
     try:


Test patch:
diff --git a/test/test_canonical_system.py b/test/test_canonical_system.py
index 5b7df19..9515283 100644
--- a/test/test_canonical_system.py
+++ b/test/test_canonical_system.py
@@ -1,7 +1,7 @@
 import numpy as np
 from movement_primitives.dmp._canonical_system import canonical_system_alpha
 from movement_primitives.dmp._canonical_system import phase as phase_python
-from nose.tools import assert_almost_equal
+import pytest
 
 
 def test_phase_cython():
@@ -13,4 +13,4 @@ def test_phase_cython():
     for t in np.linspace(0, 1, 101):
         z_python = phase_python(t, alpha, goal_t, start_t, int_dt)
         z_cython = phase_cython(t, alpha, goal_t, start_t, int_dt)
-        assert_almost_equal(z_cython, z_python)
+        assert z_cython == pytest.approx(z_python)
diff --git a/test/test_cartesian_dmp.py b/test/test_cartesian_dmp.py
index 2629514..b1da3ce 100644
--- a/test/test_cartesian_dmp.py
+++ b/test/test_cartesian_dmp.py
@@ -5,7 +5,6 @@
 from movement_primitives.dmp._canonical_system import canonical_system_alpha
 from pytransform3d import rotations as pr
 from numpy.testing import assert_array_almost_equal, assert_raises_regex
-from nose.tools import assert_equal, assert_less
 
 
 def test_imitate_cartesian_dmp():
@@ -43,8 +42,8 @@ def test_imitate_cartesian_dmp_rounding_error():
         execution_time=execution_time, dt=dt,
         n_weights_per_dim=10)
     T, Y = dmp.open_loop()
-    assert_equal(len(T), 601)
-    assert_equal(len(Y), 601)
+    assert len(T) == 601
+    assert len(Y) == 601
 
 
 def test_step_through_cartesian_dmp():
@@ -164,8 +163,8 @@ def test_temporal_scaling():
     dmp.execution_time_ = 4.0
     _, Y4 = dmp.open_loop()
 
-    assert_less(np.linalg.norm(Y1 - Y2[::2]) / len(Y1), 1e-3)
-    assert_less(np.linalg.norm(Y2 - Y4[::2]) / len(Y2), 1e-3)
+    assert np.linalg.norm(Y1 - Y2[::2]) / len(Y1) < 1e-3
+    assert np.linalg.norm(Y2 - Y4[::2]) / len(Y2) < 1e-3
 
 
 def test_invalid_regularization_coefficient():
diff --git a/test/test_cartesian_pose_coupling_dual_dmp.py b/test/test_cartesian_pose_coupling_dual_dmp.py
index 922d23f..7f459c4 100644
--- a/test/test_cartesian_pose_coupling_dual_dmp.py
+++ b/test/test_cartesian_pose_coupling_dual_dmp.py
@@ -5,7 +5,7 @@
 import pytransform3d.rotations as pr
 import pytransform3d.trajectories as ptr
 from numpy.testing import assert_array_almost_equal
-from nose.tools import assert_almost_equal
+import pytest
 
 
 def test_pose_coupling():
@@ -105,8 +105,8 @@ def test_pose_coupling():
 
     right2left = _relative_poses(Y_dist[80:90])
     right2left_mean = np.mean(right2left, axis=0)
-    assert_almost_equal(
-        np.linalg.norm(right2left_mean[:3, 3]), 0.2, places=1)
+    assert np.linalg.norm(right2left_mean[:3, 3]) == pytest.approx(
+        0.2, abs=0.02)
 
 
 def _relative_poses(Y_pose):
diff --git a/test/test_conditional_promps.py b/test/test_conditional_promps.py
index 850cc89..ed331cb 100644
--- a/test/test_conditional_promps.py
+++ b/test/test_conditional_promps.py
@@ -2,7 +2,7 @@
 from movement_primitives.data import generate_1d_trajectory_distribution
 from movement_primitives.promp import ProMP
 from numpy.testing import assert_array_almost_equal
-from nose.tools import assert_greater, assert_almost_equal
+import pytest
 
 
 def test_certain_conditioning():
@@ -15,14 +15,14 @@ def test_certain_conditioning():
     Y_mean = promp.mean_trajectory(T)
     Y_var = promp.var_trajectory(T)
     assert_array_almost_equal(Y_mean, np.mean(Y, axis=0), decimal=3)
-    assert_greater(Y_var[0], 0)
+    assert Y_var[0] > 0
 
     for y_cond in np.linspace(-1, 2.5, 7):
         cpromp = promp.condition_position(np.array([y_cond]), y_cov=y_conditional_cov, t=0.0, t_max=1.0)
         Y_cmean = cpromp.mean_trajectory(T)
-        assert_almost_equal(Y_cmean[0, 0], y_cond)
+        assert Y_cmean[0, 0] == pytest.approx(y_cond)
         Y_cvar = cpromp.var_trajectory(T)
-        assert_almost_equal(Y_cvar[0, 0], 0)
+        assert Y_cvar[0, 0] == pytest.approx(0)
 
 
 def test_conditioning_with_default_value():
@@ -34,10 +34,10 @@ def test_conditioning_with_default_value():
     Y_mean = promp.mean_trajectory(T)
     Y_var = promp.var_trajectory(T)
     assert_array_almost_equal(Y_mean, np.mean(Y, axis=0), decimal=3)
-    assert_greater(Y_var[0], 0)
+    assert Y_var[0] > 0
 
     cpromp = promp.condition_position(np.array([0.0]), t=0.0, t_max=1.0)
     Y_cmean = cpromp.mean_trajectory(T)
-    assert_almost_equal(Y_cmean[0, 0], 0.0)
+    assert Y_cmean[0, 0] == pytest.approx(0.0)
     Y_cvar = cpromp.var_trajectory(T)
-    assert_almost_equal(Y_cvar[0, 0], 0)
+    assert Y_cvar[0, 0] == pytest.approx(0)
diff --git a/test/test_contextual_promps.py b/test/test_contextual_promps.py
index 8ddbd9d..d974869 100644
--- a/test/test_contextual_promps.py
+++ b/test/test_contextual_promps.py
@@ -1,7 +1,6 @@
 import numpy as np
 from movement_primitives.promp import ProMP
 from gmr import GMM
-from nose.tools import assert_less
 
 
 def test_contextual_promps():
@@ -32,7 +31,7 @@ def test_contextual_promps():
 
     samples = promp.sample_trajectories(T, 10, random_state)
     sample_mean = np.mean(samples, axis=0)
-    assert_less(np.linalg.norm(sample_mean - Ys[-1]) / n_steps, 0.01)
+    assert np.linalg.norm(sample_mean - Ys[-1]) / n_steps < 0.01
 
 
 if __name__ == "__main__":
diff --git a/test/test_coupling.py b/test/test_coupling.py
index c0ef393..1a10546 100644
--- a/test/test_coupling.py
+++ b/test/test_coupling.py
@@ -4,7 +4,7 @@
     CouplingTermDualCartesianPose)
 import pytransform3d.rotations as pr
 import pytransform3d.transformations as pt
-from nose.tools import assert_almost_equal, assert_less
+import pytest
 
 
 def test_coupling_1d_to_1d_pos():
@@ -26,7 +26,7 @@ def test_coupling_1d_to_1d_pos():
     T, Y = dmp.open_loop(coupling_term=ct)
 
     distances = Y[:, 1] - Y[:, 0]
-    assert_almost_equal(np.mean(distances), ct.desired_distance, places=3)
+    assert np.mean(distances) == pytest.approx(ct.desired_distance, rel=1e-3)
 
 
 def test_coupling_3d_to_3d_pos():
@@ -49,12 +49,12 @@ def test_coupling_3d_to_3d_pos():
 
     T, Y = dmp.open_loop(coupling_term=ct)
 
-    assert_almost_equal(
-        np.median(Y[:, 3] - Y[:, 0]), ct.desired_distance[0], places=1)
-    assert_almost_equal(
-        np.median(Y[:, 4] - Y[:, 1]), ct.desired_distance[1], places=1)
-    assert_almost_equal(
-        np.median(Y[:, 5] - Y[:, 2]), ct.desired_distance[2], places=1)
+    assert (np.median(Y[:, 3] - Y[:, 0])
+            == pytest.approx(ct.desired_distance[0], rel=1e-1))
+    assert (np.median(Y[:, 4] - Y[:, 1])
+            == pytest.approx(ct.desired_distance[1], rel=1e-1))
+    assert (np.median(Y[:, 5] - Y[:, 2])
+            == pytest.approx(ct.desired_distance[2], rel=1e-1))
 
 
 def test_coupling_term_dual_cartesian_pose():
@@ -116,4 +116,4 @@ def test_coupling_term_dual_cartesian_pose():
         right2origin = pt.transform_from_pq(y[7:])
         right2left = pt.concat(right2origin, pt.invert_transform(left2origin))
         error = np.linalg.norm(right2left - desired_distance)
-        assert_less(error, 0.25)
+        assert error < 0.25
diff --git a/test/test_dataset.py b/test/test_dataset.py
index 4fa199c..f2d0439 100644
--- a/test/test_dataset.py
+++ b/test/test_dataset.py
@@ -2,8 +2,7 @@
 from movement_primitives.data import (
     generate_minimum_jerk, load_lasa, generate_1d_trajectory_distribution)
 from numpy.testing import assert_array_almost_equal
-from nose.tools import (assert_raises_regexp, assert_greater_equal,
-                        assert_less_equal, assert_equal)
+import pytest
 
 
 def test_minimum_jerk_boundaries():
@@ -21,25 +20,25 @@ def test_minimum_jerk_boundaries():
 
     for t in range(X.shape[0]):
         for d in range(X.shape[1]):
-            assert_greater_equal(X[t, d], x0[d])
-            assert_less_equal(X[t, d], g[d])
+            assert X[t, d] >= x0[d]
+            assert X[t, d] <= g[d]
 
-    assert_raises_regexp(ValueError, "Shape .* must be equal",
-                         generate_minimum_jerk, x0, np.zeros(1))
+    with pytest.raises(ValueError, match="Shape .* must be equal"):
+        generate_minimum_jerk(x0, np.zeros(1))
 
 
 def test_lasa():
     T, X, Xd, Xdd, dt, shape_name = load_lasa(0)
-    assert_equal(T.shape[0], X.shape[0])
-    assert_equal(T.shape[1], X.shape[1])
-    assert_equal(X.shape[2], 2)
-    assert_equal(Xd.shape[0], X.shape[0])
-    assert_equal(Xd.shape[1], X.shape[1])
-    assert_equal(Xd.shape[2], X.shape[2])
-    assert_equal(Xdd.shape[0], X.shape[0])
-    assert_equal(Xdd.shape[1], X.shape[1])
-    assert_equal(Xdd.shape[2], X.shape[2])
-    assert_equal(shape_name, "Angle")
+    assert T.shape[0] == X.shape[0]
+    assert T.shape[1] == X.shape[1]
+    assert X.shape[2] == 2
+    assert Xd.shape[0] == X.shape[0]
+    assert Xd.shape[1] == X.shape[1]
+    assert Xd.shape[2] == X.shape[2]
+    assert Xdd.shape[0] == X.shape[0]
+    assert Xdd.shape[1] == X.shape[1]
+    assert Xdd.shape[2] == X.shape[2]
+    assert shape_name == "Angle"
 
 
 def test_toy1d():
diff --git a/test/test_dmp.py b/test/test_dmp.py
index 34c7dd9..42d1b2c 100644
--- a/test/test_dmp.py
+++ b/test/test_dmp.py
@@ -1,17 +1,16 @@
 import numpy as np
 from pytransform3d import rotations as pr
 from movement_primitives.dmp import DMP
-from nose.tools import (assert_almost_equal, assert_equal, assert_less,
-                        assert_raises_regexp)
 from numpy.testing import assert_array_almost_equal, assert_raises_regex
+import pytest
 
 
 def test_dmp_step_function_unknown():
     dmp = DMP(n_dims=1, execution_time=1.0, dt=0.01, n_weights_per_dim=6)
-    assert_raises_regexp(ValueError, "Step function must be",
-                         dmp.open_loop, step_function="unknown")
-    assert_raises_regexp(ValueError, "Step function must be",
-                         dmp.step, np.zeros(1), np.zeros(1), step_function="unknown")
+    with pytest.raises(ValueError, match="Step function must be"):
+        dmp.open_loop(step_function="unknown")
+    with pytest.raises(ValueError, match="Step function must be"):
+        dmp.step(np.zeros(1), np.zeros(1), step_function="unknown")
 
 
 def test_dmp1d():
@@ -26,12 +25,12 @@ def test_dmp1d():
     dmp.forcing_term.weights_ = 200 * random_state.randn(*dmp.forcing_term.weights_.shape)
 
     T, Y = dmp.open_loop(run_t=2 * execution_time)
-    assert_almost_equal(T[0], 0.0)
-    assert_almost_equal(T[-1], 2 * execution_time)
+    assert T[0] == pytest.approx(0.0)
+    assert T[-1] == pytest.approx(2 * execution_time)
 
-    assert_equal(Y.ndim, 2)
-    assert_equal(Y.shape[0], 41)
-    assert_equal(Y.shape[1], 1)
+    assert Y.ndim == 2
+    assert Y.shape[0] == 41
+    assert Y.shape[1] == 1
     assert_array_almost_equal(Y[0], start_y)
     assert_array_almost_equal(Y[-1], goal_y, decimal=3)
 
@@ -48,7 +47,7 @@ def test_dmp_steps():
     for i in range(101):
         y, yd = sd.step(y, yd)
     error = np.linalg.norm(goal_y - y)
-    assert_less(error, 1e-4)
+    assert error < 1e-4
 
 
 def test_dmp_reset():
@@ -63,18 +62,18 @@ def test_dmp_reset():
     for i in range(101):
         y, yd = sd.step(y, yd)
     error = np.linalg.norm(goal_y - y)
-    assert_less(error, 1e-4)
+    assert error < 1e-4
 
     sd.reset()
     y = np.copy(start_y)
     yd = np.copy(start_yd)
     y, yd = sd.step(y, yd)
     error = np.linalg.norm(goal_y - y)
-    assert_less(1e-4, error)
+    assert 1e-4 < error
     for i in range(100):
         y, yd = sd.step(y, yd)
     error = np.linalg.norm(goal_y - y)
-    assert_less(error, 1e-4)
+    assert error < 1e-4
 
 
 def test_dmp1d_imitation():
@@ -142,7 +141,7 @@ def test_compare_integrators():
     T_rk4, Y_rk4 = dmp.open_loop(step_function="rk4")
     error_euler = np.linalg.norm(Y_demo - Y_euler)
     error_rk4 = np.linalg.norm(Y_demo - Y_rk4)
-    assert_less(error_rk4, error_euler)
+    assert error_rk4 < error_euler
 
 
 def test_compare_rk4_python_cython():
@@ -181,7 +180,7 @@ def test_set_current_time():
     for i in range(13):
         y, yd = dmp.step(y, yd)
     error = np.linalg.norm(goal_y - y)
-    assert_less(error, 1e-2)
+    assert error < 1e-2
 
 
 def test_get_set_weights():
@@ -249,13 +248,13 @@ def test_temporal_scaling():
     dmp.execution_time_ = 4.0
     _, Y4 = dmp.open_loop()
 
-    assert_less(np.linalg.norm(Y1 - Y2[::2]) / len(Y1), 1e-3)
-    assert_less(np.linalg.norm(Y2 - Y4[::2]) / len(Y2), 1e-3)
+    assert np.linalg.norm(Y1 - Y2[::2]) / len(Y1) < 1e-3
+    assert np.linalg.norm(Y2 - Y4[::2]) / len(Y2) < 1e-3
 
 
 def test_n_weights():
     dmp = DMP(n_dims=5, n_weights_per_dim=9)
-    assert_equal(dmp.n_weights, 45)
+    assert dmp.n_weights == 45
 
 
 if __name__ == "__main__":
diff --git a/test/test_dmp_canonical_system.py b/test/test_dmp_canonical_system.py
index 3cc9b6a..7b26a76 100644
--- a/test/test_dmp_canonical_system.py
+++ b/test/test_dmp_canonical_system.py
@@ -1,16 +1,15 @@
 import numpy as np
+import pytest
+
 from movement_primitives.dmp._canonical_system import canonical_system_alpha, phase
-from nose.tools import assert_raises_regexp
 from numpy.testing import assert_array_equal, assert_array_almost_equal
 
 
 def test_canonical_system_alpha_errors():
-    assert_raises_regexp(
-        ValueError, "Final phase must be > 0!",
-        canonical_system_alpha, -0.01, 1.0, 0.0)
-    assert_raises_regexp(
-        ValueError, "Goal must be chronologically after start!",
-        canonical_system_alpha, 0.01, 0.0, 1.0)
+    with pytest.raises(ValueError, match="Final phase must be > 0!"):
+        canonical_system_alpha(-0.01, 1.0, 0.0)
+    with pytest.raises(ValueError, match="Goal must be chronologically after start!"):
+        canonical_system_alpha(0.01, 0.0, 1.0)
 
 
 def test_phase():
diff --git a/test/test_dmp_fast.py b/test/test_dmp_fast.py
index bfd2498..e9d2fdc 100644
--- a/test/test_dmp_fast.py
+++ b/test/test_dmp_fast.py
@@ -3,14 +3,14 @@
 from pytransform3d.rotations import compact_axis_angle_from_quaternion as compact_axis_angle_from_quaternion_python
 from pytransform3d.rotations import concatenate_quaternions as concatenate_quaternions_python
 from pytransform3d.rotations import random_quaternion, assert_compact_axis_angle_equal, assert_quaternion_equal
-from nose import SkipTest
+import pytest
 
 
 def test_compact_axis_angle_from_quaternion():
     try:
         from movement_primitives.dmp_fast import compact_axis_angle_from_quaternion as compact_axis_angle_from_quaternion_cython
     except ImportError:
-        raise SkipTest("Cython extension is not available")
+        pytest.skip("Cython extension is not available")
 
     q = np.array([-9.99988684e-01, -4.73967909e-03,  3.10305586e-04,  2.67831240e-04])
     axis_angle_python = compact_axis_angle_from_quaternion_python(q.copy())
@@ -71,7 +71,7 @@ def test_concatenate_quaternions():
     try:
         from movement_primitives.dmp_fast import concatenate_quaternions as concatenate_quaternions_cython
     except ImportError:
-        raise SkipTest("Cython extension is not available")
+        pytest.skip("Cython extension is not available")
 
     random_state = np.random.RandomState(1)
     for _ in range(1000):
diff --git a/test/test_dmp_forcing_term.py b/test/test_dmp_forcing_term.py
index 54bde17..020b8b7 100644
--- a/test/test_dmp_forcing_term.py
+++ b/test/test_dmp_forcing_term.py
@@ -1,19 +1,18 @@
 import numpy as np
+import pytest
+
 from movement_primitives.dmp._canonical_system import canonical_system_alpha, phase
 from movement_primitives.dmp._forcing_term import ForcingTerm
-from nose.tools import assert_equal, assert_raises_regexp
 
 
 def test_invalid_arguments():
     alpha_z = canonical_system_alpha(goal_z=0.01, goal_t=1.0, start_t=0.0)
-    assert_raises_regexp(
-        ValueError, "The number of weights per dimension must be > 1!",
-        ForcingTerm, n_dims=2, n_weights_per_dim=-1, goal_t=1.0, start_t=0.0,
-        overlap=0.7, alpha_z=alpha_z)
-    assert_raises_regexp(
-        ValueError, "Goal must be chronologically after start!",
-        ForcingTerm, n_dims=2, n_weights_per_dim=2, goal_t=0.0, start_t=1.0,
-        overlap=0.7, alpha_z=alpha_z)
+    with pytest.raises(ValueError, match="The number of weights per dimension must be > 1!"):
+        ForcingTerm(n_dims=2, n_weights_per_dim=-1, goal_t=1.0, start_t=0.0,
+                    overlap=0.7, alpha_z=alpha_z)
+    with pytest.raises(ValueError, match="Goal must be chronologically after start!"):
+        ForcingTerm(n_dims=2, n_weights_per_dim=2, goal_t=0.0, start_t=1.0,
+                    overlap=0.7, alpha_z=alpha_z)
 
 
 def test_forcing_term():
@@ -27,9 +26,9 @@ def test_forcing_term():
     forcing_term.weights_ = random_state.randn(*forcing_term.weights_.shape)
     f = forcing_term(T)
 
-    assert_equal(f.ndim, 2)
-    assert_equal(f.shape[0], n_dims)
-    assert_equal(f.shape[1], len(T))
+    assert f.ndim == 2
+    assert f.shape[0] == n_dims
+    assert f.shape[1] == len(T)
 
 
 def test_activations():
@@ -44,8 +43,8 @@ def test_activations():
     z = phase(T, alpha_z, goal_t=1.0, start_t=0.0)
     activations = forcing_term._activations(z)
 
-    assert_equal(activations.shape[0], n_weights_per_dim)
-    assert_equal(activations.shape[1], len(T))
+    assert activations.shape[0] == n_weights_per_dim
+    assert activations.shape[1] == len(T)
 
 
 if __name__ == "__main__":
diff --git a/test/test_dmp_smooth_spatial_scaling.py b/test/test_dmp_smooth_spatial_scaling.py
index 16b2872..9f95f2d 100644
--- a/test/test_dmp_smooth_spatial_scaling.py
+++ b/test/test_dmp_smooth_spatial_scaling.py
@@ -2,7 +2,6 @@
 from pytransform3d.rotations import quaternion_gradient, assert_quaternion_equal
 from movement_primitives.dmp import (
     DMP, DMPWithFinalVelocity, CartesianDMP, DualCartesianDMP)
-from nose.tools import assert_less
 from numpy.testing import assert_array_almost_equal
 
 
@@ -32,7 +31,7 @@ def test_smooth_scaling_dmp():
         Yd_dmp_smooth = np.gradient(Y_dmp_smooth, axis=0)
         Ydd_dmp_smooth = np.gradient(Yd_dmp_smooth, axis=0)
         # with smooth scaling we avoid large accelerations in the beginning
-        assert_less(np.max(np.abs(Ydd_dmp_smooth)), 0.2 * np.max(np.abs(Ydd_dmp)))
+        assert np.max(np.abs(Ydd_dmp_smooth)) < 0.2 * np.max(np.abs(Ydd_dmp))
         assert_array_almost_equal(Y_dmp[-1], new_goal, decimal=1)
 
 
@@ -61,10 +60,8 @@ def test_smooth_scaling_cartesian_dmp():
         Yd_orn_dmp_smooth = quaternion_gradient(Y_dmp_smooth[:, 3:])
         Ydd_orn_dmp_smooth = np.gradient(Yd_orn_dmp_smooth, axis=0)
         # with smooth scaling we avoid large accelerations in the beginning
-        assert_less(np.max(np.abs(Ydd_pos_dmp_smooth)),
-                    0.2 * np.max(np.abs(Ydd_pos_dmp)))
-        assert_less(np.max(np.abs(Ydd_orn_dmp_smooth)),
-                    0.2 * np.max(np.abs(Ydd_orn_dmp)))
+        assert np.max(np.abs(Ydd_pos_dmp_smooth)) < 0.2 * np.max(np.abs(Ydd_pos_dmp))
+        assert np.max(np.abs(Ydd_orn_dmp_smooth)) < 0.2 * np.max(np.abs(Ydd_orn_dmp))
         assert_array_almost_equal(Y_dmp[-1, :3], new_goal[:3], decimal=1)
         assert_quaternion_equal(Y_dmp[-1, 3:], new_goal[3:], decimal=4)
 
@@ -96,9 +93,7 @@ def test_smooth_scaling_dual_cartesian_dmp():
         Yd_orn_dmp_smooth = quaternion_gradient(Y_dmp_smooth[:, 3:7])
         Ydd_orn_dmp_smooth = np.gradient(Yd_orn_dmp_smooth, axis=0)
         # with smooth scaling we avoid large accelerations in the beginning
-        assert_less(np.max(np.abs(Ydd_pos_dmp_smooth)),
-                    0.2 * np.max(np.abs(Ydd_pos_dmp)))
-        assert_less(np.max(np.abs(Ydd_orn_dmp_smooth)),
-                    0.2 * np.max(np.abs(Ydd_orn_dmp)))
+        assert np.max(np.abs(Ydd_pos_dmp_smooth)) < 0.2 * np.max(np.abs(Ydd_pos_dmp))
+        assert np.max(np.abs(Ydd_orn_dmp_smooth)) < 0.2 * np.max(np.abs(Ydd_orn_dmp))
         assert_array_almost_equal(Y_dmp[-1, :3], new_goal[:3], decimal=1)
         assert_quaternion_equal(Y_dmp[-1, 3:7], new_goal[3:7], decimal=4)
diff --git a/test/test_dmp_with_final_velocity.py b/test/test_dmp_with_final_velocity.py
index e768eba..f872bad 100644
--- a/test/test_dmp_with_final_velocity.py
+++ b/test/test_dmp_with_final_velocity.py
@@ -1,7 +1,7 @@
 import numpy as np
 from movement_primitives.dmp import DMPWithFinalVelocity
 from numpy.testing import assert_array_almost_equal
-from nose.tools import assert_almost_equal
+import pytest
 
 
 def test_final_velocity():
@@ -56,21 +56,21 @@ def test_temporal_scaling():
 
     dmp.configure(goal_yd=goal_yd)
     T2, Y2 = dmp.open_loop()
-    assert_almost_equal(T2[-1], 2.0)
+    assert T2[-1] == pytest.approx(2.0)
     Yd2 = np.column_stack((np.gradient(Y2[:, 0]),
                            np.gradient(Y2[:, 1]))) / dmp.dt_
     assert_array_almost_equal(Yd2[-1], dmp.goal_yd, decimal=1)
 
     dmp.execution_time_ = 1.0
     T1, Y1 = dmp.open_loop()
-    assert_almost_equal(T1[-1], 1.0)
+    assert T1[-1] == pytest.approx(1.0)
     Yd1 = np.column_stack((np.gradient(Y1[:, 0]),
                            np.gradient(Y1[:, 1]))) / dmp.dt_
     assert_array_almost_equal(Yd1[-1], dmp.goal_yd, decimal=1)
 
     dmp.execution_time_ = 4.0
     T4, Y4 = dmp.open_loop()
-    assert_almost_equal(T4[-1], 4.0, places=2)
+    assert T4[-1] == pytest.approx(4.0, rel=1e-2)
     Yd4 = np.column_stack((np.gradient(Y4[:, 0]),
                            np.gradient(Y4[:, 1]))) / dmp.dt_
     assert_array_almost_equal(Yd4[-1], dmp.goal_yd, decimal=1)
diff --git a/test/test_dual_cartesian_dmp.py b/test/test_dual_cartesian_dmp.py
index 342db7e..5120f1f 100644
--- a/test/test_dual_cartesian_dmp.py
+++ b/test/test_dual_cartesian_dmp.py
@@ -1,13 +1,14 @@
 import numpy as np
+import pytest
+
 from movement_primitives.dmp import DualCartesianDMP
-from nose.tools import assert_raises_regexp, assert_less
 
 
 def test_invalid_step_function():
     dmp = DualCartesianDMP(
         execution_time=1.0, dt=0.01, n_weights_per_dim=10, int_dt=0.001)
-    assert_raises_regexp(ValueError, "Step function", dmp.open_loop,
-                         step_function="invalid")
+    with pytest.raises(ValueError, match="Step function"):
+        dmp.open_loop(step_function="invalid")
 
 
 def test_temporal_scaling():
@@ -34,5 +35,5 @@ def test_temporal_scaling():
     dmp.execution_time_ = 4.0
     _, Y4 = dmp.open_loop()
 
-    assert_less(np.linalg.norm(Y1 - Y2[::2]) / len(Y1), 1e-3)
-    assert_less(np.linalg.norm(Y2 - Y4[::2]) / len(Y2), 1e-3)
+    assert np.linalg.norm(Y1 - Y2[::2]) / len(Y1) < 1e-3
+    assert np.linalg.norm(Y2 - Y4[::2]) / len(Y2) < 1e-3
diff --git a/test/test_io.py b/test/test_io.py
index a6a66ef..837258a 100644
--- a/test/test_io.py
+++ b/test/test_io.py
@@ -1,5 +1,6 @@
 import os
 import numpy as np
+import pytest
 from pytransform3d import rotations as pr
 from pytransform3d import batch_rotations as pbr
 from movement_primitives.dmp import DMP, DualCartesianDMP
@@ -8,7 +9,6 @@
     write_pickle, read_pickle, write_yaml, read_yaml, write_json, read_json,
     _dict_to_object)
 from numpy.testing import assert_array_almost_equal
-from nose.tools import assert_raises_regexp
 
 
 def test_pickle_io():
@@ -124,6 +124,6 @@ def test_json_io():
 
 
 def test_invalid_class():
-    assert_raises_regexp(
-        ImportError, "cannot import name", _dict_to_object,
-        {"module": "movement_primitives", "class": "DMPNotExisting"})
+    with pytest.raises(ImportError, match="cannot import name"):
+        _dict_to_object({"module": "movement_primitives",
+                         "class": "DMPNotExisting"})
diff --git a/test/test_obstacle_avoidance.py b/test/test_obstacle_avoidance.py
index 5fc6cde..60eb357 100644
--- a/test/test_obstacle_avoidance.py
+++ b/test/test_obstacle_avoidance.py
@@ -3,7 +3,6 @@
 from movement_primitives.dmp import (
     DMP, CouplingTermObstacleAvoidance2D, CouplingTermObstacleAvoidance3D,
     DMPWithFinalVelocity)
-from nose.tools import assert_less
 from numpy.testing import assert_array_almost_equal
 
 
@@ -20,14 +19,14 @@ def test_obstacle_avoidance_2d():
 
     T, Y = dmp.open_loop()
     min_dist = min(cdist(Y, obstacle[np.newaxis]))
-    assert_less(min_dist, 0.03)
+    assert min_dist < 0.03
     for _ in range(20):
         start_y_random = 0.2 + 0.2 * random_state.randn(2)
         coupling_term = CouplingTermObstacleAvoidance2D(obstacle)
         dmp.configure(start_y=start_y_random)
         T, Y = dmp.open_loop(coupling_term=coupling_term)
         min_dist = min(cdist(Y, obstacle[np.newaxis]))
-        assert_less(0.1, min_dist)
+        assert 0.1 < min_dist
 
 
 def test_obstacle_avoidance_2d_rk4_python():
@@ -43,14 +42,14 @@ def test_obstacle_avoidance_2d_rk4_python():
 
     T, Y = dmp.open_loop(step_function="rk4")
     min_dist = min(cdist(Y, obstacle[np.newaxis]))
-    assert_less(min_dist, 0.03)
+    assert min_dist < 0.03
     for _ in range(20):
         start_y_random = 0.2 + 0.2 * random_state.randn(2)
         coupling_term = CouplingTermObstacleAvoidance2D(obstacle)
         dmp.configure(start_y=start_y_random)
         T, Y = dmp.open_loop(coupling_term=coupling_term, step_function="rk4")
         min_dist = min(cdist(Y, obstacle[np.newaxis]))
-        assert_less(0.1, min_dist)
+        assert 0.1 < min_dist
 
 
 def test_obstacle_avoidance_2d_fast():
@@ -66,14 +65,14 @@ def test_obstacle_avoidance_2d_fast():
 
     T, Y = dmp.open_loop()
     min_dist = min(cdist(Y, obstacle[np.newaxis]))
-    assert_less(min_dist, 0.03)
+    assert min_dist < 0.03
     for _ in range(20):
         start_y_random = 0.2 + 0.2 * random_state.randn(2)
         coupling_term = CouplingTermObstacleAvoidance2D(obstacle, fast=True)
         dmp.configure(start_y=start_y_random)
         T, Y = dmp.open_loop(coupling_term=coupling_term)
         min_dist = min(cdist(Y, obstacle[np.newaxis]))
-        assert_less(0.1, min_dist)
+        assert 0.1 < min_dist
 
 
 def test_obstacle_avoidance_3d():
@@ -89,14 +88,14 @@ def test_obstacle_avoidance_3d():
 
     T, Y = dmp.open_loop()
     min_dist = min(cdist(Y, obstacle[np.newaxis]))
-    assert_less(min_dist, 0.03)
+    assert min_dist < 0.03
     for _ in range(20):
         start_y_random = 0.2 + 0.2 * random_state.randn(3)
         coupling_term = CouplingTermObstacleAvoidance3D(obstacle)
         dmp.configure(start_y=start_y_random)
         T, Y = dmp.open_loop(coupling_term=coupling_term)
         min_dist = min(cdist(Y, obstacle[np.newaxis]))
-        assert_less(0.13, min_dist)
+        assert 0.13 < min_dist
 
 
 def test_obstacle_avoidance_3d_with_final_velocity():
@@ -113,13 +112,13 @@ def test_obstacle_avoidance_3d_with_final_velocity():
 
     T, Y = dmp.open_loop()
     min_dist = min(cdist(Y, obstacle[np.newaxis]))
-    assert_less(min_dist, 0.03)
+    assert min_dist < 0.03
     for _ in range(10):
         start_y_random = 0.2 + 0.2 * random_state.randn(3)
         coupling_term = CouplingTermObstacleAvoidance3D(obstacle)
         dmp.configure(start_y=start_y_random)
         T, Y = dmp.open_loop(coupling_term=coupling_term)
         min_dist = min(cdist(Y, obstacle[np.newaxis]))
-        assert_less(0.1, min_dist)
+        assert 0.1 < min_dist
         goal_yd_actual = (Y[-1] - Y[-2]) / 0.01
         assert_array_almost_equal(np.ones(3), goal_yd_actual, decimal=1)
diff --git a/test/test_promp.py b/test/test_promp.py
index 239dc61..e35f6f4 100644
--- a/test/test_promp.py
+++ b/test/test_promp.py
@@ -1,6 +1,5 @@
 import numpy as np
 from movement_primitives.promp import ProMP
-from nose.tools import assert_less, assert_greater
 from numpy.testing import assert_array_almost_equal
 
 
@@ -24,9 +23,9 @@ def test_imitate():
     samples = promp.sample_trajectories(T[0], 10, random_state)
 
     mean_trajectory = promp.mean_trajectory(T[0])
-    assert_less(np.linalg.norm(np.mean(samples, axis=0) - mean_trajectory) / n_steps, 0.001)
+    assert np.linalg.norm(np.mean(samples, axis=0) - mean_trajectory) / n_steps < 0.001
     std_trajectory = np.sqrt(promp.var_trajectory(T[0]))
-    assert_less(np.linalg.norm(np.std(samples, axis=0) - std_trajectory) / n_steps, 0.001)
+    assert np.linalg.norm(np.std(samples, axis=0) - std_trajectory) / n_steps < 0.001
 
 
 def test_imitate_abort_optimization():
@@ -49,9 +48,9 @@ def test_imitate_abort_optimization():
     samples = promp.sample_trajectories(T[0], 10, random_state)
 
     mean_trajectory = promp.mean_trajectory(T[0])
-    assert_greater(np.linalg.norm(np.mean(samples, axis=0) - mean_trajectory) / n_steps, 0.001)
+    assert np.linalg.norm(np.mean(samples, axis=0) - mean_trajectory) / n_steps > 0.001
     std_trajectory = np.sqrt(promp.var_trajectory(T[0]))
-    assert_greater(np.linalg.norm(np.std(samples, axis=0) - std_trajectory) / n_steps, 0.001)
+    assert np.linalg.norm(np.std(samples, axis=0) - std_trajectory) / n_steps > 0.001
 
 
 def test_promp():
@@ -75,10 +74,10 @@ def test_promp():
     random_state = np.random.RandomState(0)
     samples = promp.sample_trajectories(T[0], 20, random_state)
 
-    assert_less(np.linalg.norm(np.mean(samples, axis=0) - mean_trajectory) / n_steps, 0.01)
+    assert np.linalg.norm(np.mean(samples, axis=0) - mean_trajectory) / n_steps < 0.01
 
     std_trajectory = np.sqrt(promp.var_trajectory(T[0]))
-    assert_less(np.linalg.norm(np.std(samples, axis=0) - std_trajectory) / n_steps, 0.012)
+    assert np.linalg.norm(np.std(samples, axis=0) - std_trajectory) / n_steps < 0.012
 
 
 def test_promp_velocities():
diff --git a/test/test_spring_damper.py b/test/test_spring_damper.py
index 36cdce0..92e94c7 100644
--- a/test/test_spring_damper.py
+++ b/test/test_spring_damper.py
@@ -3,7 +3,7 @@
 from pytransform3d import trajectories as ptr
 from movement_primitives.spring_damper import SpringDamper, SpringDamperOrientation
 from numpy.testing import assert_array_almost_equal
-from nose.tools import assert_less, assert_almost_equal
+import pytest
 
 
 def test_spring_damper():
@@ -33,7 +33,7 @@ def test_spring_damper_steps():
     for i in range(100):
         y, yd = sd.step(y, yd)
     error = np.linalg.norm(goal_y - y)
-    assert_less(error, 6e-4)
+    assert error < 6e-4
 
 
 def test_spring_damper_reset():
@@ -49,10 +49,10 @@ def test_spring_damper_reset():
     for i in range(100):
         y, yd = sd.step(y, yd)
     error = np.linalg.norm(goal_y - y)
-    assert_less(error, 6e-4)
-    assert_almost_equal(1, sd.t)
+    assert error < 6e-4
+    assert 1 == pytest.approx(sd.t)
     sd.reset()
-    assert_almost_equal(0, sd.t)
+    assert 0 == pytest.approx(sd.t)
 
 
 def test_spring_damper_quaternion():
@@ -85,7 +85,7 @@ def test_spring_damper_quaternion_steps():
     for i in range(100):
         y, yd = sd.step(y, yd)
     error = np.linalg.norm(goal - y)
-    assert_less(error, 1e-3)
+    assert error < 1e-3
 
 
 def test_spring_damper_quaternion_reset():
@@ -102,10 +102,10 @@ def test_spring_damper_quaternion_reset():
     for i in range(100):
         y, yd = sd.step(y, yd)
     error = np.linalg.norm(goal - y)
-    assert_less(error, 1e-3)
-    assert_almost_equal(1, sd.t)
+    assert error < 1e-3
+    assert 1 == pytest.approx(sd.t)
     sd.reset()
-    assert_almost_equal(0, sd.t)
+    assert 0 == pytest.approx(sd.t)
 
 
 if __name__ == "__main__":
diff --git a/test/test_spring_damper_obstacle_avoidance.py b/test/test_spring_damper_obstacle_avoidance.py
index 7503e1a..76430ce 100644
--- a/test/test_spring_damper_obstacle_avoidance.py
+++ b/test/test_spring_damper_obstacle_avoidance.py
@@ -2,10 +2,9 @@
 import numpy as np
 from movement_primitives.spring_damper import SpringDamper
 from movement_primitives.dmp import CouplingTermObstacleAvoidance2D
-from nose.tools import assert_greater
 
 
-def test_spring_damper_obstacle_avoidance():
+def test_spring_damper_obstacle_avoidance(returns=False):
     start_y = np.zeros(2)
     goal_y = np.ones(2)
 
@@ -15,12 +14,13 @@ def test_spring_damper_obstacle_avoidance():
     ct = CouplingTermObstacleAvoidance2D(obstacle_position=obstacle_position)
     T, Y = sd.open_loop(run_t=10.0, coupling_term=ct)
     min_dist = min(np.linalg.norm(Y - obstacle_position, axis=1))
-    assert_greater(min_dist, 0.3)
-    return T, Y, sd, obstacle_position
+    assert min_dist > 0.3
+    if returns:
+        return T, Y, sd, obstacle_position
 
 
 if __name__ == "__main__":
-    T, Y, sd, obstacle_position = test_spring_damper_obstacle_avoidance()
+    T, Y, sd, obstacle_position = test_spring_damper_obstacle_avoidance(True)
     fig = plt.figure()
     ax = fig.add_subplot(111)
     ax.set_xlabel("x")
diff --git a/test/test_state_following_dmp.py b/test/test_state_following_dmp.py
index 2390c2a..e93e5a3 100644
--- a/test/test_state_following_dmp.py
+++ b/test/test_state_following_dmp.py
@@ -1,7 +1,7 @@
 import numpy as np
 from movement_primitives.dmp import StateFollowingDMP
 from movement_primitives.dmp._state_following_dmp import StateFollowingForcingTerm
-from nose.tools import assert_almost_equal, assert_less, assert_raises_regexp
+import pytest
 
 
 def test_state_following_dmp2d():
@@ -17,13 +17,13 @@ def test_state_following_dmp2d():
 
     T, Y = dmp.open_loop(run_t=execution_time)
 
-    assert_almost_equal(T[0], 0.0, places=3)
-    assert_almost_equal(T[-1], execution_time, places=2)
+    assert T[0] == pytest.approx(0.0, rel=1e-3)
+    assert T[-1] == pytest.approx(execution_time, rel=1e-2)
 
     for i in range(n_viapoints):
         viapoint = dmp.forcing_term.viapoints[i]
         min_dist = np.min(np.linalg.norm(Y - viapoint[np.newaxis], axis=1))
-        assert_less(min_dist, 0.02)
+        assert min_dist < 0.02
 
 
 def test_state_following_dmp2d_stepwise():
@@ -48,15 +48,14 @@ def test_state_following_dmp2d_stepwise():
     for i in range(n_viapoints):
         viapoint = dmp.forcing_term.viapoints[i]
         min_dist = np.min(np.linalg.norm(Y - viapoint[np.newaxis], axis=1))
-        assert_less(min_dist, 0.02)
+        assert min_dist < 0.02
 
 
 def test_invalid_viapoints():
-    assert_raises_regexp(
-        ValueError, "The number of viapoints",
-        StateFollowingForcingTerm,2, -1, 1.0, 0.0, 0.7, 6)
+    with pytest.raises(ValueError, match="The number of viapoints"):
+        StateFollowingForcingTerm(2, -1, 1.0, 0.0, 0.7, 6)
+
 
 def test_invalid_times():
-    assert_raises_regexp(
-        ValueError, "Goal must be chronologically after start",
-        StateFollowingForcingTerm,2, 5, 0.0, 1.0, 0.7, 6)
+    with pytest.raises(ValueError, match="Goal must be chronologically after start"):
+        StateFollowingForcingTerm(2, 5, 0.0, 1.0, 0.7, 6)