add tests to satisfy codecov

This commit is contained in:
Stefano
2026-03-02 10:24:45 +09:00
parent 3b59616cbe
commit 5788a75acc
2 changed files with 101 additions and 2 deletions

View File

@@ -14,15 +14,15 @@ logger = logging.getLogger(__name__)
class CrossMarketPairList(IPairList):
is_pairlist_generator = True
supports_backtesting = SupportsBacktesting.BIASED
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._mode: str = self._pairlistconfig.get("mode", "whitelist")
self._trading_mode: str = self._config["trading_mode"]
self._stake_currency: str = self._config["stake_currency"]
self._target_mode = "futures" if self._trading_mode == "spot" else "spot"
self._target_mode = "spot" if self._config["trading_mode"] == "futures" else "futures"
self._refresh_period = self._pairlistconfig.get("refresh_period", 1800)
self._pair_cache: FtTTLCache = FtTTLCache(maxsize=1, ttl=self._refresh_period)
@@ -115,6 +115,9 @@ class CrossMarketPairList(IPairList):
for pair in pairlist:
base = self._exchange.get_pair_base_currency(pair)
if not base:
self.log_once(
f"Unable to get base currency for pair {pair}, skipping it.", logger.warning
)
filtered_pairlist.remove(pair)
continue
found_in_bases = base in bases

View File

@@ -2685,6 +2685,102 @@ def test_CrossMarketPairlist_filter(
assert pm.whitelist == result
def test_CrossMarketPairlist_gen_pairlist_uses_cache(mocker, default_conf_usdt, markets):
default_conf_usdt["trading_mode"] = "spot"
default_conf_usdt["pairlists"] = [{"method": "CrossMarketPairList", "mode": "whitelist"}]
mocker.patch.multiple(
EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
)
exchange = get_patched_exchange(mocker, default_conf_usdt)
pm = PairListManager(exchange, default_conf_usdt)
pl = pm._pairlist_handlers[0]
pl._pair_cache["pairlist"] = ["ETH/USDT", "ADA/USDT"]
pl._exchange.get_markets = MagicMock(
side_effect=AssertionError("get_markets should not be called")
)
result = pl.gen_pairlist({})
assert result == ["ETH/USDT", "ADA/USDT"]
# Make sure the returned list is a copy, not the cached one
assert result is not pl._pair_cache["pairlist"]
result.append("BTC/USDT")
# Make sure the cache is not modified
assert pl._pair_cache["pairlist"] == ["ETH/USDT", "ADA/USDT"]
def test_CrossMarketPairList_breaks_prefix_loop_on_match(mocker, default_conf_usdt, markets):
default_conf_usdt["trading_mode"] = "spot"
default_conf_usdt["pairlists"] = [{"method": "CrossMarketPairList", "mode": "whitelist"}]
mocker.patch.multiple(
EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
)
exchange = get_patched_exchange(mocker, default_conf_usdt)
pm = PairListManager(exchange, default_conf_usdt)
pl = pm._pairlist_handlers[0]
# Force base lookup path
mocker.patch.object(pl, "get_base_list", return_value=["1000PEPE"])
mocker.patch.object(pl._exchange, "get_pair_base_currency", return_value="PEPE")
class PrefixesWithGuard:
def __iter__(self):
yield "1000" # first prefix => match via "1000PEPE"
raise AssertionError("Prefix loop did not break after match")
mocker.patch(
"freqtrade.plugins.pairlist.CrossMarketPairList.PairPrefixes",
new=PrefixesWithGuard(),
)
result = pl.filter_pairlist(["PEPE/USDT"], {})
assert result == ["PEPE/USDT"]
def test_CrossMarketPairList_breaks_prefix_loop_on_delayed_match(
mocker, default_conf_usdt, markets
):
default_conf_usdt["trading_mode"] = "spot"
default_conf_usdt["pairlists"] = [{"method": "CrossMarketPairList", "mode": "whitelist"}]
mocker.patch.multiple(
EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
)
exchange = get_patched_exchange(mocker, default_conf_usdt)
pm = PairListManager(exchange, default_conf_usdt)
pl = pm._pairlist_handlers[0]
# Force second matching path: base startswith prefix and removeprefix() matches bases.
mocker.patch.object(pl, "get_base_list", return_value=["PEPE"])
mocker.patch.object(pl._exchange, "get_pair_base_currency", return_value="1000PEPE")
class PrefixesWithGuard:
def __iter__(self):
yield "X" # no match, loop should continue
yield "1000" # second path should match via removeprefix -> PEPE and break
raise AssertionError("Prefix loop did not break after delayed match")
mocker.patch(
"freqtrade.plugins.pairlist.CrossMarketPairList.PairPrefixes",
new=PrefixesWithGuard(),
)
result = pl.filter_pairlist(["1000PEPE/USDT"], {})
assert result == ["1000PEPE/USDT"]
@pytest.mark.parametrize(
"pairlists,expected_error,expected_warning",
[