diff --git a/internal/integrationtest/main/main_test.go b/internal/integrationtest/main/main_test.go
new file mode 100644
index 00000000000..940118410ff
--- /dev/null
+++ b/internal/integrationtest/main/main_test.go
@@ -0,0 +1,166 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2022 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package main_test
+
+import (
+	"encoding/json"
+	"strings"
+	"testing"
+
+	"github.com/arduino/arduino-cli/internal/integrationtest"
+	"github.com/arduino/go-paths-helper"
+	"github.com/stretchr/testify/require"
+	semver "go.bug.st/relaxed-semver"
+	"go.bug.st/testsuite"
+	"go.bug.st/testsuite/requirejson"
+)
+
+func TestHelp(t *testing.T) {
+	env := testsuite.NewEnvironment(t)
+	defer env.CleanUp()
+
+	cli := integrationtest.NewArduinoCliWithinEnvironment(env, &integrationtest.ArduinoCLIConfig{
+		ArduinoCLIPath:         paths.New("..", "..", "..", "arduino-cli"),
+		UseSharedStagingFolder: true,
+	})
+
+	// Run help and check the output message
+	stdout, stderr, err := cli.Run("help")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	require.Contains(t, string(stdout), "Usage")
+}
+
+func TestVersion(t *testing.T) {
+	env := testsuite.NewEnvironment(t)
+	defer env.CleanUp()
+
+	cli := integrationtest.NewArduinoCliWithinEnvironment(env, &integrationtest.ArduinoCLIConfig{
+		ArduinoCLIPath:         paths.New("..", "..", "..", "arduino-cli"),
+		UseSharedStagingFolder: true,
+	})
+
+	// Run version and check the output message
+	stdout, stderr, err := cli.Run("version")
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "Version:")
+	require.Contains(t, string(stdout), "Commit:")
+	require.Empty(t, stderr)
+
+	// Checks if "version --format json" has a json as an output
+	stdout, _, err = cli.Run("version", "--format", "json")
+	require.NoError(t, err)
+	var jsonMap map[string]string
+	err = json.Unmarshal(stdout, &jsonMap)
+	require.NoError(t, err)
+
+	// Checks if Application's value is arduino-cli
+	require.Equal(t, jsonMap["Application"], "arduino-cli")
+
+	// Checks if VersionString's value is git-snapshot, nightly or a valid semantic versioning
+	switch version := jsonMap["VersionString"]; version {
+	case "git-snapshot":
+		require.Contains(t, version, "git-snapshot")
+	case "nigthly":
+		require.Contains(t, version, "nightly")
+	default:
+		_, err = semver.Parse(version)
+		require.NoError(t, err)
+	}
+
+	// Checks if Commit's value is not empty
+	require.NotEmpty(t, jsonMap["Commit"])
+}
+
+func TestLogOptions(t *testing.T) {
+	// Using version as a test command
+	env := testsuite.NewEnvironment(t)
+	defer env.CleanUp()
+
+	cli := integrationtest.NewArduinoCliWithinEnvironment(env, &integrationtest.ArduinoCLIConfig{
+		ArduinoCLIPath:         paths.New("..", "..", "..", "arduino-cli"),
+		UseSharedStagingFolder: true,
+	})
+
+	// No logs
+	stdout, _, err := cli.Run("version")
+	require.NoError(t, err)
+	trimOut := strings.TrimSpace(string(stdout))
+	outLines := strings.Split(trimOut, "\n")
+	require.Len(t, outLines, 1)
+
+	// Plain text logs on stdout
+	stdout, _, err = cli.Run("version", "-v")
+	require.NoError(t, err)
+	trimOut = strings.TrimSpace(string(stdout))
+	outLines = strings.Split(trimOut, "\n")
+	require.Greater(t, len(outLines), 1)
+	require.True(t, strings.HasPrefix(outLines[0], "\x1b[36mINFO\x1b[0m")) // account for the colors
+
+	// Plain text logs on file
+	logFile := cli.DataDir().Join("log.txt")
+	_, _, err = cli.Run("version", "--log-file", logFile.String())
+	require.NoError(t, err)
+	lines, _ := logFile.ReadFileAsLines()
+	require.True(t, strings.HasPrefix(lines[0], "time=\""))
+
+	// json on stdout
+	stdout, _, err = cli.Run("version", "-v", "--log-format", "JSON")
+	require.NoError(t, err)
+	trimOut = strings.TrimSpace(string(stdout))
+	outLines = strings.Split(trimOut, "\n")
+	requirejson.Contains(t, []byte(outLines[0]), `{ "level" }`)
+
+	// Check if log.json contains readable json in each line
+	var v interface{}
+	logFileJson := cli.DataDir().Join("log.json")
+	_, _, err = cli.Run("version", "--log-format", "JSON", "--log-file", logFileJson.String())
+	require.NoError(t, err)
+	fileContent, err := logFileJson.ReadFileAsLines()
+	require.NoError(t, err)
+	for _, line := range fileContent {
+		// exclude empty lines since they are not valid json
+		if line == "" {
+			continue
+		}
+		err = json.Unmarshal([]byte(line), &v)
+		require.NoError(t, err)
+	}
+}
+
+func TestInventoryCreation(t *testing.T) {
+	// Using version as a test command
+	env := testsuite.NewEnvironment(t)
+	defer env.CleanUp()
+
+	cli := integrationtest.NewArduinoCliWithinEnvironment(env, &integrationtest.ArduinoCLIConfig{
+		ArduinoCLIPath:         paths.New("..", "..", "..", "arduino-cli"),
+		UseSharedStagingFolder: true,
+	})
+
+	// no logs
+	stdout, _, err := cli.Run("version")
+	require.NoError(t, err)
+	line := strings.TrimSpace(string(stdout))
+	outLines := strings.Split(line, "\n")
+	require.Len(t, outLines, 1)
+
+	// parse inventory file
+	inventoryFile := cli.DataDir().Join("inventory.yaml")
+	stream, err := inventoryFile.ReadFile()
+	require.NoError(t, err)
+	require.True(t, strings.Contains(string(stream), "installation"))
+}
diff --git a/test/test_main.py b/test/test_main.py
deleted file mode 100644
index 91cddc57732..00000000000
--- a/test/test_main.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# This file is part of arduino-cli.
-#
-# Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-#
-# This software is released under the GNU General Public License version 3,
-# which covers the main part of arduino-cli.
-# The terms of this license can be found at:
-# https://www.gnu.org/licenses/gpl-3.0.en.html
-#
-# You can be released from the requirements of the above licenses by purchasing
-# a commercial license. Buying such a license is mandatory if you want to modify or
-# otherwise use the software for commercial activities involving the Arduino
-# software without disclosing the source code of your own applications. To purchase
-# a commercial license, send an email to license@arduino.cc.
-import json
-import os
-
-import semver
-import yaml
-
-
-def test_help(run_command):
-    result = run_command(["help"])
-    assert result.ok
-    assert result.stderr == ""
-    assert "Usage" in result.stdout
-
-
-def test_version(run_command):
-    result = run_command(["version"])
-    assert result.ok
-    assert "Version:" in result.stdout
-    assert "Commit:" in result.stdout
-    assert "" == result.stderr
-
-    result = run_command(["version", "--format", "json"])
-    assert result.ok
-    parsed_out = json.loads(result.stdout)
-    assert parsed_out.get("Application", False) == "arduino-cli"
-    version = parsed_out.get("VersionString", False)
-    assert semver.VersionInfo.isvalid(version=version) or "git-snapshot" in version or "nightly" in version
-    assert isinstance(parsed_out.get("Commit", False), str)
-
-
-def test_log_options(run_command, data_dir):
-    """
-    using `version` as a test command
-    """
-
-    # no logs
-    out_lines = run_command(["version"]).stdout.strip().split("\n")
-    assert len(out_lines) == 1
-
-    # plain text logs on stdoud
-    out_lines = run_command(["version", "-v"]).stdout.strip().split("\n")
-    assert len(out_lines) > 1
-    assert out_lines[0].startswith("\x1b[36mINFO\x1b[0m")  # account for the colors
-
-    # plain text logs on file
-    log_file = os.path.join(data_dir, "log.txt")
-    run_command(["version", "--log-file", log_file])
-    with open(log_file) as f:
-        lines = f.readlines()
-        assert lines[0].startswith('time="')  # file format is different from console
-
-    # json on stdout
-    out_lines = run_command(["version", "-v", "--log-format", "JSON"]).stdout.strip().split("\n")
-    lg = json.loads(out_lines[0])
-    assert "level" in lg
-
-    # json on file
-    log_file = os.path.join(data_dir, "log.json")
-    run_command(["version", "--log-format", "json", "--log-file", log_file])
-    with open(log_file) as f:
-        for line in f.readlines():
-            json.loads(line)
-
-
-def test_inventory_creation(run_command, data_dir):
-    """
-    using `version` as a test command
-    """
-
-    # no logs
-    out_lines = run_command(["version"]).stdout.strip().split("\n")
-    assert len(out_lines) == 1
-
-    # parse inventory file
-    inventory_file = os.path.join(data_dir, "inventory.yaml")
-    with open(inventory_file, "r") as stream:
-        inventory = yaml.safe_load(stream)
-        assert "installation" in inventory