diff --git a/HLT/Trigger/TrigControl/TrigCommon/CMakeLists.txt b/HLT/Trigger/TrigControl/TrigCommon/CMakeLists.txt
index 4396893f04e4d9a90bdfc2fb4f80c49c064fbf41..e1f85d545ba5b1a0dc524b3511b3284d996ca575 100644
--- a/HLT/Trigger/TrigControl/TrigCommon/CMakeLists.txt
+++ b/HLT/Trigger/TrigControl/TrigCommon/CMakeLists.txt
@@ -19,5 +19,12 @@ atlas_add_test( flake8
    POST_EXEC_SCRIPT nopost.sh )
 
 # Tests:
-atlas_add_test( AthHLT
-   SCRIPT python ${CMAKE_CURRENT_SOURCE_DIR}/python/AthHLT.py )
+atlas_add_test( test_AthHLT
+   SCRIPT python ${CMAKE_CURRENT_SOURCE_DIR}/python/AthHLT.py
+   POST_EXEC_SCRIPT nopost.sh )
+
+atlas_add_test( athenaHLT_jo_noopts
+   SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/share/test_athenaHLT.sh dummy.py)
+
+atlas_add_test( athenaHLT_jo_allopts
+   SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/share/test_athenaHLT.sh --number-of-events 3 --skip-events 7 -l ERROR,FATAL -c 'x=1' -c 'y=2' -C 'x=2' -o out.data --threads 2 --nprocs 4 --timeout 777 --python-setup mysetup.py --partition mypart dummy.py)
diff --git a/HLT/Trigger/TrigControl/TrigCommon/bin/athenaHLT.py b/HLT/Trigger/TrigControl/TrigCommon/bin/athenaHLT.py
index f9b355415ef49c8953c4e64b3bbdbe50e1de76a8..4a9ad45ee0846b845559ca1dc50bdae2679d7164 100755
--- a/HLT/Trigger/TrigControl/TrigCommon/bin/athenaHLT.py
+++ b/HLT/Trigger/TrigControl/TrigCommon/bin/athenaHLT.py
@@ -45,9 +45,9 @@ from TrigCommon import AthHLT
 from AthenaCommon.Logging import logging
 log = logging.getLogger('athenaHLT')
 
-#
-# The following arg_* methods are used as custom types in argparse
-#
+##
+## The following arg_* methods are used as custom types in argparse
+##
 def arg_sor_time(s):
    """Convert possible SOR time arguments to an OWLTime compatible string"""
    fmt = '%d/%m/%y %H:%M:%S.%f'
@@ -119,7 +119,10 @@ def update_nested_dict(d, u):
 
 
 def HLTMPPy_cfgdict(args):
-   """Create the configuration dictionary as expected by HLTMPPy"""
+   """
+   Create the configuration dictionary as expected by HLTMPPy as defined in
+   https://gitlab.cern.ch/atlas-tdaq-software/HLTMPPU/blob/master/python/HLTMPPy/runner.py
+   """
 
    cdict = {}
    cdict['HLTMPPU'] = {
@@ -178,7 +181,7 @@ def HLTMPPy_cfgdict(args):
    }
 
    cdict['trigger'] = {
-      'library': ['TrigServices', 'TrigPSC', 'TrigConfigSvc'],
+      'library': ['TrigServices', 'TrigPSC'],
       'joType' : args.joboptionsvc_type
    }
    if not args.use_database:      # job options
@@ -244,6 +247,7 @@ def main():
                                     add_help=False)
    parser.expert_groups = []   # Keep list of expert option groups
 
+   ## Global options
    g = parser.add_argument_group('Options')
    g.add_argument('jobOptions', help='job options file')
    g.add_argument('--file', '-f', action='append', required=True, help='input RAW file')
@@ -260,6 +264,7 @@ def main():
    g.add_argument('--interactive', '-i', action='store_true', help='interactive mode')
    g.add_argument('--help', '-h', nargs='?', choices=['all'], action=MyHelp, help='show help')
 
+   ## Performance and debugging
    g = parser.add_argument_group('Performance and debugging')
    g.add_argument('--perfmon', action='store_true', help='enable PerfMon')
    g.add_argument('--leak-check', metavar='<stage>', nargs='?', const='execute',
@@ -272,6 +277,7 @@ def main():
    g.add_argument('--show-includes', '-s', action='store_true', help='show printout of included files')
    g.add_argument('--timeout', metavar='SEC', default=3600*10, help='timeout in seconds')
 
+   ## Database
    g = parser.add_argument_group('Database')
    g.add_argument('--use-database', '-b', action='store_true', help='configure from trigger database')
    g.add_argument('--db-type', default='Coral', choices=['MySQL','Oracle','SQLite','Coral'], help='database type')
@@ -280,12 +286,14 @@ def main():
    g.add_argument('--l1psk', type=int, default=0, help='L1 prescale key')
    g.add_argument('--hltpsk', type=int, default=0, help='HLT prescale key')
 
+   ## Online histogramming
    g = parser.add_argument_group('Online Histogramming')
    g.add_argument('--oh-monitoring', '-M', action='store_true',
                   help='enable OH monitoring')
    g.add_argument('--oh-interval', metavar='SEC', type=int, default=5,
                   help='seconds between histogram publications.')
 
+   ## Conditions
    g = parser.add_argument_group('Conditions')
    g.add_argument('--run-number', '-R', metavar='RUN', type=int,
                   help='run number (if None, read from first event)')
@@ -297,7 +305,7 @@ def main():
    g.add_argument('--detector-mask', metavar='MASK', type=arg_detector_mask,
                   help='detector mask (if None, read from COOL)')
 
-   # Expert options
+   ## Expert options
    g = parser.add_argument_group('Expert')
    parser.expert_groups.append(g)
    g.add_argument('--joboptionsvc-type', metavar='TYPE', default='JobOptionsSvc', help='JobOptionsSvc type')
@@ -323,7 +331,7 @@ def main():
    # update parameters based on SOR
    update_run_params(args)
 
-   # configure HLTMPPU and run
+   # get HLTMPPY config dictionary
    cdict = HLTMPPy_cfgdict(args)
 
    # Apply any expert-level overrides
@@ -332,8 +340,10 @@ def main():
    # Modify pre/postcommands if necessary
    update_pcommands(args, cdict)
 
+   # Run HLTMPPU
    from HLTMPPy.runner import runHLTMPPy
    runHLTMPPy(cdict)
 
+
 if "__main__" in __name__:
-   main()
+   sys.exit(main())
diff --git a/HLT/Trigger/TrigControl/TrigCommon/share/athenaHLT_jo_allopts.ref b/HLT/Trigger/TrigControl/TrigCommon/share/athenaHLT_jo_allopts.ref
new file mode 100644
index 0000000000000000000000000000000000000000..9cda86352a9cb6810fa0d1f6828b8916ba6e9a72
--- /dev/null
+++ b/HLT/Trigger/TrigControl/TrigCommon/share/athenaHLT_jo_allopts.ref
@@ -0,0 +1,166 @@
+<Configuration>
+  <HLTMPPUApplication>
+    <numForks>4</numForks>
+    <childLogRoot>/scratch/fwinkl/athenaHLT/HLT/Trigger/TrigControl/TrigCommon/unitTestRun</childLogRoot>
+    <InfoServiceLibrary>MonSvcInfoService</InfoServiceLibrary>
+    <softTimeoutFraction>0.9</softTimeoutFraction>
+    <HLTImplementationLibraries>
+      <library>TrigServices</library>
+      <library>TrigPSC</library>
+    </HLTImplementationLibraries>
+    <UID>HLTMPPy</UID>
+    <HardTimeout>777</HardTimeout>
+    <finalizeTimeout>120</finalizeTimeout>
+    <numberOfEventSlots>2</numberOfEventSlots>
+    <DataSourceLibrary>DFFileBackend</DataSourceLibrary>
+    <numberOfAthenaMTThreads>2</numberOfAthenaMTThreads>
+    <DataSource>
+      <HLTDFFileBackend>
+        <preload>False</preload>
+        <numEvents>3</numEvents>
+        <start_id>1</start_id>
+        <library>DFFileBackend</library>
+        <fileOffset>-1</fileOffset>
+        <UID>DataSource-is-DCM</UID>
+        <compressionLevel>2</compressionLevel>
+        <skipEvents>7</skipEvents>
+        <compressionFormat>ZLIB</compressionFormat>
+        <outputFileName>out.data</outputFileName>
+        <loopOverFiles>False</loopOverFiles>
+        <fileList>
+          <file>dummy.data</file>
+        </fileList>
+        <extraL1Robs/>
+      </HLTDFFileBackend>
+    </DataSource>
+    <InfoService>
+      <HLTMonInfoImpl>
+        <UID>hltMonSvc</UID>
+        <library>MonSvcInfoService</library>
+        <ConfigurationRules>
+          <ConfigurationRuleBundle>
+            <UID>HltpuConfigurationRuleBundle</UID>
+            <Rules>
+              <ConfigurationRule>
+                <ExcludeFilter></ExcludeFilter>
+                <Name>Dumm</Name>
+                <UID>HltpuOHRule</UID>
+                <Parameters>
+                  <OHPublishingParameters>
+                    <PublishInterval>5</PublishInterval>
+                    <ROOTProvider>${TDAQ_APPLICATION_NAME}</ROOTProvider>
+                    <OHServer>${TDAQ_OH_SERVER=HLT-Histogramming}</OHServer>
+                    <UID>HltpuOHPublishingParameters</UID>
+                    <NumberOfSlots>5</NumberOfSlots>
+                  </OHPublishingParameters>
+                </Parameters>
+                <IncludeFilter>.*</IncludeFilter>
+              </ConfigurationRule>
+              <ConfigurationRule>
+                <ExcludeFilter></ExcludeFilter>
+                <Name>DummDumm</Name>
+                <UID>HltpuISRule</UID>
+                <Parameters>
+                  <ISPublishingParameters>
+                    <PublishInterval>10</PublishInterval>
+                    <UID>HltpuISPublishingParameters</UID>
+                    <NumberOfSlots>1</NumberOfSlots>
+                    <ISServer>${TDAQ_IS_SERVER=DF}</ISServer>
+                  </ISPublishingParameters>
+                </Parameters>
+                <IncludeFilter>.*</IncludeFilter>
+              </ConfigurationRule>
+            </Rules>
+          </ConfigurationRuleBundle>
+        </ConfigurationRules>
+      </HLTMonInfoImpl>
+    </InfoService>
+  </HLTMPPUApplication>
+  <Partition>
+    <UID>mypart</UID>
+    <LogRoot>/scratch/fwinkl/athenaHLT/HLT/Trigger/TrigControl/TrigCommon/unitTestRun</LogRoot>
+    <TriggerConfiguration>
+      <TriggerConfiguration>
+        <L1TriggerConfiguration>
+          <L1TriggerConfiguration>
+            <ConfigureLvl1MenuFrom>DB</ConfigureLvl1MenuFrom>
+            <Lvl1BunchGroupKey>0</Lvl1BunchGroupKey>
+            <UID>L1TrigConf</UID>
+            <Lvl1PrescaleKey>0</Lvl1PrescaleKey>
+          </L1TriggerConfiguration>
+        </L1TriggerConfiguration>
+        <hlt>
+          <HLTImplementationJobOptions>
+            <libraries>
+              <library>TrigServices</library>
+              <library>TrigPSC</library>
+            </libraries>
+            <preCommands>
+              <preCommand>x=1</preCommand>
+              <preCommand>y=2</preCommand>
+              <preCommand>_run_number=327265</preCommand>
+              <preCommand>include('TrigServices/OfflineTHistSvc.py')</preCommand>
+            </preCommands>
+            <postCommands>
+              <postCommand>x=2</postCommand>
+            </postCommands>
+            <UID>HLTImplementationJobOptions-1</UID>
+            <evtSel>NONE</evtSel>
+            <HLTCommonParameters>
+              <HLTCommonParameters>
+                <factoryName></factoryName>
+                <dllName></dllName>
+                <messageSvcType>TrigMessageSvc</messageSvcType>
+                <jobOptionsSvcType>JobOptionsSvc</jobOptionsSvcType>
+              </HLTCommonParameters>
+            </HLTCommonParameters>
+            <logLevels>
+              <logLevel>INFO</logLevel>
+              <logLevel>ERROR</logLevel>
+            </logLevels>
+            <pythonSetupFile>mysetup.py</pythonSetupFile>
+            <jobOptionsPath>dummy.py</jobOptionsPath>
+          </HLTImplementationJobOptions>
+        </hlt>
+        <UID>JobOptionsTriggerConfig-1</UID>
+        <TriggerDBConnection>
+          <TriggerDBConnection>
+            <Name>dummy</Name>
+            <Server>TRIGGERDB</Server>
+            <Alias>TRIGGERDB</Alias>
+            <User></User>
+            <Password></Password>
+            <Type>Coral</Type>
+            <SuperMasterKey>0</SuperMasterKey>
+          </TriggerDBConnection>
+        </TriggerDBConnection>
+      </TriggerConfiguration>
+    </TriggerConfiguration>
+  </Partition>
+  <ROS2ROBS/>
+</Configuration>
+<RunParams>
+  <totalTime>0</totalTime>
+  <run_type>Physics</run_type>
+  <timeEOR>1/1/70 01:00:00</timeEOR>
+  <det_mask>00000000000000000001fffffffffff7</det_mask>
+  <beam_type>0</beam_type>
+  <filename_tag></filename_tag>
+  <max_events>0</max_events>
+  <run_number>327265</run_number>
+  <timeSOR>22/11/18 11:02:32.703856</timeSOR>
+  <trigger_type>0</trigger_type>
+  <T0_project_tag></T0_project_tag>
+  <beam_energy>0</beam_energy>
+  <recording_enabled>0</recording_enabled>
+</RunParams>
+<Magnets>
+  <ToroidsCurrent>
+    <ts>22/11/18 11:02:32.703856</ts>
+    <value>20400</value>
+  </ToroidsCurrent>
+  <SolenoidCurrent>
+    <ts>22/11/18 11:02:32.703856</ts>
+    <value>7730</value>
+  </SolenoidCurrent>
+</Magnets>
diff --git a/HLT/Trigger/TrigControl/TrigCommon/share/athenaHLT_jo_noopts.ref b/HLT/Trigger/TrigControl/TrigCommon/share/athenaHLT_jo_noopts.ref
new file mode 100644
index 0000000000000000000000000000000000000000..6083e1b27b98483f5d21fbdef7bfd9089da082bf
--- /dev/null
+++ b/HLT/Trigger/TrigControl/TrigCommon/share/athenaHLT_jo_noopts.ref
@@ -0,0 +1,161 @@
+<Configuration>
+  <HLTMPPUApplication>
+    <numForks>1</numForks>
+    <childLogRoot>/scratch/fwinkl/athenaHLT/HLT/Trigger/TrigControl/TrigCommon/unitTestRun</childLogRoot>
+    <InfoServiceLibrary>MonSvcInfoService</InfoServiceLibrary>
+    <softTimeoutFraction>0.9</softTimeoutFraction>
+    <HLTImplementationLibraries>
+      <library>TrigServices</library>
+      <library>TrigPSC</library>
+    </HLTImplementationLibraries>
+    <UID>HLTMPPy</UID>
+    <HardTimeout>36000</HardTimeout>
+    <finalizeTimeout>120</finalizeTimeout>
+    <numberOfEventSlots>1</numberOfEventSlots>
+    <DataSourceLibrary>DFFileBackend</DataSourceLibrary>
+    <numberOfAthenaMTThreads>1</numberOfAthenaMTThreads>
+    <DataSource>
+      <HLTDFFileBackend>
+        <preload>False</preload>
+        <numEvents>-1</numEvents>
+        <start_id>1</start_id>
+        <library>DFFileBackend</library>
+        <fileOffset>-1</fileOffset>
+        <UID>DataSource-is-DCM</UID>
+        <compressionLevel>2</compressionLevel>
+        <skipEvents>0</skipEvents>
+        <compressionFormat>ZLIB</compressionFormat>
+        <loopOverFiles>False</loopOverFiles>
+        <fileList>
+          <file>dummy.data</file>
+        </fileList>
+        <extraL1Robs/>
+      </HLTDFFileBackend>
+    </DataSource>
+    <InfoService>
+      <HLTMonInfoImpl>
+        <UID>hltMonSvc</UID>
+        <library>MonSvcInfoService</library>
+        <ConfigurationRules>
+          <ConfigurationRuleBundle>
+            <UID>HltpuConfigurationRuleBundle</UID>
+            <Rules>
+              <ConfigurationRule>
+                <ExcludeFilter></ExcludeFilter>
+                <Name>Dumm</Name>
+                <UID>HltpuOHRule</UID>
+                <Parameters>
+                  <OHPublishingParameters>
+                    <PublishInterval>5</PublishInterval>
+                    <ROOTProvider>${TDAQ_APPLICATION_NAME}</ROOTProvider>
+                    <OHServer>${TDAQ_OH_SERVER=HLT-Histogramming}</OHServer>
+                    <UID>HltpuOHPublishingParameters</UID>
+                    <NumberOfSlots>5</NumberOfSlots>
+                  </OHPublishingParameters>
+                </Parameters>
+                <IncludeFilter>.*</IncludeFilter>
+              </ConfigurationRule>
+              <ConfigurationRule>
+                <ExcludeFilter></ExcludeFilter>
+                <Name>DummDumm</Name>
+                <UID>HltpuISRule</UID>
+                <Parameters>
+                  <ISPublishingParameters>
+                    <PublishInterval>10</PublishInterval>
+                    <UID>HltpuISPublishingParameters</UID>
+                    <NumberOfSlots>1</NumberOfSlots>
+                    <ISServer>${TDAQ_IS_SERVER=DF}</ISServer>
+                  </ISPublishingParameters>
+                </Parameters>
+                <IncludeFilter>.*</IncludeFilter>
+              </ConfigurationRule>
+            </Rules>
+          </ConfigurationRuleBundle>
+        </ConfigurationRules>
+      </HLTMonInfoImpl>
+    </InfoService>
+  </HLTMPPUApplication>
+  <Partition>
+    <UID>athenaHLT</UID>
+    <LogRoot>/scratch/fwinkl/athenaHLT/HLT/Trigger/TrigControl/TrigCommon/unitTestRun</LogRoot>
+    <TriggerConfiguration>
+      <TriggerConfiguration>
+        <L1TriggerConfiguration>
+          <L1TriggerConfiguration>
+            <ConfigureLvl1MenuFrom>DB</ConfigureLvl1MenuFrom>
+            <Lvl1BunchGroupKey>0</Lvl1BunchGroupKey>
+            <UID>L1TrigConf</UID>
+            <Lvl1PrescaleKey>0</Lvl1PrescaleKey>
+          </L1TriggerConfiguration>
+        </L1TriggerConfiguration>
+        <hlt>
+          <HLTImplementationJobOptions>
+            <libraries>
+              <library>TrigServices</library>
+              <library>TrigPSC</library>
+            </libraries>
+            <preCommands>
+              <preCommand>_run_number=327265</preCommand>
+              <preCommand>include('TrigServices/OfflineTHistSvc.py')</preCommand>
+            </preCommands>
+            <postCommands/>
+            <UID>HLTImplementationJobOptions-1</UID>
+            <evtSel>NONE</evtSel>
+            <HLTCommonParameters>
+              <HLTCommonParameters>
+                <factoryName></factoryName>
+                <dllName></dllName>
+                <messageSvcType>TrigMessageSvc</messageSvcType>
+                <jobOptionsSvcType>JobOptionsSvc</jobOptionsSvcType>
+              </HLTCommonParameters>
+            </HLTCommonParameters>
+            <logLevels>
+              <logLevel>INFO</logLevel>
+              <logLevel>ERROR</logLevel>
+            </logLevels>
+            <pythonSetupFile>TrigPSC/TrigPSCPythonSetup.py</pythonSetupFile>
+            <jobOptionsPath>dummy.py</jobOptionsPath>
+          </HLTImplementationJobOptions>
+        </hlt>
+        <UID>JobOptionsTriggerConfig-1</UID>
+        <TriggerDBConnection>
+          <TriggerDBConnection>
+            <Name>dummy</Name>
+            <Server>TRIGGERDB</Server>
+            <Alias>TRIGGERDB</Alias>
+            <User></User>
+            <Password></Password>
+            <Type>Coral</Type>
+            <SuperMasterKey>0</SuperMasterKey>
+          </TriggerDBConnection>
+        </TriggerDBConnection>
+      </TriggerConfiguration>
+    </TriggerConfiguration>
+  </Partition>
+  <ROS2ROBS/>
+</Configuration>
+<RunParams>
+  <totalTime>0</totalTime>
+  <run_type>Physics</run_type>
+  <timeEOR>1/1/70 01:00:00</timeEOR>
+  <det_mask>00000000000000000001fffffffffff7</det_mask>
+  <beam_type>0</beam_type>
+  <filename_tag></filename_tag>
+  <max_events>0</max_events>
+  <run_number>327265</run_number>
+  <timeSOR>22/11/18 11:02:32.703856</timeSOR>
+  <trigger_type>0</trigger_type>
+  <T0_project_tag></T0_project_tag>
+  <beam_energy>0</beam_energy>
+  <recording_enabled>0</recording_enabled>
+</RunParams>
+<Magnets>
+  <ToroidsCurrent>
+    <ts>22/11/18 11:02:32.703856</ts>
+    <value>20400</value>
+  </ToroidsCurrent>
+  <SolenoidCurrent>
+    <ts>22/11/18 11:02:32.703856</ts>
+    <value>7730</value>
+  </SolenoidCurrent>
+</Magnets>
diff --git a/HLT/Trigger/TrigControl/TrigCommon/share/test_athenaHLT.sh b/HLT/Trigger/TrigControl/TrigCommon/share/test_athenaHLT.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4ae2f732aae7b2a6a2c9328efa268d00b9461c45
--- /dev/null
+++ b/HLT/Trigger/TrigControl/TrigCommon/share/test_athenaHLT.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+#
+# Configuration testing script for athenaHLT.py
+#
+
+test_options=$@
+
+# Cleanup any orphaned processes
+trap cleanup INT TERM EXIT
+function cleanup {
+    sid=`ps -o sess= -p $$`  # our own session id
+    pkill -9 --parent 1 --session $sid ipc_server
+    pkill -9 --parent 1 --session $sid is_server
+}
+
+# We only test the configuration stage, so these dummy values are just fine.
+# Specifying run/sor/detmask avoids the COOL lookup.
+file="dummy.data"
+run="327265"
+sortime="1542880952703855872"
+detmask="00000000000000000001fffffffffff7"
+
+# Run only config stage (exit immediately via interactive mode) and filter final ptree
+# If there was a failure, the exit code will be non-zero
+echo "e" | athenaHLT.py --file ${file} --detector-mask ${detmask} --run-number ${run} --sor-time ${sortime} --interactive ${test_options} | sed -n '/<Configuration>/,/<\/Magnets>/p;/<\/Magnets>/q' | grep '<'