From 8072382adb6c0b29c6fce6ecdabe19c19833259b Mon Sep 17 00:00:00 2001 From: sbs2001 Date: Sat, 14 Dec 2019 22:21:14 +0530 Subject: [PATCH] Change Django tests to pytests Signed-off-by: sbs2001 --- .travis.yml | 3 +- pytest.ini | 2 + requirements.txt | 7 +- vulnerabilities/tests/conftest.py | 43 +++ vulnerabilities/tests/test_api.py | 161 +++++------ vulnerabilities/tests/test_data_dump.py | 353 +++++++++++------------ vulnerabilities/tests/test_import_cli.py | 48 +-- vulnerabilities/tests/test_models.py | 78 +++-- vulnerabilities/tests/test_npm.py | 152 +++++----- 9 files changed, 422 insertions(+), 425 deletions(-) create mode 100644 pytest.ini create mode 100644 vulnerabilities/tests/conftest.py diff --git a/.travis.yml b/.travis.yml index 2ea5c455c..34cec8358 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,7 @@ before_script: - ./manage.py migrate script: - - python3.6 -m pytest -v vulnerabilities/tests/test_scrapers.py vulnerabilities/tests/test_api_data.py - - ./manage.py test vulnerabilities/tests + - pytest notifications: email: false diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..8a0f512df --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +DJANGO_SETTINGS_MODULE = vulnerablecode.settings \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 4593abdec..b1654e68f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,16 +4,17 @@ beautifulsoup4==4.7.1 lxml==4.3.3 django==2.2.8 djangorestframework==3.9.2 -django-filter==2.1.0 +django-filter==2.2.0 packageurl-python==0.8.7 semantic-version==2.8.2 # Tests -pytest==3.2.3 +pytest==5.3.2 +pytest-django==3.7.0 pycodestyle==2.5.0 # Deployment gunicorn==19.7.1 -whitenoise==3.3.1 +whitenoise==5.0.1 dj_database_url==0.4.2 psycopg2==2.8.4 diff --git a/vulnerabilities/tests/conftest.py b/vulnerabilities/tests/conftest.py new file mode 100644 index 000000000..19a036168 --- /dev/null +++ b/vulnerabilities/tests/conftest.py @@ -0,0 +1,43 @@ + +import pytest +import os +import json + + +from vulnerabilities.api import PackageSerializer +from vulnerabilities.data_dump import debian_dump +from vulnerabilities.data_dump import ubuntu_dump +from vulnerabilities.data_dump import archlinux_dump +from vulnerabilities.scraper import archlinux +from vulnerabilities.scraper import debian +from vulnerabilities.scraper import ubuntu +from vulnerabilities.models import Package + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +TEST_DATA = os.path.join(BASE_DIR, 'test_data/') + + +@pytest.fixture +def setDebianData(db): + with open(os.path.join(TEST_DATA, 'debian.json')) as f: + test_data = json.load(f) + + extract_data = debian.extract_vulnerabilities(test_data) + debian_dump(extract_data) + + +@pytest.fixture +def setUbuntuData(db): + with open(os.path.join(TEST_DATA, 'ubuntu_main.html')) as f: + test_data = f.read() + + data = ubuntu.extract_cves(test_data) + ubuntu_dump(data) + + +@pytest.fixture +def setArchLinuxData(db): + with open(os.path.join(TEST_DATA, 'archlinux.json')) as f: + test_data = json.load(f) + + archlinux_dump(test_data) diff --git a/vulnerabilities/tests/test_api.py b/vulnerabilities/tests/test_api.py index 293dea767..492e72b6b 100644 --- a/vulnerabilities/tests/test_api.py +++ b/vulnerabilities/tests/test_api.py @@ -23,8 +23,9 @@ import json import os +import pytest -from django.test import TestCase +from django.test import Client from vulnerabilities.api import PackageSerializer from vulnerabilities.data_dump import debian_dump @@ -38,114 +39,94 @@ TEST_DATA = os.path.join(BASE_DIR, 'test_data/') -class TestDebianResponse(TestCase): - @classmethod - def setUpTestData(cls): - with open(os.path.join(TEST_DATA, 'debian.json')) as f: - test_data = json.load(f) +def test_debian_query_by_name(setDebianData): - extract_data = debian.extract_vulnerabilities(test_data) - debian_dump(extract_data) + client = Client() + response = client.get('/api/packages/?name=mimetex', format='json').data + assert 4 == response['count'] + first_result = response['results'][0] + assert 'mimetex' == first_result['name'] + versions = {r['version'] for r in response['results']} + assert '1.50-1.1' in versions + assert '1.74-1' in versions - Package.objects.create( - name='mimetex', - version='1.50-1.1', - type='deb', - namespace='ubuntu' - ) - - def test_query_by_name(self): - response = self.client.get('/api/packages/?name=mimetex', format='json').data - - self.assertEqual(5, response['count']) - - first_result = response['results'][0] - self.assertEqual('mimetex', first_result['name']) - - versions = {r['version'] for r in response['results']} - self.assertIn('1.50-1.1', versions) - self.assertIn('1.74-1', versions) + purls = {r['package_url'] for r in response['results']} + assert 'pkg:deb/debian/mimetex@1.50-1.1?distro=jessie' in purls + assert 'pkg:deb/debian/mimetex@1.74-1?distro=jessie' in purls - purls = {r['package_url'] for r in response['results']} - self.assertIn('pkg:deb/debian/mimetex@1.50-1.1?distro=jessie', purls) - self.assertIn('pkg:deb/debian/mimetex@1.74-1?distro=jessie', purls) - def test_query_by_invalid_package_url(self): - url = '/api/packages/?package_url=invalid_purl' - response = self.client.get(url, format='json') +def test_debian_query_by_invalid_package_url(setDebianData): + client = Client() + url = '/api/packages/?package_url=invalid_purl' + response = client.get(url, format='json') - self.assertEqual(400, response.status_code) - self.assertIn('error', response.data) - error = response.data['error'] - self.assertIn('invalid_purl', error) + assert 400 == response.status_code + assert 'error' in response.data + error = response.data['error'] + assert 'invalid_purl' in error - def test_query_by_package_url(self): - url = '/api/packages/?package_url=pkg:deb/debian/mimetex@1.50-1.1?distro=jessie' - response = self.client.get(url, format='json').data - self.assertEqual(2, response['count']) +def test_debian_query_by_package_url(setDebianData): + client = Client() + url = '/api/packages/?package_url=pkg:deb/debian/mimetex@1.50-1.1?distro=jessie' + response = client.get(url, format='json').data - first_result = response['results'][0] - self.assertEqual('mimetex', first_result['name']) + assert 2 == response['count'] - versions = {r['version'] for r in response['results']} - self.assertIn('1.50-1.1', versions) - self.assertNotIn('1.74-1', versions) + first_result = response['results'][0] + assert 'mimetex' == first_result['name'] + versions = {r['version'] for r in response['results']} + assert '1.50-1.1' in versions + assert '1.74-1' not in versions - def test_query_by_package_url_without_namespace(self): - url = '/api/packages/?package_url=pkg:deb/mimetex@1.50-1.1' - response = self.client.get(url, format='json').data - self.assertEqual(3, response['count']) +def test_debian_query_by_package_url_without_namespace(setDebianData): - first_result = response['results'][0] - self.assertEqual('mimetex', first_result['name']) - - purls = {r['package_url'] for r in response['results']} - self.assertIn('pkg:deb/debian/mimetex@1.50-1.1?distro=jessie', purls) - self.assertIn('pkg:deb/ubuntu/mimetex@1.50-1.1', purls) - - -class TestUbuntuResponse(TestCase): - def test_ubuntu_response(self): - with open(os.path.join(TEST_DATA, 'ubuntu_main.html')) as f: - test_data = f.read() - - extract_data = ubuntu.extract_cves(test_data) - ubuntu_dump(extract_data) - response = self.client.get('/api/packages/?name=automake', format='json') + Package.objects.create( + name='mimetex', + version='1.50-1.1', + type='deb', + namespace='ubuntu' + ) + client = Client() + url = '/api/packages/?package_url=pkg:deb/mimetex@1.50-1.1' + response = client.get(url, format='json').data - result = response.data.get('results')[0] - self.assertEqual('automake', result['name']) - self.assertEqual(None, result['version']) - self.assertEqual(1, len(result['vulnerabilities'])) + assert 3 == response['count'] - vuln = result['vulnerabilities'][0] - self.assertEqual(0, len(vuln['references'])) + first_result = response['results'][0] + assert 'mimetex' == first_result['name'] + purls = {r['package_url'] for r in response['results']} + assert 'pkg:deb/debian/mimetex@1.50-1.1?distro=jessie' in purls + assert 'pkg:deb/ubuntu/mimetex@1.50-1.1' in purls -class TestSerializers(TestCase): - @classmethod - def setUpTestData(cls): - with open(os.path.join(TEST_DATA, 'debian.json')) as f: - test_data = json.load(f) - extract_data = debian.extract_vulnerabilities(test_data) - debian_dump(extract_data) +def test_debian_package_serializer(setDebianData): + client = Client() + pk = Package.objects.filter(name="mimetex") + response = PackageSerializer(pk, many=True).data + print(response) + assert 4 == len(response) - def test_package_serializer(self): - pk = Package.objects.filter(name="mimetex") - response = PackageSerializer(pk, many=True).data + first_result = response[0] + assert 'mimetex' == first_result['name'] - self.assertEqual(4, len(response)) + versions = {r['version'] for r in response} + assert '1.50-1.1' in versions + assert '1.74-1' in versions - first_result = response[0] - self.assertEqual('mimetex', first_result['name']) + purls = {r['package_url'] for r in response} + assert 'pkg:deb/debian/mimetex@1.50-1.1?distro=jessie' in purls + assert 'pkg:deb/debian/mimetex@1.74-1?distro=jessie' in purls - versions = {r['version'] for r in response} - self.assertIn('1.50-1.1', versions) - self.assertIn('1.74-1', versions) - purls = {r['package_url'] for r in response} - self.assertIn('pkg:deb/debian/mimetex@1.50-1.1?distro=jessie', purls) - self.assertIn('pkg:deb/debian/mimetex@1.74-1?distro=jessie', purls) +def test_ubuntu_response(setUbuntuData): + client = Client() + response = client.get('/api/packages/?name=automake', format='json') + result = response.data.get('results')[0] + assert 'automake' == result['name'] + assert result['version'] is None + assert 1 == len(result['vulnerabilities']) + vuln = result['vulnerabilities'][0] + assert 0 == len(vuln['references']) diff --git a/vulnerabilities/tests/test_data_dump.py b/vulnerabilities/tests/test_data_dump.py index 3f46b517b..bbad3918a 100644 --- a/vulnerabilities/tests/test_data_dump.py +++ b/vulnerabilities/tests/test_data_dump.py @@ -23,207 +23,180 @@ import json import os +import pytest -from django.test import TestCase - -from vulnerabilities.data_dump import archlinux_dump -from vulnerabilities.data_dump import debian_dump -from vulnerabilities.data_dump import ubuntu_dump from vulnerabilities.models import ImpactedPackage from vulnerabilities.models import Package from vulnerabilities.models import PackageReference from vulnerabilities.models import ResolvedPackage from vulnerabilities.models import Vulnerability from vulnerabilities.models import VulnerabilityReference -from vulnerabilities.scraper import archlinux -from vulnerabilities.scraper import debian -from vulnerabilities.scraper import ubuntu - BASE_DIR = os.path.dirname(os.path.abspath(__file__)) TEST_DATA = os.path.join(BASE_DIR, 'test_data/') -class TestDebianDataDump(TestCase): - @classmethod - def setUpTestData(cls): - with open(os.path.join(TEST_DATA, 'debian.json')) as f: - test_data = json.load(f) - - extract_data = debian.extract_vulnerabilities(test_data) - debian_dump(extract_data) - - def test_Vulnerability(self): - """ - Check that all vulnerabilities from the test data are stored in the database - """ - self.assertEqual(3, Vulnerability.objects.count()) - - self.assertTrue(Vulnerability.objects.filter(cve_id='CVE-2009-1382')) - self.assertTrue(Vulnerability.objects.filter(cve_id='CVE-2009-2459')) - self.assertTrue(Vulnerability.objects.filter(cve_id='CVE-2014-8242')) - - def test_VulnerabilityReference(self): - """ - Check that no vulnerability references were found in the test data - """ - self.assertEqual(0, VulnerabilityReference.objects.count()) - - def test_Package(self): - """ - Check that all packages from the test data are stored in the database - """ - # There are five rows in Package because currently the models allow duplicates - # (see issue #28). - self.assertEqual(5, Package.objects.count()) - - self.assertTrue(Package.objects.filter(name='mimetex')) - - pkg = Package.objects.get(name='librsync') - self.assertEqual('0.9.7-10', pkg.version) - self.assertEqual('deb', pkg.type) - self.assertEqual('debian', pkg.namespace) - self.assertIn('distro=jessie', pkg.qualifiers) - - def test_ImpactedPackage(self): - """ - Check that all impacted packages from the test data are stored in the database - """ - impacted_pkgs = ImpactedPackage.objects.all() - - self.assertEqual(1, impacted_pkgs.count()) - - ip = impacted_pkgs[0] - self.assertEqual('librsync', ip.package.name) - self.assertEqual('0.9.7-10', ip.package.version) - - def test_ResolvedPackage(self): - """ - Check that all resolved packages from the test data are stored in the database - """ - resolved_pkgs = ResolvedPackage.objects.all() - versions = [rp.package.version for rp in resolved_pkgs] - - self.assertEqual(4, resolved_pkgs.count()) - self.assertEqual('mimetex', resolved_pkgs[0].package.name) - self.assertIn('1.50-1.1', versions) - self.assertIn('1.74-1', versions) - - -class TestUbuntuDataDump(TestCase): - @classmethod - def setUpTestData(cls): - with open(os.path.join(TEST_DATA, 'ubuntu_main.html')) as f: - test_data = f.read() - - data = ubuntu.extract_cves(test_data) - ubuntu_dump(data) - - def test_data_dump(self): - """ - Check basic data import - """ - self.assertTrue(Vulnerability.objects.filter(cve_id='CVE-2002-2439')) - pkgs = Package.objects.filter(name='gcc-4.6') - self.assertTrue(pkgs) - - pkg = pkgs[0] - self.assertEqual('deb', pkg.type) - self.assertEqual('ubuntu', pkg.namespace) - - -class TestArchLinuxDataDump(TestCase): - - CVE_IDS = ('CVE-2018-11362', 'CVE-2018-11361', 'CVE-2018-11360', - 'CVE-2018-11359', 'CVE-2018-11358', 'CVE-2018-11357', - 'CVE-2018-11356', 'CVE-2018-11355', 'CVE-2018-11354') - - @classmethod - def setUpTestData(cls): - with open(os.path.join(TEST_DATA, 'archlinux.json')) as f: - test_data = json.load(f) - - archlinux_dump(test_data) - - def test_Vulnerability(self): - """ - Check that all vulnerabilities from the test data are stored in the database - """ - self.assertEqual(len(self.CVE_IDS), Vulnerability.objects.count()) - - for cve_id in self.CVE_IDS: - self.assertTrue(Vulnerability.objects.filter(cve_id=cve_id)) - - def test_VulnerabilityReference(self): - """ - Check that all vulnerability references from the test data are stored in the database - """ - for ref in ('ASA-201805-22', 'ASA-201805-23', 'ASA-201805-24', 'ASA-201805-25', 'AVG-708'): - self.assertEqual( - len(self.CVE_IDS), - VulnerabilityReference.objects.filter(reference_id=ref).count() +def test_debian_Vulnerability(setDebianData): + """ + Check that all vulnerabilities from the test data are stored in the database + """ + assert 3 == Vulnerability.objects.count() + + assert Vulnerability.objects.filter(cve_id='CVE-2009-1382') + assert Vulnerability.objects.filter(cve_id='CVE-2009-2459') + assert Vulnerability.objects.filter(cve_id='CVE-2014-8242') + + +def test_debian_VulnerabilityReference(setDebianData): + """ + Check that no vulnerability references were found in the test data + """ + assert 0 == VulnerabilityReference.objects.count() + + +def test_debian_Package(setDebianData): + """ + Check that all packages from the test data are stored in the database + """ + # There are five rows in Package because currently the models allow duplicates + # (see issue #28). + assert 5 == Package.objects.count() + + assert Package.objects.filter(name='mimetex') + + pkg = Package.objects.get(name='librsync') + assert '0.9.7-10' == pkg.version + assert 'deb' == pkg.type + assert 'debian' == pkg.namespace + assert 'distro=jessie' in pkg.qualifiers + + +def test_debian_ImpactedPackage(setDebianData): + """ + Check that all impacted packages from the test data are stored in the database + """ + impacted_pkgs = ImpactedPackage.objects.all() + + assert 1 == impacted_pkgs.count() + + ip = impacted_pkgs[0] + assert 'librsync' == ip.package.name + assert '0.9.7-10' == ip.package.version + + +def test_debian_ResolvedPackage(setDebianData): + """ + Check that all resolved packages from the test data are stored in the database + """ + resolved_pkgs = ResolvedPackage.objects.all() + versions = [rp.package.version for rp in resolved_pkgs] + + assert 4 == resolved_pkgs.count() + assert 'mimetex' == resolved_pkgs[0].package.name + assert '1.50-1.1' in versions + assert '1.74-1' in versions + + +def test_ubuntu_data_dump(setUbuntuData): + """ + Check basic data import + """ + assert Vulnerability.objects.filter(cve_id='CVE-2002-2439') + pkgs = Package.objects.filter(name='gcc-4.6') + assert pkgs + + pkg = pkgs[0] + assert 'deb' == pkg.type + assert 'ubuntu' == pkg.namespace + + +CVE_IDS = ('CVE-2018-11362', 'CVE-2018-11361', 'CVE-2018-11360', + 'CVE-2018-11359', 'CVE-2018-11358', 'CVE-2018-11357', + 'CVE-2018-11356', 'CVE-2018-11355', 'CVE-2018-11354') + + +def test_arch_Vulnerability(setArchLinuxData): + """ + Check that all vulnerabilities from the test data are stored in the database + """ + assert len(CVE_IDS) == Vulnerability.objects.count() + + for cve_id in CVE_IDS: + assert Vulnerability.objects.filter(cve_id=cve_id) + + +def test_arch_VulnerabilityReference(setArchLinuxData): + """ + Check that all vulnerability references from the test data are stored in the database + """ + for ref in ('ASA-201805-22', 'ASA-201805-23', 'ASA-201805-24', 'ASA-201805-25', 'AVG-708'): + assert len(CVE_IDS) == VulnerabilityReference.objects.filter( + reference_id=ref).count() + + for ref in CVE_IDS: + url = f'https://security.archlinux.org/{ref}' + assert 1 == VulnerabilityReference.objects.filter(url=url).count() + + +def test_arch_Package(setArchLinuxData): + """ + Check that all packages from the test data are stored in the database + """ + assert 8 == Package.objects.count() + + for pkg in ('wireshark-common', 'wireshark-gtk', 'wireshark-cli', 'wireshark-qt'): + for ver in ('2.6.0-1', '2.6.1-1'): + assert Package.objects.filter(name=pkg, version=ver) + + for pkg in Package.objects.filter(name='wireshark-cli'): + assert 'pacman' == pkg.type + assert 'archlinux' == pkg.namespace + + +def test_arch_PackageReference(setArchLinuxData): + """ + Check that no package references were found in the test data + """ + assert 0 == PackageReference.objects.count() + + +def test_arch_ImpactedPackage(setArchLinuxData): + """ + Check there is one ImpactedPackage for the number of packages + with the affected version number, times the number of vulnerabilities + """ + packages = Package.objects.filter(version='2.6.0-1') + vulnerabilities = Vulnerability.objects.all() + + impacted_pkgs_count = ImpactedPackage.objects.count() + expected_count = packages.count() * vulnerabilities.count() + + assert expected_count == impacted_pkgs_count + + for pkg in packages: + for vuln in vulnerabilities: + assert ImpactedPackage.objects.filter( + package=pkg, + vulnerability=vuln, ) - for ref in self.CVE_IDS: - url = f'https://security.archlinux.org/{ref}' - self.assertEqual(1, VulnerabilityReference.objects.filter(url=url).count()) - - def test_Package(self): - """ - Check that all packages from the test data are stored in the database - """ - self.assertEqual(8, Package.objects.count()) - - for pkg in ('wireshark-common', 'wireshark-gtk', 'wireshark-cli', 'wireshark-qt'): - for ver in ('2.6.0-1', '2.6.1-1'): - self.assertTrue(Package.objects.filter(name=pkg, version=ver)) - - for pkg in Package.objects.filter(name='wireshark-cli'): - self.assertEqual('pacman', pkg.type) - self.assertEqual('archlinux', pkg.namespace) - - def test_PackageReference(self): - """ - Check that no package references were found in the test data - """ - self.assertEqual(0, PackageReference.objects.count()) - - def test_ImpactedPackage(self): - """ - Check there is one ImpactedPackage for the number of packages - with the affected version number, times the number of vulnerabilities - """ - packages = Package.objects.filter(version='2.6.0-1') - vulnerabilities = Vulnerability.objects.all() - - impacted_pkgs_count = ImpactedPackage.objects.count() - expected_count = packages.count() * vulnerabilities.count() - - self.assertEqual(expected_count, impacted_pkgs_count) - - for pkg in packages: - for vuln in vulnerabilities: - self.assertTrue(ImpactedPackage.objects.filter( - package=pkg, - vulnerability=vuln, - )) - - def test_ResolvedPackage(self): - """ - Check there is one ResolvedPackage for the number of packages - with the fixed version number, times the number of vulnerabilities - """ - packages = Package.objects.filter(version='2.6.1-1') - vulnerabilities = Vulnerability.objects.all() - - resolved_pkgs_count = ResolvedPackage.objects.count() - expected_count = packages.count() * vulnerabilities.count() - - self.assertEqual(expected_count, resolved_pkgs_count) - - for pkg in packages: - for vuln in vulnerabilities: - self.assertTrue(ResolvedPackage.objects.filter( - package=pkg, - vulnerability=vuln, - )) + +def test_arch_ResolvedPackage(setArchLinuxData): + """ + Check there is one ResolvedPackage for the number of packages + with the fixed version number, times the number of vulnerabilities + """ + packages = Package.objects.filter(version='2.6.1-1') + vulnerabilities = Vulnerability.objects.all() + + resolved_pkgs_count = ResolvedPackage.objects.count() + expected_count = packages.count() * vulnerabilities.count() + + assert expected_count == resolved_pkgs_count + + for pkg in packages: + for vuln in vulnerabilities: + assert ResolvedPackage.objects.filter( + package=pkg, + vulnerability=vuln, + ) diff --git a/vulnerabilities/tests/test_import_cli.py b/vulnerabilities/tests/test_import_cli.py index fdc5afeda..1f2c5dabc 100644 --- a/vulnerabilities/tests/test_import_cli.py +++ b/vulnerabilities/tests/test_import_cli.py @@ -1,4 +1,3 @@ -# # Copyright (c) 2017 nexB Inc. and others. All rights reserved. # http://nexb.com and https://github.com/nexB/vulnerablecode/ # The VulnerableCode software is licensed under the Apache License version 2.0. @@ -21,37 +20,40 @@ # VulnerableCode is a free software code scanning tool from nexB Inc. and others. # Visit https://github.com/nexB/vulnerablecode/ for support and download. + +import pytest from io import StringIO from django.core.management import call_command from django.core.management.base import CommandError -from django.test import TestCase -class ImportCommandTest(TestCase): - def test_list_sources(self): - buf = StringIO() +def test_list_sources(): + + buf = StringIO() + call_command('import', '--list', stdout=buf) + out = buf.getvalue() + assert 'npm' in out + assert 'debian' in out + assert 'ubuntu' in out + assert 'archlinux' in out + + +def test_missing_sources(): - call_command('import', '--list', stdout=buf) + with pytest.raises(CommandError) as cm: + call_command('import', stdout=StringIO()) - out = buf.getvalue() - self.assertIn('npm', out) - self.assertIn('debian', out) - self.assertIn('ubuntu', out) - self.assertIn('archlinux', out) + err = str(cm) + assert 'Please provide at least one data source' in err - def test_missing_sources(self): - with self.assertRaises(CommandError) as cm: - call_command('import', stdout=StringIO()) - err = str(cm.exception) - self.assertIn('Please provide at least one data source', err) +def test_unknown_sources(): - def test_unknown_sources(self): - with self.assertRaises(CommandError) as cm: - call_command('import', 'debian', 'foo', 'bar', stdout=StringIO()) + with pytest.raises(CommandError) as cm: + call_command('import', 'debian', 'foo', 'bar', stdout=StringIO()) - err = str(cm.exception) - self.assertIn('bar', err) - self.assertIn('foo', err) - self.assertNotIn('debian', err) + err = str(cm) + assert 'bar' in err + assert 'foo' in err + assert 'debian' not in err diff --git a/vulnerabilities/tests/test_models.py b/vulnerabilities/tests/test_models.py index 912186003..f66ac6ef5 100644 --- a/vulnerabilities/tests/test_models.py +++ b/vulnerabilities/tests/test_models.py @@ -21,7 +21,7 @@ # VulnerableCode is a free software code scanning tool from nexB Inc. and others. # Visit https://github.com/nexB/vulnerablecode/ for support and download. -from django.test import TestCase +import pytest from vulnerabilities.models import Vulnerability from vulnerabilities.models import VulnerabilityReference @@ -29,53 +29,49 @@ from vulnerabilities.models import PackageReference -class TestVulnerability(TestCase): - def test_vulnerability(self): - Vulnerability.objects.create( - summary="Affected package xyz", - cvss="7.8" - ) +def test_vulnerability(db): + Vulnerability.objects.create( + summary="Affected package xyz", + cvss="7.8" + ) - self.assertTrue(Vulnerability.objects.get(summary="Affected package xyz")) - self.assertTrue(Vulnerability.objects.get(cvss="7.8")) + assert Vulnerability.objects.get(summary="Affected package xyz") + assert Vulnerability.objects.get(cvss="7.8") -class TestVulnerabilityReference(TestCase): - def test_vulnerability_reference(self): - VulnerabilityReference.objects.create( - vulnerability=Vulnerability.objects.create(summary="XYZ"), - reference_id="CVE-2017-8564", - source="NVD", - url="http://mitre.com" - ) +def test_vulnerability_reference(db): + VulnerabilityReference.objects.create( + vulnerability=Vulnerability.objects.create(summary="XYZ"), + reference_id="CVE-2017-8564", + source="NVD", + url="http://mitre.com" + ) - self.assertTrue(VulnerabilityReference.objects.get(reference_id="CVE-2017-8564")) - self.assertTrue(VulnerabilityReference.objects.get(source="NVD")) - self.assertTrue(VulnerabilityReference.objects.get(url="http://mitre.com")) + assert VulnerabilityReference.objects.get(reference_id="CVE-2017-8564") + assert VulnerabilityReference.objects.get(source="NVD") + assert VulnerabilityReference.objects.get(url="http://mitre.com") -class TestPackage(TestCase): - def test_package(self): - Package.objects.create( - name="Firefox", - version="1.5.4" - ) +def test_package(db): + Package.objects.create( + name="Firefox", + version="1.5.4" + ) - self.assertTrue(Package.objects.get(name="Firefox")) - self.assertTrue(Package.objects.get(version="1.5.4")) + assert Package.objects.get(name="Firefox") + assert Package.objects.get(version="1.5.4") -class TestPackageReference(TestCase): - def test_package_reference(self): - PackageReference.objects.create( - package=Package.objects.create(name="Iceweasel"), - platform="Maven", - repository="http://central.maven.org", - name="org.apache.commons.io", - version="7.6.5" - ) +def test_package_reference(db): + PackageReference.objects.create( + package=Package.objects.create(name="Iceweasel"), + platform="Maven", + repository="http://central.maven.org", + name="org.apache.commons.io", + version="7.6.5" + ) - self.assertTrue(PackageReference.objects.get(platform="Maven")) - self.assertTrue(PackageReference.objects.get(repository="http://central.maven.org")) - self.assertTrue(PackageReference.objects.get(name="org.apache.commons.io")) - self.assertTrue(PackageReference.objects.get(version="7.6.5")) + assert PackageReference.objects.get(platform="Maven") + assert PackageReference.objects.get(repository="http://central.maven.org") + assert PackageReference.objects.get(name="org.apache.commons.io") + assert PackageReference.objects.get(version="7.6.5") diff --git a/vulnerabilities/tests/test_npm.py b/vulnerabilities/tests/test_npm.py index facfe41ca..2eb2644cc 100644 --- a/vulnerabilities/tests/test_npm.py +++ b/vulnerabilities/tests/test_npm.py @@ -24,7 +24,6 @@ import os import json -from django.test import TestCase from vulnerabilities.scraper.npm import extract_data from vulnerabilities.scraper.npm import get_all_versions @@ -34,83 +33,84 @@ TEST_DATA = os.path.join(BASE_DIR, 'test_data/') -class NPMScrapperTest(TestCase): - def test_remove_space(self): - res = remove_spaces(">= 1.2.1 || <= 2.1.1") - self.assertEqual(res, '>=1.2.1 || <=2.1.1') +def test_remove_space(): + res = remove_spaces(">= 1.2.1 || <= 2.1.1") + assert res == '>=1.2.1 || <=2.1.1' - res = remove_spaces(">= v1.2.1 || <= V2.1.1") - self.assertEqual(res, '>=1.2.1 || <=2.1.1') + res = remove_spaces(">= v1.2.1 || <= V2.1.1") + assert res == '>=1.2.1 || <=2.1.1' - def test_get_all_versions(self): - x = get_all_versions('electron') - expected = ['0.1.2', '2.0.0', '3.0.0', - '4.0.0', '5.0.0', '6.0.0', '7.0.0'] - self.assertTrue(set(expected) <= set(x)) - def test_extract_data(self): - with open(os.path.join(TEST_DATA, 'npm_test.json')) as f: - test_data = json.load(f) +def test_get_all_versions(): + x = get_all_versions('electron') + expected = ['0.1.2', '2.0.0', '3.0.0', + '4.0.0', '5.0.0', '6.0.0', '7.0.0'] + assert set(expected) <= set(x) - expected = { - 'package_name': 'hapi', - 'cve_ids': ['CVE-2014-4671'], - 'fixed_versions': [ - '6.1.0', '6.2.0', '6.2.1', '6.2.2', '6.3.0', '6.4.0', - '6.5.0', '6.5.1', '6.6.0', '6.7.0', '6.7.1', '6.8.0', - '6.8.1', '6.9.0', '6.10.0', '6.11.0', '6.11.1', '7.0.0', - '7.0.1', '7.1.0', '7.1.1', '7.2.0', '7.3.0', '7.4.0', - '7.5.0', '7.5.1', '7.5.2', '8.0.0', '7.5.3', '8.1.0', - '8.2.0', '8.3.0', '8.3.1', '8.4.0', '8.5.0', '8.5.1', - '8.5.2', '8.5.3', '8.6.0', '8.6.1', '8.8.0', '8.8.1', - '9.0.0', '9.0.1', '9.0.2', '9.0.3', '9.0.4', '9.1.0', - '9.2.0', '9.3.0', '9.3.1', '10.0.0', '10.0.1', '10.1.0', - '10.2.1', '10.4.0', '10.4.1', '10.5.0', '11.0.0', '11.0.1', - '11.0.2', '11.0.3', '11.0.4', '11.0.5', '11.1.0', '11.1.1', - '11.1.2', '11.1.3', '11.1.4', '12.0.0', '12.0.1', '12.1.0', - '9.5.1', '13.0.0', '13.1.0', '13.2.0', '13.2.1', '13.2.2', - '13.3.0', '13.4.0', '13.4.1', '13.4.2', '13.5.0', '14.0.0', - '13.5.3', '14.1.0', '14.2.0', '15.0.1', '15.0.2', '15.0.3', - '15.1.0', '15.1.1', '15.2.0', '16.0.0', '16.0.1', '16.0.2', - '16.0.3', '16.1.0', '16.1.1', '16.2.0', '16.3.0', '16.3.1', - '16.4.0', '16.4.1', '16.4.2', '16.4.3', '16.5.0', '16.5.1', - '16.5.2', '16.6.0', '16.6.1', '16.6.2', '17.0.0', '17.0.1', - '17.0.2', '17.1.0', '17.1.1', '17.2.0', '17.2.1', '16.6.3', - '17.2.2', '17.2.3', '17.3.0', '17.3.1', '17.4.0', '17.5.0', - '17.5.1', '17.5.2', '17.5.3', '17.5.4', '17.5.5', '17.6.0', - '17.6.1', '17.6.2', '17.6.3', '16.6.4', '17.6.4', '16.6.5', - '17.7.0', '16.7.0', '17.8.0', '17.8.1', '18.0.0', '17.8.2', - '17.8.3', '18.0.1', '17.8.4', '18.1.0', '17.8.5'], - 'affected_versions': [ - '0.0.1', '0.0.2', '0.0.3', '0.0.4', '0.0.5', '0.0.6', '0.1.0', - '0.1.1', '0.1.2', '0.1.3', '0.2.0', '0.2.1', '0.3.0', '0.4.0', - '0.4.1', '0.4.2', '0.4.3', '0.4.4', '0.5.0', '0.5.1', '0.6.0', - '0.6.1', '0.5.2', '0.7.0', '0.7.1', '0.8.0', '0.8.1', '0.8.2', - '0.8.3', '0.8.4', '0.9.0', '0.9.1', '0.9.2', '0.10.0', '0.10.1', - '0.11.0', '0.11.1', '0.11.2', '0.11.3', '0.12.0', '0.13.0', - '0.13.1', '0.13.2', '0.11.4', '0.13.3', '0.14.0', '0.14.1', - '0.14.2', '0.15.0', '0.15.1', '0.15.2', '0.15.3', '0.15.4', - '0.15.5', '0.15.6', '0.15.7', '0.15.8', '0.15.9', '0.16.0', - '1.0.0', '1.0.1', '1.0.2', '1.0.3', '1.1.0', '1.2.0', '1.3.0', - '1.4.0', '1.5.0', '1.6.0', '1.6.1', '1.6.2', '1.7.0', '1.7.1', - '1.7.2', '1.7.3', '1.8.0', '1.8.1', '1.8.2', '1.8.3', '1.9.0', - '1.9.1', '1.9.2', '1.9.3', '1.9.4', '1.9.5', '1.9.6', '1.9.7', - '1.10.0', '1.11.0', '1.11.1', '1.12.0', '1.13.0', '1.14.0', - '1.15.0', '1.16.0', '1.16.1', '1.17.0', '1.18.0', '1.19.0', - '1.19.1', '1.19.2', '1.19.3', '1.19.4', '1.19.5', '1.20.0', - '2.0.0', '2.1.0', '2.1.1', '2.1.2', '2.2.0', '2.3.0', '2.4.0', - '2.5.0', '2.6.0', '3.0.0', '3.0.1', '3.0.2', '3.1.0', '4.0.0', - '4.0.1', '4.0.2', '4.0.3', '4.1.0', '4.1.1', '4.1.2', '4.1.3', - '4.1.4', '5.0.0', '5.1.0', '6.0.0', '6.0.1', '6.0.2'], - 'severity': 'moderate' - } - got = extract_data(test_data)[0] - # Check if expected affected version and fixed version is subset of what we get from online - self.assertTrue(set(expected['fixed_versions']) - <= set(got['fixed_versions'])) - self.assertTrue(set(expected['affected_versions']) <= set( - got['affected_versions'])) - self.assertEqual(expected['package_name'], got['package_name']) - self.assertEqual(expected['severity'], got['severity']) - self.assertEqual(expected['cve_ids'], got['cve_ids']) +def test_extract_data(): + with open(os.path.join(TEST_DATA, 'npm_test.json')) as f: + test_data = json.load(f) + + expected = { + 'package_name': 'hapi', + 'cve_ids': ['CVE-2014-4671'], + 'fixed_versions': [ + '6.1.0', '6.2.0', '6.2.1', '6.2.2', '6.3.0', '6.4.0', + '6.5.0', '6.5.1', '6.6.0', '6.7.0', '6.7.1', '6.8.0', + '6.8.1', '6.9.0', '6.10.0', '6.11.0', '6.11.1', '7.0.0', + '7.0.1', '7.1.0', '7.1.1', '7.2.0', '7.3.0', '7.4.0', + '7.5.0', '7.5.1', '7.5.2', '8.0.0', '7.5.3', '8.1.0', + '8.2.0', '8.3.0', '8.3.1', '8.4.0', '8.5.0', '8.5.1', + '8.5.2', '8.5.3', '8.6.0', '8.6.1', '8.8.0', '8.8.1', + '9.0.0', '9.0.1', '9.0.2', '9.0.3', '9.0.4', '9.1.0', + '9.2.0', '9.3.0', '9.3.1', '10.0.0', '10.0.1', '10.1.0', + '10.2.1', '10.4.0', '10.4.1', '10.5.0', '11.0.0', '11.0.1', + '11.0.2', '11.0.3', '11.0.4', '11.0.5', '11.1.0', '11.1.1', + '11.1.2', '11.1.3', '11.1.4', '12.0.0', '12.0.1', '12.1.0', + '9.5.1', '13.0.0', '13.1.0', '13.2.0', '13.2.1', '13.2.2', + '13.3.0', '13.4.0', '13.4.1', '13.4.2', '13.5.0', '14.0.0', + '13.5.3', '14.1.0', '14.2.0', '15.0.1', '15.0.2', '15.0.3', + '15.1.0', '15.1.1', '15.2.0', '16.0.0', '16.0.1', '16.0.2', + '16.0.3', '16.1.0', '16.1.1', '16.2.0', '16.3.0', '16.3.1', + '16.4.0', '16.4.1', '16.4.2', '16.4.3', '16.5.0', '16.5.1', + '16.5.2', '16.6.0', '16.6.1', '16.6.2', '17.0.0', '17.0.1', + '17.0.2', '17.1.0', '17.1.1', '17.2.0', '17.2.1', '16.6.3', + '17.2.2', '17.2.3', '17.3.0', '17.3.1', '17.4.0', '17.5.0', + '17.5.1', '17.5.2', '17.5.3', '17.5.4', '17.5.5', '17.6.0', + '17.6.1', '17.6.2', '17.6.3', '16.6.4', '17.6.4', '16.6.5', + '17.7.0', '16.7.0', '17.8.0', '17.8.1', '18.0.0', '17.8.2', + '17.8.3', '18.0.1', '17.8.4', '18.1.0', '17.8.5'], + 'affected_versions': [ + '0.0.1', '0.0.2', '0.0.3', '0.0.4', '0.0.5', '0.0.6', '0.1.0', + '0.1.1', '0.1.2', '0.1.3', '0.2.0', '0.2.1', '0.3.0', '0.4.0', + '0.4.1', '0.4.2', '0.4.3', '0.4.4', '0.5.0', '0.5.1', '0.6.0', + '0.6.1', '0.5.2', '0.7.0', '0.7.1', '0.8.0', '0.8.1', '0.8.2', + '0.8.3', '0.8.4', '0.9.0', '0.9.1', '0.9.2', '0.10.0', '0.10.1', + '0.11.0', '0.11.1', '0.11.2', '0.11.3', '0.12.0', '0.13.0', + '0.13.1', '0.13.2', '0.11.4', '0.13.3', '0.14.0', '0.14.1', + '0.14.2', '0.15.0', '0.15.1', '0.15.2', '0.15.3', '0.15.4', + '0.15.5', '0.15.6', '0.15.7', '0.15.8', '0.15.9', '0.16.0', + '1.0.0', '1.0.1', '1.0.2', '1.0.3', '1.1.0', '1.2.0', '1.3.0', + '1.4.0', '1.5.0', '1.6.0', '1.6.1', '1.6.2', '1.7.0', '1.7.1', + '1.7.2', '1.7.3', '1.8.0', '1.8.1', '1.8.2', '1.8.3', '1.9.0', + '1.9.1', '1.9.2', '1.9.3', '1.9.4', '1.9.5', '1.9.6', '1.9.7', + '1.10.0', '1.11.0', '1.11.1', '1.12.0', '1.13.0', '1.14.0', + '1.15.0', '1.16.0', '1.16.1', '1.17.0', '1.18.0', '1.19.0', + '1.19.1', '1.19.2', '1.19.3', '1.19.4', '1.19.5', '1.20.0', + '2.0.0', '2.1.0', '2.1.1', '2.1.2', '2.2.0', '2.3.0', '2.4.0', + '2.5.0', '2.6.0', '3.0.0', '3.0.1', '3.0.2', '3.1.0', '4.0.0', + '4.0.1', '4.0.2', '4.0.3', '4.1.0', '4.1.1', '4.1.2', '4.1.3', + '4.1.4', '5.0.0', '5.1.0', '6.0.0', '6.0.1', '6.0.2'], + 'severity': 'moderate' + } + got = extract_data(test_data)[0] + # Check if expected affected version and fixed version is subset of what we get from online + assert set(expected['affected_versions']) <= set( + got['affected_versions']) + assert set(expected['fixed_versions']) <= set( + got['fixed_versions']) + + assert expected['package_name'] == got['package_name'] + assert expected['severity'] == got['severity'] + assert expected['cve_ids'] == got['cve_ids']