diff --git a/MooreOnlineConf/options/align_analyzer.py b/MooreOnlineConf/options/align_analyzer.py
index 033c3a86e3eaf46cdf5a8a1b104cc8b592a1bf7d..8e97ce6a0402119ff642048ba9a2dfd51b433bba 100644
--- a/MooreOnlineConf/options/align_analyzer.py
+++ b/MooreOnlineConf/options/align_analyzer.py
@@ -34,10 +34,17 @@ ensure_output_dir(online_options.analyzer_output_path, online_options.tag)
 ensure_output_dir(online_options.iterator_output_path, online_options.tag)
 print(f"Will write analyzer output to {online_options.analyzer_output_path}")
 
-INPUT_DATA_PATH = Path("/calib/align/LHCb/Velo")
-files = [
-    sorted((INPUT_DATA_PATH / run).iterdir()) for run in online_options.runs
-]
+if OnlineEnv.PartitionName != "TESTALIGNMENT":
+    INPUT_DATA_PATH = Path("/calib/align/LHCb/Velo")
+
+    files = [
+        sorted((INPUT_DATA_PATH / run).iterdir())
+        for run in online_options.runs
+    ]
+else:
+    INPUT_DATA_PATH = Path("input_data")
+    files = [sorted(INPUT_DATA_PATH.iterdir())]
+
 files_per_node = distribute_files(online_options.nodes, files)
 
 utgid = os.environ["UTGID"]
@@ -66,8 +73,14 @@ Gaudi__Histograming__Sink__Root(
         histofile.with_stem(histofile.stem + "_new"))
 HistogramPersistencySvc().OutputFile = str(histofile)
 AlignAlgorithm().OutputDataFile = str(derivfile)
-DD4hepSvc().ConditionsOverlayInitPath = str(
+AlignAlgorithm().OnlineOverlayPath = str(
     online_options.iterator_output_path / "OverlayRoot")
+print("iterator path", online_options.iterator_output_path)
+DD4hepSvc().UseConditionsOverlay = True
+
+#DD4hepSvc().ConditionsOverlayInitPath = str(
+#    online_options.iterator_output_path / "OverlayRoot")
+#print("overlay dir:", DD4hepSvc().ConditionsOverlayInitPath)
 
 # input_files = ['/scratch/rmatev/aligninputfiles/00146082_00000001_1.mdf']
 # input_files = ['/scratch/rmatev/aligninputfiles2/Minbias_MagDown_Boole_lhcbhead3379_dddb-20220705_sim-20220705-vc-md100_lumi0.mdf']
@@ -92,7 +105,7 @@ application.config.enablePause = True
 application.config.execMode = 1
 application.config.numEventThreads = 4
 application.config.numStatusThreads = 1
-application.config.FILE_maxEventsIn = 1000
+application.config.FILE_maxEventsIn = 5000
 application.app.Runable = DummyRunable()
 application.app.TopAlg.insert(0, application.updateAndReset)
 application.app.EvtSel = 'NONE'
diff --git a/MooreOnlineConf/options/align_iterator.py b/MooreOnlineConf/options/align_iterator.py
index be1783f783caa45f6fa03c886d960792835cc611..c52c0965cb3d94de814150dada8bcfab6d09be51 100644
--- a/MooreOnlineConf/options/align_iterator.py
+++ b/MooreOnlineConf/options/align_iterator.py
@@ -46,9 +46,9 @@ iterator.DerivativeFiles = [
 ]
 iterator.RunNumber = min(map(int, online_options.runs))
 overlay_path = online_options.iterator_output_path / "OverlayRoot"
-overlay_path.mkdir()
+overlay_path.mkdir(exist_ok=True)
 iterator.OverlayRoot = str(overlay_path)
-
-DD4hepSvc().ConditionsOverlayInitPath = iterator.OverlayRoot
+DD4hepSvc().UseConditionsOverlay = True
+#DD4hepSvc().ConditionsOverlayInitPath = iterator.OverlayRoot
 AlignUpdateTool(name="updateTool").LogFile = str(
     online_options.iterator_output_path / "alignlog.txt")
diff --git a/MooreOnlineConf/options/align_options.py b/MooreOnlineConf/options/align_options.py
index dfec7df88c554bba4764d85976936d57dddb7bc7..080446150293f05bb54141b8098f161d5e866813 100644
--- a/MooreOnlineConf/options/align_options.py
+++ b/MooreOnlineConf/options/align_options.py
@@ -15,6 +15,8 @@ from Configurables import LHCb__Det__LbDD4hep__DD4hepSvc as DD4hepSvc
 options.input_type = 'Online'
 options.dddb_tag = 'upgrade/master'
 options.conddb_tag = 'upgrade/master'
+options.geometry_version = "trunk"
+options.conditions_version = "master"
 
 online_cond_path = '/group/online/hlt/conditions.run3/lhcb-conditions-database'
 if os.path.exists(online_cond_path):
diff --git a/MooreOnlineConf/python/MooreOnlineConf/utils.py b/MooreOnlineConf/python/MooreOnlineConf/utils.py
index 36908a3952334f41ab27e4a019c3da9ac6a0fb3f..3f1b5a0e39b91876fd31fabfcd1568bd5ed267e2 100644
--- a/MooreOnlineConf/python/MooreOnlineConf/utils.py
+++ b/MooreOnlineConf/python/MooreOnlineConf/utils.py
@@ -49,6 +49,8 @@ def chunks(lst, n):
 
 
 def distribute_files(nodes, files):
+    """
+    """
     n_files_per_run = min(len(fs) for fs in files)
     n_files_per_run_per_node = max(n_files_per_run // len(nodes), 1)
     x = list(
@@ -99,12 +101,16 @@ def alignment_options(OnlineEnv) -> OnlineAlignmentOpts:
     data_id = runs[0] if len(runs) == 1 else f"{runs[0]}-{runs[-1]}"
 
     prefix = Path()
-    if not OnlineEnv.PartitionName.startswith("TEST"):
+    if OnlineEnv.PartitionName == "LHCbA":
         prefix = Path("/calib/align")
 
     analyzer_output_path = prefix / activity / "analyzer" / data_id
     iterator_output_path = prefix / activity / "iterator" / data_id
 
+    # overwrite some options for CI test
+    if OnlineEnv.PartitionName == "TESTALIGNMENT":
+        runs = [253597]
+
     return OnlineAlignmentOpts(tag, runs, nodes, analyzer_output_path,
                                iterator_output_path)
 
diff --git a/MooreScripts/job/VeloHalf/runAnalyzer.sh b/MooreScripts/job/VeloHalf/runAnalyzer.sh
index 2642cbcb535b01f1575da876de9f6a724a04d8f6..f5f411b53f09f3dc2c435b5c0190d25dc10d9d4f 100755
--- a/MooreScripts/job/VeloHalf/runAnalyzer.sh
+++ b/MooreScripts/job/VeloHalf/runAnalyzer.sh
@@ -17,5 +17,5 @@ setup_options_path MONITORING
 exec_gaudirun \
     $MOOREONLINECONFROOT/options/verbosity.py \
     $MOOREONLINECONFROOT/options/align_options.py \
-    $HUMBOLDTROOT/options/AlignVPHalvesModules_OfflineAnalyzer.py \
+    $HUMBOLDTROOT/options/AlignVPHalvesModules_Analyzer.py \
     $MOOREONLINECONFROOT/options/align_analyzer.py
diff --git a/MooreScripts/job/runAlignDrv.sh b/MooreScripts/job/runAlignDrv.sh
index 8640bbdb443bee925618432f3f60f6a251a4bf71..92eb6d2e7878074e923e60bf2b111575d4dcba4f 100755
--- a/MooreScripts/job/runAlignDrv.sh
+++ b/MooreScripts/job/runAlignDrv.sh
@@ -12,4 +12,4 @@
 set -euo pipefail
 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
 sub_activity=${ACTIVITY#"Alignment|"}
-source ${sub_activity}/runIterator.sh
+source ${DIR}/${sub_activity}/runIterator.sh
diff --git a/MooreScripts/job/runAlignWrk.sh b/MooreScripts/job/runAlignWrk.sh
index 051b293068258628240a482f5e197dff81c030b9..2092da235c8a528ccb7e068982bc6667a3dea268 100755
--- a/MooreScripts/job/runAlignWrk.sh
+++ b/MooreScripts/job/runAlignWrk.sh
@@ -12,4 +12,4 @@
 set -euo pipefail
 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
 sub_activity=${ACTIVITY#"Alignment|"}
-source ${sub_activity}/runAnalyzer.sh
+source ${DIR}/${sub_activity}/runAnalyzer.sh
diff --git a/MooreScripts/python/MooreScripts/testbench/scenarios/alignment.py b/MooreScripts/python/MooreScripts/testbench/scenarios/alignment.py
index 52b7c2911d4e2fa6468fb10b816d02254cc84061..8b8e49f5e9bf7e653b0e028e1ef503fdaf804eb6 100644
--- a/MooreScripts/python/MooreScripts/testbench/scenarios/alignment.py
+++ b/MooreScripts/python/MooreScripts/testbench/scenarios/alignment.py
@@ -49,7 +49,7 @@ async def run(tasks, args):
     await tasks_send_command(tasks, "start")
     await tasks_wait_for_status(tasks, "RUNNING")
 
-    for iteration in range(2):
+    for iteration in range(10):
         log.info(f"Running analyzer for iteration {iteration} ...")
         await tasks_wait_for_status(analyzers, "PAUSED")
 
diff --git a/MooreScripts/tests/options/VeloHalf/Arch.xml b/MooreScripts/tests/options/VeloHalf/Arch.xml
index 255c3c3618e9c23a6b9bb650c1c40244cbcb947a..bdf6ef46828a625f720017710656f1dfafd53a90 100644
--- a/MooreScripts/tests/options/VeloHalf/Arch.xml
+++ b/MooreScripts/tests/options/VeloHalf/Arch.xml
@@ -10,7 +10,7 @@
 -->
 <tasks_inventory>
 
-  <task name="AlignWrk" user="${USER}" group="${GROUP}" instances="2">
+  <task name="AlignWrk" user="${USER}" group="${GROUP}" instances="1">
     <command>${MOORESCRIPTSROOT}/job/VeloHalf/runAnalyzer.sh</command>
     <argument name="-type" value="${NAME}" />
     <argument name="-runinfo" value="${RUNINFO}" />
diff --git a/MooreScripts/tests/qmtest/alignment.qmt b/MooreScripts/tests/qmtest/alignment.qmt
new file mode 100644
index 0000000000000000000000000000000000000000..d73863d58b943ce0645d7b56997f6056dc6c0ddb
--- /dev/null
+++ b/MooreScripts/tests/qmtest/alignment.qmt
@@ -0,0 +1,39 @@
+<?xml version="1.0" ?><!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<!--
+    (c) Copyright 2021 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.
+-->
+<!--
+Run an HLT2 job in the Online testbench
+-->
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+<argument name="program"><text>$MOORESCRIPTSROOT/scripts/testbench.py</text></argument>
+<argument name="args"><set>
+  <text>--working-dir=testalignment</text>
+  <text>--partition=TESTALIGNMENT</text>
+  <text>--test-file-db-key=2022_raw_hlt1_253597</text>
+  <text>$MOORESCRIPTSROOT/tests/options/VeloHalf/Arch.xml</text>
+  <text>alignment</text>
+</set></argument>
+<argument name="unsupported_platforms"><set>
+  <text>detdesc</text>
+</set></argument>
+<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
+<argument name="validator"><text>
+
+# No validator for now: only check the exit code
+
+import glob
+workdir = self._common_tmpdir
+for fn in glob.glob(workdir + "/testalignment/*.*"):
+    if not fn.endswith(".mdf"):
+        result[os.path.basename(fn)] = open(fn).read()
+
+</text></argument>
+</extension>
diff --git a/README.md b/README.md
index bdd8cbc2308fe0aa8d142078b743e2c3ab0fdf1c..37afbea70b08a2576047412333757b668f114bdf 100644
--- a/README.md
+++ b/README.md
@@ -181,6 +181,68 @@ The automatic LHCbPR throughput test of HLT2 uses the testbench. You can run in
 MooreOnline/run bash -c '$PRCONFIGROOT/scripts/benchmark-scripts/MooreOnline_hlt2_pp_default.sh'
 ```
 
+## Non-interactive test bench
+
+### Velo alignment example
+
+```sh
+MooreOnline/run MooreOnline/MooreScripts/scripts/testbench.py --help
+MooreOnline/run MooreOnline/MooreScripts/scripts/testbench.py --working-dir=output MooreOnline/MooreScripts/tests/options/VeloHalf/Arch.xml alignment
+```
+
+<details><summary> `tree output` (click to expand) </summary>
+
+```
+output
+├── AlignDrv_0.dump
+├── AlignDrv_0.env
+├── AlignDrv_0.log
+├── AlignDrv_0.opts
+├── AlignWrk_0.dump
+├── AlignWrk_0.env
+├── AlignWrk_0.log
+├── AlignWrk_0.opts
+├── AlignWrk_1.dump
+├── AlignWrk_1.env
+├── AlignWrk_1.log
+├── AlignWrk_1.opts
+├── emu.log
+├── NodeList.opts
+├── OnlineEnvBase.py
+├── OnlineEnv.opts
+├── __pycache__
+│   └── OnlineEnvBase.cpython-39.pyc
+├── RunList.opts
+├── setup.vars
+└── VeloHalf
+    ├── analyzer
+    │   └── 0000255623
+    │       ├── derivatives-TEST_N8190402_AlignWrk_0.out
+    │       ├── derivatives-TEST_N8190402_AlignWrk_1.out
+    │       ├── histograms-TEST_N8190402_AlignWrk_0_new.root
+    │       ├── histograms-TEST_N8190402_AlignWrk_1_new.root
+    │       └── tag
+    └── iterator
+        └── 0000255623
+            ├── alignlog.txt
+            ├── new-constants-0
+            │   └── Conditions
+            │       └── VP
+            │           └── Alignment
+            │               ├── Global.yml
+            │               └── Modules.yml
+            ├── new-constants-1
+            ├── OverlayRoot
+            │   └── Conditions
+            │       └── VP
+            │           └── Alignment
+            │               ├── Global.yml
+            │               └── Modules.yml
+            └── tag
+```
+
+</details>
+
 ## Online system tips
 
 ### Temporary files from HLT1 storage