diff --git a/end2end-tests/tests/common/mod.rs b/end2end-tests/tests/common/mod.rs
index b1c6dc50cae6b708cab8a01700831b45f4167265..3a5ee6939f508bcb30900eac536b86975082c2d0 100644
--- a/end2end-tests/tests/common/mod.rs
+++ b/end2end-tests/tests/common/mod.rs
@@ -104,7 +104,10 @@ struct FullNode {
     ws_port: u16,
 }
 
-pub async fn spawn_node(maybe_genesis_conf_file: Option<PathBuf>) -> (Client, Process, u16) {
+pub async fn spawn_node(
+    maybe_genesis_conf_file: Option<PathBuf>,
+    no_spawn: bool,
+) -> (Client, Option<Process>, u16) {
     println!("maybe_genesis_conf_file={:?}", maybe_genesis_conf_file);
     let duniter_binary_path = std::env::var("DUNITER_BINARY_PATH").unwrap_or_else(|_| {
         if std::path::Path::new(DUNITER_DOCKER_PATH).exists() {
@@ -114,29 +117,36 @@ pub async fn spawn_node(maybe_genesis_conf_file: Option<PathBuf>) -> (Client, Pr
         }
     });
 
-    let FullNode {
-        process,
-        p2p_port: _,
-        ws_port,
-    } = spawn_full_node(
-        &[
-            "--chain=gdev_dev",
-            "--execution=Native",
-            "--sealing=manual",
-            // Necessary options which were previously set by --dev option:
-            "--force-authoring",
-            "--rpc-cors=all",
-            "--alice",
-            "--tmp",
-        ],
-        &duniter_binary_path,
-        maybe_genesis_conf_file,
-    );
-    let client = Client::from_url(format!("ws://127.0.0.1:{}", ws_port))
+    let mut the_ws_port = 9944;
+    let mut opt_process = None;
+    // Eventually spawn a node (we most likely will - unless --no-spawn option is used)
+    if !no_spawn {
+        let FullNode {
+            process,
+            p2p_port: _,
+            ws_port,
+        } = spawn_full_node(
+            &[
+                "--chain=gdev_dev",
+                "--execution=Native",
+                "--sealing=manual",
+                // Necessary options which were previously set by --dev option:
+                "--force-authoring",
+                "--rpc-cors=all",
+                "--alice",
+                "--tmp",
+            ],
+            &duniter_binary_path,
+            maybe_genesis_conf_file,
+        );
+        opt_process = Some(process);
+        the_ws_port = ws_port;
+    }
+    let client = Client::from_url(format!("ws://127.0.0.1:{}", the_ws_port))
         .await
         .expect("fail to connect to node");
 
-    (client, process, ws_port)
+    (client, opt_process, the_ws_port)
 }
 
 pub async fn create_empty_block(client: &Client) -> Result<()> {
diff --git a/end2end-tests/tests/cucumber_tests.rs b/end2end-tests/tests/cucumber_tests.rs
index dcb7d842bd593e19103928724a820aa272b45edd..b21cf2b8ca01690ac3b337dbacf6a27f97f37ea9 100644
--- a/end2end-tests/tests/cucumber_tests.rs
+++ b/end2end-tests/tests/cucumber_tests.rs
@@ -38,11 +38,11 @@ pub struct DuniterWorld {
 
 impl DuniterWorld {
     // Write methods
-    async fn init(&mut self, maybe_genesis_conf_file: Option<PathBuf>) {
+    async fn init(&mut self, maybe_genesis_conf_file: Option<PathBuf>, no_spawn: bool) {
         if let Some(ref mut inner) = self.inner {
             inner.kill();
         }
-        self.inner = Some(DuniterWorldInner::new(maybe_genesis_conf_file).await);
+        self.inner = Some(DuniterWorldInner::new(maybe_genesis_conf_file, no_spawn).await);
     }
     fn kill(&mut self) {
         if let Some(ref mut inner) = self.inner {
@@ -119,13 +119,13 @@ impl World for DuniterWorld {
 
 struct DuniterWorldInner {
     client: Client,
-    process: Process,
+    process: Option<Process>,
     ws_port: u16,
 }
 
 impl DuniterWorldInner {
-    async fn new(maybe_genesis_conf_file: Option<PathBuf>) -> Self {
-        let (client, process, ws_port) = spawn_node(maybe_genesis_conf_file).await;
+    async fn new(maybe_genesis_conf_file: Option<PathBuf>, no_spawn: bool) -> Self {
+        let (client, process, ws_port) = spawn_node(maybe_genesis_conf_file, no_spawn).await;
         DuniterWorldInner {
             client,
             process,
@@ -133,7 +133,9 @@ impl DuniterWorldInner {
         }
     }
     fn kill(&mut self) {
-        self.process.kill();
+        if let Some(p) = &mut self.process {
+            p.kill();
+        }
     }
 }
 
@@ -559,6 +561,9 @@ struct CustomOpts {
     /// Keep running
     #[clap(short, long)]
     keep_running: bool,
+    /// Do not spawn a node, reuse expected node on port 9944
+    #[clap(long)]
+    no_spawn: bool,
 
     /// For compliance with Jetbrains IDE which pushes extra args.
     /// https://youtrack.jetbrains.com/issue/CPP-33071/cargo-test-adds-extra-options-which-conflict-with-Cucumber
@@ -587,6 +592,7 @@ async fn main() {
 
     let opts = cucumber::cli::Opts::<_, _, _, CustomOpts>::parsed();
     let keep_running = opts.custom.keep_running;
+    let no_spawn = opts.custom.no_spawn;
 
     // Handle crtl+C
     let running = Arc::new(AtomicBool::new(true));
@@ -599,7 +605,7 @@ async fn main() {
     DuniterWorld::cucumber()
         //.fail_on_skipped()
         .max_concurrent_scenarios(4)
-        .before(|feature, _rule, scenario, world| {
+        .before(move |feature, _rule, scenario, world| {
             let mut genesis_conf_file_path = PathBuf::new();
             genesis_conf_file_path.push("cucumber-genesis");
             genesis_conf_file_path.push(&format!(
@@ -607,7 +613,7 @@ async fn main() {
                 genesis_conf_name(&feature.tags, &scenario.tags)
             ));
             world.set_ignore_errors(ignore_errors(&scenario.tags));
-            Box::pin(world.init(Some(genesis_conf_file_path)))
+            Box::pin(world.init(Some(genesis_conf_file_path), no_spawn))
         })
         .after(move |_feature, _rule, _scenario, maybe_world| {
             if keep_running {