Skip to content

Commit 6b9e09a

Browse files
committed
refactor: 전반적인 테스트 리펙토링
1 parent 03a8c94 commit 6b9e09a

29 files changed

Lines changed: 1554 additions & 1230 deletions

app/admin_api/test/shop/conftest.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,19 @@
22
from notification.models import EmailNotificationTemplate
33
from shop.conftest import ( # noqa: F401
44
anon_client,
5-
completed_order,
65
customer_client,
7-
donation_completed_order,
86
donation_product,
9-
donation_refunded_order,
10-
empty_cart,
117
mock_portone_kcp_receipt,
128
mock_portone_register,
139
mock_portone_req_cancel_payment,
1410
modifiable_option_relation,
1511
option,
1612
option_group,
13+
order_factory,
1714
other_client,
1815
other_user,
19-
partial_refunded_order,
20-
pending_order,
2116
product,
2217
products_by_status,
23-
refunded_order,
2418
single_product_cart,
2519
staff_client,
2620
staff_user,

app/admin_api/test/shop/order_notifications_api_test.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ def test_notification_send_rejects_non_superuser(customer_client):
2121

2222

2323
@pytest.mark.django_db
24-
def test_notification_preview_returns_recipients_for_completed_order(api_client, completed_order, order_email_template):
24+
def test_notification_preview_returns_recipients_for_completed_order(api_client, order_email_template, order_factory):
25+
completed_order = order_factory(status="completed")
2526
response = OrderNotificationsAdminApi(http_client=api_client).preview(
2627
{"channel": "email", "template_id": str(order_email_template.id)}
2728
)
@@ -50,7 +51,8 @@ def test_notification_preview_returns_recipients_for_completed_order(api_client,
5051

5152

5253
@pytest.mark.django_db
53-
def test_notification_preview_rejects_unknown_template_id(api_client, completed_order):
54+
def test_notification_preview_rejects_unknown_template_id(api_client, order_factory):
55+
order_factory(status="completed")
5456
response = OrderNotificationsAdminApi(http_client=api_client).preview(
5557
{"channel": "email", "template_id": "00000000-0000-0000-0000-000000000000"}
5658
)
@@ -62,7 +64,8 @@ def test_notification_preview_rejects_unknown_template_id(api_client, completed_
6264

6365

6466
@pytest.mark.django_db
65-
def test_notification_preview_excludes_refunded_orders(api_client, refunded_order, order_email_template):
67+
def test_notification_preview_excludes_refunded_orders(api_client, order_email_template, order_factory):
68+
order_factory(status="refunded")
6669
response = OrderNotificationsAdminApi(http_client=api_client).preview(
6770
{"channel": "email", "template_id": str(order_email_template.id)}
6871
)
@@ -74,8 +77,8 @@ def test_notification_preview_excludes_refunded_orders(api_client, refunded_orde
7477

7578

7679
@pytest.mark.django_db
77-
def test_notification_send_creates_history_for_completed_order(api_client, completed_order, order_email_template):
78-
# order_email_template 의 모든 변수가 Order 에서 자동 추출되므로 context_override 불필요.
80+
def test_notification_send_creates_history_for_completed_order(api_client, order_email_template, order_factory):
81+
order_factory(status="completed")
7982
response = OrderNotificationsAdminApi(http_client=api_client).send(
8083
{"channel": "email", "template_id": str(order_email_template.id)}
8184
)
@@ -90,8 +93,8 @@ def test_notification_send_creates_history_for_completed_order(api_client, compl
9093

9194

9295
@pytest.mark.django_db
93-
def test_notification_preview_skips_order_without_customer_info(api_client, completed_order, order_email_template):
94-
# hard_delete 로 reverse OneToOne 부재 → to_representation 의 customer_info guard 가 None 반환.
96+
def test_notification_preview_skips_order_without_customer_info(api_client, order_email_template, order_factory):
97+
completed_order = order_factory(status="completed")
9598
CustomerInfo.objects.filter(order=completed_order).hard_delete()
9699
response = OrderNotificationsAdminApi(http_client=api_client).preview(
97100
{"channel": "email", "template_id": str(order_email_template.id)}
@@ -101,7 +104,8 @@ def test_notification_preview_skips_order_without_customer_info(api_client, comp
101104

102105

103106
@pytest.mark.django_db
104-
def test_notification_preview_skips_order_with_empty_recipient_field(api_client, completed_order, order_email_template):
107+
def test_notification_preview_skips_order_with_empty_recipient_field(api_client, order_email_template, order_factory):
108+
completed_order = order_factory(status="completed")
105109
completed_order.customer_info.email = ""
106110
completed_order.customer_info.save()
107111
response = OrderNotificationsAdminApi(http_client=api_client).preview(
@@ -112,8 +116,8 @@ def test_notification_preview_skips_order_with_empty_recipient_field(api_client,
112116

113117

114118
@pytest.mark.django_db
115-
def test_notification_preview_skips_order_with_no_active_products(api_client, completed_order, order_email_template):
116-
# OPR soft-delete → admin queryset 의 products prefetch (filter_active) 가 제외 → next() 가 None.
119+
def test_notification_preview_skips_order_with_no_active_products(api_client, order_email_template, order_factory):
120+
completed_order = order_factory(status="completed")
117121
completed_order.products.first().delete()
118122
response = OrderNotificationsAdminApi(http_client=api_client).preview(
119123
{"channel": "email", "template_id": str(order_email_template.id)}
@@ -123,8 +127,8 @@ def test_notification_preview_skips_order_with_no_active_products(api_client, co
123127

124128

125129
@pytest.mark.django_db
126-
def test_notification_send_rejects_when_no_eligible_recipients(api_client, completed_order, order_email_template):
127-
# 모든 매칭 order 가 customer_info 부재 → items=[] → "발송 대상이 없습니다" 400.
130+
def test_notification_send_rejects_when_no_eligible_recipients(api_client, order_email_template, order_factory):
131+
completed_order = order_factory(status="completed")
128132
CustomerInfo.objects.filter(order=completed_order).hard_delete()
129133
response = OrderNotificationsAdminApi(http_client=api_client).send(
130134
{"channel": "email", "template_id": str(order_email_template.id)}
@@ -135,9 +139,9 @@ def test_notification_send_rejects_when_no_eligible_recipients(api_client, compl
135139

136140
@pytest.mark.django_db
137141
def test_notification_send_rejects_when_recipients_have_missing_template_variables(
138-
api_client, completed_order, superuser
142+
api_client, superuser, order_factory
139143
):
140-
# Order 에서 추출되지 않는 변수 (`coupon_code`) 를 요구하는 템플릿 → missing_variables 발생 → 400.
144+
order_factory(status="completed")
141145
template = EmailNotificationTemplate.objects.create(
142146
code="coupon",
143147
title="쿠폰",

app/admin_api/test/shop/orders_api_test.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ def test_admin_list_rejects_non_superuser_client(request, client_fixture):
2828

2929

3030
@pytest.mark.django_db
31-
def test_admin_list_returns_only_orders_with_payment_history_and_products(api_client, completed_order, empty_cart):
31+
def test_admin_list_returns_only_orders_with_payment_history_and_products(api_client, order_factory):
32+
completed_order = order_factory(status="completed")
33+
order_factory(status="empty")
3234
response = OrdersAdminApi(http_client=api_client).list()
3335
assert response.status_code == HTTP_200_OK
3436
assert response.json() == {
@@ -40,7 +42,9 @@ def test_admin_list_returns_only_orders_with_payment_history_and_products(api_cl
4042

4143

4244
@pytest.mark.django_db
43-
def test_admin_list_filters_by_status_csv(api_client, completed_order, refunded_order):
45+
def test_admin_list_filters_by_status_csv(api_client, order_factory):
46+
order_factory(status="completed")
47+
refunded_order = order_factory(status="refunded")
4448
response = OrdersAdminApi(http_client=api_client).list({"status": "refunded"})
4549
assert response.status_code == HTTP_200_OK
4650
assert response.json() == {
@@ -52,8 +56,8 @@ def test_admin_list_filters_by_status_csv(api_client, completed_order, refunded_
5256

5357

5458
@pytest.mark.django_db
55-
def test_admin_list_filters_by_product_id_distinct(api_client, completed_order, product):
56-
# distinct=True 라 OPR 여러 개 매칭돼도 같은 order 한 번만 반환.
59+
def test_admin_list_filters_by_product_id_distinct(api_client, product, order_factory):
60+
completed_order = order_factory(status="completed")
5761
response = OrdersAdminApi(http_client=api_client).list({"product_id": str(product.id)})
5862
assert response.status_code == HTTP_200_OK
5963
assert response.json() == {
@@ -65,16 +69,16 @@ def test_admin_list_filters_by_product_id_distinct(api_client, completed_order,
6569

6670

6771
@pytest.mark.django_db
68-
def test_admin_retrieve_returns_nested_payload(api_client, completed_order):
72+
def test_admin_retrieve_returns_nested_payload(api_client, order_factory):
73+
completed_order = order_factory(status="completed")
6974
response = OrdersAdminApi(http_client=api_client).retrieve(completed_order.id)
7075
assert response.status_code == HTTP_200_OK
7176
assert response.json() == OrderAdminSerializer(instance=OrderAdminViewSet.queryset.get(id=completed_order.id)).data
7277

7378

7479
@pytest.mark.django_db
75-
def test_admin_refund_action_refunds_order_with_valid_totp(
76-
api_client, completed_order, mock_portone_req_cancel_payment
77-
):
80+
def test_admin_refund_action_refunds_order_with_valid_totp(api_client, mock_portone_req_cancel_payment, order_factory):
81+
completed_order = order_factory(status="completed")
7882
response = OrdersAdminApi(http_client=api_client).refund(completed_order.id, totp=valid_refund_totp())
7983
assert response.status_code == HTTP_204_NO_CONTENT
8084
completed_order.refresh_from_db()
@@ -84,23 +88,26 @@ def test_admin_refund_action_refunds_order_with_valid_totp(
8488

8589

8690
@pytest.mark.django_db
87-
def test_admin_refund_action_rejects_invalid_totp(api_client, completed_order, mock_portone_req_cancel_payment):
91+
def test_admin_refund_action_rejects_invalid_totp(api_client, mock_portone_req_cancel_payment, order_factory):
92+
completed_order = order_factory(status="completed")
8893
response = OrdersAdminApi(http_client=api_client).refund(completed_order.id, totp="000000")
8994
assert response.status_code == HTTP_400_BAD_REQUEST
9095
mock_portone_req_cancel_payment.assert_not_called()
9196

9297

9398
@pytest.mark.django_db
94-
def test_admin_refund_action_rejects_missing_totp(api_client, completed_order, mock_portone_req_cancel_payment):
99+
def test_admin_refund_action_rejects_missing_totp(api_client, mock_portone_req_cancel_payment, order_factory):
100+
completed_order = order_factory(status="completed")
95101
response = OrdersAdminApi(http_client=api_client).refund(completed_order.id)
96102
assert response.status_code == HTTP_400_BAD_REQUEST
97103
mock_portone_req_cancel_payment.assert_not_called()
98104

99105

100106
@pytest.mark.django_db
101107
def test_admin_refund_product_action_does_partial_refund(
102-
api_client, completed_order, product, mock_portone_req_cancel_payment
108+
api_client, product, mock_portone_req_cancel_payment, order_factory
103109
):
110+
completed_order = order_factory(status="completed")
104111
target_opr = completed_order.products.first()
105112
OrderProductRelation.objects.create(
106113
order=completed_order, product=product, price=product.price, status=OrderProductRelation.OrderProductStatus.paid
@@ -116,16 +123,17 @@ def test_admin_refund_product_action_does_partial_refund(
116123

117124

118125
@pytest.mark.django_db
119-
def test_admin_refund_product_action_returns_404_for_unknown_rel(api_client, completed_order):
126+
def test_admin_refund_product_action_returns_404_for_unknown_rel(api_client, order_factory):
127+
completed_order = order_factory(status="completed")
120128
response = OrdersAdminApi(http_client=api_client).refund_product(
121129
completed_order.id, "00000000-0000-0000-0000-000000000000", totp=valid_refund_totp()
122130
)
123131
assert response.status_code == HTTP_404_NOT_FOUND
124132

125133

126134
@pytest.mark.django_db
127-
def test_admin_refund_allows_expired_window(api_client, completed_order, mock_portone_req_cancel_payment):
128-
# admin endpoint 는 check_refundable_date=False 로 expired 상품도 환불 가능.
135+
def test_admin_refund_allows_expired_window(api_client, mock_portone_req_cancel_payment, order_factory):
136+
completed_order = order_factory(status="completed")
129137
product = completed_order.products.first().product
130138
product.refundable_ends_at = datetime(2020, 1, 1, tzinfo=timezone.utc)
131139
product.save()
@@ -196,8 +204,9 @@ def test_admin_import_csv_returns_400_for_invalid_rows_without_persisting(api_cl
196204
@freeze_time(datetime(2026, 5, 23, 15, 30, 45, tzinfo=timezone.utc))
197205
@pytest.mark.django_db
198206
def test_admin_export_returns_xlsx_filtering_refunded_per_include_flag(
199-
api_client, customer_user, refunded_order, product, include_refunded
207+
api_client, customer_user, product, include_refunded, order_factory
200208
):
209+
refunded_order = order_factory(status="refunded")
201210
response = OrdersAdminApi(http_client=api_client).export(
202211
{"product_ids": [str(product.id)], "include_refunded": include_refunded}
203212
)
@@ -262,7 +271,8 @@ def test_admin_export_rejects_missing_or_empty_product_ids(api_client, payload):
262271

263272

264273
@pytest.mark.django_db
265-
def test_admin_partial_update_modifies_existing_customer_info(api_client, completed_order):
274+
def test_admin_partial_update_modifies_existing_customer_info(api_client, order_factory):
275+
completed_order = order_factory(status="completed")
266276
response = OrdersAdminApi(http_client=api_client).update(
267277
completed_order.id,
268278
{"customer_info": {"name": "수정", "phone": "01099998888", "email": "new@x.com", "organization": "Z"}},
@@ -274,7 +284,8 @@ def test_admin_partial_update_modifies_existing_customer_info(api_client, comple
274284

275285

276286
@pytest.mark.django_db
277-
def test_admin_partial_update_creates_customer_info_when_missing(api_client, completed_order):
287+
def test_admin_partial_update_creates_customer_info_when_missing(api_client, order_factory):
288+
completed_order = order_factory(status="completed")
278289
CustomerInfo.objects.filter(order=completed_order).hard_delete()
279290
response = OrdersAdminApi(http_client=api_client).update(
280291
completed_order.id,
@@ -285,7 +296,8 @@ def test_admin_partial_update_creates_customer_info_when_missing(api_client, com
285296

286297

287298
@pytest.mark.django_db
288-
def test_admin_list_filters_by_user_id(api_client, completed_order, customer_user, other_user, product):
299+
def test_admin_list_filters_by_user_id(api_client, customer_user, other_user, product, order_factory):
300+
completed_order = order_factory(status="completed")
289301
other_order = Order.objects.create(user=other_user, name="other")
290302
OrderProductRelation.objects.create(
291303
order=other_order, product=product, price=product.price, status=OrderProductRelation.OrderProductStatus.paid

0 commit comments

Comments
 (0)