diff --git a/tests/app/conftest.py b/tests/app/conftest.py
index d4a45ae063c6b185382acd230f6f99120f2ad5b6..15ea03221b5ce175b0010cd319970fc063677f8c 100644
--- a/tests/app/conftest.py
+++ b/tests/app/conftest.py
@@ -20,35 +20,30 @@ import pytest
 from fastapi.testclient import TestClient
 
 from nomad.app.main import app
+from nomad.app.v1.routers.auth import generate_simple_token, generate_upload_token
 from nomad.datamodel import User
-from nomad.app.v1.routers.auth import generate_upload_token, generate_simple_token
 
 
 def create_auth_headers(token: str):
     return {'Authorization': f'Bearer {token}'}
 
 
-@pytest.fixture(scope='module')
+@pytest.fixture(scope='session')
 def user0_auth(user0: User):
     return create_auth_headers(user0.user_id)
 
 
-@pytest.fixture(scope='module')
+@pytest.fixture(scope='session')
 def user1_auth(user1: User):
     return create_auth_headers(user1.user_id)
 
 
-@pytest.fixture(scope='module')
+@pytest.fixture(scope='session')
 def user2_auth(user2: User):
     return create_auth_headers(user2.user_id)
 
 
-@pytest.fixture(scope='module')
-def user3_auth(user3: User):
-    return create_auth_headers(user3.user_id)
-
-
-@pytest.fixture(scope='module')
+@pytest.fixture(scope='session')
 def invalid_user_auth():
     return create_auth_headers('invalid.bearer.token')
 
@@ -59,30 +54,19 @@ def app_token_auth(user1: User):
     return create_auth_headers(app_token)
 
 
-@pytest.fixture(scope='module')
-def auth_dict(
-    user0,
-    user1,
-    user2,
-    user3,
-    user0_auth,
-    user1_auth,
-    user2_auth,
-    user3_auth,
-    invalid_user_auth,
-):
+@pytest.fixture(scope='session')
+def auth_dict(users_dict, invalid_user_auth):
     """
-    Returns a dictionary of the form {user_name: (auth_headers, token)}. The key 'invalid'
+    Returns a dictionary of the form {user_label: (auth_headers, token)}. The key 'invalid'
     contains an example of invalid credentials, and the key None contains (None, None).
     """
-    return {
-        'user0': (user0_auth, generate_upload_token(user0)),
-        'user1': (user1_auth, generate_upload_token(user1)),
-        'user2': (user2_auth, generate_upload_token(user2)),
-        'user3': (user3_auth, generate_upload_token(user3)),
-        'invalid': (invalid_user_auth, 'invalid.upload.token'),
-        None: (None, None),
+    auths = {
+        label: (create_auth_headers(user.user_id), generate_upload_token(user))
+        for label, user in users_dict.items()
     }
+    auths['invalid'] = (invalid_user_auth, 'invalid.upload.token')
+    auths[None] = (None, None)
+    return auths
 
 
 @pytest.fixture(scope='session')
diff --git a/tests/app/v1/routers/uploads/common.py b/tests/app/v1/routers/uploads/common.py
index a3432721be44576bc738c3855ff0b581aea8040c..259eb4c80d4f05b28b29b2d45dec97bea8a4373f 100644
--- a/tests/app/v1/routers/uploads/common.py
+++ b/tests/app/v1/routers/uploads/common.py
@@ -19,3 +19,15 @@ def assert_upload(response_json, **kwargs):
     for key, value in kwargs.items():
         assert data.get(key, None) == value
     return data
+
+
+def assert_entry(entry, has_metadata=True, **kwargs):
+    """Checks the content of a returned entry dictionary."""
+    assert 'upload_id' in entry
+    assert 'entry_id' in entry
+    assert 'entry_create_time' in entry
+    assert not entry['process_running']
+    for key, value in kwargs.items():
+        assert entry.get(key, None) == value
+    if has_metadata:
+        assert 'entry_metadata' in entry
diff --git a/tests/app/v1/routers/uploads/test_basic_uploads.py b/tests/app/v1/routers/uploads/test_basic_uploads.py
index 4528f4a69ba470b0601daa0f1cc380dc6e4328e0..d3559e5d7dd82c07bc61375fab3891b9fc9734f4 100644
--- a/tests/app/v1/routers/uploads/test_basic_uploads.py
+++ b/tests/app/v1/routers/uploads/test_basic_uploads.py
@@ -16,46 +16,47 @@
 # limitations under the License.
 #
 
-import pytest
 import io
 import os
-import requests
 import time
 import zipfile
 from datetime import datetime
-from typing import List, Dict, Any, Iterable
-from tests.app.v1.routers.uploads.common import assert_upload
+from typing import Any, Dict, Iterable, List
 
-from tests.utils import build_url, set_upload_entry_metadata
-from tests.test_files import (
-    example_file_mainfile_different_atoms,
-    example_file_vasp_with_binary,
-    example_file_aux,
-    example_file_unparsable,
-    example_file_corrupt_zip,
-    empty_file,
-    assert_upload_files,
+import pytest
+import requests
+
+from nomad import files, infrastructure
+from nomad.bundles import BundleExporter
+from nomad.config import config
+from nomad.config.models.config import BundleImportSettings
+from nomad.datamodel import EntryMetadata
+from nomad.files import PublicUploadFiles, StagingUploadFiles, UploadFiles
+from nomad.processing import Entry, ProcessStatus, Upload
+from tests.app.v1.routers.common import (
+    assert_browser_download_headers,
+    assert_response,
+    perform_get,
 )
-from tests.test_search import assert_search_upload
 from tests.processing.test_edit_metadata import (
-    assert_metadata_edited,
-    all_coauthor_metadata,
     all_admin_metadata,
+    all_coauthor_metadata,
+    assert_metadata_edited,
 )
-from tests.app.v1.routers.common import (
-    assert_response,
-    assert_browser_download_headers,
-    perform_get,
+from tests.test_files import (
+    assert_upload_files,
+    empty_file,
+    example_file_aux,
+    example_file_corrupt_zip,
+    example_file_mainfile_different_atoms,
+    example_file_unparsable,
+    example_file_vasp_with_binary,
 )
-from nomad import files, infrastructure
-from nomad.config import config
-from nomad.config.models.config import BundleImportSettings
-from nomad.processing import Upload, Entry, ProcessStatus
-from nomad.files import UploadFiles, StagingUploadFiles, PublicUploadFiles
-from nomad.bundles import BundleExporter
-from nomad.datamodel import EntryMetadata
+from tests.test_search import assert_search_upload
+from tests.utils import build_url, set_upload_entry_metadata
 
 from ..test_entries import assert_archive_response
+from .common import assert_entry, assert_upload
 
 """
 These are the tests for all API operations below ``uploads``. The tests are organized
@@ -357,17 +358,6 @@ def assert_gets_published(
     assert_upload_files(upload_id, entries, files.PublicUploadFiles, published=True)
 
 
-def assert_entry(entry, **kwargs):
-    """Checks the content of a returned entry dictionary."""
-    assert 'upload_id' in entry
-    assert 'entry_id' in entry
-    assert 'entry_create_time' in entry
-    assert not entry['process_running']
-    for key, value in kwargs.items():
-        assert entry.get(key, None) == value
-    assert 'entry_metadata' in entry
-
-
 def assert_pagination(pagination, expected_pagination):
     """Checks that the contents of `paginaion` matches what is expected."""
     for key, value in expected_pagination.items():
diff --git a/tests/fixtures/users.py b/tests/fixtures/users.py
index 6c97444f2877b54ab647da0d6b3331bb624e53e9..3d3742fd7e4723e7092322be9864990a0995da8f 100644
--- a/tests/fixtures/users.py
+++ b/tests/fixtures/users.py
@@ -2,7 +2,7 @@
 User fixtures:
 - user0: admin user
 - user1: default user to use
-- user2, user3: additional users for access or interaction tests
+- user2, user3, ...: additional users for access or interaction tests
 """
 
 import pytest
@@ -10,41 +10,50 @@ import pytest
 from nomad import infrastructure
 from nomad.config import config
 from nomad.datamodel import User
-from tests.utils import fake_user_uuid
+from tests.utils import fake_user_uuid, generate_convert_label
 
 admin_user_id = fake_user_uuid(0)
 
+
+def fake_user(num, first_name, last_name, *, email=None, **kwargs):
+    if email is None:
+        email = f'{first_name}.{last_name}@nomad-fairdi.tests.de'.lower()
+
+    username = f'{first_name[0]}{last_name}'.lower()
+
+    return dict(
+        user_id=fake_user_uuid(num),
+        username=username,
+        email=email,
+        first_name=first_name,
+        last_name=last_name,
+        **kwargs,
+    )
+
+
 users = {
     fake_user_uuid(0): dict(username='admin', email='admin', user_id=fake_user_uuid(0)),
-    fake_user_uuid(1): dict(
-        username='scooper',
-        email='sheldon.cooper@nomad-coe.eu',
-        first_name='Sheldon',
-        last_name='Cooper',
-        user_id=fake_user_uuid(1),
+    fake_user_uuid(1): fake_user(
+        1,
+        'Sheldon',
+        'Cooper',
+        email='sheldon.cooper@nomad-coe.eu',  # domain differs from default
         is_oasis_admin=True,
     ),
-    fake_user_uuid(2): dict(
-        username='lhofstadter',
-        email='leonard.hofstadter@nomad-fairdi.tests.de',
-        first_name='Leonard',
-        last_name='Hofstadter',
-        user_id=fake_user_uuid(2),
-    ),
-    fake_user_uuid(3): dict(
-        username='hwolowitz',
-        email='howard.wolowitz@nomad-fairdi.tests.de',
-        first_name='Howard',
-        last_name='Wolowitz',
-        user_id=fake_user_uuid(3),
-    ),
+    fake_user_uuid(2): fake_user(2, 'Leonard', 'Hofstadter'),
+    fake_user_uuid(3): fake_user(3, 'Howard', 'Wolowitz'),
+    fake_user_uuid(4): fake_user(4, 'Rajesh', 'Koothrappali'),
+    fake_user_uuid(5): fake_user(5, 'Penny', 'Hofstadter'),
+    fake_user_uuid(6): fake_user(6, 'Bernadette', 'Rostenkowski-Wolowitz'),
+    fake_user_uuid(7): fake_user(7, 'Amy', 'Fowler'),
+    fake_user_uuid(8): fake_user(8, 'Stuart', 'Bloom'),
+    fake_user_uuid(9): fake_user(9, 'Emily', 'Sweeney'),
 }
 
 
 @pytest.fixture(scope='session')
 def user_molds():
-    label_num = {f'user{i}': i for i in range(4)}
-    return {label: users[fake_user_uuid(num)] for label, num in label_num.items()}
+    return {f'user{i}': user for i, user in enumerate(users.values())}
 
 
 @pytest.fixture(scope='session')
@@ -63,18 +72,19 @@ def user2():
 
 
 @pytest.fixture(scope='session')
-def user3():
-    return User(**users[fake_user_uuid(3)])
+def users_dict(user_molds):
+    return {k: User(**v) for k, v in user_molds.items()}
+
+
+@pytest.fixture(scope='session')
+def user_label_id_mapping(user_molds):
+    return {label: value.get('user_id') for label, value in user_molds.items()}
 
 
 @pytest.fixture(scope='session')
-def users_dict(user0, user1, user2, user3):
-    return {
-        'user0': user0,
-        'user1': user1,
-        'user2': user2,
-        'user3': user3,
-    }
+def convert_user_labels_to_ids(user_label_id_mapping):
+    """Returned function converts user labels to ids, also in lists and dicts."""
+    return generate_convert_label(user_label_id_mapping)
 
 
 @pytest.fixture(scope='session', autouse=True)
@@ -84,7 +94,7 @@ def configure_admin_user_id(monkeysession):
 
 class KeycloakMock:
     def __init__(self):
-        self.id_counter = 3
+        self.id_counter = len(users)
         self.users = dict(**users)
 
     def tokenauth(self, access_token: str):
diff --git a/tests/utils.py b/tests/utils.py
index d9f452963760ee31e67593429061cc04019e3548..6a95a2154853794a8d0ba1c0ecf117ad73f7fdeb 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -18,12 +18,14 @@
 
 """Methods to help with testing of nomad@FAIRDI."""
 
-from typing import List, Union, Dict, Any
-import urllib.parse
 import json
-from logging import LogRecord
-import zipfile
 import os.path
+import urllib.parse
+import zipfile
+from logging import LogRecord
+from typing import Any, Dict, List, Union
+
+import pytest
 
 
 def assert_log(caplog, level: str, event_part: str) -> LogRecord:
@@ -160,9 +162,36 @@ def create_template_upload_file(
 
 
 def fake_user_uuid(handle):
-    return '00000000-0000-0000-0000-00000000000%d' % handle
+    uuid = '00000000-0000-0000-0000-' + str(handle).rjust(12, '0')
+    assert len(uuid) == 36
+    return uuid
 
 
 def fake_group_uuid(handle: Any):
     """Returns a test user group uuid based on the handle."""
-    return str(handle).rjust(22, 'G')
+    uuid = str(handle).rjust(22, 'G')
+    assert len(uuid) == 22
+    return uuid
+
+
+def generate_convert_label(mapping):
+    """Returned function converts labels to values according to mapping,
+    also in lists and dicts, returns copies. Missing labels persist."""
+
+    def convert(raw):
+        if isinstance(raw, str):
+            return mapping.get(raw, raw)
+
+        if isinstance(raw, list):
+            return [convert(v) for v in raw]
+
+        if isinstance(raw, dict):
+            return {k: convert(v) for k, v in raw.items()}
+
+        return raw
+
+    return convert
+
+
+def dict_to_params(d):
+    return [pytest.param(*item, id=id) for id, item in d.items()]