-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(test): add tests and GH workflow for pytest
- Loading branch information
1 parent
03e2ab1
commit 868bba9
Showing
5 changed files
with
264 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: Python Tests | ||
|
||
on: | ||
pull_request: | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Set up Python 3.9 | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: 3.9 | ||
|
||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install pytest pytest-cov | ||
pip install -r requirements.txt | ||
- name: Run pytest with coverage | ||
run: | | ||
python -m pytest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
from unittest.mock import MagicMock | ||
from unittest.mock import patch | ||
|
||
import pytest | ||
|
||
|
||
@pytest.fixture(autouse=True) | ||
def setup_env(monkeypatch): | ||
monkeypatch.setenv('GITHUB_TOKEN', 'fake-token') | ||
monkeypatch.setenv('GITHUB_REPOSITORY', 'fake/repo') | ||
|
||
|
||
@pytest.fixture(scope='module') | ||
def github_client_mock(): | ||
with patch('github.Github') as MockGithub: | ||
mock_github = MockGithub.return_value | ||
mock_repo = MagicMock() | ||
mock_github.get_repo.return_value = mock_repo | ||
yield mock_github, mock_repo | ||
|
||
|
||
# Correct fixture to mock JIRA client | ||
@pytest.fixture(scope='module') | ||
def mock_jira_client(): | ||
with patch('jira.JIRA') as MockJIRA: | ||
mock_jira = MockJIRA.return_value | ||
yield mock_jira | ||
|
||
|
||
@pytest.fixture | ||
def sync_issue_module(github_client_mock): | ||
from importlib import reload | ||
import sync_issue | ||
|
||
reload(sync_issue) # Reload to apply the mocked Github client | ||
return sync_issue | ||
|
||
|
||
# Example test function | ||
def test_handle_issue_opened_creates_jira_issue(sync_issue_module, github_client_mock): | ||
_, mock_repo = github_client_mock | ||
mock_jira_client = MagicMock() | ||
mock_event = { | ||
'issue': { | ||
'number': 123, | ||
'title': 'New Issue', | ||
'body': 'Issue description here.', | ||
'user': {'login': 'user123'}, | ||
'labels': [], | ||
'html_url': 'https://github.com/user/repo/issues/123', | ||
'state': 'open', | ||
} | ||
} | ||
|
||
with patch('sync_issue._find_jira_issue', return_value=None) as mock_find_jira_issue, patch( | ||
'sync_issue._create_jira_issue' | ||
) as mock_create_jira_issue: | ||
sync_issue_module.handle_issue_opened(mock_jira_client, mock_event) | ||
|
||
mock_find_jira_issue.assert_called_once() | ||
mock_create_jira_issue.assert_called_once() | ||
|
||
|
||
def test_handle_issue_labeled_adds_label(sync_issue_module, github_client_mock, mock_jira_client): | ||
# Setup | ||
mock_github, mock_repo = github_client_mock | ||
|
||
mock_event = { | ||
'issue': { | ||
'number': 123, | ||
'title': 'Issue for Labeling', | ||
'body': 'Label me!', | ||
'user': {'login': 'user456'}, | ||
'labels': [{'name': 'bug'}], | ||
'html_url': 'https://github.com/user/repo/issues/123', | ||
'state': 'open', | ||
}, | ||
'label': {'name': 'bug'}, | ||
} | ||
|
||
# Adjusting the mock to behave more like a list that can be appended to | ||
mock_jira_issue = MagicMock() | ||
labels_list = ['existing-label'] # Starting with an existing label for demonstration | ||
mock_jira_issue.fields.labels = labels_list | ||
|
||
def update_labels(fields=None): | ||
if fields and 'labels' in fields: | ||
labels_list.extend(fields['labels']) # Simulate adding new labels | ||
|
||
mock_jira_issue.update = MagicMock(side_effect=update_labels) | ||
|
||
with patch('sync_issue._find_jira_issue', return_value=mock_jira_issue), patch( | ||
'sync_issue._get_jira_label', side_effect=lambda x: x['name'] | ||
): | ||
sync_issue_module.handle_issue_labeled(mock_jira_client, mock_event) | ||
|
||
assert 'bug' in labels_list, "Label 'bug' was not added to the JIRA issue labels" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import importlib | ||
from unittest.mock import MagicMock | ||
from unittest.mock import patch | ||
|
||
import pytest | ||
|
||
|
||
# Patch the GitHub client before importing modules that use it | ||
@pytest.fixture(autouse=True) | ||
def mock_env_vars(monkeypatch): | ||
monkeypatch.setenv('GITHUB_TOKEN', 'fake-token') | ||
monkeypatch.setenv('GITHUB_REPOSITORY', 'fake/repo') | ||
|
||
|
||
@pytest.fixture | ||
def mock_github(): | ||
with patch('github.Github') as MockGithub: | ||
mock_repo = MagicMock() | ||
mock_pr = MagicMock() | ||
mock_pr.number = 1 | ||
mock_pr.title = 'Test PR' | ||
mock_pr.html_url = 'http://example.com/testpr' | ||
mock_pr.user.login = 'testuser' | ||
mock_pr.labels = [] | ||
mock_pr.state = 'open' | ||
mock_pr.body = 'Test body' | ||
mock_repo.get_pulls.return_value = [mock_pr] | ||
mock_repo.has_in_collaborators.return_value = False | ||
|
||
MockGithub.return_value.get_repo.return_value = mock_repo | ||
yield mock_repo | ||
|
||
|
||
@pytest.fixture | ||
def sync_pr_module(mock_github): | ||
# Import the module | ||
import sync_pr | ||
|
||
# Reload the module to ensure the mock is applied | ||
importlib.reload(sync_pr) | ||
# Return the reloaded module | ||
return sync_pr | ||
|
||
|
||
@pytest.fixture | ||
def mock_sync_issue(): | ||
with patch('sync_pr._create_jira_issue') as mock_create_jira_issue, patch( | ||
'sync_pr._find_jira_issue', return_value=None | ||
) as mock_find_jira_issue: | ||
yield mock_create_jira_issue, mock_find_jira_issue | ||
|
||
|
||
def test_sync_remain_prs(sync_pr_module, mock_sync_issue, mock_github): | ||
mock_jira = MagicMock() | ||
mock_create_jira_issue, mock_find_jira_issue = mock_sync_issue | ||
|
||
# Use the function from the reloaded module | ||
sync_pr_module.sync_remain_prs(mock_jira) | ||
|
||
# Verify _find_jira_issue was called once with the mock_jira client and the PR data | ||
assert mock_find_jira_issue.call_count == 1 | ||
|
||
# Verify _create_jira_issue was called once since no corresponding JIRA issue was found | ||
assert mock_create_jira_issue.call_count == 1 | ||
|
||
# Example of verifying call arguments (simplified) | ||
call_args = mock_create_jira_issue.call_args | ||
assert 'Test PR' in call_args[0][1]['title'], 'PR title does not match expected value' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import json | ||
from unittest.mock import MagicMock | ||
from unittest.mock import patch | ||
|
||
import pytest | ||
|
||
|
||
@pytest.fixture | ||
def mock_environment(tmp_path, monkeypatch): | ||
event_file = tmp_path / 'event.json' | ||
monkeypatch.setenv('GITHUB_REPOSITORY', 'espressif/esp-idf') | ||
monkeypatch.setenv('GITHUB_TOKEN', 'fake-token') | ||
monkeypatch.setenv('GITHUB_EVENT_PATH', str(event_file)) | ||
monkeypatch.setenv('JIRA_URL', 'https://jira.example.com') | ||
monkeypatch.setenv('JIRA_USER', 'user') | ||
monkeypatch.setenv('JIRA_PASS', 'pass') | ||
return event_file | ||
|
||
|
||
@pytest.fixture | ||
def sync_to_jira_main(monkeypatch): | ||
monkeypatch.setattr('github.Github', MagicMock()) | ||
monkeypatch.setattr('jira.JIRA', MagicMock()) | ||
|
||
# Import the main function dynamically after applying mocks | ||
from sync_to_jira import main as dynamically_imported_main | ||
|
||
return dynamically_imported_main | ||
|
||
|
||
def test_not_running_in_github_action_context(capsys, sync_to_jira_main, monkeypatch): | ||
monkeypatch.delenv('GITHUB_REPOSITORY', raising=False) | ||
sync_to_jira_main() | ||
captured = capsys.readouterr() | ||
assert 'Not running in GitHub action context, nothing to do' in captured.out | ||
|
||
|
||
def test_not_espressif_repo(capsys, sync_to_jira_main, monkeypatch): | ||
monkeypatch.setenv('GITHUB_REPOSITORY', 'other/repo') | ||
sync_to_jira_main() | ||
captured = capsys.readouterr() | ||
assert 'Not an Espressif repo, nothing to sync to JIRA' in captured.out | ||
|
||
|
||
def test_handle_issue_opened_event(mock_environment, sync_to_jira_main, monkeypatch): | ||
event_data = { | ||
'action': 'opened', | ||
'issue': { | ||
'number': 1, | ||
'title': 'Test issue', | ||
'body': 'This is a test issue', | ||
'user': {'login': 'testuser'}, | ||
'html_url': 'https://github.com/espressif/esp-idf/issues/1', | ||
}, | ||
} | ||
mock_environment.write_text(json.dumps(event_data)) | ||
monkeypatch.setenv('GITHUB_EVENT_NAME', 'issues') | ||
|
||
with patch('sync_to_jira.handle_issue_opened') as mock_handle_issue_opened: | ||
sync_to_jira_main() | ||
mock_handle_issue_opened.assert_called_once() |