diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f81f0a98d1a51c61a24bfb404dddf574be82cebd..f463d1347be2c288410b8558d6dbdbf26baca7d1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,125 +4,30 @@ stages:
   - package
   - deploy
 
-centos7:
+.test:
   stage: test
-  except:
-    - tags
-  image: gitlab-registry.cern.ch/lhcb-docker/python-deployment:centos7
-  script:
-    - python --version
-    - pip install -e .
-    - python setup.py nosetests --cover-package xenv
-    - mkdir -p cover_report && mv -f cover cover_report/$CI_JOB_NAME
-    - xenv --help
-  coverage: '/^TOTAL.*\s+(\d+\%)$/'
-  artifacts:
-    paths:
-      - cover_report
-    when: always
-    expire_in: 1 week
-
-slc6:
-  stage: test
-  except:
-    - tags
-  image: gitlab-registry.cern.ch/lhcb-docker/python-deployment:slc6
-  script:
-    - python --version
-    - pip install -e .
-    - python setup.py nosetests --cover-package xenv
-    - mkdir -p cover_report && mv -f cover cover_report/$CI_JOB_NAME
-    - xenv --help
-  coverage: '/^TOTAL.*\s+(\d+\%)$/'
-  artifacts:
-    paths:
-      - cover_report
-    when: always
-    expire_in: 1 week
-
-slc5:
-  stage: test
-  except:
-    - tags
-  image: gitlab-registry.cern.ch/lhcb-docker/python-deployment:slc5
-  script:
-    - python --version
-    - pip install -e .
-    - python setup.py nosetests --cover-package xenv
-    - mkdir -p cover_report && mv -f cover cover_report/$CI_JOB_NAME
-    - xenv --help
-  coverage: '/^TOTAL.*\s+(\d+\%)$/'
-  artifacts:
-    paths:
-      - cover_report
-    when: always
-    expire_in: 1 week
-
-python2.7:
-  stage: test
-  image: gitlab-registry.cern.ch/lhcb-docker/python-deployment:python-2.7
+  image: registry.cern.ch/docker.io/library/${CI_JOB_NAME}
   script:
     - python --version
+    - python -m venv .venv
+    - . .venv/bin/activate
     - pip install -e .
-    - python setup.py nosetests --cover-package xenv
+    - pip install nose coverage
+    - nosetests -v --detailed-errors --with-doctest --with-coverage --cover-erase --cover-html --cover-package=xenv
     - mkdir -p cover_report && mv -f cover cover_report/$CI_JOB_NAME
     - xenv --help
-  coverage: '/^TOTAL.*\s+(\d+\%)$/'
   artifacts:
     paths:
       - cover_report
     when: always
     expire_in: 1 week
 
-python3.5:
-  stage: test
-  except:
-    - tags
-  image: gitlab-registry.cern.ch/lhcb-docker/python-deployment:python-3.5
-  script:
-    - python --version
-    - pip install -e .
-    - python setup.py nosetests --cover-package xenv
-    - mkdir -p cover_report && mv -f cover cover_report/$CI_JOB_NAME
-    - xenv --help
+python:3.7:
+  extends: .test
   coverage: '/^TOTAL.*\s+(\d+\%)$/'
-  artifacts:
-    paths:
-      - cover_report
-    when: always
-    expire_in: 1 week
 
-python3.6:
-  stage: test
-  image: gitlab-registry.cern.ch/lhcb-docker/python-deployment:python-3.6
-  script:
-    - python --version
-    - pip install -e .
-    - python setup.py nosetests --cover-package xenv
-    - mkdir -p cover_report && mv -f cover cover_report/$CI_JOB_NAME
-    - xenv --help
-  coverage: '/^TOTAL.*\s+(\d+\%)$/'
-  artifacts:
-    paths:
-      - cover_report
-    when: always
-    expire_in: 1 week
-
-python3.7:
-  stage: test
-  image: gitlab-registry.cern.ch/lhcb-docker/python-deployment:python-3.7
-  script:
-    - python --version
-    - pip install -e .
-    - python setup.py nosetests --cover-package xenv
-    - mkdir -p cover_report && mv -f cover cover_report/$CI_JOB_NAME
-    - xenv --help
-  coverage: '/^TOTAL.*\s+(\d+\%)$/'
-  artifacts:
-    paths:
-      - cover_report
-    when: always
-    expire_in: 1 week
+python:3.9:
+  extends: .test
 
 integration-test:
   stage: integration
diff --git a/pyproject.toml b/pyproject.toml
index e408fbd696f725563a2f43bdc24dc62de5eaf327..99d07c0205968d6e8c1acad75bd933f85a30478e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -38,11 +38,3 @@ include-package-data = false
 [tool.setuptools.packages.find]
 exclude = []
 namespaces = false
-
-[tool.nosetests]
-verbosity = "2"
-detailed-errors = "1"
-with-doctest = "1"
-with-coverage = "1"
-cover-erase = "1"
-cover-html = "1"