diff --git a/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_production_streams.py b/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_production_streams.py
index 6becf80e9fd2a8945a1387d1bdffe7d12ea6bb28..a3e982c3c5bcf368696a6298c11c47c33cd2422c 100644
--- a/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_production_streams.py
+++ b/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_production_streams.py
@@ -17,14 +17,14 @@ from RecoConf.hlt2_global_reco import make_fastest_reconstruction
 from Hlt2Conf.settings.hlt2_pp_commissioning import _make_streams
 import re
 import json
+from PRConfig.bandwidth_helpers import FileNameHelper
 
-import os
-if not os.path.exists('tmp/MDF'): os.system('mkdir -p tmp/MDF')
-if not os.path.exists('tmp/Output'): os.system('mkdir -p tmp/Output')
-
-options.output_file = 'tmp/MDF/baseline-production-{stream}.mdf'
+fname_helper = FileNameHelper(process="hlt2")
+fname_helper.make_tmp_dirs()
+options.output_file = fname_helper.mdf_fname_for_Moore(
+    stream_config="production")
 options.output_type = 'MDF'
-options.output_manifest_file = 'tmp/MDF/baseline-production-streams.tck.json'
+options.output_manifest_file = fname_helper.tck(stream_config="production")
 
 to_remove = [
     'Hlt2Lumi',
@@ -86,7 +86,9 @@ def make_module_streams():
                 linedict.update({stream: filtered})  # Modify dictionary
 
     # Write out stream configuration to JSON file for use later in the test
-    with open('tmp/Output/hlt2-production-stream-config.json', 'w') as f:
+    with open(
+            fname_helper.stream_config_json_path(stream_config="production"),
+            'w') as f:
         json.dump({k: [line.name for line in v]
                    for k, v in linedict.items()}, f)
 
diff --git a/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_streamless.py b/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_streamless.py
deleted file mode 100644
index 3a12025c94b686432bbfcdf825aedb77ea421d0c..0000000000000000000000000000000000000000
--- a/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_streamless.py
+++ /dev/null
@@ -1,111 +0,0 @@
-###############################################################################
-# (c) Copyright 2000-2023 CERN for the benefit of the LHCb Collaboration      #
-#                                                                             #
-# This software is distributed under the terms of the GNU General Public      #
-# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
-#                                                                             #
-# In applying this licence, CERN does not waive the privileges and immunities #
-# granted to it by virtue of its status as an Intergovernmental Organization  #
-# or submit itself to any jurisdiction.                                       #
-###############################################################################
-
-from Moore import options, run_moore
-from RecoConf.global_tools import stateProvider_with_simplified_geom
-from RecoConf.reconstruction_objects import reconstruction
-from RecoConf.hlt2_global_reco import reconstruction as hlt2_reconstruction
-from RecoConf.hlt2_global_reco import make_fastest_reconstruction
-import Moore
-from Moore.streams_hlt2 import HLT2_REPORT_RAW_BANK_TYPES
-import re
-
-from Hlt2Conf.lines import (
-    b_to_open_charm,
-    inclusive_detached_dilepton,
-    rd,
-    bandq,
-    topological_b,
-    pid,
-    qee,
-    charm,
-    b_to_charmonia,
-    semileptonic,
-    monitoring,
-    charmonium_to_dimuon,
-    bnoc,
-    trackeff,
-    ift,
-)
-
-modules = [
-    b_to_open_charm, rd, bandq, charm, b_to_charmonia, semileptonic, bnoc,
-    charmonium_to_dimuon, qee, topological_b, inclusive_detached_dilepton, pid,
-    monitoring, trackeff, ift
-]
-
-import os
-if not os.path.exists('tmp/MDF'): os.system('mkdir -p tmp/MDF')
-
-options.output_file = 'tmp/MDF/baseline-{stream}-all.mdf'
-options.output_type = 'MDF'
-options.output_manifest_file = 'tmp/MDF/baseline-streamless-all.tck.json'
-
-# removed due to hlt1_filter_codes, which dont work on 2023 HLT1-filtered minbias
-to_remove = [
-    'Hlt2IFT_SMOG2GECPassthrough', 'Hlt2IFT_SMOG2LumiPassthrough',
-    'Hlt2IFT_SMOG2MBPassthrough', 'Hlt2IFT_Femtoscopy_InclLambdaLL',
-    'Hlt2IFT_Femtoscopy_InclXiLLL', 'Hlt2IFT_Femtoscopy_InclOmegaLLL',
-    'Hlt2IFT_Femtoscopy_LambdaP', 'Hlt2IFT_Femtoscopy_LambdaP_lowK',
-    'Hlt2IFT_Femtoscopy_LambdaLambda', 'Hlt2IFT_Femtoscopy_LambdaLambda_lowK',
-    'Hlt2IFT_Femtoscopy_XiP', 'Hlt2IFT_Femtoscopy_XiP_lowK',
-    'Hlt2IFT_Femtoscopy_XiLambda', 'Hlt2IFT_Femtoscopy_XiLambda_lowK',
-    'Hlt2IFT_Femtoscopy_XiXi', 'Hlt2IFT_Femtoscopy_OmegaP',
-    'Hlt2IFT_Femtoscopy_OmegaP', 'Hlt2IFT_Femtoscopy_OmegaP_lowK',
-    'Hlt2IFT_Femtoscopy_OmegaLambda', 'Hlt2IFT_Femtoscopy_OmegaXi',
-    'Hlt2IFT_Femtoscopy_OmegaOmega', 'Hlt2QEE_DiElectronPrompt_PersistPhotons',
-    'Hlt2QEE_DiElectronPrompt_PersistPhotons_FULL',
-    'Hlt2QEE_DiElectronDisplaced_PersistPhotons',
-    'Hlt2QEE_DiElectronDisplaced_PersistPhotons_FULL',
-    'Hlt2QEE_DiElectronPrompt_PersistPhotonsSS',
-    'Hlt2QEE_DiElectronDisplaced_PersistPhotonsSS'
-]
-
-
-def make_module_lines(modules):
-
-    builders = []
-    for mod in modules:
-        try:
-            lines = mod.all_lines
-        except AttributeError:
-            raise AttributeError(
-                'line module {} does not define mandatory `all_lines`'.format(
-                    mod.__name__))
-        for name, builder in lines.items():
-            if all([
-                    re.search(regex_pattern, name) is None
-                    for regex_pattern in to_remove
-            ]):
-                builders.append(builder())
-            else:
-                print(f"Manually removed {name} line.")
-
-    return builders
-
-
-def make_module_streams():
-    return dict(streamless=make_module_lines(modules))
-
-
-banks_default = list(HLT2_REPORT_RAW_BANK_TYPES)
-
-Moore.streams_hlt2.DETECTOR_RAW_BANK_TYPES_PER_STREAM = {
-    'streamless': banks_default
-}
-Moore.streams_hlt2.stream_bits = {'streamless': 66}
-
-# Only running thread-safe lines
-public_tools = [stateProvider_with_simplified_geom()]
-with reconstruction.bind(from_file=False),\
-    hlt2_reconstruction.bind(make_reconstruction=make_fastest_reconstruction):
-    config = run_moore(
-        options, make_module_streams, public_tools, exclude_incompatible=True)
diff --git a/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_wg_streams.py b/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_wg_streams.py
index 601b61b46b33b4b218d0035702b72a52e71c4dc5..e13cc848cc54cf821280b186c3fbe7026c1a20c2 100644
--- a/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_wg_streams.py
+++ b/Hlt/Hlt2Conf/tests/options/bandwidth/hlt2_bandwidth_wg_streams.py
@@ -16,6 +16,7 @@ from RecoConf.hlt2_global_reco import reconstruction as hlt2_reconstruction
 from RecoConf.hlt2_global_reco import make_fastest_reconstruction
 import Moore
 from Moore.streams_hlt2 import DETECTOR_RAW_BANK_TYPES, HLT2_REPORT_RAW_BANK_TYPES
+from PRConfig.bandwidth_helpers import FileNameHelper
 import json
 import re
 
@@ -37,12 +38,29 @@ from Hlt2Conf.lines import (
     ift,
 )
 
-import os
-if not os.path.exists('tmp/MDF'): os.system('mkdir -p tmp/MDF')
+MODULES = dict(
+    b_to_open_charm=b_to_open_charm,
+    dilepton=inclusive_detached_dilepton,
+    rd=rd,
+    bandq=bandq,
+    topo_b=topological_b,
+    pid=pid,
+    qee=qee,
+    charm=charm,
+    b_to_charmonia=b_to_charmonia,
+    slepton=semileptonic,
+    monitoring=monitoring,
+    c_to_dimuon=charmonium_to_dimuon,
+    bnoc=bnoc,
+    trackeff=trackeff,
+    ift=ift,
+)
 
-options.output_file = 'tmp/MDF/baseline-wg-{stream}.mdf'
+fname_helper = FileNameHelper(process="hlt2")
+fname_helper.make_tmp_dirs()
+options.output_file = fname_helper.mdf_fname_for_Moore(stream_config="wg")
 options.output_type = 'MDF'
-options.output_manifest_file = 'tmp/MDF/baseline-wg-streams.tck.json'
+options.output_manifest_file = fname_helper.tck(stream_config="wg")
 
 # removed due to hlt1_filter_codes, which dont work on 2023 HLT1-filtered minbias
 to_remove = [
@@ -65,16 +83,11 @@ to_remove = [
 ]
 
 
-def make_module_lines(modules):
+def make_module_lines(mod):
 
     builders = []
-    for mod in modules:
-        try:
-            lines = mod.all_lines
-        except AttributeError:
-            raise AttributeError(
-                'line module {} does not define mandatory `all_lines`'.format(
-                    mod.__name__))
+    try:
+        lines = mod.all_lines
         for name, builder in lines.items():
             if all([
                     re.search(regex_pattern, name) is None
@@ -83,32 +96,25 @@ def make_module_lines(modules):
                 builders.append(builder())
             else:
                 print(f"Manually removed {name} line.")
+    except AttributeError:
+        raise AttributeError(
+            f'line module {mod.__name__} does not define mandatory `all_lines`'
+        )
 
     return builders
 
 
 def make_module_streams():
 
-    linedict = dict(
-        b_to_open_charm=make_module_lines([b_to_open_charm]),
-        dilepton=make_module_lines([inclusive_detached_dilepton]),
-        rd=make_module_lines([rd]),
-        bandq=make_module_lines([bandq]),
-        topo_b=make_module_lines([topological_b]),
-        pid=make_module_lines([pid]),
-        qee=make_module_lines([qee]),
-        charm=make_module_lines([charm]),
-        b_to_charmonia=make_module_lines([b_to_charmonia]),
-        slepton=make_module_lines([semileptonic]),
-        monitoring=make_module_lines([monitoring]),
-        c_to_dimuon=make_module_lines([charmonium_to_dimuon]),
-        bnoc=make_module_lines([bnoc]),
-        trackeff=make_module_lines([trackeff]),
-        ift=make_module_lines([ift]),
-    )
+    linedict = {}
+    for mod_name, module in MODULES.items():
+        builders = make_module_lines(module)
+        if builders:
+            linedict[mod_name] = builders
 
     # Write out stream configuration to JSON file for use later in the test
-    with open('tmp/Output/hlt2-wg-stream-config.json', 'w') as f:
+    with open(fname_helper.stream_config_json_path(stream_config="wg"),
+              'w') as f:
         json.dump({k: [line.name for line in v]
                    for k, v in linedict.items()}, f)
 
diff --git a/Hlt/Hlt2Conf/tests/options/bandwidth/spruce_bandwidth_streamless.py b/Hlt/Hlt2Conf/tests/options/bandwidth/spruce_bandwidth_streamless.py
deleted file mode 100644
index 65af3500485b054d76c40bb48b5a31da73414ca2..0000000000000000000000000000000000000000
--- a/Hlt/Hlt2Conf/tests/options/bandwidth/spruce_bandwidth_streamless.py
+++ /dev/null
@@ -1,91 +0,0 @@
-###############################################################################
-# (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration           #
-#                                                                             #
-# This software is distributed under the terms of the GNU General Public      #
-# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
-#                                                                             #
-# In applying this licence, CERN does not waive the privileges and immunities #
-# granted to it by virtue of its status as an Intergovernmental Organization  #
-# or submit itself to any jurisdiction.                                       #
-###############################################################################
-'''
-Test option for the Sprucing bandwidth test in LHCbPR
-
-The streaming configuration in this test is `streamless`,
-which means all lines are booked into one single stream
-
-To launch it in Moore, run with
-    ./run gaudirun.py spruce_bandwidth_input.py spruce_bandwidth_streamless.py
-'''
-from Moore import options, run_moore
-from RecoConf.global_tools import stateProvider_with_simplified_geom
-from RecoConf.reconstruction_objects import reconstruction
-import Moore
-import Moore.streams_spruce
-from PyConf.application import metainfo_repos
-import logging
-log = logging.getLogger()
-
-from Moore.persistence.hlt2_tistos import list_of_full_stream_lines
-from Hlt2Conf.sprucing_settings.fixed_line_configs import lines_for_TISTOS_BW_Aug2023 as lines_for_TISTOS
-
-from Hlt2Conf.lines import (
-    b_to_open_charm,
-    rd,
-    bandq,
-    qee,
-    charm,
-    b_to_charmonia,
-    semileptonic,
-    charmonium_to_dimuon,
-    bnoc,
-)
-
-modules = [
-    b_to_open_charm, rd, bandq, charm, b_to_charmonia, semileptonic, bnoc,
-    charmonium_to_dimuon, qee
-]
-
-import os
-if not os.path.exists('tmp/MDF'): os.system('mkdir -p tmp/MDF')
-
-metainfo_repos.global_bind(extra_central_tags=['key-ac5f2a28'])
-options.input_raw_format = 0.3
-options.input_process = 'Hlt2'
-options.output_file = 'tmp/MDF/baseline-{stream}-all.mdf'
-options.output_type = 'MDF'
-options.output_manifest_file = 'tmp/MDF/baseline-streamless-all.tck.json'
-
-
-def make_module_lines(modules):
-
-    builders = []
-    for mod in modules:
-        try:
-            lines = mod.sprucing_lines
-            if 'SpruceB2OC_BdToDsmK_DsmToHHH_FEST' in lines.keys():
-                print("Removing SpruceB2OC_BdToDsmK_DsmToHHH_FEST")
-                lines.pop('SpruceB2OC_BdToDsmK_DsmToHHH_FEST')
-        except AttributeError:
-            log.info('line module {} does not define `sprucing_lines`'.format(
-                mod.__name__))
-            continue
-        for name, builder in lines.items():
-            builders.append(builder())
-
-    return builders
-
-
-def make_module_streams():
-    return dict(streamless=make_module_lines(modules))
-
-
-Moore.streams_spruce.stream_banks = {'streamless': []}
-
-# Only running thread-safe lines
-public_tools = [stateProvider_with_simplified_geom()]
-with reconstruction.bind(
-        from_file=True,
-        spruce=True), list_of_full_stream_lines.bind(lines=lines_for_TISTOS):
-    config = run_moore(
-        options, make_module_streams, public_tools, exclude_incompatible=True)
diff --git a/Hlt/Hlt2Conf/tests/options/bandwidth/spruce_bandwidth_wg_streams.py b/Hlt/Hlt2Conf/tests/options/bandwidth/spruce_bandwidth_wg_streams.py
index bd8dc83206b627d30659ca833cb180dd4fe643dd..d1feaa765feaadf17a94716c6abcfafd341d073a 100644
--- a/Hlt/Hlt2Conf/tests/options/bandwidth/spruce_bandwidth_wg_streams.py
+++ b/Hlt/Hlt2Conf/tests/options/bandwidth/spruce_bandwidth_wg_streams.py
@@ -25,6 +25,8 @@ import Moore
 import Moore.streams_spruce
 from PyConf.application import metainfo_repos
 import logging
+import json
+from PRConfig.bandwidth_helpers import FileNameHelper
 log = logging.getLogger()
 
 from Moore.persistence.hlt2_tistos import list_of_full_stream_lines
@@ -42,72 +44,66 @@ from Hlt2Conf.lines import (
     bnoc,
 )
 
-modules = [
-    b_to_open_charm, rd, bandq, qee, charm, b_to_charmonia, semileptonic,
-    charmonium_to_dimuon, bnoc
-]
-module_names = [
-    'b_to_open_charm',
-    'rd',
-    'bandq',
-    'qee',
-    'charm',
-    'b_to_charmonia',
-    'slepton',
-    'c_to_dimuon',
-    'bnoc',
-]
-
-import os
-if not os.path.exists('tmp/MDF'): os.system('mkdir -p tmp/MDF')
+MODULES = {
+    "b_to_open_charm": b_to_open_charm,
+    'rd': rd,
+    'bandq': bandq,
+    'qee': qee,
+    'charm': charm,
+    'b_to_charmonia': b_to_charmonia,
+    'slepton': semileptonic,
+    'c_to_dimuon': charmonium_to_dimuon,
+    'bnoc': bnoc
+}
 
 metainfo_repos.global_bind(extra_central_tags=['key-ac5f2a28'])
 options.input_raw_format = 0.3
 options.input_process = 'Hlt2'
-options.output_file = 'tmp/MDF/baseline-wg-{stream}.mdf'
+
+fname_helper = FileNameHelper(process="spruce")
+fname_helper.make_tmp_dirs()
+options.output_file = fname_helper.mdf_fname_for_Moore(stream_config="wg")
 options.output_type = 'MDF'
-options.output_manifest_file = 'tmp/MDF/baseline-wg-streams.tck.json'
+options.output_manifest_file = fname_helper.tck(stream_config="wg")
 
 
-def make_module_lines(modules):
+def make_module_lines(mod):
 
     builders = []
-    for mod in modules:
-        try:
-            lines = mod.sprucing_lines
-            if 'SpruceB2OC_BdToDsmK_DsmToHHH_FEST' in lines.keys():
-                print("Removing SpruceB2OC_BdToDsmK_DsmToHHH_FEST")
-                lines.pop('SpruceB2OC_BdToDsmK_DsmToHHH_FEST')
-        except AttributeError:
-            log.info('line module {} does not define `sprucing_lines`'.format(
-                mod.__name__))
-            continue
-        for name, builder in lines.items():
+    try:
+        lines = mod.sprucing_lines
+        if 'SpruceB2OC_BdToDsmK_DsmToHHH_FEST' in lines.keys():
+            print("Removing SpruceB2OC_BdToDsmK_DsmToHHH_FEST")
+            lines.pop('SpruceB2OC_BdToDsmK_DsmToHHH_FEST')
+        for builder in lines.values():
             builders.append(builder())
+    except AttributeError:
+        log.info(
+            f'line module {mod.__name__} does not define `sprucing_lines`')
 
     return builders
 
 
 def make_module_streams():
 
-    linedict = dict(
-        b_to_open_charm=make_module_lines([b_to_open_charm]),
-        rd=make_module_lines([rd]),
-        bandq=make_module_lines([bandq]),
-        qee=make_module_lines([qee]),
-        charm=make_module_lines([charm]),
-        b_to_charmonia=make_module_lines([b_to_charmonia]),
-        slepton=make_module_lines([semileptonic]),
-        c_to_dimuon=make_module_lines([charmonium_to_dimuon]),
-        bnoc=make_module_lines([bnoc]),
-    )
+    linedict = {}
+    for mod_name, module in MODULES.items():
+        builders = make_module_lines(module)
+        if builders:
+            linedict[mod_name] = builders
+
+    # Write out stream configuration to JSON file for use later in the test
+    with open(fname_helper.stream_config_json_path(stream_config="wg"),
+              'w') as f:
+        json.dump({k: [line.name for line in v]
+                   for k, v in linedict.items()}, f)
 
     return linedict
 
 
 Moore.streams_spruce.stream_banks = {
     module_name: []
-    for module_name in module_names
+    for module_name in MODULES.keys()
 }
 
 # Only running thread-safe lines