diff --git a/.github/workflows/check-code-generation-task.yml b/.github/workflows/check-code-generation-task.yml new file mode 100644 index 00000000..074b9e7c --- /dev/null +++ b/.github/workflows/check-code-generation-task.yml @@ -0,0 +1,47 @@ +name: Check Code Generation + +on: + push: + paths: + - ".github/workflows/check-code-generation-task.ya?ml" + - "Taskfile.yml" + - "go.mod" + - "go.sum" + - "**/*.go" + - "etc/schemas/**/*.json" + pull_request: + paths: + - ".github/workflows/check-code-generation-task.ya?ml" + - "Taskfile.yml" + - "go.mod" + - "go.sum" + - "**/*.go" + - "etc/schemas/**/*.json" + +env: + BUILDS_ARTIFACT: build-artifacts + +jobs: + test-go: + runs-on: ubuntu-latest + + steps: + - name: Checkout local repository + uses: actions/checkout@v2 + + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: "1.16" + + - name: Install Taskfile + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Generate code + run: task go:generate + + - name: Check for forgotten code generation + run: git diff --color --exit-code diff --git a/.github/workflows/test.yml b/.github/workflows/publish-go-tester-task.yml similarity index 59% rename from .github/workflows/test.yml rename to .github/workflows/publish-go-tester-task.yml index 552cc2fd..80fd3ef8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/publish-go-tester-task.yml @@ -1,94 +1,37 @@ -name: Run tests +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/publish-go-tester-task.md +name: Publish Tester Build +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows on: push: paths: - - ".github/workflows/test.yml" - - "Taskfile.yml" + - ".github/workflows/publish-go-tester-task.ya?ml" - "go.mod" - "go.sum" - - "**/*.go" - - "**/testdata/**" - - "etc/schemas/**/*.json" - - "pyproject.toml" - - "test/**" - - "Taskfile.yml" + - "Taskfile.ya?ml" + - "**.go" pull_request: paths: - - ".github/workflows/test.yml" - - "Taskfile.yml" + - ".github/workflows/publish-go-tester-task.ya?ml" - "go.mod" - "go.sum" - - "**/*.go" - - "**/testdata/**" - - "etc/schemas/**/*.json" - - "pyproject.toml" - - "test/**" - - "Taskfile.yml" + - "Taskfile.ya?ml" + - "**.go" + workflow_dispatch: + repository_dispatch: env: + # As defined by the Taskfile's DIST_DIR variable + DIST_DIR: dist BUILDS_ARTIFACT: build-artifacts jobs: - test-go: - strategy: - matrix: - operating-system: - - ubuntu-latest - - windows-latest - - macOS-latest - - runs-on: ${{ matrix.operating-system }} - - steps: - - name: Checkout local repository - uses: actions/checkout@v2 - - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: "1.16" - - - name: Install Taskfile - uses: arduino/setup-task@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - version: 3.x - - - name: Generate code - run: task go:generate - - - name: Check for forgotten code generation - run: git diff --color --exit-code - - - name: Run unit tests - run: task go:test-unit - - - name: Send unit tests coverage to Codecov - if: matrix.operating-system == 'ubuntu-latest' - uses: codecov/codecov-action@v1 - with: - file: ./coverage_unit.txt - flags: unit - fail_ci_if_error: true - - - name: Install Python - uses: actions/setup-python@v2 - with: - python-version: "3.9" - - - name: Install Poetry - run: pip install poetry - - - name: Run integration tests - run: task test-integration - build: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: fetch-depth: 0 @@ -112,7 +55,7 @@ jobs: - name: Upload combined builds artifact uses: actions/upload-artifact@v2 with: - path: dist/ + path: ${{ env.DIST_DIR }} name: ${{ env.BUILDS_ARTIFACT }} artifacts: diff --git a/.github/workflows/test-go-integration-task.yml b/.github/workflows/test-go-integration-task.yml new file mode 100644 index 00000000..7664a0f0 --- /dev/null +++ b/.github/workflows/test-go-integration-task.yml @@ -0,0 +1,60 @@ +name: Test Integration + +on: + push: + paths: + - ".github/workflows/test-go-integration-task.ya?ml" + - "Taskfile.ya?ml" + - "**.go" + - "go.mod" + - "go.sum" + - "poetry.lock" + - "pyproject.toml" + - "tests/**" + pull_request: + paths: + - ".github/workflows/test-go-integration-task.ya?ml" + - "Taskfile.ya?ml" + - "**.go" + - "go.mod" + - "go.sum" + - "poetry.lock" + - "pyproject.toml" + - "tests/**" + +jobs: + test-go: + strategy: + matrix: + operating-system: + - ubuntu-latest + - windows-latest + - macOS-latest + + runs-on: ${{ matrix.operating-system }} + + steps: + - name: Checkout local repository + uses: actions/checkout@v2 + + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: "1.16" + + - name: Install Taskfile + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Install Python + uses: actions/setup-python@v2 + with: + python-version: "3.9" + + - name: Install Poetry + run: pip install poetry + + - name: Run integration tests + run: task go:test-integration diff --git a/.github/workflows/test-go-task.yml b/.github/workflows/test-go-task.yml new file mode 100644 index 00000000..8c07e24b --- /dev/null +++ b/.github/workflows/test-go-task.yml @@ -0,0 +1,59 @@ +name: Run tests + +on: + push: + paths: + - ".github/workflows/test-go-task.ya?ml" + - "Taskfile.yml" + - "go.mod" + - "go.sum" + - "**/*.go" + - "**/testdata/**" + pull_request: + paths: + - ".github/workflows/test-go-task.ya?ml" + - "Taskfile.yml" + - "go.mod" + - "go.sum" + - "**/*.go" + - "**/testdata/**" + +env: + BUILDS_ARTIFACT: build-artifacts + +jobs: + test-go: + strategy: + matrix: + operating-system: + - ubuntu-latest + - windows-latest + - macOS-latest + + runs-on: ${{ matrix.operating-system }} + + steps: + - name: Checkout local repository + uses: actions/checkout@v2 + + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: "1.16" + + - name: Install Taskfile + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Run unit tests + run: task go:test + + - name: Send unit tests coverage to Codecov + if: matrix.operating-system == 'ubuntu-latest' + uses: codecov/codecov-action@v1 + with: + file: ./coverage_unit.txt + flags: unit + fail_ci_if_error: true diff --git a/README.md b/README.md index 135a3f55..a1380d75 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # Arduino Lint -[![Tests Status](https://github.com/arduino/arduino-lint/workflows/Run%20tests/badge.svg)](https://github.com/arduino/arduino-lint/actions?workflow=Run+tests) +[![Test Go status](https://github.com/arduino/arduino-lint/actions/workflows/test-go-task.yml/badge.svg)](https://github.com/arduino/arduino-lint/actions/workflows/test-go-task.yml) +[![Test Integration status](https://github.com/arduino/arduino-lint/actions/workflows/test-go-integration-task.yml/badge.svg)](https://github.com/arduino/arduino-lint/actions/workflows/test-go-integration-task.yml) [![Check Go status](https://github.com/arduino/arduino-lint/actions/workflows/check-go-task.yml/badge.svg)](https://github.com/arduino/arduino-lint/actions/workflows/check-go-task.yml) +[![Check Code Generation status](https://github.com/arduino/arduino-lint/actions/workflows/check-code-generation-task.yml/badge.svg)](https://github.com/arduino/arduino-lint/actions/workflows/check-code-generation-task.yml) +[![Publish Tester Build status](https://github.com/arduino/arduino-lint/actions/workflows/publish-go-tester-task.yml/badge.svg)](https://github.com/arduino/arduino-lint/actions/workflows/publish-go-tester-task.yml) [![Publish Nightly Build status](https://github.com/arduino/arduino-lint/actions/workflows/publish-go-nightly-task.yml/badge.svg)](https://github.com/arduino/arduino-lint/actions/workflows/publish-go-nightly-task.yml) [![Check Python status](https://github.com/arduino/arduino-lint/actions/workflows/check-python-task.yml/badge.svg)](https://github.com/arduino/arduino-lint/actions/workflows/check-python-task.yml) [![Check Markdown status](https://github.com/arduino/arduino-lint/actions/workflows/check-markdown-task.yml/badge.svg)](https://github.com/arduino/arduino-lint/actions/workflows/check-markdown-task.yml) diff --git a/Taskfile.yml b/Taskfile.yml index 1920bcd5..a44e8c77 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -9,7 +9,7 @@ vars: PROJECT_NAME: "arduino-lint" DIST_DIR: "dist" DEFAULT_GO_PACKAGES: - sh: echo `go list ./... | grep --invert-match 'github.com/arduino/arduino-lint/internal/rule/schema/schemadata' | tr '\n' ' '` + sh: echo $(go list ./... | grep --invert-match 'github.com/arduino/arduino-lint/internal/rule/schema/schemadata' | tr '\n' ' ') # build vars COMMIT: sh: echo "$(git log --no-show-signature -n 1 --format=%h)" @@ -28,7 +28,6 @@ vars: -X {{.CONFIGURATION_PACKAGE}}.Commit={{.COMMIT}} -X {{.CONFIGURATION_PACKAGE}}.Timestamp={{.TIMESTAMP}} ' - GOFLAGS: "-timeout 10m -v -coverpkg=./... -covermode=atomic" DOCS_VERSION: dev DOCS_ALIAS: "" DOCS_REMOTE: "origin" @@ -41,14 +40,20 @@ vars: tasks: build: desc: Build the project - cmds: - - go build -v {{.LDFLAGS}} + deps: + - task: go:build test: desc: Run tests cmds: - - task: go:test-unit - - task: test-integration + - task: go:test + - task: go:test-integration + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/go-task/Taskfile.yml + go:build: + desc: Build the Go code + cmds: + - go build -v {{.LDFLAGS}} go:generate: desc: Generate Go code @@ -60,17 +65,27 @@ tasks: - go generate ./... - task: go:format - go:test-unit: + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-go-task/Taskfile.yml + go:test: desc: Run unit tests cmds: - - go test -short -run '{{default ".*" .TEST_REGEX}}' {{default "-v" .GOFLAGS}} -coverprofile=coverage_unit.txt {{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}} + - | + go test \ + -v \ + -short \ + -run '{{default ".*" .GO_TEST_REGEX}}' \ + {{default "-timeout 10m -coverpkg=./... -covermode=atomic" .GO_TEST_FLAGS}} \ + -coverprofile=coverage_unit.txt \ + {{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}} - test-integration: + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-go-integration-task/Taskfile.yml + go:test-integration: desc: Run integration tests + deps: + - task: go:build + - task: poetry:install-deps cmds: - - task: build - - poetry install --no-root - - poetry run pytest test + - poetry run pytest tests check: desc: Lint and check formatting of all files diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 26821b8a..de9065c6 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -118,26 +118,26 @@ task test To run only the Go unit tests, run: ``` -task go:test-unit +task go:test ``` By default, all tests for all Arduino Lint's Go packages are run. To run unit tests for only one or more specific packages, you can set the `TARGETS` environment variable, e.g.: ``` -TARGETS=./internal/rule task go:test-unit +TARGETS=./internal/rule task go:test ``` Alternatively, to run only some specific test(s), you can specify a regex to match against the test function name, e.g.: ``` -TEST_REGEX='^TestLibraryProperties.*' task go:test-unit +TEST_REGEX='^TestLibraryProperties.*' task go:test ``` Both can be combined as well, typically to run only a specific test: ``` -TEST_REGEX='^TestFindProjects$' TARGETS=./internal/project task go:test-unit +TEST_REGEX='^TestFindProjects$' TARGETS=./internal/project task go:test ``` #### Integration tests @@ -153,7 +153,7 @@ For these reasons, in addition to regular unit tests the project has a suite of After the software requirements have been installed, you should be able to run the tests with: ``` -task test-integration +task go:test-integration ``` This will automatically install the necessary dependencies, if not already installed, and run the integration tests @@ -162,7 +162,7 @@ automatically. To run specific tests, you must run `pytest` from the virtual environment created by Poetry. ``` -poetry run pytest test/test_all.py::test_report_file +poetry run pytest tests/test_all.py::test_report_file ``` You can avoid writing the `poetry run` prefix each time by creating a new shell inside the virtual environment: diff --git a/poetry.lock b/poetry.lock index 39cec3e2..f9008c4c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -164,7 +164,7 @@ python-versions = "*" [[package]] name = "invoke" -version = "1.4.1" +version = "1.6.0" description = "Pythonic task execution" category = "main" optional = false @@ -400,24 +400,23 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pytest" -version = "6.1.2" +version = "6.2.4" description = "pytest: simple powerful testing with Python" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [package.dependencies] atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=17.4.0" +attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<1.0" +pluggy = ">=0.12,<1.0.0a1" py = ">=1.8.2" toml = "*" [package.extras] -checkqa_mypy = ["mypy (==0.780)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] @@ -536,7 +535,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "64ddf6ae94dabf07642e06bb8b54784702b1349abf5c7b398f6c35b4fb2d40e9" +content-hash = "34a7bca079636d788474fddc713c22b14e6830c62f1f5a0e09187d9f841ff4f2" [metadata.files] appdirs = [ @@ -595,9 +594,9 @@ iniconfig = [ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] invoke = [ - {file = "invoke-1.4.1-py2-none-any.whl", hash = "sha256:93e12876d88130c8e0d7fd6618dd5387d6b36da55ad541481dfa5e001656f134"}, - {file = "invoke-1.4.1-py3-none-any.whl", hash = "sha256:87b3ef9d72a1667e104f89b159eaf8a514dbf2f3576885b2bbdefe74c3fb2132"}, - {file = "invoke-1.4.1.tar.gz", hash = "sha256:de3f23bfe669e3db1085789fd859eb8ca8e0c5d9c20811e2407fa042e8a5e15d"}, + {file = "invoke-1.6.0-py2-none-any.whl", hash = "sha256:e6c9917a1e3e73e7ea91fdf82d5f151ccfe85bf30cc65cdb892444c02dbb5f74"}, + {file = "invoke-1.6.0-py3-none-any.whl", hash = "sha256:769e90caeb1bd07d484821732f931f1ad8916a38e3f3e618644687fc09cb6317"}, + {file = "invoke-1.6.0.tar.gz", hash = "sha256:374d1e2ecf78981da94bfaf95366216aaec27c2d6a7b7d5818d92da55aa258d3"}, ] jinja2 = [ {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, @@ -715,8 +714,8 @@ pyparsing = [ {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pytest = [ - {file = "pytest-6.1.2-py3-none-any.whl", hash = "sha256:4288fed0d9153d9646bfcdf0c0428197dba1ecb27a33bb6e031d002fa88653fe"}, - {file = "pytest-6.1.2.tar.gz", hash = "sha256:c0a7e94a8cdbc5422a51ccdad8e6f1024795939cc89159a0ae7f0b316ad3823e"}, + {file = "pytest-6.2.4-py3-none-any.whl", hash = "sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"}, + {file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"}, ] python-dateutil = [ {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, diff --git a/pyproject.toml b/pyproject.toml index afcbe124..881ea065 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,8 +8,8 @@ authors = ["Arduino "] python = "^3.9" # Integration tests dependencies. -invoke = "1.4.1" -pytest = "6.1.2" +invoke = "^1.5.0" +pytest = "^6.2.4" python-dateutil = "^2.8.1" semver = "^2.13.0" diff --git a/test/__init__.py b/tests/__init__.py similarity index 83% rename from test/__init__.py rename to tests/__init__.py index 83a466af..947ae6b4 100644 --- a/test/__init__.py +++ b/tests/__init__.py @@ -1,9 +1,8 @@ -# This file is part of Arduino Lint. -# +# Source: +# https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-python/__init__.py # 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 Lint. # The terms of this license can be found at: # https: // www.gnu.org/licenses/gpl-3.0.en.html # diff --git a/test/pytest.ini b/tests/pytest.ini similarity index 67% rename from test/pytest.ini rename to tests/pytest.ini index d3f2009f..b8beed3f 100644 --- a/test/pytest.ini +++ b/tests/pytest.ini @@ -1,3 +1,4 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-python/pytest.ini [pytest] filterwarnings = error diff --git a/test/test_all.py b/tests/test_all.py similarity index 93% rename from test/test_all.py rename to tests/test_all.py index 038572a1..1faa8135 100644 --- a/test/test_all.py +++ b/tests/test_all.py @@ -1,9 +1,8 @@ -# This file is part of Arduino Lint. -# +# Source: +# https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-integration/test_all.py # 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 Lint. # The terms of this license can be found at: # https: // www.gnu.org/licenses/gpl-3.0.en.html # @@ -13,8 +12,10 @@ # 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 pathlib import platform +import shutil import typing import dateutil.parser @@ -265,10 +266,12 @@ def run_command(pytestconfig, working_dir) -> typing.Callable[..., invoke.runner http://docs.pyinvoke.org/en/1.4/api/runners.html#invoke.runners.Result """ - arduino_lint_path = pathlib.Path(pytestconfig.rootdir).parent / "arduino-lint" + executable_path = pathlib.Path(pytestconfig.rootdir).parent / "arduino-lint" def _run( - cmd: list, custom_working_dir: typing.Optional[str] = None, custom_env: typing.Optional[dict] = None + cmd: list, + custom_working_dir: typing.Optional[str] = None, + custom_env: typing.Optional[dict] = None, ) -> invoke.runners.Result: if cmd is None: cmd = [] @@ -277,7 +280,7 @@ def _run( quoted_cmd = [] for token in cmd: quoted_cmd.append(f'"{token}"') - cli_full_line = '"{}" {}'.format(arduino_lint_path, " ".join(quoted_cmd)) + cli_full_line = '"{}" {}'.format(executable_path, " ".join(quoted_cmd)) run_context = invoke.context.Context() # It might happen that we need to change directories between drives on Windows, # in that case the "/d" flag must be used otherwise directory wouldn't change @@ -289,7 +292,12 @@ def _run( # wrapping the path in quotation marks is the safest approach with run_context.prefix(f'{cd_command} "{custom_working_dir}"'): return run_context.run( - command=cli_full_line, echo=False, hide=True, warn=True, env=custom_env, encoding="utf-8" + command=cli_full_line, + echo=False, + hide=True, + warn=True, + env=custom_env, + encoding="utf-8", ) return _run @@ -300,5 +308,6 @@ def working_dir(tmpdir_factory) -> str: """Create a temporary folder for the test to run in. It will be created before running each test and deleted at the end. This way all the tests work in isolation. """ - work_dir = tmpdir_factory.mktemp(basename="ArduinoLintTestWork") - yield str(work_dir) + work_dir = tmpdir_factory.mktemp(basename="IntegrationTestWorkingDir") + yield os.path.realpath(work_dir) + shutil.rmtree(work_dir, ignore_errors=True) diff --git a/test/testdata/ARDUINO_LINT_OFFICIAL/Arduino_Lib/library.properties b/tests/testdata/ARDUINO_LINT_OFFICIAL/Arduino_Lib/library.properties similarity index 100% rename from test/testdata/ARDUINO_LINT_OFFICIAL/Arduino_Lib/library.properties rename to tests/testdata/ARDUINO_LINT_OFFICIAL/Arduino_Lib/library.properties diff --git a/test/testdata/ARDUINO_LINT_OFFICIAL/Arduino_Lib/src/Arduino_Lib.h b/tests/testdata/ARDUINO_LINT_OFFICIAL/Arduino_Lib/src/Arduino_Lib.h similarity index 100% rename from test/testdata/ARDUINO_LINT_OFFICIAL/Arduino_Lib/src/Arduino_Lib.h rename to tests/testdata/ARDUINO_LINT_OFFICIAL/Arduino_Lib/src/Arduino_Lib.h diff --git a/test/testdata/InvalidSketch/Invalid Sketch.ino b/tests/testdata/InvalidSketch/Invalid Sketch.ino similarity index 100% rename from test/testdata/InvalidSketch/Invalid Sketch.ino rename to tests/testdata/InvalidSketch/Invalid Sketch.ino diff --git a/test/testdata/ValidSketch/LICENSE b/tests/testdata/ValidSketch/LICENSE similarity index 100% rename from test/testdata/ValidSketch/LICENSE rename to tests/testdata/ValidSketch/LICENSE diff --git a/test/testdata/ValidSketch/README.md b/tests/testdata/ValidSketch/README.md similarity index 100% rename from test/testdata/ValidSketch/README.md rename to tests/testdata/ValidSketch/README.md diff --git a/test/testdata/ValidSketch/ValidSketch.ino b/tests/testdata/ValidSketch/ValidSketch.ino similarity index 100% rename from test/testdata/ValidSketch/ValidSketch.ino rename to tests/testdata/ValidSketch/ValidSketch.ino diff --git a/test/testdata/compliance/Invalid/Invalid Sketch.ino b/tests/testdata/compliance/Invalid/Invalid Sketch.ino similarity index 100% rename from test/testdata/compliance/Invalid/Invalid Sketch.ino rename to tests/testdata/compliance/Invalid/Invalid Sketch.ino diff --git a/test/testdata/compliance/Permissive/MismatchedFilename.ino b/tests/testdata/compliance/Permissive/MismatchedFilename.ino similarity index 100% rename from test/testdata/compliance/Permissive/MismatchedFilename.ino rename to tests/testdata/compliance/Permissive/MismatchedFilename.ino diff --git a/test/testdata/compliance/Specification/Specification.ino b/tests/testdata/compliance/Specification/Specification.ino similarity index 100% rename from test/testdata/compliance/Specification/Specification.ino rename to tests/testdata/compliance/Specification/Specification.ino diff --git a/test/testdata/compliance/Strict/LICENSE b/tests/testdata/compliance/Strict/LICENSE similarity index 100% rename from test/testdata/compliance/Strict/LICENSE rename to tests/testdata/compliance/Strict/LICENSE diff --git a/test/testdata/compliance/Strict/README.md b/tests/testdata/compliance/Strict/README.md similarity index 100% rename from test/testdata/compliance/Strict/README.md rename to tests/testdata/compliance/Strict/README.md diff --git a/test/testdata/compliance/Strict/Strict.ino b/tests/testdata/compliance/Strict/Strict.ino similarity index 100% rename from test/testdata/compliance/Strict/Strict.ino rename to tests/testdata/compliance/Strict/Strict.ino diff --git a/test/testdata/library-manager/ARDUINO_LINT_LIBRARY_MANAGER_INDEXING/Servo/Servo.h b/tests/testdata/library-manager/ARDUINO_LINT_LIBRARY_MANAGER_INDEXING/Servo/Servo.h similarity index 100% rename from test/testdata/library-manager/ARDUINO_LINT_LIBRARY_MANAGER_INDEXING/Servo/Servo.h rename to tests/testdata/library-manager/ARDUINO_LINT_LIBRARY_MANAGER_INDEXING/Servo/Servo.h diff --git a/test/testdata/library-manager/ARDUINO_LINT_LIBRARY_MANAGER_INDEXING/Servo/library.properties b/tests/testdata/library-manager/ARDUINO_LINT_LIBRARY_MANAGER_INDEXING/Servo/library.properties similarity index 100% rename from test/testdata/library-manager/ARDUINO_LINT_LIBRARY_MANAGER_INDEXING/Servo/library.properties rename to tests/testdata/library-manager/ARDUINO_LINT_LIBRARY_MANAGER_INDEXING/Servo/library.properties diff --git a/test/testdata/library-manager/False/False.h b/tests/testdata/library-manager/False/False.h similarity index 100% rename from test/testdata/library-manager/False/False.h rename to tests/testdata/library-manager/False/False.h diff --git a/test/testdata/library-manager/Invalid/.gitkeep b/tests/testdata/library-manager/Invalid/.gitkeep similarity index 100% rename from test/testdata/library-manager/Invalid/.gitkeep rename to tests/testdata/library-manager/Invalid/.gitkeep diff --git a/test/testdata/library-manager/Submit/Submit.h b/tests/testdata/library-manager/Submit/Submit.h similarity index 100% rename from test/testdata/library-manager/Submit/Submit.h rename to tests/testdata/library-manager/Submit/Submit.h diff --git a/test/testdata/library-manager/Submit/library.properties b/tests/testdata/library-manager/Submit/library.properties similarity index 100% rename from test/testdata/library-manager/Submit/library.properties rename to tests/testdata/library-manager/Submit/library.properties diff --git a/test/testdata/library-manager/Update/Update.h b/tests/testdata/library-manager/Update/Update.h similarity index 100% rename from test/testdata/library-manager/Update/Update.h rename to tests/testdata/library-manager/Update/Update.h diff --git a/test/testdata/library-manager/Update/library.properties b/tests/testdata/library-manager/Update/library.properties similarity index 100% rename from test/testdata/library-manager/Update/library.properties rename to tests/testdata/library-manager/Update/library.properties diff --git a/test/testdata/project-type/Library/Library.h b/tests/testdata/project-type/Library/Library.h similarity index 100% rename from test/testdata/project-type/Library/Library.h rename to tests/testdata/project-type/Library/Library.h diff --git a/test/testdata/project-type/Library/library.properties b/tests/testdata/project-type/Library/library.properties similarity index 100% rename from test/testdata/project-type/Library/library.properties rename to tests/testdata/project-type/Library/library.properties diff --git a/test/testdata/project-type/PackageIndex/package_valid_index.json b/tests/testdata/project-type/PackageIndex/package_valid_index.json similarity index 100% rename from test/testdata/project-type/PackageIndex/package_valid_index.json rename to tests/testdata/project-type/PackageIndex/package_valid_index.json diff --git a/test/testdata/project-type/Platform/boards.txt b/tests/testdata/project-type/Platform/boards.txt similarity index 100% rename from test/testdata/project-type/Platform/boards.txt rename to tests/testdata/project-type/Platform/boards.txt diff --git a/test/testdata/project-type/Sketch/Sketch.ino b/tests/testdata/project-type/Sketch/Sketch.ino similarity index 100% rename from test/testdata/project-type/Sketch/Sketch.ino rename to tests/testdata/project-type/Sketch/Sketch.ino diff --git a/test/testdata/recursive/SpecificationSketch/SpecificationSketch.ino b/tests/testdata/recursive/SpecificationSketch/SpecificationSketch.ino similarity index 100% rename from test/testdata/recursive/SpecificationSketch/SpecificationSketch.ino rename to tests/testdata/recursive/SpecificationSketch/SpecificationSketch.ino diff --git a/test/testdata/verbose/HasWarnings/HasWarnings.ino b/tests/testdata/verbose/HasWarnings/HasWarnings.ino similarity index 100% rename from test/testdata/verbose/HasWarnings/HasWarnings.ino rename to tests/testdata/verbose/HasWarnings/HasWarnings.ino