From 54943524b219bfb0e9b88dae8534becfdb3dca4b Mon Sep 17 00:00:00 2001 From: Haibo Lin Date: Wed, 3 Jul 2019 15:17:26 +0800 Subject: [PATCH 1/3] Move images to misc dir --- LICENSE | 4 ++-- README.rst | 2 +- .../prod-listings-manager.png | Bin .../prod-listings-manager.svg | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename prod-listings-manager.png => misc/prod-listings-manager.png (100%) rename prod-listings-manager.svg => misc/prod-listings-manager.svg (100%) diff --git a/LICENSE b/LICENSE index 5c29fde..47d3438 100644 --- a/LICENSE +++ b/LICENSE @@ -55,5 +55,5 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -prod-listings-manager.png and prod-listings-manager.svg are licensed under a -Creative Commons Attribution 3.0 Unported license (CC BY 3.0). +misc/prod-listings-manager.png and misc/prod-listings-manager.svg are licensed +under a Creative Commons Attribution 3.0 Unported license (CC BY 3.0). diff --git a/README.rst b/README.rst index 9ec8234..f143e1f 100644 --- a/README.rst +++ b/README.rst @@ -46,7 +46,7 @@ Goals with this project Architecture diagram -------------------- -.. image:: prod-listings-manager.png +.. image:: misc/prod-listings-manager.png :width: 958px :align: center :height: 364px diff --git a/prod-listings-manager.png b/misc/prod-listings-manager.png similarity index 100% rename from prod-listings-manager.png rename to misc/prod-listings-manager.png diff --git a/prod-listings-manager.svg b/misc/prod-listings-manager.svg similarity index 100% rename from prod-listings-manager.svg rename to misc/prod-listings-manager.svg From 13f3bf48e24432f4dbdc7561d6713ce6c23a0227 Mon Sep 17 00:00:00 2001 From: Haibo Lin Date: Wed, 3 Jul 2019 16:37:25 +0800 Subject: [PATCH 2/3] Relocate tests dir http://flask.pocoo.org/docs/1.0/tutorial/layout/ --- product-listings-manager.spec | 13 ++----------- product_listings_manager/tests/__init__.py | 0 setup.py | 2 +- {product_listings_manager => tests}/conftest.py | 0 .../tests => tests}/test_http_404.py | 0 .../tests => tests}/test_products.py | 0 .../tests => tests}/test_rest_api_v1.py | 0 .../tests => tests}/test_root.py | 0 tox.ini | 4 +++- 9 files changed, 6 insertions(+), 13 deletions(-) delete mode 100644 product_listings_manager/tests/__init__.py rename {product_listings_manager => tests}/conftest.py (100%) rename {product_listings_manager/tests => tests}/test_http_404.py (100%) rename {product_listings_manager/tests => tests}/test_products.py (100%) rename {product_listings_manager/tests => tests}/test_rest_api_v1.py (100%) rename {product_listings_manager/tests => tests}/test_root.py (100%) diff --git a/product-listings-manager.spec b/product-listings-manager.spec index d61c24a..7bff2c5 100644 --- a/product-listings-manager.spec +++ b/product-listings-manager.spec @@ -23,9 +23,8 @@ BuildRequires: python3-flask-sqlalchemy BuildRequires: python3-flask-restful BuildRequires: python3-koji BuildRequires: python3-psycopg2 -BuildRequires: python3-pytest +BuildRequires: python3-setuptools BuildRequires: python3-sqlalchemy -BuildRequires: python3-mock Requires: python3-flask Requires: python3-flask-sqlalchemy Requires: python3-flask-restful @@ -40,8 +39,7 @@ BuildRequires: python-psycopg2 BuildRequires: python-sqlalchemy BuildRequires: python2-flask-restful BuildRequires: python2-koji -BuildRequires: pytest -BuildRequires: python-mock +BuildRequires: python2-setuptools Requires: python-flask Requires: python-flask-sqlalchemy Requires: python-sqlalchemy @@ -75,13 +73,6 @@ composedb. mkdir -p %{buildroot}%{_sysconfdir}/%{name} cp -p %{modname}/config.py %{buildroot}%{_sysconfdir}/%{name} -%check -%if %{with python3} -py.test-3 -v %{modname}/tests -%else -py.test-2.7 -v %{modname}/tests -%endif - %files %license LICENSE %doc README.rst diff --git a/product_listings_manager/tests/__init__.py b/product_listings_manager/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/setup.py b/setup.py index 43989c2..f7c6661 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ def read_module_contents(): url='https://github.com/release-engineering/product-listings-manager', license='MIT', long_description=LONG_DESCRIPTION, - packages=find_packages(), + packages=find_packages(exclude=['tests']), install_requires=[ 'Flask', 'Flask-Restful', diff --git a/product_listings_manager/conftest.py b/tests/conftest.py similarity index 100% rename from product_listings_manager/conftest.py rename to tests/conftest.py diff --git a/product_listings_manager/tests/test_http_404.py b/tests/test_http_404.py similarity index 100% rename from product_listings_manager/tests/test_http_404.py rename to tests/test_http_404.py diff --git a/product_listings_manager/tests/test_products.py b/tests/test_products.py similarity index 100% rename from product_listings_manager/tests/test_products.py rename to tests/test_products.py diff --git a/product_listings_manager/tests/test_rest_api_v1.py b/tests/test_rest_api_v1.py similarity index 100% rename from product_listings_manager/tests/test_rest_api_v1.py rename to tests/test_rest_api_v1.py diff --git a/product_listings_manager/tests/test_root.py b/tests/test_root.py similarity index 100% rename from product_listings_manager/tests/test_root.py rename to tests/test_root.py diff --git a/tox.ini b/tox.ini index ab99884..c3810ad 100644 --- a/tox.ini +++ b/tox.ini @@ -2,6 +2,8 @@ envlist = py27,py36,py37 [testenv] +setenv = + PYTHONPATH = {toxinidir} # Set RPM_PY_VERBOSE to "true" to debug koji package installation failures passenv = RPM_PY_VERBOSE deps = @@ -11,7 +13,7 @@ deps = flake8 commands = flake8 - pytest --cov=product_listings_manager --cov-report=term-missing -v product_listings_manager/tests/ + pytest --cov=product_listings_manager --cov-report=term-missing -v tests [flake8] ignore = E501 From 9209d26d051e59d346282351182a6e4600088f0b Mon Sep 17 00:00:00 2001 From: Haibo Lin Date: Fri, 5 Jul 2019 19:02:46 +0800 Subject: [PATCH 3/3] Add more tests TODO: Test database query logic using sqlite and testing data. JIRA: COMPOSE-3667 --- product_listings_manager/models.py | 2 +- tests/conftest.py | 8 ++ tests/test_http_404.py | 11 -- tests/test_live.py | 108 ++++++++++++++ tests/test_products.py | 222 ++++++++++++++++++++--------- tests/test_rest_api_v1.py | 96 ++++++++++--- tests/test_root.py | 11 -- 7 files changed, 350 insertions(+), 108 deletions(-) create mode 100644 tests/test_live.py diff --git a/product_listings_manager/models.py b/product_listings_manager/models.py index 95e1ac3..a1c9643 100644 --- a/product_listings_manager/models.py +++ b/product_listings_manager/models.py @@ -128,4 +128,4 @@ class ModuleOverrides(db.Model): product_arch = db.Column(db.String(32), primary_key=True) def __repr__(self): - return '' % (self.name, self.stream, self.product, self.product_arch) + return '' % (self.name, self.stream, self.product, self.product_arch) diff --git a/tests/conftest.py b/tests/conftest.py index 339c188..c680b50 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,8 @@ import json import pytest +from product_listings_manager.app import create_app + if not hasattr(Response, 'get_json'): def get_json(self, force=False, silent=False, cache=True): @@ -27,3 +29,9 @@ def pytest_collection_modifyitems(config, items): for item in items: if "live" in item.keywords: item.add_marker(skip_live) + + +@pytest.fixture +def client(): + client = create_app().test_client() + yield client diff --git a/tests/test_http_404.py b/tests/test_http_404.py index 4c0ea92..bccce18 100644 --- a/tests/test_http_404.py +++ b/tests/test_http_404.py @@ -1,14 +1,3 @@ -import pytest - -from product_listings_manager.app import create_app - - -@pytest.yield_fixture -def client(): - client = create_app().test_client() - yield client - - class TestHttp404(object): def test_http_404(self, client): r = client.get('/nonexistent') diff --git a/tests/test_live.py b/tests/test_live.py new file mode 100644 index 0000000..2bc6ccf --- /dev/null +++ b/tests/test_live.py @@ -0,0 +1,108 @@ +from product_listings_manager.app import create_app +from product_listings_manager.products import Products +from product_listings_manager.products import getProductInfo +from product_listings_manager.products import getProductListings +from product_listings_manager.products import getModuleProductListings +from product_listings_manager.products import getProductLabels +import pytest + + +@pytest.fixture(scope='module') +def app(): + app = create_app() + with app.app_context(): + yield app + + +@pytest.mark.live +class TestProductLive(object): + + def test_score(self): + # release = ??? + # assert Products.score(release) = ??? + pass + + def test_my_sort(self): + # x, y = (???, ???) + # assert Products.my_sort(x, y) == ??? + pass + + def test_get_product_info(self, app): + product = 'RHEL-6-Server-EXTRAS-6' + result = Products.get_product_info(product) + assert result == ('6.9', ['EXTRAS-6']) + + def test_get_overrides(self): + pass + + def test_get_match_versions(self): + pass + + def test_get_srconly_flag(self): + pass + + def test_precalc_treelist(self): + pass + + def test_dest_get_archs(self): + pass + + def test_get_module(self): + pass + + def test_get_module_overrides(self): + pass + + def test_precalc_module_trees(self): + pass + + +@pytest.mark.live +class TestGetProductInfo(object): + + def test_simple(self, app): + label = 'RHEL-6-Server-EXTRAS-6' + result = getProductInfo(label) + assert result == ('6.9', ['EXTRAS-6']) + + +@pytest.mark.live +class TestGetProductListings(object): + + def test_simple(self, app): + label = 'RHEL-6-Server-EXTRAS-6' + build = 'dumb-init-1.2.0-1.20170802gitd283f8a.el6' + result = getProductListings(label, build) + expected = \ + {'EXTRAS-6': + {'dumb-init-1.2.0-1.20170802gitd283f8a.el6': + {'src': ['x86_64'], 'x86_64': ['x86_64']}, + 'dumb-init-debuginfo-1.2.0-1.20170802gitd283f8a.el6': + {'x86_64': ['x86_64']}, + } + } + assert result == expected + + +@pytest.mark.live +class TestGetModuleProductListings(object): + + def test_getModuleProductListings(self, app): + label = 'RHEL-8.0.0' + module = 'ruby-2.5-820190111110530.9edba152' + result = getModuleProductListings(label, module) + expected = { + 'AppStream-8.0.0': ['aarch64', 'ppc64le', 's390x', 'x86_64'] + } + assert result == expected + + +@pytest.mark.live +class TestProductLabels(object): + + def test_getProductLabels(self, app): + result = getProductLabels() + assert len(result) > 1200 + assert {'label': 'RHEL-6'} in result + assert {'label': 'RHEL-6-Client'} in result + assert {'label': 'RHEL-6-Server'} in result diff --git a/tests/test_products.py b/tests/test_products.py index 2bc6ccf..353bb9c 100644 --- a/tests/test_products.py +++ b/tests/test_products.py @@ -1,10 +1,18 @@ +import pytest +from mock import patch + from product_listings_manager.app import create_app +from product_listings_manager.models import MatchVersions as MatchVersionsModel +from product_listings_manager.models import ModuleOverrides as ModuleOverridesModel +from product_listings_manager.models import Products as ProductsModel +from product_listings_manager.models import Overrides as OverridesModel +from product_listings_manager.models import Trees as TreesModel from product_listings_manager.products import Products +from product_listings_manager.products import ProductListingsNotFoundError from product_listings_manager.products import getProductInfo from product_listings_manager.products import getProductListings from product_listings_manager.products import getModuleProductListings from product_listings_manager.products import getProductLabels -import pytest @pytest.fixture(scope='module') @@ -14,95 +22,177 @@ def app(): yield app -@pytest.mark.live -class TestProductLive(object): +class TestProduct(object): def test_score(self): - # release = ??? - # assert Products.score(release) = ??? - pass + assert 0 == Products.score('Test1') + assert 1 == Products.score('alpha') + assert 2 == Products.score('BETA3') + assert 3 == Products.score('rc') + assert 4 == Products.score('Gold') + assert 5 == Products.score('U5') + assert 5 == Products.score('U1-beta') + assert -1 == Products.score('other') def test_my_sort(self): - # x, y = (???, ???) - # assert Products.my_sort(x, y) == ??? - pass - - def test_get_product_info(self, app): - product = 'RHEL-6-Server-EXTRAS-6' - result = Products.get_product_info(product) - assert result == ('6.9', ['EXTRAS-6']) - - def test_get_overrides(self): - pass + # x starts with y + assert -1 == Products.my_sort('U1-beta', 'U1') + + # y starts with x + assert 1 == Products.my_sort('U1', 'U1-beta') + + # score(x) == score(y) + assert -1 == Products.my_sort('7.1', '7.2') + assert -1 == Products.my_sort('U3', 'U4') + assert 1 == Products.my_sort('7.2', '7.1') + assert 1 == Products.my_sort('U4', 'U3') + assert 0 == Products.my_sort('8.0.0', '8.0.0') + + # score(x) != score(y) + assert -1 == Products.my_sort('Beta1', 'Gold') + assert 1 == Products.my_sort('6.9', '6.3') + assert 1 == Products.my_sort('8.1', '8.0.0') + + @patch('product_listings_manager.products.models.Products') + def test_get_product_info(self, mock_products_model): + label = 'RHEL-7' + mock_products_model.query.filter_by.return_value.all.return_value = [ + ProductsModel(id=1, label=label, version='7.2', variant='Server'), + ProductsModel(id=2, label=label, version='7.3', variant='Server'), + ProductsModel(id=3, label=label, version='7.4', variant='Server'), + ProductsModel(id=4, label=label, version='7.4', variant='Client') + ] + result = Products.get_product_info(label) + assert result == ('7.4', ['Server', 'Client']) + + @patch('product_listings_manager.products.models.Products') + def test_get_product_info_not_found(self, mock_products_model): + mock_products_model.query.filter_by.return_value.all.return_value = [] + label = 'Fake-label' + with pytest.raises(ProductListingsNotFoundError) as excinfo: + Products.get_product_info(label) + assert 'Could not find a product with label: {}'.format(label) == str(excinfo.value) + + @patch('product_listings_manager.products.models.Overrides') + def test_get_overrides(self, mock_overrides_model): + label = 'RHEL-7' + version = '7.5' + mock_overrides_model.query.join.return_value.filter.return_value.all.return_value = [ + OverridesModel(name='fake', pkg_arch='src', product_arch='x86_64', include=True), + OverridesModel(name='fake', pkg_arch='src', product_arch='ppc64', include=True), + OverridesModel(name='fake', pkg_arch='x86_64', product_arch='x86_64', include=False) + ] + assert Products.get_overrides(label, version) == { + 'fake': { + 'src': { + 'ppc64': True, + 'x86_64': True + }, + 'x86_64': { + 'x86_64': False + } + } + } - def test_get_match_versions(self): - pass + @patch('product_listings_manager.products.models.MatchVersions') + def test_get_match_versions(self, mock_matchversions_model): + product = 'fake-product' + mock_matchversions_model.query.filter_by.return_value.all.return_value = [ + MatchVersionsModel(name='fake1'), + MatchVersionsModel(name='fake2'), + ] + assert Products.get_match_versions(product) == ['fake1', 'fake2'] def test_get_srconly_flag(self): pass - def test_precalc_treelist(self): - pass + @patch('product_listings_manager.products.models.Trees') + def test_precalc_treelist(self, mock_trees_model): + mock_trees_model.query.join.return_value.order_by.return_value.filter.return_value.filter.return_value.all.return_value = [ + TreesModel(id=3, arch='x86_64'), + TreesModel(id=2, arch='x86_64'), + TreesModel(id=1, arch='ppc64'), + ] + assert sorted(Products.precalc_treelist('fake-product', '7.5', 'Server')) == sorted([1, 3]) def test_dest_get_archs(self): pass - def test_get_module(self): - pass + @patch('product_listings_manager.products.models.ModuleOverrides') + def test_get_module_overrides(self, mock_moduleoverrides_model): + module_name = 'perl' + module_stream = '5.24' + mock_moduleoverrides_model.query.join.return_value.filter.return_value.filter.return_value.all.return_value = [ + ModuleOverridesModel(name=module_name, stream=module_stream, product=1, product_arch='x86_64'), + ModuleOverridesModel(name=module_name, stream=module_stream, product=1, product_arch='ppc64le'), + ModuleOverridesModel(name=module_name, stream=module_stream, product=1, product_arch='s390x'), + ] + assert Products.get_module_overrides('fake', 'fake', module_name, module_stream, 'fake') == ['x86_64', 'ppc64le', 's390x'] + + @patch('product_listings_manager.products.models.Products') + def test_get_product_labels(self, mock_products_model): + mock_products_model.query.with_entities.return_value.distinct.return_value.all.return_value = [ + ProductsModel(label='label1'), + ProductsModel(label='label2'), + ] + assert Products.get_product_labels() == [{'label': 'label1'}, {'label': 'label2'}] - def test_get_module_overrides(self): - pass - - def test_precalc_module_trees(self): - pass - -@pytest.mark.live class TestGetProductInfo(object): - def test_simple(self, app): - label = 'RHEL-6-Server-EXTRAS-6' - result = getProductInfo(label) - assert result == ('6.9', ['EXTRAS-6']) + @patch('product_listings_manager.products.Products.get_product_info') + def test_getProductInfo(self, mock_get_product_info): + label = 'Fake-label' + getProductInfo(label) + mock_get_product_info.assert_called_once_with(label) -@pytest.mark.live class TestGetProductListings(object): - def test_simple(self, app): - label = 'RHEL-6-Server-EXTRAS-6' - build = 'dumb-init-1.2.0-1.20170802gitd283f8a.el6' - result = getProductListings(label, build) - expected = \ - {'EXTRAS-6': - {'dumb-init-1.2.0-1.20170802gitd283f8a.el6': - {'src': ['x86_64'], 'x86_64': ['x86_64']}, - 'dumb-init-debuginfo-1.2.0-1.20170802gitd283f8a.el6': - {'x86_64': ['x86_64']}, - } - } - assert result == expected - - -@pytest.mark.live + @patch('product_listings_manager.products.get_koji_session') + def test_rpms_not_found(self, mock_get_koji_session): + mock_get_koji_session.return_value.listRPMs.return_value = [] + build = 'fake-build-1.0-1.el6' + with pytest.raises(ProductListingsNotFoundError) as excinfo: + getProductListings('fake-label', build) + assert "Could not find any RPMs for build: {}".format(build) == str(excinfo.value) + + class TestGetModuleProductListings(object): - def test_getModuleProductListings(self, app): - label = 'RHEL-8.0.0' - module = 'ruby-2.5-820190111110530.9edba152' - result = getModuleProductListings(label, module) - expected = { - 'AppStream-8.0.0': ['aarch64', 'ppc64le', 's390x', 'x86_64'] - } - assert result == expected + @patch('product_listings_manager.products.get_build') + def test_not_module_build(self, mock_get_build): + mock_get_build.return_value = {'name': 'perl'} + nvr = 'perl-5.16.3-1.el7' + with pytest.raises(ProductListingsNotFoundError) as excinfo: + getModuleProductListings('fake-label', nvr) + assert "It's not a module build: {}".format(nvr) == str(excinfo.value) + + @patch('product_listings_manager.products.Products.get_module_overrides') + @patch('product_listings_manager.products.Products.get_product_info') + @patch('product_listings_manager.products.Products.precalc_treelist') + @patch('product_listings_manager.products.get_build') + @patch('product_listings_manager.products.models.Trees') + def test_getModuleProductListings(self, mock_trees_model, mock_get_build, mock_precalc_treelist, mock_get_product_info, mock_get_module_overrides): + + mock_trees_model.query.with_entities.return_value.join.return_value.filter.return_value.filter.return_value = [ + ('x86_64',), + ] + nvr = 'perl-5.24-8010020190529084201.3af8e029' + mock_get_product_info.return_value = ('8.0', ['AppStream-8.0']) + + # test without overrides + mock_get_module_overrides.return_value = [] + assert getModuleProductListings('fake-label', nvr) == {'AppStream-8.0': ['x86_64']} + + # test with overrides + mock_get_module_overrides.return_value = ['ppc64le'] + assert getModuleProductListings('fake-label', nvr) == {'AppStream-8.0': ['ppc64le', 'x86_64']} -@pytest.mark.live class TestProductLabels(object): - def test_getProductLabels(self, app): - result = getProductLabels() - assert len(result) > 1200 - assert {'label': 'RHEL-6'} in result - assert {'label': 'RHEL-6-Client'} in result - assert {'label': 'RHEL-6-Server'} in result + @patch('product_listings_manager.products.Products.get_product_labels') + def test_getProductLabels(self, mock_get_product_labels): + getProductLabels() + mock_get_product_labels.assert_called_once_with() diff --git a/tests/test_rest_api_v1.py b/tests/test_rest_api_v1.py index 739ddcf..d88a492 100644 --- a/tests/test_rest_api_v1.py +++ b/tests/test_rest_api_v1.py @@ -1,17 +1,8 @@ -import pytest - from mock import patch -from product_listings_manager.app import create_app from product_listings_manager import products -@pytest.yield_fixture -def client(): - client = create_app().test_client() - yield client - - class TestIndex(object): def test_get_index(self, client): r = client.get('/api/v1.0/') @@ -35,17 +26,62 @@ def test_get_version(self, client): assert r.get_json() == {'version': __version__} +class TestHealth(object): + def test_health_db_fail(self, client): + r = client.get('/api/v1.0/health') + assert r.status_code == 503 + data = r.get_json() + assert data['ok'] is False + assert 'DB Error:' in data['message'] + + @patch('product_listings_manager.rest_api_v1.db') + @patch('product_listings_manager.rest_api_v1.products.get_koji_session') + def test_health_koji_fail(self, mock_koji, mock_db, client): + mock_db.return_value.engine.return_value.execute.return_value = 1 + mock_koji.side_effect = Exception('koji connect error') + r = client.get('/api/v1.0/health') + assert r.status_code == 503 + data = r.get_json() + assert data['ok'] is False + assert 'Koji Error: koji connect error' in data['message'] + + @patch('product_listings_manager.rest_api_v1.db') + @patch('product_listings_manager.rest_api_v1.products.get_koji_session') + def test_health_ok(self, mock_koji, mock_db, client): + mock_db.return_value.engine.return_value.execute.return_value = 1 + mock_koji.return_value.getAPIVersion.return_value = 1 + r = client.get('/api/v1.0/health') + assert r.status_code == 200 + assert r.get_json() == {'ok': True, 'message': 'It works!'} + + class TestProductInfo(object): product_label = 'RHEL-6-Server-EXTRAS-6' product_info_data = ['6.9', ['EXTRAS-6']] + path = '/api/v1.0/product-info/{0}'.format(product_label) @patch('product_listings_manager.products.getProductInfo', return_value=product_info_data) def test_get_product_info(self, mock_get_product_info, client): - path = '/api/v1.0/product-info/{0}'.format(self.product_label) - r = client.get(path) + r = client.get(self.path) assert r.status_code == 200 assert r.get_json() == mock_get_product_info.return_value + @patch('product_listings_manager.products.getProductInfo') + def test_label_not_found(self, mock_getinfo, client): + msg = 'Could not find a product with label: %s' % self.product_label + mock_getinfo.side_effect = products.ProductListingsNotFoundError(msg) + r = client.get(self.path) + assert r.status_code == 404 + assert msg in r.get_json()['message'] + + @patch('product_listings_manager.products.getProductInfo') + @patch('product_listings_manager.utils.log_remote_call_error') + def test_unknown_error(self, mock_log, mock_getinfo, client): + mock_getinfo.side_effect = Exception('Unexpected error') + r = client.get(self.path) + assert r.status_code == 500 + mock_log.assert_called_once_with('API call getProductInfo() failed', self.product_label) + class TestProductListings(object): product_label = 'RHEL-6-Server-EXTRAS-6' @@ -57,11 +93,11 @@ class TestProductListings(object): } } } + path = '/api/v1.0/product-listings/{0}/{1}'.format(product_label, nvr) @patch('product_listings_manager.products.getProductListings', return_value=product_listings_data) def test_get_product_listings(self, mock_get_product_listings, client): - path = '/api/v1.0/product-listings/{0}/{1}'.format(self.product_label, self.nvr) - r = client.get(path) + r = client.get(self.path) assert r.status_code == 200 assert r.get_json() == mock_get_product_listings.return_value @@ -69,11 +105,18 @@ def test_get_product_listings(self, mock_get_product_listings, client): def test_product_listings_not_found(self, mock_get_product_listings, client): error_message = 'NOT FOUND' mock_get_product_listings.side_effect = products.ProductListingsNotFoundError(error_message) - path = '/api/v1.0/product-listings/{0}/{1}'.format(self.product_label, self.nvr) - r = client.get(path) + r = client.get(self.path) assert r.status_code == 404 assert r.get_json() == {'message': error_message} + @patch('product_listings_manager.products.getProductListings') + @patch('product_listings_manager.utils.log_remote_call_error') + def test_unknown_error(self, mock_log, mock_getlistings, client): + mock_getlistings.side_effect = Exception('Unexpected error') + r = client.get(self.path) + assert r.status_code == 500 + mock_log.assert_called_once_with('API call getProductListings() failed', self.product_label, self.nvr) + class TestModuleProductListings(object): product_label = 'RHEL-8.0.0' @@ -81,11 +124,11 @@ class TestModuleProductListings(object): product_listings_data = { 'AppStream-8.0.0': ['x86_64'] } + path = '/api/v1.0/module-product-listings/{0}/{1}'.format(product_label, nvr) @patch('product_listings_manager.products.getModuleProductListings', return_value=product_listings_data) def test_get_module_product_listings(self, mock_get_module_product_listings, client): - path = '/api/v1.0/module-product-listings/{0}/{1}'.format(self.product_label, self.nvr) - r = client.get(path) + r = client.get(self.path) assert r.status_code == 200 assert r.get_json() == mock_get_module_product_listings.return_value @@ -93,11 +136,18 @@ def test_get_module_product_listings(self, mock_get_module_product_listings, cli def test_product_listings_not_found(self, mock_get_module_product_listings, client): error_message = 'NOT FOUND' mock_get_module_product_listings.side_effect = products.ProductListingsNotFoundError(error_message) - path = '/api/v1.0/module-product-listings/{0}/{1}'.format(self.product_label, self.nvr) - r = client.get(path) + r = client.get(self.path) assert r.status_code == 404 assert error_message in r.get_json().get('message', '') + @patch('product_listings_manager.products.getModuleProductListings') + @patch('product_listings_manager.utils.log_remote_call_error') + def test_unknown_error(self, mock_log, mock_getlistings, client): + mock_getlistings.side_effect = Exception('Unexpected error') + r = client.get(self.path) + assert r.status_code == 500 + mock_log.assert_called_once_with('API call getModuleProductListings() failed', self.product_label, self.nvr) + class TestLabels(object): labels = [ @@ -110,3 +160,11 @@ def test_get_product_info(self, mock_get_product_info, client): r = client.get('/api/v1.0/product-labels') assert r.status_code == 200 assert r.get_json() == mock_get_product_info.return_value + + @patch('product_listings_manager.products.getProductLabels') + @patch('product_listings_manager.utils.log_remote_call_error') + def test_unknown_error(self, mock_log, mock_getlabels, client): + mock_getlabels.side_effect = Exception('Unexpected error') + r = client.get('/api/v1.0/product-labels') + assert r.status_code == 500 + mock_log.assert_called_once_with('API call getProductLabels() failed') diff --git a/tests/test_root.py b/tests/test_root.py index 7704bc9..627abb7 100644 --- a/tests/test_root.py +++ b/tests/test_root.py @@ -1,14 +1,3 @@ -import pytest - -from product_listings_manager.app import create_app - - -@pytest.yield_fixture -def client(): - client = create_app().test_client() - yield client - - class TestRoot(object): def test_get_version(self, client): r = client.get('/')