diff --git a/crates/provider/src/native.rs b/crates/provider/src/native.rs
index 7434cfbe0c089cc44b14d29d7f5cc1fd2fe13dad..dd3f091c4b846cd71b10cdc346f9717a80535847 100644
--- a/crates/provider/src/native.rs
+++ b/crates/provider/src/native.rs
@@ -349,20 +349,19 @@ impl<FS: FileSystem + Send + Sync + Clone + 'static> ProviderNode for NativeNode
     }
 
     async fn dump_logs(&self, local_dest: PathBuf) -> Result<(), ProviderError> {
-        let logs = self.logs().await?;
-        Ok(self.filesystem.write(local_dest, logs.as_bytes()).await?)
+        Ok(self.filesystem.copy(&self.log_path, local_dest).await?)
     }
 
     async fn run_command(
         &self,
         options: RunCommandOptions,
     ) -> Result<ExecutionResult, ProviderError> {
-        let result = Command::new(options.command)
+        let result = Command::new(options.command.clone())
             .args(options.args)
             .envs(options.env)
             .output()
             .await
-            .map_err(|err| ProviderError::RunCommandError(err.into()))?;
+            .map_err(|err| ProviderError::RunCommandError(options.command, err.into()))?;
 
         if result.status.success() {
             Ok(Ok(String::from_utf8_lossy(&result.stdout).to_string()))
@@ -738,51 +737,37 @@ mod tests {
             .await
             .unwrap();
 
+        let files = fs.files.read().await;
+
         // ensure node directories are created
-        assert!(fs
-            .files
-            .read()
-            .await
-            .contains_key(node.base_dir().as_os_str()));
-        assert!(fs
-            .files
-            .read()
-            .await
-            .contains_key(node.config_dir().as_os_str()));
-        assert!(fs
-            .files
-            .read()
-            .await
-            .contains_key(node.data_dir().as_os_str()));
-        assert!(fs
-            .files
-            .read()
-            .await
-            .contains_key(node.scripts_dir().as_os_str()));
+        assert!(files.contains_key(node.base_dir().as_os_str()));
+        assert!(files.contains_key(node.config_dir().as_os_str()));
+        assert!(files.contains_key(node.data_dir().as_os_str()));
+        assert!(files.contains_key(node.scripts_dir().as_os_str()));
 
         // ensure injected files are presents
-        assert!(matches!(
-            fs.files
-                .read()
-                .await
+        assert_eq!(
+            files
                 .get(
                     &OsString::from_str(&format!("{}/file1", node.config_dir().to_string_lossy()))
                         .unwrap()
                 )
+                .unwrap()
+                .contents()
                 .unwrap(),
-            InMemoryFile::File { contents, .. } if contents == "My file 1".as_bytes()
-        ));
-        assert!(matches!(
-            fs.files
-                .read()
-                .await
+            "My file 1"
+        );
+        assert_eq!(
+            files
                 .get(
                     &OsString::from_str(&format!("{}/file2", node.data_dir().to_string_lossy()))
                         .unwrap()
                 )
+                .unwrap()
+                .contents()
                 .unwrap(),
-            InMemoryFile::File { contents, .. } if contents == "My file 2".as_bytes()
-        ));
+            "My file 2"
+        );
 
         // retrieve running process
         let processes = procfs::process::all_processes()
@@ -844,9 +829,7 @@ mod tests {
         // ensure log file is created and logs are written 5s after process start
         sleep(Duration::from_secs(5)).await;
         assert!(
-            fs.files
-                .read()
-                .await
+            files
                 .get(node.log_path().as_os_str())
                 .unwrap()
                 .contents()
@@ -859,9 +842,7 @@ mod tests {
         // ensure logs are updated when process continue running 10s after process start
         sleep(Duration::from_secs(5)).await;
         assert!(
-            fs.files
-                .read()
-                .await
+            files
                 .get(node.log_path().as_os_str())
                 .unwrap()
                 .contents()
@@ -874,9 +855,7 @@ mod tests {
         // ensure logs are updated when process continue running 15s after process start
         sleep(Duration::from_secs(5)).await;
         assert!(
-            fs.files
-                .read()
-                .await
+            files
                 .get(node.log_path().as_os_str())
                 .unwrap()
                 .contents()
@@ -911,11 +890,11 @@ mod tests {
             .await
             .unwrap();
 
+        let files = fs.files.read().await;
+
         // ensure files have been generated correctly to right location
         assert_eq!(
-            fs.files
-                .read()
-                .await
+            files
                 .get(
                     &OsString::from_str(&format!(
                         "{}/myfile1",
@@ -929,9 +908,7 @@ mod tests {
             "My file 1\n"
         );
         assert_eq!(
-            fs.files
-                .read()
-                .await
+            files
                 .get(
                     &OsString::from_str(&format!(
                         "{}/myfile2",
@@ -1004,4 +981,164 @@ mod tests {
         // ensure namespace is destroyed
         assert_eq!(provider.namespaces().await.len(), 0);
     }
+
+    #[tokio::test]
+    async fn node_logs_method_should_return_its_logs_as_a_string() {
+        let fs = InMemoryFileSystem::new(HashMap::from([
+            (OsString::from_str("/").unwrap(), InMemoryFile::dir()),
+            (OsString::from_str("/tmp").unwrap(), InMemoryFile::dir()),
+        ]));
+        let provider = NativeProvider::new(fs.clone());
+        let namespace = provider.create_namespace().await.unwrap();
+
+        // spawn dummy node
+        let node = namespace
+            .spawn_node(SpawnNodeOptions::new(
+                "mynode",
+                "/home/user/Work/parity/zombienet-sdk/crates/provider/testing/dummy_node",
+            ))
+            .await
+            .unwrap();
+
+        // wait some time for node to write logs
+        sleep(Duration::from_secs(5)).await;
+
+        assert_eq!(
+            fs.files
+                .read()
+                .await
+                .get(node.log_path().as_os_str())
+                .unwrap()
+                .contents()
+                .unwrap(),
+            node.logs().await.unwrap()
+        );
+    }
+
+    #[tokio::test]
+    async fn node_dump_logs_method_should_writes_its_logs_to_a_given_destination() {
+        let fs = InMemoryFileSystem::new(HashMap::from([
+            (OsString::from_str("/").unwrap(), InMemoryFile::dir()),
+            (OsString::from_str("/tmp").unwrap(), InMemoryFile::dir()),
+        ]));
+        let provider = NativeProvider::new(fs.clone());
+        let namespace = provider.create_namespace().await.unwrap();
+
+        // spawn dummy node
+        let node = namespace
+            .spawn_node(SpawnNodeOptions::new(
+                "mynode",
+                "/home/user/Work/parity/zombienet-sdk/crates/provider/testing/dummy_node",
+            ))
+            .await
+            .unwrap();
+
+        // wait some time for node to write logs
+        sleep(Duration::from_secs(5)).await;
+
+        node.dump_logs(PathBuf::from("/tmp/my_log_file"))
+            .await
+            .unwrap();
+
+        let files = fs.files.read().await;
+
+        assert_eq!(
+            files
+                .get(node.log_path().as_os_str())
+                .unwrap()
+                .contents()
+                .unwrap(),
+            files
+                .get(&OsString::from_str("/tmp/my_log_file").unwrap())
+                .unwrap()
+                .contents()
+                .unwrap(),
+        );
+    }
+
+    #[tokio::test]
+    async fn node_run_command_method_should_execute_the_command_successfully_and_returns_stdout() {
+        let fs = InMemoryFileSystem::new(HashMap::from([
+            (OsString::from_str("/").unwrap(), InMemoryFile::dir()),
+            (OsString::from_str("/tmp").unwrap(), InMemoryFile::dir()),
+        ]));
+        let provider = NativeProvider::new(fs.clone());
+        let namespace = provider.create_namespace().await.unwrap();
+
+        // spawn dummy node
+        let node = namespace
+            .spawn_node(SpawnNodeOptions::new(
+                "mynode",
+                "/home/user/Work/parity/zombienet-sdk/crates/provider/testing/dummy_node",
+            ))
+            .await
+            .unwrap();
+
+        let result = node
+            .run_command(
+                RunCommandOptions::new("sh")
+                    .args(vec!["-c", "echo $MY_ENV_VAR"])
+                    .env(vec![("MY_ENV_VAR", "Here is my content")]),
+            )
+            .await;
+
+        assert!(matches!(result, Ok(Ok(stdout)) if stdout == "Here is my content\n"));
+    }
+
+    #[tokio::test]
+    async fn node_run_command_method_should_execute_the_command_successfully_and_returns_error_code_and_stderr_if_an_error_happened(
+    ) {
+        let fs = InMemoryFileSystem::new(HashMap::from([
+            (OsString::from_str("/").unwrap(), InMemoryFile::dir()),
+            (OsString::from_str("/tmp").unwrap(), InMemoryFile::dir()),
+        ]));
+        let provider = NativeProvider::new(fs.clone());
+        let namespace = provider.create_namespace().await.unwrap();
+
+        // spawn dummy node
+        let node = namespace
+            .spawn_node(SpawnNodeOptions::new(
+                "mynode",
+                "/home/user/Work/parity/zombienet-sdk/crates/provider/testing/dummy_node",
+            ))
+            .await
+            .unwrap();
+
+        let result = node
+            .run_command(RunCommandOptions::new("sh").args(vec!["-fakeargs"]))
+            .await;
+
+        assert!(
+            matches!(result, Ok(Err((exit_code, stderr))) if !exit_code.success() && stderr == "sh: 0: Illegal option -k\n")
+        );
+    }
+
+    #[tokio::test]
+    async fn node_run_command_method_should_fail_to_execute_the_command_if_command_doesnt_exists() {
+        let fs = InMemoryFileSystem::new(HashMap::from([
+            (OsString::from_str("/").unwrap(), InMemoryFile::dir()),
+            (OsString::from_str("/tmp").unwrap(), InMemoryFile::dir()),
+        ]));
+        let provider = NativeProvider::new(fs.clone());
+        let namespace = provider.create_namespace().await.unwrap();
+
+        // spawn dummy node
+        let node = namespace
+            .spawn_node(SpawnNodeOptions::new(
+                "mynode",
+                "/home/user/Work/parity/zombienet-sdk/crates/provider/testing/dummy_node",
+            ))
+            .await
+            .unwrap();
+
+        let err = node
+            .run_command(RunCommandOptions::new("myrandomprogram"))
+            .await
+            .unwrap_err();
+
+        assert_eq!(
+            err.to_string(),
+            "Error running command 'myrandomprogram': No such file or directory (os error 2)"
+        );
+    }
 }