diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 968e49a57cd02cd317b9c527627f43e790bcd1c4..2fbcc48cd70fbda3297146feabcda91155621927 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,7 +3,6 @@ image: registry.git.cccv.de/uffd/docker-images/buster
 variables:
   DEBIAN_FRONTEND: noninteractive 
   GIT_SUBMODULE_STRATEGY: normal
-  PYTHONPATH: deps/ldapalchemy
   APT_API_URL: https://packages.cccv.de
   APT_REPO: uffd
   PYLINT_PIN: pylint~=2.10.0
@@ -62,9 +61,7 @@ linter:buster:
   stage: test
   script:
   - pip3 install $PYLINT_PIN pylint-gitlab pylint-flask-sqlalchemy # this force-updates jinja2 and some other packages!
-  - python3 -m pylint --exit-zero --rcfile .pylintrc --output-format=pylint_gitlab.GitlabCodeClimateReporter uffd > codeclimate.json
-  - python3 -m pylint --exit-zero --rcfile .pylintrc --output-format=pylint_gitlab.GitlabPagesHtmlReporter uffd > pylint.html
-  - python3 -m pylint --rcfile .pylintrc --output-format=text uffd
+  - python3 -m pylint --output-format=pylint_gitlab.GitlabCodeClimateReporter:codeclimate.json,pylint_gitlab.GitlabPagesHtmlReporter:pylint.html,colorized uffd
   artifacts:
     when: always
     paths:
@@ -77,9 +74,7 @@ linter:bullseye:
   stage: test
   script:
   - pip3 install $PYLINT_PIN pylint-gitlab pylint-flask-sqlalchemy # this force-updates jinja2 and some other packages!
-  - python3 -m pylint --exit-zero --rcfile .pylintrc --output-format=pylint_gitlab.GitlabCodeClimateReporter uffd > codeclimate.json
-  - python3 -m pylint --exit-zero --rcfile .pylintrc --output-format=pylint_gitlab.GitlabPagesHtmlReporter uffd > pylint.html
-  - python3 -m pylint --rcfile .pylintrc --output-format=text uffd
+  - python3 -m pylint --output-format=pylint_gitlab.GitlabCodeClimateReporter:codeclimate.json,pylint_gitlab.GitlabPagesHtmlReporter:pylint.html,colorized uffd
   artifacts:
     when: always
     paths:
@@ -91,11 +86,11 @@ unittests:buster:
   image: registry.git.cccv.de/uffd/docker-images/buster
   stage: test
   script:
-  - service slapd start
-  - UNITTEST_OPENLDAP=1 python3-coverage run --include 'uffd/*.py' -m pytest --junitxml=report.xml || true
+  - python3-coverage run --include 'uffd/*.py' -m pytest --junitxml=report.xml || touch failed
   - python3-coverage report -m
   - python3-coverage html
   - python3-coverage xml
+  - test ! -e failed
   artifacts:
     when: always
     paths:
@@ -113,23 +108,11 @@ unittests:bullseye:
   image: registry.git.cccv.de/uffd/docker-images/bullseye
   stage: test
   script:
-  - service slapd start
-  - UNITTEST_OPENLDAP=1 python3-coverage run --include 'uffd/*.py' -m pytest --junitxml=report.xml || true
-  #- python3-coverage report -m
-  - python3-coverage html
-  #- python3-coverage xml
+  - python3 -m pytest --junitxml=report.xml
   artifacts:
     when: always
-    paths:
-    - htmlcov/index.html
-    - htmlcov
-    expose_as: 'Coverage Report'
     reports:
-      #coverage_report:
-      #  coverage_format: cobertura
-      #  path: coverage.xml
       junit: report.xml
-  #coverage: '/^TOTAL.*\s+(\d+\%)$/'
 
 html5validator:
   stage: test
diff --git a/.pylintrc b/.pylintrc
index 00c3ae55901ebfd9f756dd3002bf4eb08c0fde6b..f3f5782875309366520961e3879688638a10911e 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -11,7 +11,7 @@ ignore=CVS
 
 # Add files or directories matching the regex patterns to the blacklist. The
 # regex matches against base names, not paths.
-ignore-patterns=ldapalchemy
+ignore-patterns=
 
 # Python code to execute, usually for sys.path manipulation such as
 # pygtk.require().
diff --git a/tests/test_mail.py b/tests/test_mail.py
index f794486b465f984264bd71a0c7116c04c35f58d7..6660b3be3b43e52c48aa48d7ca5ae7e5c1d7a423 100644
--- a/tests/test_mail.py
+++ b/tests/test_mail.py
@@ -65,7 +65,7 @@ class TestMailViews(UffdTestCase):
 		self.assertEqual(sorted(m.receivers), ['foo@bar.com', 'test@bar.com'])
 		self.assertEqual(sorted(m.destinations), ['testadmin@mail.example.com', 'testuser@mail.example.com'])
 
-	@unittest.skip('We do not catch LDAP errors at the moment!') # TODO: Not sure if necessary
+	@unittest.skip('We do not catch DB errors at the moment!') # TODO
 	def test_create_error(self):
 		r = self.client.post(path=url_for('mail.update'),
 			data={'mail-uid': 'test', 'mail-receivers': 'foo@bar.com\ntest@bar.com',
diff --git a/tests/test_role.py b/tests/test_role.py
index 7061d3936abd65d949fc01c0f8b5064a1ab0f47c..c02b862c7c8e4525b5a77d55c48c84afde660f2a 100644
--- a/tests/test_role.py
+++ b/tests/test_role.py
@@ -186,7 +186,7 @@ class TestRoleViews(UffdTestCase):
 		self.assertEqual(role.name, 'base1')
 		self.assertEqual(role.description, 'Base role description1')
 		self.assertSetEqual(set(role.groups), {self.get_access_group(), self.get_users_group()})
-		# TODO: verify that group memberships are updated (currently not possible with ldap mock!)
+		# TODO: verify that group memberships are updated
 
 	def test_create(self):
 		self.assertIsNone(Role.query.filter_by(name='base').first())
diff --git a/tests/test_signup.py b/tests/test_signup.py
index 5979da3bc0f066a1fde981081deabbe67c76ac11..e77c7c4678a344a6deb826d5bfa5e87d243999e0 100644
--- a/tests/test_signup.py
+++ b/tests/test_signup.py
@@ -147,7 +147,7 @@ class TestSignupModel(UffdTestCase):
 		self.assert_finish_failure(signup, 'wrongpassword')
 		self.assert_finish_failure(refetch_signup(signup), 'wrongpassword')
 
-	def test_finish_ldaperror(self):
+	def test_finish_duplicate(self):
 		signup = Signup(loginname='testuser', displayname='New User', mail='test@example.com', password='notsecret')
 		self.assert_finish_failure(signup, 'notsecret')
 		self.assert_finish_failure(refetch_signup(signup), 'notsecret')
diff --git a/uffd/__init__.py b/uffd/__init__.py
index 6f48d7a02a0ea4db062a7820232d92e195cd8b6f..d178c85f9d4e6f7f61fffe7447d83b31ca98359e 100644
--- a/uffd/__init__.py
+++ b/uffd/__init__.py
@@ -84,7 +84,6 @@ def create_app(test_config=None): # pylint: disable=too-many-locals,too-many-sta
 
 	@app.shell_context_processor
 	def push_request_context(): #pylint: disable=unused-variable
-		app.test_request_context().push() # LDAP ORM requires request context
 		return {'db': db} | {name: getattr(models, name) for name in models.__all__}
 
 	babel = Babel(app)