Skip to content

Commit

Permalink
ci: add test-python.yml
Browse files Browse the repository at this point in the history
  • Loading branch information
hfudev committed Jan 6, 2025
1 parent 01e10d6 commit 22b251d
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 0 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/test-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Python Tests with Coverage
on:
push:
branches: [main]
paths:
- "**.py"
pull_request:
branches: [main]
paths:
- "**.py"

# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
# `contents` is for permission to the contents of the repository.
# `pull-requests` is for permission to pull request
permissions:
contents: write
checks: write
pull-requests: write

jobs:
test-python:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e '.[test]'
- name: Run tests with pytest and coverage
run: |
pytest --junitxml pytest.xml --cov-report term-missing:skip-covered --cov idf_ci tests/ | tee pytest-coverage.txt
- name: Upload coverage report to PR (Python 3.13 only)
if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
uses: MishaKav/pytest-coverage-comment@v1
with:
pytest-coverage-path: ./pytest-coverage.txt
junitxml-path: ./pytest.xml
78 changes: 78 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0

import os
from pathlib import Path

import pytest
from click.testing import CliRunner

from idf_ci.cli import cli


@pytest.fixture
def runner():
return CliRunner()


@pytest.fixture
def temp_dir(tmp_path: Path) -> str:
return str(tmp_path)


def test_build_profile_init(runner, temp_dir):
# Test init command with default path
with runner.isolated_filesystem():
result = runner.invoke(cli, ['build-profile', 'init', '--path', temp_dir])
assert result.exit_code == 0
assert f'Created build profile at {os.path.join(temp_dir, ".idf_build_apps.toml")}' in result.output
assert os.path.exists(os.path.join(temp_dir, '.idf_build_apps.toml'))

# Test init command with specific file path
specific_path = os.path.join(temp_dir, 'custom_build.toml')
result = runner.invoke(cli, ['build-profile', 'init', '--path', specific_path])
assert result.exit_code == 0
assert f'Created build profile at {specific_path}' in result.output
assert os.path.exists(specific_path)


def test_ci_profile_init(runner, temp_dir):
# Test init command with default path
with runner.isolated_filesystem():
result = runner.invoke(cli, ['ci-profile', 'init', '--path', temp_dir])
assert result.exit_code == 0
assert f'Created CI profile at {os.path.join(temp_dir, ".idf_ci.toml")}' in result.output
assert os.path.exists(os.path.join(temp_dir, '.idf_ci.toml'))

# Test init command with specific file path
specific_path = os.path.join(temp_dir, 'custom_ci.toml')
result = runner.invoke(cli, ['ci-profile', 'init', '--path', specific_path])
assert result.exit_code == 0
assert f'Created CI profile at {specific_path}' in result.output
assert os.path.exists(specific_path)


def test_completions(runner):
result = runner.invoke(cli, ['completions'])
assert result.exit_code == 0
assert 'To enable autocomplete run the following command:' in result.output
assert 'Bash:' in result.output
assert 'Zsh:' in result.output
assert 'Fish:' in result.output


def test_profile_init_file_exists(runner, temp_dir):
# Test that init doesn't fail if file already exists
build_profile_path = os.path.join(temp_dir, '.idf_build_apps.toml')
ci_profile_path = os.path.join(temp_dir, '.idf_ci.toml')

# Create files first
Path(build_profile_path).touch()
Path(ci_profile_path).touch()

# Try to init again
result = runner.invoke(cli, ['build-profile', 'init', '--path', temp_dir])
assert result.exit_code == 0

result = runner.invoke(cli, ['ci-profile', 'init', '--path', temp_dir])
assert result.exit_code == 0
120 changes: 120 additions & 0 deletions tests/test_profiles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0

import os

import pytest

from idf_ci.settings import CiSettings


@pytest.fixture
def default_settings():
return CiSettings()


def test_default_component_mapping_regexes(default_settings):
expected_regexes = [
'/components/(.+)/',
'/common_components/(.+)/',
]
assert default_settings.component_mapping_regexes == expected_regexes


def test_default_component_ignored_file_extensions(default_settings):
expected_extensions = [
'.md',
'.rst',
'.yaml',
'.yml',
'.py',
]
assert default_settings.component_ignored_file_extensions == expected_extensions


def test_get_modified_components(default_settings):
test_files = [
'components/wifi/wifi.c',
'components/bt/bt_main.c',
'common_components/esp_common/test.c',
'docs/example.md', # should be ignored
'random/file.txt', # should not match any component
]

expected_components = {'wifi', 'bt', 'esp_common'}
assert default_settings.get_modified_components(test_files) == expected_components


def test_ignored_file_extensions(default_settings):
test_files = [
'components/wifi/README.md',
'components/bt/docs.rst',
'components/esp_common/config.yaml',
'components/test/test.yml',
'components/utils/util.py',
]

assert default_settings.get_modified_components(test_files) == set()


def test_extended_component_mapping_regexes():
settings = CiSettings(
extend_component_mapping_regexes=[
'/custom/path/(.+)/',
]
)

test_files = [
'custom/path/my_component/test.c',
'components/wifi/wifi.c',
]

expected_components = {'my_component', 'wifi'}
assert settings.get_modified_components(test_files) == expected_components


def test_extended_ignored_extensions():
settings = CiSettings(
extend_component_ignored_file_extensions=[
'.txt',
'.json',
]
)

test_files = [
'components/wifi/test.txt',
'components/bt/config.json',
'components/esp_common/main.c',
]

expected_components = {'esp_common'}
assert settings.get_modified_components(test_files) == expected_components


def test_build_profile_default():
settings = CiSettings()
assert settings.build_profile == 'default'


def test_build_profile_custom():
custom_profile = 'custom_profile'
settings = CiSettings(build_profile=custom_profile)
assert settings.build_profile == custom_profile


def test_all_component_mapping_regexes(default_settings):
patterns = default_settings.all_component_mapping_regexes
assert len(patterns) == 2

test_path = '/components/test_component/test.c'
for pattern in patterns:
match = pattern.search(test_path)
if '/components/(.+)/' in pattern.pattern:
assert match is not None
assert match.group(1) == 'test_component'


def test_component_mapping_with_absolute_paths(default_settings):
abs_path = os.path.abspath('components/wifi/wifi.c')
components = default_settings.get_modified_components([abs_path])
assert components == {'wifi'}

0 comments on commit 22b251d

Please sign in to comment.