Skip to content

Commit

Permalink
Fix the formatting of the integration tests (#84)
Browse files Browse the repository at this point in the history
Fix the formatting of the integration tests using `black` and `isort`.
  • Loading branch information
camille-bouvy-frequenz authored Dec 12, 2024
2 parents 8385158 + 0f9958d commit 9e6d723
Showing 1 changed file with 94 additions and 41 deletions.
135 changes: 94 additions & 41 deletions integration_tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

"""System tests for Electricity Trading API."""
import asyncio
import os
from datetime import datetime, timedelta, timezone
from decimal import Decimal
from typing import Any, Generator

import os
import grpc
import pytest

Expand Down Expand Up @@ -38,6 +38,7 @@
MIN_PRICE = Decimal(-9999.0)
MAX_PRICE = Decimal(9999.0)


@pytest.fixture
async def set_up() -> dict[str, Any]:
"""Set up the test suite."""
Expand Down Expand Up @@ -206,6 +207,7 @@ async def test_create_order_invalid_delivery_start_15_minutes_ago(
with pytest.raises(ValueError, match="delivery_period must be in the future"):
await create_test_order(set_up, delivery_period=delivery_period)


@pytest.mark.asyncio
async def test_create_order_invalid_valid_until_one_hour_ago(
set_up: dict[str, Any]
Expand All @@ -227,9 +229,10 @@ async def test_list_gridpool_orders(set_up: dict[str, Any]) -> None:
# List the orders and check they are present
# filter by delivery period to avoid fetching too many orders
orders = [
order async for order in set_up["client"].list_gridpool_orders(
gridpool_id=GRIDPOOL_ID,
delivery_period=set_up["delivery_period"])
order
async for order in set_up["client"].list_gridpool_orders(
gridpool_id=GRIDPOOL_ID, delivery_period=set_up["delivery_period"]
)
]
listed_orders_id = [order.order_id for order in orders]
for order_id in created_orders_id:
Expand Down Expand Up @@ -330,7 +333,8 @@ async def test_cancel_all_orders(set_up: dict[str, Any]) -> None:
await set_up["client"].cancel_all_gridpool_orders(GRIDPOOL_ID)

orders = [
order async for order in set_up["client"].list_gridpool_orders(
order
async for order in set_up["client"].list_gridpool_orders(
gridpool_id=GRIDPOOL_ID,
)
]
Expand All @@ -346,10 +350,11 @@ async def test_list_gridpool_trades(set_up: dict[str, Any]) -> None:
"""Test listing gridpool trades."""
buy_order, sell_order = await create_test_trade(set_up)
trades = [
trade async for trade in set_up["client"].list_gridpool_trades(
GRIDPOOL_ID,
delivery_period=buy_order.order.delivery_period,
)
trade
async for trade in set_up["client"].list_gridpool_trades(
GRIDPOOL_ID,
delivery_period=buy_order.order.delivery_period,
)
]
assert len(trades) >= 1

Expand All @@ -358,20 +363,23 @@ async def test_list_gridpool_trades(set_up: dict[str, Any]) -> None:
async def test_list_public_trades(set_up: dict[str, Any]) -> None:
"""Test listing public trades."""
delivery_period = DeliveryPeriod(
start=datetime.fromisoformat("2024-06-10T10:00:00+00:00"),
duration=timedelta(minutes=15)
)
start=datetime.fromisoformat("2024-06-10T10:00:00+00:00"),
duration=timedelta(minutes=15),
)

public_trades = []
counter = 0
async for trade in set_up["client"].list_public_trades(delivery_period=delivery_period):
async for trade in set_up["client"].list_public_trades(
delivery_period=delivery_period
):
public_trades.append(trade)
counter += 1
if counter == 10:
break

assert len(public_trades) == 10, "Failed to retrieve 10 public trades"


@pytest.mark.asyncio
async def test_stream_gridpool_orders(set_up: dict[str, Any]) -> None:
"""Test streaming gridpool orders."""
Expand Down Expand Up @@ -417,6 +425,7 @@ async def test_stream_gridpool_trades(set_up: dict[str, Any]) -> None:
except asyncio.TimeoutError:
pytest.fail("Streaming timed out, no trade received in 15 seconds")


@pytest.mark.asyncio
async def test_create_order_zero_quantity(set_up: dict[str, Any]) -> None:
"""Test creating an order with zero quantity."""
Expand All @@ -434,26 +443,36 @@ async def test_create_order_negative_quantity(set_up: dict[str, Any]) -> None:


@pytest.mark.asyncio
async def test_create_order_maximum_price_precision_exceeded(set_up: dict[str, Any]) -> None:
async def test_create_order_maximum_price_precision_exceeded(
set_up: dict[str, Any]
) -> None:
"""Test creating an order with excessive decimal precision in price."""
excessive_precision_price = Price(amount=Decimal("56.123"), currency=Currency.EUR)
with pytest.raises(ValueError, match="cannot have more than 2 decimal places"):
await create_test_order(set_up, price=excessive_precision_price)


@pytest.mark.asyncio
async def test_create_order_maximum_quantity_precision_exceeded(set_up: dict[str, Any]) -> None:
async def test_create_order_maximum_quantity_precision_exceeded(
set_up: dict[str, Any]
) -> None:
"""Test creating an order with excessive decimal precision in quantity."""
excessive_precision_quantity = Power(mw=Decimal("0.5001"))
with pytest.raises(ValueError, match="The quantity cannot have more than 1 decimal."):
with pytest.raises(
ValueError, match="The quantity cannot have more than 1 decimal."
):
await create_test_order(set_up, quantity=excessive_precision_quantity)


@pytest.mark.asyncio
async def test_cancel_non_existent_order(set_up: dict[str, Any]) -> None:
"""Test canceling a non-existent order and expecting an error."""
non_existent_order_id = 999999
with pytest.raises(grpc.aio.AioRpcError) as excinfo:
await set_up["client"].cancel_gridpool_order(GRIDPOOL_ID, non_existent_order_id)
assert excinfo.value.code() == grpc.StatusCode.UNAVAILABLE, "Cancelling non-existent order should return an error"
assert (
excinfo.value.code() == grpc.StatusCode.UNAVAILABLE
), "Cancelling non-existent order should return an error"


@pytest.mark.asyncio
Expand All @@ -462,14 +481,20 @@ async def test_cancel_already_cancelled_order(set_up: dict[str, Any]) -> None:
order = await create_test_order(set_up)
await set_up["client"].cancel_gridpool_order(GRIDPOOL_ID, order.order_id)
with pytest.raises(grpc.aio.AioRpcError) as excinfo:
cancelled_order = await set_up["client"].cancel_gridpool_order(GRIDPOOL_ID, order.order_id)
assert excinfo.value.code() == grpc.StatusCode.INVALID_ARGUMENT, "Order is already cancelled"
cancelled_order = await set_up["client"].cancel_gridpool_order(
GRIDPOOL_ID, order.order_id
)
assert (
excinfo.value.code() == grpc.StatusCode.INVALID_ARGUMENT
), "Order is already cancelled"


@pytest.mark.asyncio
async def test_create_order_with_invalid_delivery_area(set_up: dict[str, Any]) -> None:
"""Test creating an order with an invalid delivery area code."""
invalid_delivery_area = DeliveryArea(code="INVALID_CODE", code_type=EnergyMarketCodeType.EUROPE_EIC)
invalid_delivery_area = DeliveryArea(
code="INVALID_CODE", code_type=EnergyMarketCodeType.EUROPE_EIC
)
with pytest.raises(grpc.aio.AioRpcError) as excinfo:
await set_up["client"].create_gridpool_order(
gridpool_id=GRIDPOOL_ID,
Expand All @@ -481,22 +506,28 @@ async def test_create_order_with_invalid_delivery_area(set_up: dict[str, Any]) -
quantity=set_up["quantity"],
tag="invalid-delivery-area",
)
assert excinfo.value.code() == grpc.StatusCode.UNAVAILABLE, "Delivery area not found"
assert (
excinfo.value.code() == grpc.StatusCode.UNAVAILABLE
), "Delivery area not found"


@pytest.mark.asyncio
async def test_create_order_below_minimum_quantity(set_up: dict[str, Any]) -> None:
"""Test creating an order with a quantity below the minimum allowed."""
below_min_quantity = Power(mw=MIN_QUANTITY_MW - Decimal("0.01"))
with pytest.raises(ValueError, match=f"Quantity must be at least {MIN_QUANTITY_MW} MW."):
with pytest.raises(
ValueError, match=f"Quantity must be at least {MIN_QUANTITY_MW} MW."
):
await create_test_order(set_up, quantity=below_min_quantity)


@pytest.mark.asyncio
async def test_create_order_above_maximum_price(set_up: dict[str, Any]) -> None:
"""Test creating an order with a price above the maximum allowed."""
above_max_price = Price(amount=MAX_PRICE + Decimal("0.01"), currency=Currency.EUR)
with pytest.raises(ValueError, match=f"Price must be between {MIN_PRICE} and {MAX_PRICE}."):
with pytest.raises(
ValueError, match=f"Price must be between {MIN_PRICE} and {MAX_PRICE}."
):
await create_test_order(set_up, price=above_max_price)


Expand All @@ -505,56 +536,75 @@ async def test_create_order_at_maximum_price(set_up: dict[str, Any]) -> None:
"""Test creating an order with the exact maximum allowed price."""
max_price = Price(amount=MAX_PRICE, currency=Currency.EUR)
order = await create_test_order(set_up, price=max_price)
assert order.order.price.amount == max_price.amount, "Order with maximum price was not created correctly"
assert (
order.order.price.amount == max_price.amount
), "Order with maximum price was not created correctly"


@pytest.mark.asyncio
async def test_create_order_at_minimum_quantity_and_price(set_up: dict[str, Any]) -> None:
async def test_create_order_at_minimum_quantity_and_price(
set_up: dict[str, Any]
) -> None:
"""Test creating an order with the exact minimum allowed quantity and price."""
min_quantity = Power(mw=MIN_QUANTITY_MW)
min_price = Price(amount=MIN_PRICE, currency=Currency.EUR)
order = await create_test_order(set_up, quantity=min_quantity, price=min_price)
assert order.order.quantity.mw == min_quantity.mw, \
"Order with minimum quantity was not created correctly"
assert order.order.price.amount == min_price.amount, \
"Order with minimum price was not created correctly"
assert (
order.order.quantity.mw == min_quantity.mw
), "Order with minimum quantity was not created correctly"
assert (
order.order.price.amount == min_price.amount
), "Order with minimum price was not created correctly"


@pytest.mark.asyncio
async def test_update_order_to_invalid_price(set_up: dict[str, Any]) -> None:
"""Test updating an order to have a price outside the valid range."""
order = await create_test_order(set_up)
invalid_price = Price(amount=MAX_PRICE + Decimal("0.01"), currency=Currency.EUR)
with pytest.raises(ValueError, match=f"Price must be between {MIN_PRICE} and {MAX_PRICE}."):
with pytest.raises(
ValueError, match=f"Price must be between {MIN_PRICE} and {MAX_PRICE}."
):
await set_up["client"].update_gridpool_order(
gridpool_id=GRIDPOOL_ID, order_id=order.order_id, price=invalid_price
)




@pytest.mark.asyncio
async def test_concurrent_cancel_and_update_order(set_up: dict[str, Any]) -> None:
"""Test concurrent cancellation and update of the same order."""
order = await create_test_order(set_up)
new_price = Price(amount=Decimal("50"), currency=Currency.EUR)

cancelled_order = await set_up["client"].cancel_gridpool_order(GRIDPOOL_ID, order.order_id)
cancelled_order = await set_up["client"].cancel_gridpool_order(
GRIDPOOL_ID, order.order_id
)

with pytest.raises(grpc.aio.AioRpcError) as excinfo:
await set_up["client"].update_gridpool_order(
gridpool_id=GRIDPOOL_ID, order_id=order.order_id, price=new_price
)
assert excinfo.value.code() == grpc.StatusCode.INVALID_ARGUMENT, "Order is already cancelled"
assert (
excinfo.value.code() == grpc.StatusCode.INVALID_ARGUMENT
), "Order is already cancelled"


@pytest.mark.asyncio
async def test_multiple_streams_different_filters(set_up: dict[str, Any]) -> None:
"""Test creating multiple streams with different filters and ensure independent operation."""
area_1 = DeliveryArea(code="10YDE-EON------1", code_type=EnergyMarketCodeType.EUROPE_EIC)
area_2 = DeliveryArea(code="10YDE-RWENET---I", code_type=EnergyMarketCodeType.EUROPE_EIC)
area_1 = DeliveryArea(
code="10YDE-EON------1", code_type=EnergyMarketCodeType.EUROPE_EIC
)
area_2 = DeliveryArea(
code="10YDE-RWENET---I", code_type=EnergyMarketCodeType.EUROPE_EIC
)

stream_1 = await set_up["client"].stream_gridpool_orders(GRIDPOOL_ID, delivery_area=area_1)
stream_2 = await set_up["client"].stream_gridpool_orders(GRIDPOOL_ID, delivery_area=area_2)
stream_1 = await set_up["client"].stream_gridpool_orders(
GRIDPOOL_ID, delivery_area=area_1
)
stream_2 = await set_up["client"].stream_gridpool_orders(
GRIDPOOL_ID, delivery_area=area_2
)

# Create orders in each area to see if they appear on correct streams
order_1 = await create_test_order(set_up, delivery_area=area_1)
Expand All @@ -564,13 +614,16 @@ async def test_multiple_streams_different_filters(set_up: dict[str, Any]) -> Non
streamed_order_1 = await asyncio.wait_for(anext(stream_1), timeout=15)
streamed_order_2 = await asyncio.wait_for(anext(stream_2), timeout=15)

assert streamed_order_1.order == order_1.order, "Streamed order does not match area-specific order in stream 1"
assert streamed_order_2.order == order_2.order, "Streamed order does not match area-specific order in stream 2"
assert (
streamed_order_1.order == order_1.order
), "Streamed order does not match area-specific order in stream 1"
assert (
streamed_order_2.order == order_2.order
), "Streamed order does not match area-specific order in stream 2"
except asyncio.TimeoutError:
pytest.fail("Failed to receive streamed orders within timeout")



@pytest.fixture(scope="session")
def event_loop() -> Generator[asyncio.AbstractEventLoop, None, None]:
"""Create an event loop for the tests."""
Expand Down

0 comments on commit 9e6d723

Please sign in to comment.