From 36d60fa8a8b7ee6fc2118808aa14d7ef19079111 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 13 Oct 2020 19:54:27 +0200 Subject: [PATCH 01/13] First small compat test --- tests/exchange/test_ccxt_compat.py | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/exchange/test_ccxt_compat.py diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py new file mode 100644 index 000000000..e6deebf62 --- /dev/null +++ b/tests/exchange/test_ccxt_compat.py @@ -0,0 +1,43 @@ +""" +Tests in this file do NOT mock network calls, so they are expected to be fluky at times. + +However, these tests should give a good idea to determine if a new exchange is +suitable to run with freqtrade. + +""" + +from freqtrade.resolvers.exchange_resolver import ExchangeResolver +import pytest + +# Exchanges that should be tested +EXCHANGES = ['bittrex', 'binance', 'kraken', 'ftx'] + + +@pytest.fixture +def exchange_conf(default_conf): + default_conf['exchange']['pair_whitelist'] = [] + return default_conf + + +@pytest.mark.parametrize('exchange', EXCHANGES) +def test_ccxt_fetch_l2_orderbook(exchange_conf, exchange): + + exchange_conf['exchange']['name'] = exchange + exchange_conf['exchange']['name'] = exchange + + exchange = ExchangeResolver.load_exchange(exchange, exchange_conf) + l2 = exchange.fetch_l2_order_book('BTC/USDT') + assert 'asks' in l2 + assert 'bids' in l2 + + for val in [1, 2, 5, 25, 100]: + l2 = exchange.fetch_l2_order_book('BTC/USDT', val) + if not exchange._ft_has['l2_limit_range'] or val in exchange._ft_has['l2_limit_range']: + assert len(l2['asks']) == val + assert len(l2['bids']) == val + else: + next_limit = exchange.get_next_limit_in_list(val, exchange._ft_has['l2_limit_range']) + assert len(l2['asks']) == next_limit + assert len(l2['asks']) == next_limit + + From 38af1b2a5dd51ce659b1e7ee13f30237ff332afa Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 23 Oct 2020 20:46:01 +0200 Subject: [PATCH 02/13] Improve compat tests --- tests/conftest.py | 6 +- tests/exchange/test_ccxt_compat.py | 109 ++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 27 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 965980f7a..e7e9a3096 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -223,7 +223,11 @@ def init_persistence(default_conf): @pytest.fixture(scope="function") -def default_conf(testdatadir): +def default_conf(): + return get_default_conf() + + +def get_default_conf(testdatadir): """ Returns validated configuration suitable for most tests """ configuration = { "max_open_trades": 1, diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index e6deebf62..6b6fbcfc9 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -6,38 +6,95 @@ suitable to run with freqtrade. """ -from freqtrade.resolvers.exchange_resolver import ExchangeResolver import pytest +from pathlib import Path +from freqtrade.resolvers.exchange_resolver import ExchangeResolver +from tests.conftest import get_default_conf + # Exchanges that should be tested -EXCHANGES = ['bittrex', 'binance', 'kraken', 'ftx'] +EXCHANGES = { + 'bittrex': { + 'pair': 'BTC/USDT', + 'hasQuoteVolume': False + }, + 'binance': { + 'pair': 'BTC/USDT', + 'hasQuoteVolume': True + }, + 'kraken': { + 'pair': 'BTC/USDT', + 'hasQuoteVolume': True + }, + 'ftx': { + 'pair': 'BTC/USDT', + 'hasQuoteVolume': True + } +} -@pytest.fixture -def exchange_conf(default_conf): - default_conf['exchange']['pair_whitelist'] = [] - return default_conf +@pytest.fixture(scope="class") +def exchange_conf(): + config = get_default_conf((Path(__file__).parent / "testdata").resolve()) + config['exchange']['pair_whitelist'] = [] + return config -@pytest.mark.parametrize('exchange', EXCHANGES) -def test_ccxt_fetch_l2_orderbook(exchange_conf, exchange): - - exchange_conf['exchange']['name'] = exchange - exchange_conf['exchange']['name'] = exchange - - exchange = ExchangeResolver.load_exchange(exchange, exchange_conf) - l2 = exchange.fetch_l2_order_book('BTC/USDT') - assert 'asks' in l2 - assert 'bids' in l2 - - for val in [1, 2, 5, 25, 100]: - l2 = exchange.fetch_l2_order_book('BTC/USDT', val) - if not exchange._ft_has['l2_limit_range'] or val in exchange._ft_has['l2_limit_range']: - assert len(l2['asks']) == val - assert len(l2['bids']) == val - else: - next_limit = exchange.get_next_limit_in_list(val, exchange._ft_has['l2_limit_range']) - assert len(l2['asks']) == next_limit - assert len(l2['asks']) == next_limit +@pytest.fixture(params=EXCHANGES, scope="class") +def exchange(request, exchange_conf): + exchange_conf['exchange']['name'] = request.param + exchange = ExchangeResolver.load_exchange(request.param, exchange_conf, validate=False) + yield exchange, request.param +class TestCCXTExchange(): + + def test_load_markets(self, exchange): + exchange, exchangename = exchange + pair = EXCHANGES[exchangename]['pair'] + markets = exchange.markets + assert pair in markets + assert isinstance(markets[pair], dict) + + def test_ccxt_fetch_tickers(self, exchange): + exchange, exchangename = exchange + pair = EXCHANGES[exchangename]['pair'] + + tickers = exchange.get_tickers() + assert pair in tickers + assert 'ask' in tickers[pair] + assert tickers[pair]['ask'] is not None + assert 'bid' in tickers[pair] + assert tickers[pair]['bid'] is not None + assert 'quoteVolume' in tickers[pair] + if EXCHANGES[exchangename].get('hasQuoteVolume'): + assert tickers[pair]['quoteVolume'] is not None + + def test_ccxt_fetch_ticker(self, exchange): + exchange, exchangename = exchange + pair = EXCHANGES[exchangename]['pair'] + + ticker = exchange.fetch_ticker(pair) + assert 'ask' in ticker + assert ticker['ask'] is not None + assert 'bid' in ticker + assert ticker['bid'] is not None + assert 'quoteVolume' in ticker + if EXCHANGES[exchangename].get('hasQuoteVolume'): + assert ticker['quoteVolume'] is not None + + def test_ccxt_fetch_l2_orderbook(self, exchange): + exchange, exchangename = exchange + l2 = exchange.fetch_l2_order_book('BTC/USDT') + assert 'asks' in l2 + assert 'bids' in l2 + + for val in [1, 2, 5, 25, 100]: + l2 = exchange.fetch_l2_order_book('BTC/USDT', val) + if not exchange._ft_has['l2_limit_range'] or val in exchange._ft_has['l2_limit_range']: + assert len(l2['asks']) == val + assert len(l2['bids']) == val + else: + next_limit = exchange.get_next_limit_in_list(val, exchange._ft_has['l2_limit_range']) + assert len(l2['asks']) == next_limit + assert len(l2['asks']) == next_limit From 79ed89e4872705f40780266dc08811b1a019e6cb Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 23 Oct 2020 20:49:46 +0200 Subject: [PATCH 03/13] Add test for fee calculation --- tests/exchange/test_ccxt_compat.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 6b6fbcfc9..082d1dcf4 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -98,3 +98,12 @@ class TestCCXTExchange(): next_limit = exchange.get_next_limit_in_list(val, exchange._ft_has['l2_limit_range']) assert len(l2['asks']) == next_limit assert len(l2['asks']) == next_limit + + def test_ccxt_get_fee(self, exchange): + exchange, exchangename = exchange + pair = EXCHANGES[exchangename]['pair'] + + assert exchange.get_fee(pair, 'limit', 'buy') > 0 < 1 + assert exchange.get_fee(pair, 'limit', 'sell') > 0 < 1 + assert exchange.get_fee(pair, 'market', 'buy') > 0 < 1 + assert exchange.get_fee(pair, 'market', 'sell') > 0 < 1 From 7833d9935cd73cf1e78887308dff64e73fe51605 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 23 Oct 2020 20:50:31 +0200 Subject: [PATCH 04/13] Add dummy test for fetch_ohlcv --- tests/exchange/test_ccxt_compat.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 082d1dcf4..c1b8ab6f3 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -99,6 +99,10 @@ class TestCCXTExchange(): assert len(l2['asks']) == next_limit assert len(l2['asks']) == next_limit + def test_fetch_ohlcv(self, exchange): + # TODO: Implement me + pass + def test_ccxt_get_fee(self, exchange): exchange, exchangename = exchange pair = EXCHANGES[exchangename]['pair'] From b7d4ff9c216c7e37d906e5dc06e20daf3c463b35 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 24 Oct 2020 13:14:45 +0200 Subject: [PATCH 05/13] Add test for fetch_ohlcv (against exchange) --- tests/exchange/test_ccxt_compat.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index c1b8ab6f3..fa3bd45c8 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -3,7 +3,6 @@ Tests in this file do NOT mock network calls, so they are expected to be fluky a However, these tests should give a good idea to determine if a new exchange is suitable to run with freqtrade. - """ import pytest @@ -16,19 +15,23 @@ from tests.conftest import get_default_conf EXCHANGES = { 'bittrex': { 'pair': 'BTC/USDT', - 'hasQuoteVolume': False + 'hasQuoteVolume': False, + 'timeframe': '5m', }, 'binance': { 'pair': 'BTC/USDT', - 'hasQuoteVolume': True + 'hasQuoteVolume': True, + 'timeframe': '5m', }, 'kraken': { 'pair': 'BTC/USDT', - 'hasQuoteVolume': True + 'hasQuoteVolume': True, + 'timeframe': '5m', }, 'ftx': { 'pair': 'BTC/USDT', - 'hasQuoteVolume': True + 'hasQuoteVolume': True, + 'timeframe': '5m', } } @@ -100,8 +103,13 @@ class TestCCXTExchange(): assert len(l2['asks']) == next_limit def test_fetch_ohlcv(self, exchange): - # TODO: Implement me - pass + exchange, exchangename = exchange + pair = EXCHANGES[exchangename]['pair'] + timeframe = EXCHANGES[exchangename]['timeframe'] + pair_tf = (pair, timeframe) + ohlcv = exchange.refresh_latest_ohlcv([pair_tf]) + assert isinstance(ohlcv, list) + assert len(exchange.klines(pair_tf)) > 200 def test_ccxt_get_fee(self, exchange): exchange, exchangename = exchange From a6e6ce16b116cd299090f133ce5e50c6be06b713 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 13 Dec 2020 10:31:24 +0100 Subject: [PATCH 06/13] Fix test failures --- tests/conftest.py | 4 ++-- tests/exchange/test_ccxt_compat.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index e7e9a3096..a57b8c505 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -223,8 +223,8 @@ def init_persistence(default_conf): @pytest.fixture(scope="function") -def default_conf(): - return get_default_conf() +def default_conf(testdatadir): + return get_default_conf(testdatadir) def get_default_conf(testdatadir): diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index fa3bd45c8..1e8ddf319 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -88,12 +88,13 @@ class TestCCXTExchange(): def test_ccxt_fetch_l2_orderbook(self, exchange): exchange, exchangename = exchange - l2 = exchange.fetch_l2_order_book('BTC/USDT') + pair = EXCHANGES[exchangename]['pair'] + l2 = exchange.fetch_l2_order_book(pair) assert 'asks' in l2 assert 'bids' in l2 for val in [1, 2, 5, 25, 100]: - l2 = exchange.fetch_l2_order_book('BTC/USDT', val) + l2 = exchange.fetch_l2_order_book(pair, val) if not exchange._ft_has['l2_limit_range'] or val in exchange._ft_has['l2_limit_range']: assert len(l2['asks']) == val assert len(l2['bids']) == val From 2016eea2120dab76968f49237e967689a515e3c9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 23 Dec 2020 15:29:39 +0100 Subject: [PATCH 07/13] Fix some test-errors in ccxt_compat --- tests/exchange/test_ccxt_compat.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 1e8ddf319..25b26d489 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -100,8 +100,12 @@ class TestCCXTExchange(): assert len(l2['bids']) == val else: next_limit = exchange.get_next_limit_in_list(val, exchange._ft_has['l2_limit_range']) - assert len(l2['asks']) == next_limit - assert len(l2['asks']) == next_limit + if next_limit > 200: + assert len(l2['asks']) > 200 + assert len(l2['asks']) > 200 + else: + assert len(l2['asks']) == next_limit + assert len(l2['asks']) == next_limit def test_fetch_ohlcv(self, exchange): exchange, exchangename = exchange @@ -116,7 +120,7 @@ class TestCCXTExchange(): exchange, exchangename = exchange pair = EXCHANGES[exchangename]['pair'] - assert exchange.get_fee(pair, 'limit', 'buy') > 0 < 1 - assert exchange.get_fee(pair, 'limit', 'sell') > 0 < 1 - assert exchange.get_fee(pair, 'market', 'buy') > 0 < 1 - assert exchange.get_fee(pair, 'market', 'sell') > 0 < 1 + assert 0 < exchange.get_fee(pair, 'limit', 'buy') < 1 + assert 0 < exchange.get_fee(pair, 'limit', 'sell') < 1 + assert 0 < exchange.get_fee(pair, 'market', 'buy') < 1 + assert 0 < exchange.get_fee(pair, 'market', 'sell') < 1 From 0981287c62398724ffc16ee80fc7165b3c37c8bf Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 23 Dec 2020 15:41:23 +0100 Subject: [PATCH 08/13] Improve test syntax for ccxt_compat tests --- tests/exchange/test_ccxt_compat.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 25b26d489..09cc50f14 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -92,15 +92,16 @@ class TestCCXTExchange(): l2 = exchange.fetch_l2_order_book(pair) assert 'asks' in l2 assert 'bids' in l2 - + l2_limit_range = exchange._ft_has['l2_limit_range'] for val in [1, 2, 5, 25, 100]: l2 = exchange.fetch_l2_order_book(pair, val) - if not exchange._ft_has['l2_limit_range'] or val in exchange._ft_has['l2_limit_range']: + if not l2_limit_range or val in l2_limit_range: assert len(l2['asks']) == val assert len(l2['bids']) == val else: - next_limit = exchange.get_next_limit_in_list(val, exchange._ft_has['l2_limit_range']) + next_limit = exchange.get_next_limit_in_list(val, l2_limit_range) if next_limit > 200: + # Large orderbook sizes can be a problem for some exchanges (bitrex ...) assert len(l2['asks']) > 200 assert len(l2['asks']) > 200 else: @@ -116,6 +117,8 @@ class TestCCXTExchange(): assert isinstance(ohlcv, list) assert len(exchange.klines(pair_tf)) > 200 + # TODO: tests fetch_trades (?) + def test_ccxt_get_fee(self, exchange): exchange, exchangename = exchange pair = EXCHANGES[exchangename]['pair'] From b39de171c88af56edc0b9a773a1d507583264c7d Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 23 Dec 2020 15:46:08 +0100 Subject: [PATCH 09/13] Don't run longrun regularily --- .github/workflows/ci.yml | 6 ++++++ tests/conftest.py | 13 +++++++++++++ tests/exchange/test_ccxt_compat.py | 1 + 3 files changed, 20 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36a9fc374..daa10fea7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,12 @@ jobs: - name: Tests run: | pytest --random-order --cov=freqtrade --cov-config=.coveragerc + if: matrix.python-version != '3.9' + + - name: Tests incl. ccxt compatibility tests + run: | + pytest --random-order --cov=freqtrade --cov-config=.coveragerc --longrun + if: matrix.python-version == '3.9' - name: Coveralls if: (startsWith(matrix.os, 'ubuntu-20') && matrix.python-version == '3.8') diff --git a/tests/conftest.py b/tests/conftest.py index a57b8c505..9eda0e973 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -33,6 +33,19 @@ logging.getLogger('').setLevel(logging.INFO) np.seterr(all='raise') +def pytest_addoption(parser): + parser.addoption('--longrun', action='store_true', dest="longrun", + default=False, help="Enable long-run tests (ccxt compat)") + + +def pytest_configure(config): + config.addinivalue_line( + "markers", "longrun: mark test that is running slowly and should not be run regularily" + ) + if not config.option.longrun: + setattr(config.option, 'markexpr', 'not longrun') + + def log_has(line, logs): # caplog mocker returns log as a tuple: ('freqtrade.something', logging.WARNING, 'foobar') # and we want to match line against foobar in the tuple diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 09cc50f14..90cdebcdd 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -50,6 +50,7 @@ def exchange(request, exchange_conf): yield exchange, request.param +@pytest.mark.longrun class TestCCXTExchange(): def test_load_markets(self, exchange): From 5599490aa286675d57dfe3860330faf5af23c402 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 23 Dec 2020 15:50:24 +0100 Subject: [PATCH 10/13] Adjust ohlcv test after rebase --- tests/exchange/test_ccxt_compat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 90cdebcdd..6d495582b 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -115,7 +115,8 @@ class TestCCXTExchange(): timeframe = EXCHANGES[exchangename]['timeframe'] pair_tf = (pair, timeframe) ohlcv = exchange.refresh_latest_ohlcv([pair_tf]) - assert isinstance(ohlcv, list) + assert isinstance(ohlcv, dict) + assert len(ohlcv[pair_tf]) == len(exchange.klines(pair_tf)) assert len(exchange.klines(pair_tf)) > 200 # TODO: tests fetch_trades (?) From 65d91b7cbb6ab4a388d66dc2834edc94fecb1cf2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 23 Dec 2020 15:53:41 +0100 Subject: [PATCH 11/13] Add note on adding new exchange with compat tests --- docs/developer.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/developer.md b/docs/developer.md index dcbaa3ca9..6440dba82 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -242,6 +242,8 @@ The `IProtection` parent class provides a helper method for this in `calculate_l Most exchanges supported by CCXT should work out of the box. +To quickly test the public endpoints of an exchange, add a configuration for your exchange to `test_ccxt_compat.py` and run these tests with `pytest --longrun`. + ### Stoploss On Exchange Check if the new exchange supports Stoploss on Exchange orders through their API. From 721d0fb2a8c4b5c3f582436c05cfa1ff1086475a Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 23 Dec 2020 15:55:46 +0100 Subject: [PATCH 12/13] Improve wording of developer docs --- docs/developer.md | 3 ++- tests/exchange/test_ccxt_compat.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/developer.md b/docs/developer.md index 6440dba82..de489a348 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -242,7 +242,8 @@ The `IProtection` parent class provides a helper method for this in `calculate_l Most exchanges supported by CCXT should work out of the box. -To quickly test the public endpoints of an exchange, add a configuration for your exchange to `test_ccxt_compat.py` and run these tests with `pytest --longrun`. +To quickly test the public endpoints of an exchange, add a configuration for your exchange to `test_ccxt_compat.py` and run these tests with `pytest --longrun tests/exchange/test_ccxt_compat.py`. +Completing these tests successfully a good basis point (it's a requirement, actually), however these won't guarantee correct exchange functioning, as this only tests public endpoints, but no private endpoint (like generate order or similar). ### Stoploss On Exchange diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 6d495582b..8db56685a 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -5,8 +5,10 @@ However, these tests should give a good idea to determine if a new exchange is suitable to run with freqtrade. """ -import pytest from pathlib import Path + +import pytest + from freqtrade.resolvers.exchange_resolver import ExchangeResolver from tests.conftest import get_default_conf From 1713841d0b0ed672c9f16229a482497d1b296df3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 23 Dec 2020 16:20:17 +0100 Subject: [PATCH 13/13] Initialize markets at startup for ccxt tests --- tests/exchange/test_ccxt_compat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 8db56685a..0c8b7bdcf 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -48,7 +48,8 @@ def exchange_conf(): @pytest.fixture(params=EXCHANGES, scope="class") def exchange(request, exchange_conf): exchange_conf['exchange']['name'] = request.param - exchange = ExchangeResolver.load_exchange(request.param, exchange_conf, validate=False) + exchange = ExchangeResolver.load_exchange(request.param, exchange_conf, validate=True) + yield exchange, request.param