diff --git a/scripts/run-linux-armv7 b/scripts/run-linux-armv7
index 368201bfbd2ef3b2404c445ea6d0e34e09aa5472..e7818c2ee5eb3b11664120ef9f8e6ee38375560d 100755
--- a/scripts/run-linux-armv7
+++ b/scripts/run-linux-armv7
@@ -1,4 +1,17 @@
 #!/bin/sh
 set -eu
 
+case "$0" in
+    /*) test_runner=$0 ;;
+    *) test_runner=$(pwd)/$0 ;;
+esac
+case "$1" in
+    /*) test_executable=$1 ;;
+    *) test_executable=$(pwd)/$1 ;;
+esac
+
+TIT_TEST_RUNNER=$test_runner
+TIT_TEST_EXECUTABLE=$test_executable
+export TIT_TEST_RUNNER TIT_TEST_EXECUTABLE
+
 exec /usr/bin/qemu-arm -L /usr/arm-linux-gnueabihf "$@"
diff --git a/src/lib.rs b/src/lib.rs
index 1ca09a26fb81ca5f90dcf2468331c318e88d5208..781fb17854488b406ccf30ea958d1b5ef0c01ef7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -76,6 +76,9 @@
 #[path = "../tests/ssh.rs"]
 mod ssh_tests;
 #[cfg(test)]
+#[path = "../tests/process.rs"]
+mod test_process;
+#[cfg(test)]
 #[path = "../tests/web_session.rs"]
 mod web_session_tests;
 #[cfg(test)]
diff --git a/tests/git_http.rs b/tests/git_http.rs
index 4952d1d924cc8b54b019405cab30893eaf2a1249..cdad45f9dddcbb12149057cb6593d29c71070d16 100644
--- a/tests/git_http.rs
+++ b/tests/git_http.rs
@@ -280,7 +280,7 @@
     let git_binary = command_output(Command::new("which").arg("git"));
     let git_exec_path = command_output(Command::new("git").arg("--exec-path"));
     let driver_path = std::env::var_os("PATH").expect("the test driver PATH");
-    let output = Command::new(std::env::current_exe().expect("find the test executable"))
+    let output = crate::test_process::current_exe()
         .args([
             "--exact",
             "git_http_tests::server_process_does_not_invoke_git",
diff --git a/tests/git_push_ssh.rs b/tests/git_push_ssh.rs
index a7a20a6cfd08a991f255a9159e9ae3c547e1b11d..02e9b699804b894380920ffef945db4b9a5fd7bd 100644
--- a/tests/git_push_ssh.rs
+++ b/tests/git_push_ssh.rs
@@ -454,7 +454,7 @@
     private_key: &Path,
     ready: &Path,
 ) -> Child {
-    Command::new(env::current_exe().expect("find the integration test executable"))
+    crate::test_process::current_exe()
         .args([
             "--exact",
             "git_push_ssh_tests::git_push_crash_child",
diff --git a/tests/process.rs b/tests/process.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c2b531dd84eeaf2c66a32af7301a4858776e62c2
--- /dev/null
+++ b/tests/process.rs
@@ -1,0 +1,17 @@
+use std::env;
+use std::process::Command;
+
+pub(crate) fn current_exe() -> Command {
+    match (
+        env::var_os("TIT_TEST_RUNNER"),
+        env::var_os("TIT_TEST_EXECUTABLE"),
+    ) {
+        (Some(runner), Some(executable)) => {
+            let mut command = Command::new(runner);
+            command.arg(executable);
+            command
+        }
+        (None, None) => Command::new(env::current_exe().expect("find the current test executable")),
+        _ => panic!("the test runner and test executable must be set together"),
+    }
+}
diff --git a/tests/sqlite.rs b/tests/sqlite.rs
index 6859f8acd70322ba5a5937268968a1421ba57d1f..d5920f821032c03a96514a6c7fb017f0eee4091d 100644
--- a/tests/sqlite.rs
+++ b/tests/sqlite.rs
@@ -1,6 +1,6 @@
 use crate::store;
 
-use std::process::{Child, Command};
+use std::process::Child;
 use std::sync::mpsc;
 use std::sync::{Arc, atomic::AtomicBool, atomic::Ordering};
 use std::thread;
@@ -140,7 +140,7 @@
     database_path: &std::path::Path,
     ready_path: &std::path::Path,
 ) -> Child {
-    Command::new(env::current_exe().expect("find the integration test executable"))
+    crate::test_process::current_exe()
         .args([
             "--exact",
             "sqlite_tests::crash_child",
