diff --git a/bob/bio/face/test/test_algorithms.py b/bob/bio/face/test/test_algorithms.py
index ca2243baaf399ba6beb17c68c488d0e81dedf58a..3581e94a7c6a2193236696772faa84cdbe556dd2 100644
--- a/bob/bio/face/test/test_algorithms.py
+++ b/bob/bio/face/test/test_algorithms.py
@@ -20,12 +20,8 @@
 import bob.io.base
 import bob.ip.gabor
 
-import unittest
-import os
 import numpy
 import math
-import tempfile
-from nose.plugins.skip import SkipTest
 
 import pkg_resources
 
diff --git a/bob/bio/face/test/test_baselines.py b/bob/bio/face/test/test_baselines.py
index b1177216d7e614b01df203909466b9078d01ad42..2de487ade1ec3753ec208d87f9fbb6c8fa98a9e1 100644
--- a/bob/bio/face/test/test_baselines.py
+++ b/bob/bio/face/test/test_baselines.py
@@ -1,4 +1,3 @@
-from bob.extension.config import load
 import pkg_resources
 import numpy as np
 from bob.pipelines import Sample, SampleSet, DelayedSample
@@ -12,7 +11,7 @@ import os
 import bob.io.base
 import functools
 import copy
-from nose.plugins.attrib import attr
+import pytest
 
 from bob.bio.base.test.utils import is_library_available
 
@@ -107,37 +106,37 @@ def run_baseline(baseline, samples_for_training=[]):
         assert "scores" in dirs
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_facenet_baseline():
     run_baseline("facenet-sanderberg")
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_inception_resnetv2_msceleb():
     run_baseline("inception-resnetv2-msceleb")
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_inception_resnetv2_casiawebface():
     run_baseline("inception-resnetv2-casiawebface")
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_inception_resnetv1_msceleb():
     run_baseline("inception-resnetv1-msceleb")
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_inception_resnetv1_casiawebface():
     run_baseline("inception-resnetv1-casiawebface")
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("mxnet")
 def test_arcface_insightface():
     run_baseline("arcface-insightface")
diff --git a/bob/bio/face/test/test_databases.py b/bob/bio/face/test/test_databases.py
index 7526f6e997a477e12e27b7c2e371b452d0122c87..b3b3171091a8c10de5a7ab534a718a580bb0faed 100644
--- a/bob/bio/face/test/test_databases.py
+++ b/bob/bio/face/test/test_databases.py
@@ -18,13 +18,13 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
-from nose.plugins.skip import SkipTest
+import pytest
 
+import os
 import bob.bio.base
 from bob.bio.base.test.utils import db_available
 from bob.bio.base.test.test_database_implementations import (
     check_database,
-    check_database_zt,
 )
 import bob.core
 from bob.extension.download import get_file
@@ -72,14 +72,14 @@ def test_arface():
     try:
         check_database(database, groups=("dev", "eval"))
     except IOError as e:
-        raise SkipTest(
-            "The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'"
+        pytest.skip("The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'"
             % e
+
         )
     try:
         _check_annotations(database)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The annotations could not be queried; probably the annotation files are missing. Here is the error: '%s'"
             % e
         )
@@ -93,7 +93,7 @@ def test_atnt():
     try:
         check_database(database)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'"
             % e
         )
@@ -109,14 +109,14 @@ def test_gbu():
         check_database(database, protocol="Bad", models_depend=True)
         check_database(database, protocol="Ugly", models_depend=True)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'"
             % e
         )
     try:
         _check_annotations(database, limit_files=1000)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The annotations could not be queried; probably the annotation files are missing. Here is the error: '%s'"
             % e
         )
@@ -144,14 +144,14 @@ def test_lfw():
             models_depend=True,
         )
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'"
             % e
         )
     try:
         _check_annotations(database, limit_files=1000)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The annotations could not be queried; probably the annotation files are missing. Here is the error: '%s'"
             % e
         )
@@ -167,7 +167,7 @@ def test_mobio():
     # Removing the file before the test
     try:
         os.remove(filename)
-    except:
+    except Exception:
         pass
 
     protocols = MobioDatabase.protocols()
@@ -206,7 +206,7 @@ def test_multipie():
     # Removing the file before the test
     try:
         os.remove(filename)
-    except:
+    except Exception:
         pass
 
     protocols = MultipieDatabase.protocols()
@@ -239,14 +239,14 @@ def test_replay_licit():
     try:
         check_database(database, groups=("dev", "eval"))
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The database could not be queried; probably the db.sql3 file is missing. Here is the error: '%s'"
             % e
         )
     try:
         _check_annotations(database, topleft=True)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The annotations could not be queried; probably the annotation files are missing. Here is the error: '%s'"
             % e
         )
@@ -260,14 +260,14 @@ def test_replay_spoof():
     try:
         check_database(database, groups=("dev", "eval"))
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The database could not be queried; probably the db.sql3 file is missing. Here is the error: '%s'"
             % e
         )
     try:
         _check_annotations(database, topleft=True)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The annotations could not be queried; probably the annotation files are missing. Here is the error: '%s'"
             % e
         )
@@ -281,14 +281,14 @@ def test_replaymobile_licit():
     try:
         check_database(database, groups=("dev", "eval"))
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The database could not be queried; probably the db.sql3 file is missing. Here is the error: '%s'"
             % e
         )
     try:
         _check_annotations(database, topleft=True, limit_files=20)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The annotations could not be queried; probably the annotation files are missing. Here is the error: '%s'"
             % e
         )
@@ -302,14 +302,14 @@ def test_replaymobile_spoof():
     try:
         check_database(database, groups=("dev", "eval"))
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The database could not be queried; probably the db.sql3 file is missing. Here is the error: '%s'"
             % e
         )
     try:
         _check_annotations(database, topleft=True, limit_files=20)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The annotations could not be queried; probably the annotation files are missing. Here is the error: '%s'"
             % e
         )
@@ -323,11 +323,11 @@ def test_ijbc():
     try:
         check_database(database, models_depend=True, training_depends=True)
     except IOError as e:
-        raise SkipTest("The database could not queried; Here is the error: '%s'" % e)
+        pytest.skip("The database could not queried; Here is the error: '%s'" % e)
     try:
         _check_annotations(database, topleft=True, limit_files=1000)
     except IOError as e:
-        raise SkipTest(
+        pytest.skip(
             "The annotations could not be queried; probably the annotation files are missing. Here is the error: '%s'"
             % e
         )
@@ -341,7 +341,7 @@ def test_fargo():
     try:
         check_database(database)
     except IOError as e:
-        raise SkipTest("The database could not queried; Here is the error: '%s'" % e)
+        pytest.skip("The database could not queried; Here is the error: '%s'" % e)
 
 
 def test_meds():
@@ -355,7 +355,7 @@ def test_meds():
     # Removing the file before the test
     try:
         os.remove(filename)
-    except:
+    except Exception:
         pass
 
     database = MEDSDatabase("verification_fold1")
@@ -382,7 +382,7 @@ def test_morph():
     # Removing the file before the test
     try:
         os.remove(filename)
-    except:
+    except Exception:
         pass
 
     database = MorphDatabase("verification_fold1")
diff --git a/bob/bio/face/test/test_embeddings.py b/bob/bio/face/test/test_embeddings.py
index 10b5cf27e548ba960165477eaf3708ca1716661e..9432e3e06a283acb5ec7df54362040d8625db4b0 100644
--- a/bob/bio/face/test/test_embeddings.py
+++ b/bob/bio/face/test/test_embeddings.py
@@ -4,10 +4,10 @@ import numpy as np
 from bob.pipelines import Sample, wrap
 import pkg_resources
 from bob.bio.base.test.utils import is_library_available
-from nose.plugins.attrib import attr
+import pytest
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_idiap_inceptionv2_msceleb():
     from bob.bio.face.embeddings.tf2_inception_resnet import (
@@ -34,7 +34,7 @@ def test_idiap_inceptionv2_msceleb():
     assert output.size == 128, output.shape
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_idiap_inceptionv2_msceleb_memory_demanding():
     from bob.bio.face.embeddings.tf2_inception_resnet import (
@@ -62,7 +62,7 @@ def test_idiap_inceptionv2_msceleb_memory_demanding():
     assert output.size == 128, output.shape
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_idiap_inceptionv2_casia():
     from bob.bio.face.embeddings.tf2_inception_resnet import (
@@ -89,7 +89,7 @@ def test_idiap_inceptionv2_casia():
     assert output.size == 128, output.shape
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_idiap_inceptionv1_msceleb():
     from bob.bio.face.embeddings.tf2_inception_resnet import (
@@ -116,7 +116,7 @@ def test_idiap_inceptionv1_msceleb():
     assert output.size == 128, output.shape
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_idiap_inceptionv1_casia():
     from bob.bio.face.embeddings.tf2_inception_resnet import (
@@ -143,7 +143,7 @@ def test_idiap_inceptionv1_casia():
     assert output.size == 128, output.shape
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_facenet_sanderberg():
     from bob.bio.face.embeddings.tf2_inception_resnet import (
@@ -170,7 +170,7 @@ def test_facenet_sanderberg():
     assert output.size == 128, output.shape
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("mxnet")
 def test_arcface_insight_face():
     from bob.bio.face.embeddings.mxnet_models import ArcFaceInsightFace
diff --git a/bob/bio/face/test/test_extractors.py b/bob/bio/face/test/test_extractors.py
index 30936866027d58884bb4e6c236eea39d866e7f37..c935beb2848b067fa87a51c9db0ee688f8c961d5 100644
--- a/bob/bio/face/test/test_extractors.py
+++ b/bob/bio/face/test/test_extractors.py
@@ -20,14 +20,10 @@
 import bob.bio.base
 import bob.bio.face
 
-import unittest
-import os
 import numpy
 import math
-from nose.plugins.skip import SkipTest
 
 import bob.io.base.test_utils
-from bob.bio.base.test import utils
 
 import pkg_resources
 
diff --git a/bob/bio/face/test/test_picklability.py b/bob/bio/face/test/test_picklability.py
index b5c60ae4c3f7359686a8d18c8afc92642f38fd39..c6870fc4c7971442b72077fe7e4af5604187b37a 100644
--- a/bob/bio/face/test/test_picklability.py
+++ b/bob/bio/face/test/test_picklability.py
@@ -2,7 +2,6 @@ import bob.bio.face
 import bob.bio.base
 import numpy as np
 import pickle
-import nose
 
 import bob.ip.base
 import bob.ip.flandmark
@@ -41,13 +40,13 @@ def assert_picklable_with_exceptions(obj):
     obj = obj.__dict__
     new_obj = new_obj.__dict__
     assert len(obj) == len(new_obj)
-    nose.tools.assert_equal(sorted(list(obj.keys())), sorted(list(new_obj.keys())))
+    assert sorted(list(obj.keys())) == sorted(list(new_obj.keys()))
     for k, v in obj.items():
         if isinstance(v, np.ndarray):
             np.testing.assert_equal(v, new_obj[k])
         else:
             if type(v) not in exception_list:
-                nose.tools.assert_equal(v, new_obj[k])
+                assert v == new_obj[k]
     return True
 
 
diff --git a/bob/bio/face/test/test_transformers.py b/bob/bio/face/test/test_transformers.py
index 309f344c094395f3b7dc649e1a85a6e48498fc77..1af1a86d50c9cebdaf3cf46dca9356d1b64e4ce1 100644
--- a/bob/bio/face/test/test_transformers.py
+++ b/bob/bio/face/test/test_transformers.py
@@ -1,10 +1,8 @@
-from bob.extension.config import load
-import pkg_resources
 import numpy as np
-from bob.pipelines import Sample, SampleSet
+from bob.pipelines import Sample
 from bob.bio.base import load_resource
 from bob.bio.base.test.utils import is_library_available
-from nose.plugins.attrib import attr
+import pytest
 
 
 def get_fake_sample(face_size=(160, 160), eyes={"leye": (46, 107), "reye": (46, 53)}):
@@ -14,7 +12,7 @@ def get_fake_sample(face_size=(160, 160), eyes={"leye": (46, 107), "reye": (46,
     return Sample(data, key="1", annotations=annotations)
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_facenet_sanderberg():
     transformer = load_resource("facenet-sanderberg", "transformer")
@@ -26,7 +24,7 @@ def test_facenet_sanderberg():
     assert transformed_sample.data.size == 128
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_inception_resnetv2_msceleb():
     transformer = load_resource("inception-resnetv2-msceleb", "transformer")
@@ -38,7 +36,7 @@ def test_inception_resnetv2_msceleb():
     assert transformed_sample.data.size == 128
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_inception_resnetv2_casiawebface():
     transformer = load_resource("inception-resnetv2-casiawebface", "transformer")
@@ -50,7 +48,7 @@ def test_inception_resnetv2_casiawebface():
     assert transformed_sample.data.size == 128
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_inception_resnetv1_msceleb():
     transformer = load_resource("inception-resnetv1-msceleb", "transformer")
@@ -62,7 +60,7 @@ def test_inception_resnetv1_msceleb():
     assert transformed_sample.data.size == 128
 
 
-@attr('slow')
+@pytest.mark.slow
 @is_library_available("tensorflow")
 def test_inception_resnetv1_casiawebface():
     transformer = load_resource("inception-resnetv1-casiawebface", "transformer")
diff --git a/conda/meta.yaml b/conda/meta.yaml
index 44e4780d1e7d00aba7715bf3cab8908b0d889b51..db5a93c7fbb8802b4a3f09834211a90a5a613d5b 100644
--- a/conda/meta.yaml
+++ b/conda/meta.yaml
@@ -59,7 +59,9 @@ test:
     - {{ name }}
   commands:
     - bob bio display-face-annotations --help
-    - nosetests --with-coverage --cover-package={{ name }} -sv {{ name }}
+    # runs tests for package only, report only what is in the package
+    # creates html and xml reports and place them in specific directories
+    - pytest --verbose --cov {{ name }} --cov-report term-missing --cov-report html:{{ project_dir }}/sphinx/coverage --cov-report xml:{{ project_dir }}/coverage.xml --pyargs {{ name }}
     - sphinx-build -aEW {{ project_dir }}/doc {{ project_dir }}/sphinx
     - sphinx-build -aEb doctest {{ project_dir }}/doc sphinx
     - conda inspect linkages -p $PREFIX {{ name }}  # [not win]
@@ -67,6 +69,8 @@ test:
   requires:
     - bob-devel {{ bob_devel }}.*
     - nose
+    - pytest
+    - pytest-cov
     - coverage
     - sphinx
     - sphinx_rtd_theme
diff --git a/pyproject.toml b/pyproject.toml
index bb5e83cb40b5871b321beb790ae14606b010e4ca..ff2f6ba244a2c7caeaa4b9495c2eaf144189c396 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,3 +1,6 @@
 [build-system]
 requires = ["setuptools", "wheel", "bob.extension"]
 build-backend = "setuptools.build_meta"
+
+[tool.pytest.ini_options]
+markers = ["slow: marks tests as slow (deselect with '-m \"not slow\"')"]