Skip to content

Commit

Permalink
Migrate to pytest (#42)
Browse files Browse the repository at this point in the history
* add test requirements

* add pytest configuration

* add requirements

* refactoring ci process

* fix typo

* use async pytest

* add pytest libraries

* add pytest libraries

* remove unnecessary file

* remove event_loop fixture

* migrated to different http mock library
  • Loading branch information
exxamalte committed Jan 9, 2024
1 parent c3f39bd commit 1b783c9
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 142 deletions.
23 changes: 16 additions & 7 deletions .github/workflows/ci.yaml
Expand Up @@ -12,7 +12,7 @@ jobs:
name: Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
env:
USING_COVERAGE: '3.8'
USING_COVERAGE: '3.10'
strategy:
fail-fast: true
matrix:
Expand All @@ -28,13 +28,22 @@ jobs:
python -VV
python -m site
python -m pip install --upgrade pip setuptools wheel
python -m pip install --upgrade coverage[toml] virtualenv tox tox-gh-actions
- name: "Run tox targets for ${{ matrix.python-version }}"
run: "python -m tox"
- name: "Combine coverage"
if: "contains(env.USING_COVERAGE, matrix.python-version)"
python -m pip install -r requirements.txt
python -m pip install -r requirements-test.txt
- name: "Run tests for ${{ matrix.python-version }}"
run: |
set -xe
pip install pytest-cov
pip install coverage
pytest \
-qq \
--timeout=9 \
--durations=10 \
-n auto \
--cov aio_geojson_client \
--cov-report xml \
-o console_output_style=count \
-p no:sugar \
tests
python -m coverage xml
- name: "Upload coverage to Codecov"
if: "contains(env.USING_COVERAGE, matrix.python-version)"
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Expand Up @@ -4,3 +4,8 @@ target-version = ['py38', 'py39', 'py310', 'py311']
[tool.isort]
profile = "black"
src_paths = ["aio_geojson_client", "tests"]

[tool.pytest.ini_options]
testpaths = [
"tests",
]
6 changes: 6 additions & 0 deletions requirements-test.txt
@@ -0,0 +1,6 @@
pytest-asyncio
pytest-timeout
pytest-xdist
pytest-cov
mock
aioresponses
3 changes: 3 additions & 0 deletions requirements.txt
@@ -0,0 +1,3 @@
aiohttp>=3.7.4,<4
geojson>=2.4.0
haversine>=1.0.1
10 changes: 10 additions & 0 deletions tests/conftest.py
@@ -0,0 +1,10 @@
"""Configuration for tests."""
import pytest
from aioresponses import aioresponses


@pytest.fixture
def mock_aioresponse():
"""Return aioresponse fixture."""
with aioresponses() as m:
yield m
105 changes: 48 additions & 57 deletions tests/test_feed.py
@@ -1,5 +1,6 @@
"""Test for the generic geojson feed."""
import asyncio
from http import HTTPStatus
from unittest.mock import MagicMock

import aiohttp
Expand All @@ -15,18 +16,16 @@


@pytest.mark.asyncio
async def test_update_ok(aresponses, event_loop):
async def test_update_ok(mock_aioresponse):
"""Test updating feed is ok."""
home_coordinates = (-31.0, 151.0)
aresponses.add(
"test.url",
"/testpath",
"get",
aresponses.Response(text=load_fixture("generic_feed_1.json"), status=200),
mock_aioresponse.get(
"http://test.url/testpath",
status=HTTPStatus.OK,
body=load_fixture("generic_feed_1.json"),
)

async with aiohttp.ClientSession(loop=event_loop) as websession:

async with aiohttp.ClientSession(loop=asyncio.get_running_loop()) as websession:
feed = MockGeoJsonFeed(websession, home_coordinates, "http://test.url/testpath")
assert (
repr(feed) == "<MockGeoJsonFeed(home=(-31.0, 151.0), "
Expand Down Expand Up @@ -67,17 +66,16 @@ async def test_update_ok(aresponses, event_loop):


@pytest.mark.asyncio
async def test_update_ok_with_filtering(aresponses, event_loop):
async def test_update_ok_with_filtering(mock_aioresponse):
"""Test updating feed is ok."""
home_coordinates = (-37.0, 150.0)
aresponses.add(
"test.url",
"/testpath",
"get",
aresponses.Response(text=load_fixture("generic_feed_1.json"), status=200),
mock_aioresponse.get(
"http://test.url/testpath",
status=HTTPStatus.OK,
body=load_fixture("generic_feed_1.json"),
)

async with aiohttp.ClientSession(loop=event_loop) as websession:
async with aiohttp.ClientSession(loop=asyncio.get_running_loop()) as websession:
feed = MockGeoJsonFeed(
websession, home_coordinates, "http://test.url/testpath", filter_radius=90.0
)
Expand All @@ -91,17 +89,16 @@ async def test_update_ok_with_filtering(aresponses, event_loop):


@pytest.mark.asyncio
async def test_update_ok_with_filter_override(aresponses, event_loop):
async def test_update_ok_with_filter_override(mock_aioresponse):
"""Test updating feed is ok."""
home_coordinates = (-37.0, 150.0)
aresponses.add(
"test.url",
"/testpath",
"get",
aresponses.Response(text=load_fixture("generic_feed_1.json"), status=200),
mock_aioresponse.get(
"http://test.url/testpath",
status=HTTPStatus.OK,
body=load_fixture("generic_feed_1.json"),
)

async with aiohttp.ClientSession(loop=event_loop) as websession:
async with aiohttp.ClientSession(loop=asyncio.get_running_loop()) as websession:
feed = MockGeoJsonFeed(
websession, home_coordinates, "http://test.url/testpath", filter_radius=60.0
)
Expand All @@ -117,18 +114,16 @@ async def test_update_ok_with_filter_override(aresponses, event_loop):


@pytest.mark.asyncio
async def test_update_geometries(aresponses, event_loop):
async def test_update_geometries(mock_aioresponse):
"""Test updating feed is ok."""
home_coordinates = (-31.0, 151.0)
aresponses.add(
"test.url",
"/testpath",
"get",
aresponses.Response(text=load_fixture("generic_feed_3.json"), status=200),
mock_aioresponse.get(
"http://test.url/testpath",
status=HTTPStatus.OK,
body=load_fixture("generic_feed_3.json"),
)

async with aiohttp.ClientSession(loop=event_loop) as websession:

async with aiohttp.ClientSession(loop=asyncio.get_running_loop()) as websession:
feed = MockGeoJsonFeed(websession, home_coordinates, "http://test.url/testpath")
assert (
repr(feed) == "<MockGeoJsonFeed(home=(-31.0, 151.0), "
Expand Down Expand Up @@ -165,11 +160,11 @@ async def test_update_geometries(aresponses, event_loop):


@pytest.mark.asyncio
async def test_update_with_client_exception(event_loop):
async def test_update_with_client_exception():
"""Test updating feed results in error."""
home_coordinates = (-31.0, 151.0)

async with aiohttp.ClientSession(loop=event_loop):
async with aiohttp.ClientSession(loop=asyncio.get_running_loop()):
mock_websession = MagicMock()
mock_websession.request.side_effect = ClientOSError
feed = MockGeoJsonFeed(
Expand All @@ -181,39 +176,39 @@ async def test_update_with_client_exception(event_loop):


@pytest.mark.asyncio
async def test_update_with_request_exception(aresponses, event_loop):
async def test_update_with_request_exception(mock_aioresponse):
"""Test updating feed results in error."""
home_coordinates = (-31.0, 151.0)
aresponses.add("test.url", "/badpath", "get", aresponses.Response(status=404))
mock_aioresponse.get("http://test.url/testpath", status=HTTPStatus.NOT_FOUND)

async with aiohttp.ClientSession(loop=event_loop) as websession:
async with aiohttp.ClientSession(loop=asyncio.get_running_loop()) as websession:
feed = MockGeoJsonFeed(websession, home_coordinates, "http://test.url/badpath")
status, entries = await feed.update()
assert status == UPDATE_ERROR
assert feed.last_timestamp is None


@pytest.mark.asyncio
async def test_update_with_json_decode_error(aresponses, event_loop):
async def test_update_with_json_decode_error(mock_aioresponse):
"""Test updating feed raises exception."""
home_coordinates = (-31.0, 151.0)
aresponses.add(
"test.url", "/badjson", "get", aresponses.Response(text="NOT JSON", status=200)
mock_aioresponse.get(
"http://test.url/badjson", status=HTTPStatus.OK, body="NOT JSON"
)

async with aiohttp.ClientSession(loop=event_loop) as websession:
async with aiohttp.ClientSession(loop=asyncio.get_running_loop()) as websession:
feed = MockGeoJsonFeed(websession, home_coordinates, "http://test.url/badjson")
status, entries = await feed.update()
assert status == UPDATE_ERROR
assert entries is None


@pytest.mark.asyncio
async def test_update_with_timeout_error(event_loop):
async def test_update_with_timeout_error():
"""Test updating feed results in timeout error."""
home_coordinates = (-31.0, 151.0)

async with aiohttp.ClientSession(loop=event_loop):
async with aiohttp.ClientSession(loop=asyncio.get_running_loop()):
mock_websession = MagicMock()
mock_websession.request.side_effect = asyncio.TimeoutError
feed = MockGeoJsonFeed(
Expand All @@ -225,18 +220,16 @@ async def test_update_with_timeout_error(event_loop):


@pytest.mark.asyncio
async def test_update_ok_feed_feature(aresponses, event_loop):
async def test_update_ok_feed_feature(mock_aioresponse):
"""Test updating feed is ok."""
home_coordinates = (-31.0, 151.0)
aresponses.add(
"test.url",
"/testpath",
"get",
aresponses.Response(text=load_fixture("generic_feed_4.json"), status=200),
mock_aioresponse.get(
"http://test.url/testpath",
status=HTTPStatus.OK,
body=load_fixture("generic_feed_4.json"),
)

async with aiohttp.ClientSession(loop=event_loop) as websession:

async with aiohttp.ClientSession(loop=asyncio.get_running_loop()) as websession:
feed = MockGeoJsonFeed(websession, home_coordinates, "http://test.url/testpath")
assert (
repr(feed) == "<MockGeoJsonFeed(home=(-31.0, 151.0), "
Expand All @@ -257,18 +250,16 @@ async def test_update_ok_feed_feature(aresponses, event_loop):


@pytest.mark.asyncio
async def test_unsupported_object(aresponses, event_loop, caplog):
async def test_unsupported_object(mock_aioresponse, caplog):
"""Test updating feed is ok."""
home_coordinates = (-31.0, 151.0)
aresponses.add(
"test.url",
"/testpath",
"get",
aresponses.Response(text=load_fixture("generic_feed_5.json"), status=200),
mock_aioresponse.get(
"http://test.url/testpath",
status=HTTPStatus.OK,
body=load_fixture("generic_feed_5.json"),
)

async with aiohttp.ClientSession(loop=event_loop) as websession:

async with aiohttp.ClientSession(loop=asyncio.get_running_loop()) as websession:
feed = MockGeoJsonFeed(websession, home_coordinates, "http://test.url/testpath")
assert (
repr(feed) == "<MockGeoJsonFeed(home=(-31.0, 151.0), "
Expand Down

0 comments on commit 1b783c9

Please sign in to comment.