From db974d981f97c0c3d960f70030b7f714e9c0d20d Mon Sep 17 00:00:00 2001 From: Jan Gregorczyk Date: Tue, 26 Mar 2024 14:30:05 +0100 Subject: [PATCH 1/2] tests: api_product_filters, minor fix of filters --- Dshop/apps/products_catalogue/filters.py | 2 +- .../apps/products_catalogue/tests/conftest.py | 33 +-- .../tests/test_api_product_filters.py | 188 ++++++++++++++++++ 3 files changed, 210 insertions(+), 13 deletions(-) create mode 100644 Dshop/apps/products_catalogue/tests/test_api_product_filters.py diff --git a/Dshop/apps/products_catalogue/filters.py b/Dshop/apps/products_catalogue/filters.py index 68c15a5..fad1589 100644 --- a/Dshop/apps/products_catalogue/filters.py +++ b/Dshop/apps/products_catalogue/filters.py @@ -40,7 +40,7 @@ def filter_availability(self, queryset, name, value): value = int(value) if value in (1, 3, 7, 14): return queryset.filter(availability__lte=value) - return queryset.filter(**{name: value}) + return queryset.filter(availability=value) def __init__(self, *args, **kwargs): super(ProductFilter, self).__init__(*args, **kwargs) diff --git a/Dshop/apps/products_catalogue/tests/conftest.py b/Dshop/apps/products_catalogue/tests/conftest.py index a596187..e732b99 100644 --- a/Dshop/apps/products_catalogue/tests/conftest.py +++ b/Dshop/apps/products_catalogue/tests/conftest.py @@ -1,4 +1,4 @@ -import datetime +from decimal import Decimal import pytest from apps.products_catalogue.models import Category, Product @@ -6,15 +6,24 @@ @pytest.fixture def products(): category = Category.objects.create(name='Test Category', is_active=True) + products = [] for idx in range(1, 11): - created_at = datetime.datetime.now() - datetime.timedelta(seconds=idx) - Product.objects.create( - name=f"main product ${idx}", - category=category, - price=idx, - short_description="short desc inactive", - full_description="full_description inactive", - is_active=True, - availability=3, - created_at=created_at - ) + prod = Product.objects.create( + name=f"main product ${idx}", + category=category, + price=idx, + short_description="short desc inactive", + full_description="full_description inactive", + is_active=True, + created_at=True, + availability=3, + ) + products.append(prod) + return products + + +def expected_prod_set(prods): + return {(obj.id, obj.name, Decimal(obj.price), obj.category.id) for obj in prods} + +def api_prod_set(response): + return {(el["id"], el["name"], Decimal(el["price"]), el["category"]) for el in response.data["results"]} \ No newline at end of file diff --git a/Dshop/apps/products_catalogue/tests/test_api_product_filters.py b/Dshop/apps/products_catalogue/tests/test_api_product_filters.py new file mode 100644 index 0000000..0adf77a --- /dev/null +++ b/Dshop/apps/products_catalogue/tests/test_api_product_filters.py @@ -0,0 +1,188 @@ +from decimal import Decimal +from django.urls import reverse +import pytest +from rest_framework.test import APIClient +from apps.products_catalogue.tests.conftest import api_prod_set, expected_prod_set +from apps.products_catalogue.models import Category + + +URL = reverse("products-api-list") +pytestmark = pytest.mark.django_db + + +@pytest.fixture +def named_products(products): + products[0].name = "J" + products[1].name = "A" + products[2].name = "B" + products[3].name = "I" + products[4].name = "G" + products[5].name = "C" + products[6].name = "F" + products[7].name = "H" + products[8].name = "E" + products[9].name = "D" + products[0].save() + products[1].save() + products[2].save() + products[3].save() + products[4].save() + products[5].save() + products[6].save() + products[7].save() + products[8].save() + products[9].save() + return products + +def test_products_api_order_by_price_asc(products): + response = APIClient().get(f"{URL}?order_by=price") + products_data = response.data["results"] + print(response.data) + assert response.status_code == 200 + assert response.data["count"] == 10 + for value, prod in enumerate(products_data, start=1): + assert Decimal(prod["price"]) == Decimal(value) + +def test_products_api_order_by_price_desc(products): + response = APIClient().get(f"{URL}?order_by=-price") + products_data = response.data["results"] + assert response.status_code == 200 + assert response.data["count"] == 10 + for value, prod in zip(range(10, 5, -1), products_data): + assert Decimal(prod["price"]) == Decimal(value) + +def test_products_api_filter_by_name(products): + response = APIClient().get(f"{URL}?name=main+product+$10") + products_data = response.data["results"] + assert response.status_code == 200 + assert len(products_data) == 1 + assert products_data[0]["name"] == "main product $10" + +def test_products_api_filter_by_price(products): + PRICE = 10 + response = APIClient().get(f"{URL}?price={PRICE}") + assert response.status_code == 200 + assert len(response.data["results"]) == 1 + assert Decimal(response.data["results"][0]["price"]) == PRICE + assert response.data["results"][0]["name"] == "main product $10" + +@pytest.mark.parametrize("availability, other_availability", [ + (1, 99), + (3, 99), + (7, 99), + (14, 99), + (90, 99), + (99, 1), + (110, 99) +]) +def test_products_api_filter_by_availability(products, availability, other_availability): + for prod in products[5:]: + prod.availability = other_availability + prod.save() + remaining_products = products[:5] + for prod in remaining_products: + prod.availability = availability + prod.save() + response = APIClient().get(f"{URL}?availability={availability}") + expected_result = expected_prod_set(remaining_products) + api_results = api_prod_set(response) + assert response.status_code == 200 + assert len(response.data["results"]) == 5 + assert expected_result == api_results + +@pytest.mark.parametrize("availability, expected_count", [ + (1, 2), + (3, 4), + (7, 7), + (14, 10), +]) +def test_products_api_filters_by_availability_days(products, availability, expected_count): + products[0].availability = 1 + products[1].availability = 1 + products[2].availability = 3 + products[3].availability = 3 + products[4].availability = 7 + products[5].availability = 7 + products[6].availability = 7 + products[7].availability = 14 + products[8].availability = 14 + products[9].availability = 14 + for prod in products: + prod.save() + response = APIClient().get(f"{URL}?availability={availability}") + assert response.status_code == 200 + assert response.data["count"] == expected_count + +def test_products_api_filters_availability_by_category(products, api_client): + other_cat = Category.objects.create(name="Test Category 2") + for prod in products[5:]: + prod.category = other_cat + prod.save() + response_1 = api_client.get(f"{URL}?category_name=Test+Category") + response_2 = api_client.get(f"{URL}?category_name=Test+Category+2") + api_result_1 = api_prod_set(response_1) + api_result_2 = api_prod_set(response_2) + expected_result_1 = expected_prod_set(products[:5]) + expected_result_2 = expected_prod_set(products[5:]) + assert response_1.status_code == 200 + assert response_2.status_code == 200 + assert len(response_1.data["results"]) == 5 + assert len(response_2.data["results"]) == 5 + assert response_1.data["count"] == 5 + assert response_2.data["count"] == 5 + assert api_result_1 == expected_result_1 + assert api_result_2 == expected_result_2 + +def test_products_api_filters_price_lt(products): + MAX_PRICE = Decimal("5.5") + expected_results = expected_prod_set(products[:5]) + response = APIClient().get(f"{URL}?price__lt={MAX_PRICE}") + api_results = api_prod_set(response) + assert response.status_code == 200 + assert len(response.data["results"]) == 5 + assert api_results == expected_results + +def test_products_api_filters_price_gt(products): + MIN_PRICE = Decimal("5.5") + expected_results = expected_prod_set(products[5:]) + response = APIClient().get(f"{URL}?price__gt={MIN_PRICE}") + api_results = api_prod_set(response) + assert response.status_code == 200 + assert len(response.data["results"]) == 5 + assert api_results == expected_results + +def test_products_api_order_by_name_asc(named_products): + response = APIClient().get(f"{URL}?order_by=name") + assert response.status_code == 200 + assert len(response.data["results"]) == 5 + for name, el in zip("ABCDE", response.data["results"]): + assert name == el["name"] + +def test_products_api_order_by_name_desc(named_products): + response = APIClient().get(f"{URL}?order_by=-name") + assert response.status_code == 200 + assert len(response.data["results"]) == 5 + for name, el in zip("JIHGF", response.data["results"]): + assert name == el["name"] + +def test_products_api_oder_by_created_at_desc(products): + response = APIClient().get(f"{URL}?order_by=-created_at") + expected_results = [products[9], products[8], products[7], products[6], products[5]] + assert response.status_code == 200 + assert len(response.data["results"]) == 5 + for obj, el in zip(expected_results, response.data["results"]): + assert obj.id == el["id"] + assert obj.name == el["name"] + assert Decimal(obj.price) == Decimal(el["price"]) + assert obj.category.id == el["category"] + +def test_products_api_oder_by_created_at_asc(products): + response = APIClient().get(f"{URL}?order_by=created_at") + expected_results = products[:5] + assert response.status_code == 200 + assert len(response.data["results"]) == 5 + for obj, el in zip(expected_results, response.data["results"]): + assert obj.id == el["id"] + assert obj.name == el["name"] + assert Decimal(obj.price) == Decimal(el["price"]) + assert obj.category.id == el["category"] \ No newline at end of file From 993fdac6fb0bec1946a3f7a37e3d55368fc9959f Mon Sep 17 00:00:00 2001 From: Jan Gregorczyk Date: Tue, 9 Apr 2024 14:05:16 +0200 Subject: [PATCH 2/2] tests: api_product_filters mini refactor --- .../tests/test_api_product_filters.py | 43 ++++--------------- 1 file changed, 8 insertions(+), 35 deletions(-) diff --git a/Dshop/apps/products_catalogue/tests/test_api_product_filters.py b/Dshop/apps/products_catalogue/tests/test_api_product_filters.py index 0adf77a..69f0508 100644 --- a/Dshop/apps/products_catalogue/tests/test_api_product_filters.py +++ b/Dshop/apps/products_catalogue/tests/test_api_product_filters.py @@ -12,32 +12,14 @@ @pytest.fixture def named_products(products): - products[0].name = "J" - products[1].name = "A" - products[2].name = "B" - products[3].name = "I" - products[4].name = "G" - products[5].name = "C" - products[6].name = "F" - products[7].name = "H" - products[8].name = "E" - products[9].name = "D" - products[0].save() - products[1].save() - products[2].save() - products[3].save() - products[4].save() - products[5].save() - products[6].save() - products[7].save() - products[8].save() - products[9].save() + for prod, name in zip(products, "JABIGCFHED"): + prod.name = name + prod.save() return products def test_products_api_order_by_price_asc(products): response = APIClient().get(f"{URL}?order_by=price") products_data = response.data["results"] - print(response.data) assert response.status_code == 200 assert response.data["count"] == 10 for value, prod in enumerate(products_data, start=1): @@ -90,26 +72,17 @@ def test_products_api_filter_by_availability(products, availability, other_avail assert len(response.data["results"]) == 5 assert expected_result == api_results -@pytest.mark.parametrize("availability, expected_count", [ +@pytest.mark.parametrize("target_availability, expected_count", [ (1, 2), (3, 4), (7, 7), (14, 10), ]) -def test_products_api_filters_by_availability_days(products, availability, expected_count): - products[0].availability = 1 - products[1].availability = 1 - products[2].availability = 3 - products[3].availability = 3 - products[4].availability = 7 - products[5].availability = 7 - products[6].availability = 7 - products[7].availability = 14 - products[8].availability = 14 - products[9].availability = 14 - for prod in products: +def test_products_api_filters_by_availability_days(products, target_availability, expected_count): + for prod, availability in zip(products, [1, 1, 3, 3, 7, 7, 7, 14, 14, 14]): + prod.availability = availability prod.save() - response = APIClient().get(f"{URL}?availability={availability}") + response = APIClient().get(f"{URL}?availability={target_availability}") assert response.status_code == 200 assert response.data["count"] == expected_count