Today I Learned
날짜
2024년 8월 12일 월요일
내용
테스트코드 정상화
유지보수 중 생각보다 시간 여유가 생겨 테스트코드를 작성했다. 가장 자주 문제가 되는 부분인 서비스 활성화 부분에 대한 코드다. 특정 앱을 사용 시작했을 때 shop_detail이 제대로 바뀌는지 확인하는 코드다.
mock_s3_resource
랑 mock_send_email_for_starting_user
는 쓰이지 않는데, 뺴면 아예 오류가 뜬다. 원인이 뭐꼬…
처음에 제대로 작동이 안됐는데 이전 테스트에서 생성된 shop이 데이터베이스에 남아있어서 문제가 됐다. 각 유닛테스트가 끝나면 꼭 데이터베이스를 초기화 하는게 중요하다.
테스트코드의 커버리지
테스트 코드가 실제 코드들을 얼마나 실행하는지를 나타내는 의미다. 100%이면 테스트 코드를 통해 모든 코드를 테스트하고 있다는 의미다.
coverage run -m pytest
로 테스트한 후, coverage report -m
하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#Pytest 실행
root@c5a7e41c3e84:/code# coverage run -m pytest
# Pytest 결과
============================== test session starts ==============================
platform linux -- Python 3.10.14, pytest-7.2.0, pluggy-1.0.0
rootdir: /code
plugins: Faker-18.5.1, cov-5.0.0, anyio-3.6.2, asyncio-0.21.0
asyncio: mode=strict
collected 28 items
tests/test_pytest.py ............................ [100%]
=============================== warnings summary ================================
src/database.py:63
/code/src/database.py:63: MovedIn20Warning: Deprecated API features detected! These feature(s) are not compatible with SQLAlchemy 2.0. To prevent incompatible upgrades prior to updating applications, ensure requirements files are pinned to "sqlalchemy<2.0". Set environment variable SQLALCHEMY_WARN_20=1 to show all deprecation warnings. Set environment variable SQLALCHEMY_SILENCE_UBER_WARNING=1 to silence this message. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
Base = declarative_base()
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
========================= 28 passed, 1 warning in 7.76s =========================
# coverage 리포트 호출
root@c5a7e41c3e84:/code# coverage report -m
#coverage 결과 출력
Name Stmts Miss Cover Missing
-------------------------------------------------------------------
src/__init__.py 1 0 100%
src/classes/billing.py 109 65 40% 46-48, 66-133, 136-184, 193, 214-242, 248-263, 267-318
src/classes/general_policy.py 164 114 30% 27-28, 31-35, 46-47, 50-55, 60-61, 65, 70-76, 85-88, 91-111, 114-126, 175-176, 179-180, 185-186, 190, 198-235, 244-245, 251-255, 260-261, 265, 270-272, 281-282, 286-293, 296-300, 303-336, 341-342, 345-353
src/classes/messaging_log.py 176 139 21% 32-50, 56-102, 109-112, 122-133, 141-144, 147-158, 161, 164-172, 186-202, 206, 213-226, 229-239, 249-275, 286-391, 396-418, 423-441, 446-464
src/classes/messaging_setting.py 287 78 73% 42, 49-50, 57, 65, 309, 316, 323, 491-507, 518-522, 525-536, 539-556, 565-566, 573, 582-611, 617-631, 652-656, 679-681, 695-697, 714-716
src/classes/sales_popup.py 381 322 15% 39-57, 60-65, 69, 72-101, 104-138, 143-151, 154-156, 159-181, 184-228, 233-292, 297-361, 366-397, 402-454, 459-460, 493-494, 527-567, 572-618, 623-678, 683-731, 736-791, 804-807, 811-839, 842-867, 879-882, 886-898, 910-913, 916-928
src/classes/send_email.py 60 24 60% 18, 22, 26, 75-77, 80-91, 94, 97-101, 104-107
src/classes/send_messaging_log.py 300 230 23% 40-41, 44-47, 50-57, 62-70, 75-76, 79-99, 102-108, 111-119, 124-125, 128-153, 158-159, 162-170, 173-234, 238, 244-256, 262-276, 281-336, 341-379, 384-386, 389-417, 422-423, 426-431, 436-437, 440-469, 474-475, 479, 483, 488-498, 501-558, 565, 568, 573, 576, 581, 584, 588-600, 604-616
src/config.py 62 1 98% 13
src/crud.py 2853 2170 24% 159, 174, 212-227, 231, 253, 301, 307, 338, 343, 350-353, 377-402, 408-416, 420-444, 448-524, 533-700, 704-795, 831-850, 854-873, 900, 921, 945-946, 955-956, 980-1021, 1049-1051, 1065-1071, 1078-1094, 1230, 1248-1270, 1275-1281, 1347-1379, 1383-1453, 1458-1518, 1522-1556, 1559-1566, 1569-1789, 1792-1854, 1864-1890, 1894-1911, 1943, 1950-1951, 1955, 1971-1999, 2010-2016, 2025-2031, 2068-2079, 2083-2127, 2133-2161, 2172-2200, 2209-2216, 2220-2223, 2227-2234, 2242-2250, 2254-2256, 2260-2319, 2323-2328, 2332-2339, 2343-2350, 2354-2359, 2363-2372, 2376-2380, 2384-2386, 2390-2392, 2410-2414, 2418-2420, 2424-2439, 2449-2490, 2500-2530, 2534-2549, 2553-2557, 2561-2564, 2568-2570, 2574-2584, 2600-2695, 2708-2793, 2800-2804, 2817-2833, 2836-2851, 2854-2857, 2860-2866, 2869-2914, 2917-2926, 2934-2942, 2946-2954, 2958-2966, 2972-2979, 2983-2987, 2991-2995, 2999-3003, 3007-3015, 3029-3033, 3050-3060, 3067, 3081-3090, 3094-3102, 3108-3120, 3124-3127, 3131-3152, 3157-3198, 3202-3217, 3221-3256, 3260-3265, 3269-3274, 3278-3283, 3287-3288, 3292-3293, 3297-3298, 3302-3305, 3309-3316, 3322-3333, 3339-3346, 3354-3364, 3373-3403, 3407-3414, 3418-3425, 3429-3436, 3440-3457, 3461-3507, 3522-3764, 3768-3769, 3773-3778, 3797-3834, 3840-3857, 3866-3876, 3913-3916, 3920, 3938, 3946-3963, 3997-4003, 4032-4035, 4047, 4059-4071, 4104-4110, 4145-4163, 4183-4193, 4197-4267, 4271-4273, 4379-4383, 4387-4392, 4397, 4400-4411, 4493-4497, 4501-4504, 4508-4531, 4535-4541, 4545-4549, 4553-4563, 4567-4570, 4574-4582, 4586-4597, 4620-4626, 4637-4655, 4671-4703, 4707-4732, 4739-4754, 4759-4775, 4779-4812, 4816-4825, 4833-4958, 4966-4985, 4989-4998, 5008-5055, 5062-5071, 5076-5121, 5133-5171, 5176-5225, 5236-5279, 5284-5335, 5340-5378, 5387-5399, 5403-5414, 5422-5443, 5452-5474, 5482-5505, 5514-5547, 5554-5570, 5574-5577, 5581-5595, 5599-5611, 5621-5628, 5631-5633, 5636-5647, 5651-5660, 5663-5680, 5683-5687, 5692, 5696, 5702-5711, 5717-5727, 5733-5743, 5747-5756, 5760-5769, 5778-5800, 5807-5828, 5834-5852, 5861-5878, 5887-5900, 5909-5926, 5934-5947, 5957-5991, 5999-6026, 6035-6168, 6174-6303, 6311-6345, 6349-6395, 6401-6438, 6447-6474, 6484-6548, 6558-6592, 6596, 6600, 6618-6736, 6741-6763
src/database.py 25 2 92% 38-41
src/decorators.py 30 17 43% 15-23, 27-35, 42
src/dependencies.py 54 26 52% 18-19, 23-24, 38-42, 52-65, 69-76, 80-87
src/main.py 55 11 80% 50-51, 56, 98, 103-110
src/models.py 1121 87 92% 411, 672-679, 683, 688-692, 696, 706, 710, 719-726, 730, 735-739, 743, 782-783, 911-919, 924-925, 929, 938, 942, 1115, 1119, 1212-1213, 1218-1219, 1224-1225, 1230-1231, 1236-1237, 1242-1243, 1248-1249, 1254-1255, 1320-1326, 1330, 1581-1586, 2480-2491, 2495-2515, 2555, 2572, 2576, 2790-2791
src/routers/__init__.py 0 0 100%
src/routers/auth.py 370 268 28% 102-166, 176-192, 212, 215, 245, 251, 255, 299, 305, 310, 317-342, 351-361, 370-454, 462-543, 547, 552-578, 586-594, 607-637, 647-666, 673-675, 679, 686-698, 707-715, 729-797
src/routers/billing.py 61 37 39% 43-57, 69-77, 88-94, 104-115, 126-135, 144-172
src/routers/browse_booster_shops.py 235 154 34% 208, 217-223, 230-241, 248-254, 269-357, 365-377, 392-441, 454-460, 465-466, 470, 477-514, 519, 522, 527-554, 559-561, 565, 575-613, 622-623
src/routers/cart.py 32 16 50% 48-78
src/routers/customers.py 305 216 29% 58, 86-89, 107, 110, 115-135, 145-159, 178-195, 204-240, 271-299, 308-348, 358-368, 432-435, 441-449, 481-498, 547-610, 615-636, 640-655, 663-675, 688-713, 750-763, 800-812, 819-828, 837-887, 897-903
src/routers/integration.py 18 4 78% 31-32, 41-42
src/routers/messaging.py 261 174 33% 115-165, 173-176, 189-196, 222-231, 255-263, 271-334, 410, 427-428, 445, 460-461, 476-488, 518-549, 566-571, 595-602, 606-617, 629-651, 685-697, 731-766, 779-788, 825-837, 846-849, 857-861, 867-878, 887-904, 929-1002, 1015-1038
src/routers/orders.py 561 443 21% 147-149, 171-178, 253, 262-306, 310-416, 450-611, 639, 649-689, 708-826, 831-836, 841-849, 854-858, 864-872, 877-880, 885-886, 891-897, 904-929, 936-962, 968-981, 1034-1137, 1150-1159, 1189-1213, 1218-1233, 1255-1277, 1304-1331, 1359-1386, 1391-1394, 1401-1403, 1440-1453, 1494-1507, 1534-1559, 1595-1674, 1683-1707, 1715-1716, 1742-1765, 1788-1811, 1816-1818, 1823-1828, 1833, 1838-1849, 1854-1858, 1866-1875, 1881-1904
src/routers/shops.py 1305 953 27% 219, 224, 233-248, 253, 274-294, 310-406, 414-424, 439-480, 493-504, 532-544, 548-561, 569-581, 591-611, 623-640, 649-665, 673-707, 722-774, 789-814, 826-850, 865-885, 915-933, 957, 975-981, 996-1004, 1021-1034, 1062-1111, 1132-1151, 1185-1230, 1239-1247, 1255-1306, 1321, 1336-1350, 1358-1398, 1408-1421, 1430-1445, 1453-1454, 1463-1466, 1476-1500, 1505-1512, 1547, 1562, 1585-1596, 1602-1633, 1638-1641, 1652-1676, 1682-1701, 1707-1711, 1720-1762, 1769-1826, 1832-1847, 1859, 1897-1921, 1935-1947, 1956-1971, 1975-1981, 1986-2003, 2016-2044, 2054-2122, 2126-2168, 2172-2194, 2198-2245, 2252-2268, 2272-2310, 2320-2359, 2365-2457, 2467-2475, 2495, 2511-2517, 2526, 2603, 2643-2660, 2667-2687, 2724-2766, 2782-2785, 2814, 2817-2839, 2863-2871, 2880, 2930, 2946-2997, 3008-3023, 3030-3033, 3067-3068, 3078-3081, 3092-3095, 3103-3104, 3114-3120, 3130-3133, 3144-3151, 3161, 3181, 3196-3197, 3207-3251
src/routers/super_admin.py 236 146 38% 161-163, 168-169, 181-241, 248-249, 259-264, 280-290, 307-321, 351-390, 395-396, 405-406, 417-420, 451-489, 496-515, 527-531, 540-542, 552-558, 568-572, 581-583, 593, 609-637, 647-650, 660-665, 675, 684-741
src/routers/webhooks.py 91 66 27% 69-101, 130-152, 183-204, 237-260, 292-320, 349-358
src/schemas.py 2627 8 99% 2814-2821
src/shared/analytic.py 100 90 10% 26-40, 44-58, 61-155, 159-261
src/shared/aws.py 5 0 100%
src/shared/core_script.py 137 128 7% 14-78, 84-143, 149-195
src/shared/elastic_apm.py 4 0 100%
src/shared/logger.py 4 0 100%
src/shared/message_sender.py 127 88 31% 53-58, 62, 66, 78, 88-108, 111-172, 175-193, 199-205, 241-244, 249-265, 268-286, 291, 294, 297
src/shared/messaging_template.py 506 297 41% 19-20, 24, 339-366, 373-407, 411, 415-434, 442, 445-485, 500, 503-543, 558, 561-605, 620, 623-667, 682, 686-722, 736, 739-786, 801, 804-844
src/shared/notion.py 30 13 57% 15-51, 55-56, 92-93
src/shared/password_hasher.py 2 0 100%
src/shared/redis.py 38 21 45% 44, 63-72, 90-102, 120-123
src/shared/template.py 7 0 100%
src/shared/template_filter.py 31 24 23% 7-16, 23-35, 39-45, 49-52
src/shared_module.py 158 107 32% 50-54, 78-103, 107-119, 125-127, 133-135, 141-143, 149-151, 157-159, 171-176, 180, 184, 188-206, 210-212, 216-218, 223-225, 230-234, 238-245, 283-342, 347-363, 367
tests/__init__.py 0 0 100%
tests/dummy.py 2 0 100%
tests/factories.py 214 2 99% 356-357
tests/test_pytest.py 250 0 100%
-------------------------------------------------------------------
TOTAL 13395 6541 51%
아무래도 유닛테스트다보니 외부 API(Shopify 등)를 호출하는 코드는 테스트 작성이 힘들다. 그와 연관된 파일들이 확실히 커버리지 비율이 상당히 낮다.
회고
이제누가기획해주냐