============================= test session starts ============================= platform win32 -- Python 3.12.10, pytest-9.0.1, pluggy-1.6.0 rootdir: C:\tae\python\AutoCoinTrader configfile: pytest.ini (WARNING: ignoring pytest config in pyproject.toml!) collected 19 items src\tests\test_concurrent_buy_orders.py F.... [ 26%] src\tests\test_krw_budget_manager.py ............ [ 89%] src\tests\test_recent_sells.py .. [100%] ================================== FAILURES =================================== __________ TestConcurrentBuyOrders.test_concurrent_buy_no_overdraft ___________ self = mock_price = mock_upbit_class = mock_config = cleanup_budget = None @patch('src.order.pyupbit.Upbit') @patch('src.holdings.get_current_price') def test_concurrent_buy_no_overdraft(self, mock_price, mock_upbit_class, mock_config, cleanup_budget): """동시 매수 시 잔고 초과 인출 방지 테스트""" # Mock 설정 mock_upbit = MockUpbit(100000) # 10만원 초기 잔고 mock_upbit_class.return_value = mock_upbit mock_price.return_value = 10000 # 코인당 1만원 results = [] def buy_worker(symbol: str, amount_krw: float): """매수 워커 스레드""" result = place_buy_order_upbit(symbol, amount_krw, mock_config) results.append((symbol, result)) # 3개 스레드가 동시에 50000원씩 매수 시도 (총 150000원 > 잔고 100000원) threads = [ threading.Thread(target=buy_worker, args=(f"KRW-COIN{i}", 50000)) for i in range(3) ] for t in threads: t.start() for t in threads: t.join() # 검증 1: 성공한 주문들의 총액이 초기 잔고를 초과하지 않음 successful_orders = [ r for symbol, r in results if r.get("status") not in ("skipped_insufficient_budget", "skipped_insufficient_balance", "failed") ] total_spent = sum( r.get("amount_krw", 0) for _, r in results if r.get("status") not in ("skipped_insufficient_budget", "skipped_insufficient_balance", "failed") ) assert total_spent <= 100000, f"총 지출 {total_spent}원이 잔고 100000원을 초과" # 검증 2: 최소 2개는 성공 (100000 / 50000 = 2) > assert len(successful_orders) >= 2 E AssertionError: assert 1 >= 2 E + where 1 = len([{'amount_krw': 49975.0, 'market': 'KRW-COIN0', 'monitor': {'attempts': 0, 'filled_volume': 0.0, 'final_status': 'error', 'last_checked': 1765369729.6392872, ...}, 'price': 10049.999999999998, ...}]) src\tests\test_concurrent_buy_orders.py:133: AssertionError ------------------------------ Captured log call ------------------------------ WARNING macd_alarm:common.py:150 [KRW-COIN1] KRW 예산 할당 거부: 25원 < 최소 주문 5000원 (가용 25원) WARNING macd_alarm:order.py:369 [매수 건너뜀] KRW-COIN1 사유: KRW 예산 부족 요청 금액: 50000 KRW WARNING macd_alarm:common.py:150 [KRW-COIN2] KRW 예산 할당 거부: 25원 < 최소 주문 5000원 (가용 25원) WARNING macd_alarm:order.py:369 [매수 건너뜀] KRW-COIN2 사유: KRW 예산 부족 요청 금액: 50000 KRW ERROR macd_alarm:order.py:1190 주문 모니터링 중 오류 (1/5): 'MockUpbit' object has no attribute 'get_order' ERROR macd_alarm:order.py:1190 주문 모니터링 중 오류 (2/5): 'MockUpbit' object has no attribute 'get_order' ERROR macd_alarm:order.py:1190 주문 모니터링 중 오류 (3/5): 'MockUpbit' object has no attribute 'get_order' ERROR macd_alarm:order.py:1190 주문 모니터링 중 오류 (4/5): 'MockUpbit' object has no attribute 'get_order' ERROR macd_alarm:order.py:1190 주문 모니터링 중 오류 (5/5): 'MockUpbit' object has no attribute 'get_order' ERROR macd_alarm:order.py:1193 주문 모니터링 중단: 연속 에러 5회 초과 =========================== short test summary info =========================== FAILED src/tests/test_concurrent_buy_orders.py::TestConcurrentBuyOrders::test_concurrent_buy_no_overdraft ================== 1 failed, 18 passed in 169.65s (0:02:49) ===================