Skip to content

Commit

Permalink
Merge pull request #22 from ghinks/feat/test-reviewers
Browse files Browse the repository at this point in the history
Feat/test reviewers
  • Loading branch information
ghinks authored Jan 7, 2025
2 parents 09463f8 + 4a91468 commit 476add0
Show file tree
Hide file tree
Showing 11 changed files with 295 additions and 7 deletions.
54 changes: 53 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions pr_reviews/queries/get_reviewers_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@
HTTPS_PROXY = os.getenv("https_proxy")


async def fetch(session: aiohttp.ClientSession, url: str) -> dict[str, str]:
async def fetch(client: aiohttp.ClientSession, url: str) -> dict[str, str]:
headers = {
"Authorization": f"Bearer {GITHUB_TOKEN}",
"Accept": "application/vnd.github.v3+json",
}
if HTTPS_PROXY:
async with session.get(url,
headers=headers,
proxy=HTTPS_PROXY) as response:
async with client.get(url,
headers=headers,
proxy=HTTPS_PROXY) as response:
return await response.json()
else:
async with session.get(url, headers=headers) as response:
async with client.get(url, headers=headers) as response:
return await response.json()


Expand Down
10 changes: 9 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ aiohttp = "^3.11.2"
requests = "^2.32.3"
tabulate = "^0.9.0"
asyncio = "^3.4.3"
aioresponses = "^0.7.7"


[tool.poetry.group.dev.dependencies]
pytest = "^8.3.4"
ruff = "^0.8.4"
isort = "^5.13.2"
pytest-aiohttp = "^1.0.5"
pytest-asyncio = "^0.25.0"

[build-system]
requires = ["poetry-core"]
Expand All @@ -36,6 +39,7 @@ exclude = [
"venv",
"pr_reviews/**/__init__.py",
"tests/__init__.py",
"tests/get_reviewers/__init__.py"
]

[tool.ruff.lint]
Expand All @@ -52,4 +56,8 @@ per-file-ignores = { "tests/**/test*.py" = ["S101"] }
#PT: Pytest-specific rules
#Q: Quotes (single vs. double)
#S: Security issues
#T: Type annotations
#T: Type annotations

[tool.pytest.ini_options]
asyncio_mode = "auto" # or "strict"
required_plugins = ["pytest-asyncio"]
50 changes: 50 additions & 0 deletions tests/async_test_notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Asynch testing notes
##
## references
- [reviewers github api docs](https://docs.github.com/en/rest/pulls/reviews?apiVersion=2022-11-28)
- [github api docs](https://docs.github.com/en/rest/reference/pulls#reviews)

### sample response
```json
[
{
"id": 80,
"node_id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3ODA=",
"user": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"body": "Here is the body for the review.",
"state": "APPROVED",
"html_url": "https://github.com/octocat/Hello-World/pull/12#pullrequestreview-80",
"pull_request_url": "https://api.github.com/repos/octocat/Hello-World/pulls/12",
"_links": {
"html": {
"href": "https://github.com/octocat/Hello-World/pull/12#pullrequestreview-80"
},
"pull_request": {
"href": "https://api.github.com/repos/octocat/Hello-World/pulls/12"
}
},
"submitted_at": "2019-11-17T17:43:43Z",
"commit_id": "ecdd80bb57125d7ba9641ffaa4d7d2c19d3f3091",
"author_association": "COLLABORATOR"
}
]
```
41 changes: 41 additions & 0 deletions tests/fixtures/reviews_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"id": 80,
"node_id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3ODA=",
"user": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"body": "Here is the body for the review.",
"state": "APPROVED",
"html_url": "https://github.com/octocat/Hello-World/pull/12#pullrequestreview-80",
"pull_request_url": "https://api.github.com/repos/octocat/Hello-World/pulls/12",
"_links": {
"html": {
"href": "https://github.com/octocat/Hello-World/pull/12#pullrequestreview-80"
},
"pull_request": {
"href": "https://api.github.com/repos/octocat/Hello-World/pulls/12"
}
},
"submitted_at": "2019-11-17T17:43:43Z",
"commit_id": "ecdd80bb57125d7ba9641ffaa4d7d2c19d3f3091",
"author_association": "COLLABORATOR"
}
]
Empty file added tests/get_reviewers/__init__.py
Empty file.
45 changes: 45 additions & 0 deletions tests/get_reviewers/test_get_reviewers_rest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import json
import os
from pathlib import Path
from typing import Callable
from unittest.mock import patch

import aiohttp
import pytest
from aioresponses import aioresponses

from pr_reviews.queries.get_reviewers_rest import fetch


@pytest.fixture
def read_reviews_file() -> str:
# assume the reviews_response.json file is in the tests/fixtures directory
with Path("tests/fixtures/reviews_response.json").open("r") as file:
return json.dumps(json.load(file))

@pytest.fixture
def get_reviews_url() -> callable:
def _get_reviews_url(owner: str, repo: str, pull_number: int) -> str:
return f"https://api.github.com/repos/{owner}/{repo}/pulls/{pull_number}/reviews"
return _get_reviews_url


@pytest.fixture
def mock_aioresponse() -> aioresponses:
with aioresponses() as m:
yield m

@pytest.mark.asyncio
@patch.dict(os.environ, {"GITHUB_TOKEN": "test_token"})
async def test_get_reviewers_success(read_reviews_file: str,
get_reviews_url: Callable[[],str],
mock_aioresponse: aioresponses) -> None:
url = get_reviews_url("expressjs", "express", 1)
mock_aioresponse.get(
url,
status=200,
payload=read_reviews_file,
)
async with aiohttp.ClientSession() as client:
response = await fetch(client, url)
assert response == read_reviews_file
23 changes: 23 additions & 0 deletions tests/get_reviewers/test_get_reviewers_rest_fetch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import asyncio
import unittest

import aiohttp
from aioresponses import aioresponses

from pr_reviews.queries.get_reviewers_rest import fetch
from tests.utils import get_reviews_url, read_reviews_file


class TestFetch(unittest.TestCase):
@aioresponses()
def test_fetch_json(self, mocked: aioresponses) -> None:
url = get_reviews_url("expressjs", "express", 1)
payload = read_reviews_file()
mocked.get(url, status=200, payload=payload)

async def run_test() -> None:
async with aiohttp.ClientSession() as session:
result = await fetch(session,url)
assert result == payload

asyncio.run(run_test())
26 changes: 26 additions & 0 deletions tests/get_reviewers/test_get_reviewers_rest_fetch_batch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import asyncio
import unittest

from aioresponses import aioresponses

from pr_reviews.queries.get_reviewers_rest import fetch_batch
from tests.utils import get_reviews_url, read_reviews_file


class TestFetchBatch(unittest.TestCase):
@aioresponses()
def test_fetch_json(self, mocked: aioresponses) -> None:
payload = read_reviews_file()
urls =[]
for pull_number in range(2):
url = get_reviews_url("expressjs",
"express",
pull_number)
urls.append(url)
mocked.get(url, status=200, payload=payload)

async def run_test() -> None:
result = await fetch_batch(urls)
assert result == [payload, payload]

asyncio.run(run_test())
31 changes: 31 additions & 0 deletions tests/get_reviewers/test_get_reviewers_rest_pull_requests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import unittest

from aioresponses import aioresponses

from pr_reviews.queries.get_reviewers_rest import (
get_reviewers_for_pull_requests,
)
from tests.utils import get_reviews_url, read_reviews_file


class TestGetReviewers(unittest.TestCase):
OWNER = "expressjs"
REPO = "express"
PULL_REQUESTS: tuple[int, ...] = (1, 2)
@aioresponses()
def test_get_reviewers(self, mocked: aioresponses) -> None:
payload = read_reviews_file()
urls =[]
for pull_number in self.PULL_REQUESTS:
url = get_reviews_url(self.OWNER,
self.REPO,
pull_number)
urls.append(url)
mocked.get(url, status=200, payload=payload)

results = get_reviewers_for_pull_requests(self.OWNER,
self.REPO,
self.PULL_REQUESTS)
assert results[0]["id"] == 1


12 changes: 12 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Python
import json
from pathlib import Path


def read_reviews_file() -> str:
# assume the reviews_response.json file is in the tests/fixtures directory
with Path("tests/fixtures/reviews_response.json").open("r") as file:
return json.load(file)

def get_reviews_url(owner: str, repo: str, pull_number: int) -> str:
return f"https://api.github.com/repos/{owner}/{repo}/pulls/{pull_number}/reviews"

0 comments on commit 476add0

Please sign in to comment.