From 1c831f6b5afc6b29d869a4889519f368fc802a17 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 22 May 2020 23:20:54 +0200 Subject: [PATCH 01/42] Fix Python formatting in releng.models --- releng/models.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/releng/models.py b/releng/models.py index a9019792..60a70edc 100644 --- a/releng/models.py +++ b/releng/models.py @@ -23,8 +23,7 @@ class Release(models.Model): last_modified = models.DateTimeField(editable=False) available = models.BooleanField(default=True) info = models.TextField('Public information', blank=True) - torrent_data = models.TextField(blank=True, - help_text="base64-encoded torrent file") + torrent_data = models.TextField(blank=True, help_text="base64-encoded torrent file") class Meta: get_latest_by = 'release_date' @@ -79,7 +78,7 @@ def torrent(self): 'info_hash': None, } if 'creation date' in data: - created= datetime.utcfromtimestamp(data['creation date']) + created = datetime.utcfromtimestamp(data['creation date']) metadata['creation_date'] = created.replace(tzinfo=utc) if info: metadata['info_hash'] = hashlib.sha1(bencode(info)).hexdigest() From 1a16df1fd3da23e3a1acf70efdcc152819aec554 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 23 May 2020 01:23:55 +0200 Subject: [PATCH 02/42] Add PGP key to the Release model Add a pgp_key field to the Release model so we can display the PGP fingerprint of the used PGP key on the download page. --- releng/models.py | 3 +++ templates/public/download.html | 2 ++ 2 files changed, 5 insertions(+) diff --git a/releng/models.py b/releng/models.py index 60a70edc..aad75f11 100644 --- a/releng/models.py +++ b/releng/models.py @@ -11,6 +11,7 @@ from django.utils.safestring import mark_safe from main.utils import set_created_field, parse_markdown +from devel.fields import PGPKeyField class Release(models.Model): @@ -19,6 +20,8 @@ class Release(models.Model): kernel_version = models.CharField(max_length=50, blank=True) md5_sum = models.CharField('MD5 digest', max_length=32, blank=True) sha1_sum = models.CharField('SHA1 digest', max_length=40, blank=True) + pgp_key = PGPKeyField(max_length=40, verbose_name="PGP key fingerprint", null=True, blank=True, + help_text="consists of 40 hex digits; use `gpg --fingerprint`") created = models.DateTimeField(editable=False) last_modified = models.DateTimeField(editable=False) available = models.BooleanField(default=True) diff --git a/templates/public/download.html b/templates/public/download.html index 944fe96d..15c31a90 100644 --- a/templates/public/download.html +++ b/templates/public/download.html @@ -2,6 +2,7 @@ {% load cache %} {% load static %} {% load flags %} +{% load pgp %} {% block title %}Arch Linux - Downloads{% endblock %} @@ -98,6 +99,7 @@

Checksums

From 326b84ebc2ff97aa2d2f67bf6d0129eec847ce14 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 8 Mar 2019 21:54:22 +0100 Subject: [PATCH 03/42] mirrors: add conftest for mirrors --- mirrors/tests/conftest.py | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 mirrors/tests/conftest.py diff --git a/mirrors/tests/conftest.py b/mirrors/tests/conftest.py new file mode 100644 index 00000000..7e8077a5 --- /dev/null +++ b/mirrors/tests/conftest.py @@ -0,0 +1,47 @@ +import pytest + +from mirrors.models import CheckLocation, MirrorUrl, MirrorProtocol, Mirror + + +NAME = 'mirror1' +ADMIN_EMAIL = 'admin@archlinux.org' +HOSTNAME = 'archlinux.org' +SOURCE_IP = '127.0.0.1' +COUNTRY = 'DE' +PROTOCOL = 'https' +URL = '{}://{}'.format(PROTOCOL, HOSTNAME) + + +@pytest.fixture +def mirror(db, name=NAME, admin_email=ADMIN_EMAIL): + mirror = Mirror.objects.create(name=name, + admin_email=admin_email) + yield mirror + mirror.delete() + + +@pytest.fixture +def checklocation(db, hostname=HOSTNAME, source_ip=SOURCE_IP, country=COUNTRY): + checkloc = CheckLocation.objects.create(hostname=hostname, + source_ip=source_ip, + country=country) + yield checkloc + checkloc.delete() + + +@pytest.fixture +def mirrorprotocol(db, protocol=PROTOCOL): + mirror_protocol = MirrorProtocol.objects.create(protocol=protocol) + yield mirror_protocol + mirror_protocol.delete() + + +@pytest.fixture +def mirrorurl(db, mirror, mirrorprotocol, country=COUNTRY, + url=URL): + mirror_url = MirrorUrl.objects.create(url=url, + protocol=mirrorprotocol, + mirror=mirror, + country=country) + yield mirror_url + mirror_url.delete() From 407de3909ae106ab1f64228bec72015dc578583a Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 8 Mar 2019 21:55:07 +0100 Subject: [PATCH 04/42] mirrors: tests: convert test_models to pytest --- mirrors/tests/test_models.py | 92 ++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/mirrors/tests/test_models.py b/mirrors/tests/test_models.py index ea7345ec..58df0b59 100644 --- a/mirrors/tests/test_models.py +++ b/mirrors/tests/test_models.py @@ -1,70 +1,60 @@ -from django.test import TestCase +from mirrors.tests.conftest import NAME, HOSTNAME, PROTOCOL, URL -from mirrors.models import Mirror, CheckLocation -from mirrors.tests import create_mirror_url +def test_mirrorurl_address_families(mirrorurl): + assert not mirrorurl.address_families() is None -class MirrorUrlTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() +def test_mirrorurl_hostname(mirrorurl): + assert mirrorurl.hostname == HOSTNAME - def testAddressFamilies(self): - self.assertIsNotNone(self.mirror_url.address_families()) +def test_mirrorurl_get_absolute_url(mirrorurl): + absolute_url = mirrorurl.get_absolute_url() + expected = '/mirrors/%s/%d/' % (mirrorurl.mirror.name, mirrorurl.pk) + assert absolute_url == expected - def testHostname(self): - self.assertEqual(self.mirror_url.hostname, 'archlinux.org') +def test_mirrorurl_overview(client, mirrorurl): + response = client.get('/mirrors/') + assert response.status_code == 200 + assert mirrorurl.mirror.name in response.content.decode() - def testGetAbsoluteUrl(self): - absolute_url = self.mirror_url.get_absolute_url() - expected = '/mirrors/%s/%d/' % (self.mirror_url.mirror.name, self.mirror_url.pk) - self.assertEqual(absolute_url, expected) +def test_mirrorurl_get_full_url(mirrorurl): + assert 'mirrors/{}'.format(mirrorurl.mirror.name) in mirrorurl.get_full_url() - def test_mirror_overview(self): - response = self.client.get('/mirrors/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.mirror_url.mirror.name, response.content.decode()) +def test_mirror_url_clean(mirrorurl): + mirrorurl.clean() + # TOOD(jelle): this expects HOSTNAME to resolve, maybe mock + assert mirrorurl.has_ipv4 == True + assert mirrorurl.has_ipv6 == True - def testClean(self): - # TODO: add test for self.mirror_url.clean() - pass +def test_mirrorurl_repr(mirrorurl): + assert URL in repr(mirrorurl) - def tearDown(self): - self.mirror_url.delete() +def test_mirror_get_full_url(mirror): + assert mirror.get_absolute_url() in mirror.get_full_url() + assert 'http' in mirror.get_full_url('http') -class MirrorTest(TestCase): - def setUp(self): - self.mirror = Mirror.objects.create(name='mirror1', - admin_email='admin@archlinux.org') +def test_mirror_downstream(mirror): + assert list(mirror.downstream()) == [] - def tearDown(self): - self.mirror.delete() +def test_mirror_get_absolute_url(mirror): + absolute_url = mirror.get_absolute_url() + expected = '/mirrors/{}/'.format(mirror.name) + assert absolute_url == expected - def test_downstream(self): - self.assertEqual(list(self.mirror.downstream()), []) +def test_mirror_rer(mirror): + assert NAME in repr(mirror) - def test_get_absolute_url(self): - absolute_url = self.mirror.get_absolute_url() - expected = '/mirrors/{}/'.format(self.mirror.name) - self.assertEqual(absolute_url, expected) - def test_get_full_url(self): - self.assertIn(self.mirror.get_absolute_url(), self.mirror.get_full_url()) - self.assertIn('http', self.mirror.get_full_url('http')) +def test_checklocation_family(checklocation): + assert isinstance(checklocation.family, int) +def test_checklocation_ip_version(checklocation): + assert isinstance(checklocation.ip_version, int) -class CheckLocationTest(TestCase): - def setUp(self): - self.checkloc = CheckLocation.objects.create(hostname='arch.org', - source_ip='127.0.0.1', - country='US') +def test_checklocation_repr(checklocation): + assert HOSTNAME in repr(checklocation) - def tearDown(self): - self.checkloc.delete() - def test_family(self): - # TODO: mock socket.getaddrinfo in CheckLocation.family - self.assertIsInstance(self.checkloc.family, int) - - def test_ip_version(self): - self.assertIsInstance(self.checkloc.ip_version, int) +def test_mirrorprotocol_repr(mirrorprotocol): + assert PROTOCOL in repr(mirrorprotocol) From 7a13e2ecec0625da1e63cc112faef81e994e4c09 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 8 Mar 2019 21:56:42 +0100 Subject: [PATCH 05/42] mirrors: switch to pytest --- mirrors/tests/test_templatetags.py | 36 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/mirrors/tests/test_templatetags.py b/mirrors/tests/test_templatetags.py index ec9b61bd..453a4c5d 100644 --- a/mirrors/tests/test_templatetags.py +++ b/mirrors/tests/test_templatetags.py @@ -1,27 +1,27 @@ from datetime import timedelta -from django.test import SimpleTestCase - from mirrors.templatetags.mirror_status import duration, hours, percentage -class MirrorTemplateTagTest(SimpleTestCase): - def test_duration(self): - self.assertEqual(duration(None), u'') +def test_duration(): + assert duration(None) == '' + + assert duration(timedelta(hours=5)) == '5:00' + assert duration(timedelta(hours=5, seconds=61)) == '5:01' + + # Microseconds are skipped + assert duration(timedelta(microseconds=9999)) == '0:00' + - self.assertEqual(duration(timedelta(hours=5)), '5:00') - self.assertEqual(duration(timedelta(hours=5, seconds=61)), '5:01') - # Microseconds are skipped - self.assertEqual(duration(timedelta(microseconds=9999), ), '0:00') +def test_hours(): + assert hours(None) == '' - def test_hours(self): - self.assertEqual(hours(None), u'') + assert hours(timedelta(hours=5)) == '5 hours' + assert hours(timedelta(hours=1)) == '1 hour' + assert hours(timedelta(seconds=60*60)) == '1 hour' - self.assertEqual(hours(timedelta(hours=5)), '5 hours') - self.assertEqual(hours(timedelta(hours=1)), '1 hour') - self.assertEqual(hours(timedelta(seconds=60*60)), '1 hour') - def test_percentage(self): - self.assertEqual(percentage(None), u'') - self.assertEqual(percentage(10), '1000.0%') - self.assertEqual(percentage(10, 2), '1000.00%') +def test_percentage(): + assert percentage(None) == '' + assert percentage(10) == '1000.0%' + assert percentage(10, 2) == '1000.00%' From bb6a5f131b7570ada177d995dd347a73da0a7cea Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 8 Mar 2019 22:05:40 +0100 Subject: [PATCH 06/42] mirrors: tests: remove duplicate tests --- mirrors/tests/test_mirrorurl.py | 45 ++++++++++++++++----------------- mirrors/tests/test_models.py | 31 +---------------------- 2 files changed, 23 insertions(+), 53 deletions(-) diff --git a/mirrors/tests/test_mirrorurl.py b/mirrors/tests/test_mirrorurl.py index 4fe8f22a..836fbb80 100644 --- a/mirrors/tests/test_mirrorurl.py +++ b/mirrors/tests/test_mirrorurl.py @@ -1,31 +1,30 @@ -from django.test import TestCase +from mirrors.tests.conftest import HOSTNAME, URL -from mirrors.tests import create_mirror_url +def test_mirrorurl_address_families(mirrorurl): + assert not mirrorurl.address_families() is None -class MirrorUrlTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() +def test_mirrorurl_hostname(mirrorurl): + assert mirrorurl.hostname == HOSTNAME - def testAddressFamilies(self): - self.assertIsNotNone(self.mirror_url.address_families()) +def test_mirrorurl_get_absolute_url(mirrorurl): + absolute_url = mirrorurl.get_absolute_url() + expected = '/mirrors/%s/%d/' % (mirrorurl.mirror.name, mirrorurl.pk) + assert absolute_url == expected - def testHostname(self): - self.assertEqual(self.mirror_url.hostname, 'archlinux.org') +def test_mirrorurl_overview(client, mirrorurl): + response = client.get('/mirrors/') + assert response.status_code == 200 + assert mirrorurl.mirror.name in response.content.decode() - def testGetAbsoluteUrl(self): - absolute_url = self.mirror_url.get_absolute_url() - expected = '/mirrors/%s/%d/' % (self.mirror_url.mirror.name, self.mirror_url.pk) - self.assertEqual(absolute_url, expected) +def test_mirrorurl_get_full_url(mirrorurl): + assert 'mirrors/{}'.format(mirrorurl.mirror.name) in mirrorurl.get_full_url() - def test_mirror_overview(self): - response = self.client.get('/mirrors/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.mirror_url.mirror.name, response.content.decode()) +def test_mirror_url_clean(mirrorurl): + mirrorurl.clean() + # TOOD(jelle): this expects HOSTNAME to resolve, maybe mock + assert mirrorurl.has_ipv4 == True + assert mirrorurl.has_ipv6 == True - def testClean(self): - # TODO: add test for self.mirror_url.clean() - pass - - def tearDown(self): - self.mirror_url.delete() +def test_mirrorurl_repr(mirrorurl): + assert URL in repr(mirrorurl) diff --git a/mirrors/tests/test_models.py b/mirrors/tests/test_models.py index 58df0b59..3216eda2 100644 --- a/mirrors/tests/test_models.py +++ b/mirrors/tests/test_models.py @@ -1,33 +1,4 @@ -from mirrors.tests.conftest import NAME, HOSTNAME, PROTOCOL, URL - - -def test_mirrorurl_address_families(mirrorurl): - assert not mirrorurl.address_families() is None - -def test_mirrorurl_hostname(mirrorurl): - assert mirrorurl.hostname == HOSTNAME - -def test_mirrorurl_get_absolute_url(mirrorurl): - absolute_url = mirrorurl.get_absolute_url() - expected = '/mirrors/%s/%d/' % (mirrorurl.mirror.name, mirrorurl.pk) - assert absolute_url == expected - -def test_mirrorurl_overview(client, mirrorurl): - response = client.get('/mirrors/') - assert response.status_code == 200 - assert mirrorurl.mirror.name in response.content.decode() - -def test_mirrorurl_get_full_url(mirrorurl): - assert 'mirrors/{}'.format(mirrorurl.mirror.name) in mirrorurl.get_full_url() - -def test_mirror_url_clean(mirrorurl): - mirrorurl.clean() - # TOOD(jelle): this expects HOSTNAME to resolve, maybe mock - assert mirrorurl.has_ipv4 == True - assert mirrorurl.has_ipv6 == True - -def test_mirrorurl_repr(mirrorurl): - assert URL in repr(mirrorurl) +from mirrors.tests.conftest import NAME, HOSTNAME, PROTOCOL def test_mirror_get_full_url(mirror): From e5547f358864618fd7ae1561e06aea9279ac70fd Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 8 Mar 2019 22:23:26 +0100 Subject: [PATCH 07/42] mirrors: convert mirrorstatus to pytest --- mirrors/tests/test_mirrorstatus.py | 71 +++++++++++++++--------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/mirrors/tests/test_mirrorstatus.py b/mirrors/tests/test_mirrorstatus.py index 503ad280..58f9f6b3 100644 --- a/mirrors/tests/test_mirrorstatus.py +++ b/mirrors/tests/test_mirrorstatus.py @@ -1,49 +1,48 @@ -from django.test import TestCase +def test_mirror_status(db, client): + response = client.get('/mirrors/status/') + assert response.status_code == 200 -from mirrors.tests import create_mirror_url +def test_json_endpoint(client, settings, mirrorurl): + settings.CACHES = {'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}} + # Disables the cache_function's cache -class MirrorStatusTest(TestCase): - def test_status(self): - response = self.client.get('/mirrors/status/') - self.assertEqual(response.status_code, 200) + response = client.get('/mirrors/status/json/') + assert response.status_code == 200 + data = response.json() - def test_json_endpoint(self): - # Disables the cache_function's cache - with self.settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}): - response = self.client.get('/mirrors/status/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['urls'], []) + assert len(data['urls']) == 1 + mirror = data['urls'][0] + assert mirror['url'] == mirrorurl.url - mirror_url = create_mirror_url() - response = self.client.get('/mirrors/status/json/') - self.assertEqual(response.status_code, 200) - data = response.json() +def test_json_endpoint_empty(db, client, settings): + # Disables the cache_function's cache + settings.CACHES = {'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}} - self.assertEqual(len(data['urls']), 1) - mirror = data['urls'][0] - self.assertEqual(mirror['url'], mirror_url.url) + response = client.get('/mirrors/status/json/') + assert response.status_code == 200 + data = response.json() + assert data['urls'] == [] - mirror_url.delete() - def test_json_tier(self): - response = self.client.get('/mirrors/status/tier/99/json/') - self.assertEqual(response.status_code, 404) +def test_json_tier_not_found(db, client, settings): + response = client.get('/mirrors/status/tier/99/json/') + assert response.status_code == 404 - response = self.client.get('/mirrors/status/tier/1/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['urls'], []) - mirror_url = create_mirror_url() +def test_json_tier_empty_cache(db, client, settings): + response = client.get('/mirrors/status/tier/1/json/') + assert response.status_code == 200 + data = response.json() + assert data['urls'] == [] - # Disables the cache_function's cache - with self.settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}): - response = self.client.get('/mirrors/status/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertNotEqual(data['urls'], []) - mirror_url.delete() +def test_json_tier(client, settings, mirrorurl): + # Disables the cache_function's cache + settings.CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}} + + response = client.get('/mirrors/status/json/') + assert response.status_code == 200 + data = response.json() + assert data['urls'] != [] From 58cf8b1883ce2b7f698e6fc78f3ab44a8b16efb7 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 8 Mar 2019 22:38:18 +0100 Subject: [PATCH 08/42] mirrors: tests: port to pytest --- mirrors/tests/test_mirrors.py | 47 +++++++++++++++-------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/mirrors/tests/test_mirrors.py b/mirrors/tests/test_mirrors.py index 558f7ea5..ec5ab3d0 100644 --- a/mirrors/tests/test_mirrors.py +++ b/mirrors/tests/test_mirrors.py @@ -1,37 +1,30 @@ -from django.test import TestCase +def test_details_empty(db, client): + response = client.get('/mirrors/nothing/') + assert response.status_code == 404 -from mirrors.tests import create_mirror_url +def test_details(db, client, mirrorurl): + url = mirrorurl.mirror.get_absolute_url() -class MirrorTest(TestCase): + response = client.get(url) + assert response.status_code == 200 - def test_details(self): - response = self.client.get('/mirrors/nothing/') - self.assertEqual(response.status_code, 404) - mirror_url = create_mirror_url() - url = mirror_url.mirror.get_absolute_url() +def test_details_json_empty(db, client): + response = client.get('/mirrors/nothing/json/') + assert response.status_code == 404 - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - # FIXME: request as mirror admin +def test_details_json(db, client, mirrorurl): + url = mirrorurl.mirror.get_absolute_url() - def test_details_json(self): - response = self.client.get('/mirrors/nothing/json/') - self.assertEqual(response.status_code, 404) + response = client.get(url + 'json/') + assert response.status_code == 200 + data = response.json() + assert data['urls'] != [] - mirror_url = create_mirror_url() - url = mirror_url.mirror.get_absolute_url() - response = self.client.get(url + 'json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertNotEqual(data['urls'], []) - - def test_url_details(self): - mirror_url = create_mirror_url() - url = mirror_url.mirror.get_absolute_url() - - response = self.client.get(url + '{}/'.format(mirror_url.id)) - self.assertEqual(response.status_code, 200) +def test_url_details(db, client, mirrorurl): + url = mirrorurl.mirror.get_absolute_url() + response = client.get(url + '{}/'.format(mirrorurl.id)) + assert response.status_code == 200 From 591bcf486b3840a3846f6994c6fbbf304f74509c Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 8 Mar 2019 22:46:05 +0100 Subject: [PATCH 09/42] mirrors: tests: port to pytest --- mirrors/tests/test_mirrorresolv.py | 73 ++++++++++++++---------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/mirrors/tests/test_mirrorresolv.py b/mirrors/tests/test_mirrorresolv.py index eb7f3e32..e84838eb 100644 --- a/mirrors/tests/test_mirrorresolv.py +++ b/mirrors/tests/test_mirrorresolv.py @@ -1,44 +1,37 @@ from unittest import mock -from django.test import TestCase from django.core.management import call_command -from mirrors.tests import create_mirror_url - - -class MirrorCheckTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() - - def tearDown(self): - self.mirror_url.delete() - - @mock.patch('socket.getaddrinfo') - def test_ip4_ip6(self, getaddrinfo): - getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0)), (10, 1, 6, '', ('1a01:3f8:132:1d96::1', 0, 0, 0))] - call_command('mirrorresolv') - self.mirror_url.refresh_from_db() - self.assertEqual(self.mirror_url.has_ipv4, True) - self.assertEqual(self.mirror_url.has_ipv6, True) - - @mock.patch('socket.getaddrinfo') - def test_ip4_only(self, getaddrinfo): - getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0))] - call_command('mirrorresolv') - self.mirror_url.refresh_from_db() - self.assertEqual(self.mirror_url.has_ipv4, True) - self.assertEqual(self.mirror_url.has_ipv6, False) - - @mock.patch('socket.getaddrinfo') - def test_running_twice(self, getaddrinfo): - getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0)), (10, 1, 6, '', ('1a01:3f8:132:1d96::1', 0, 0, 0))] - - # Check if values changed - with mock.patch('mirrors.management.commands.mirrorresolv.logger') as logger: - call_command('mirrorresolv', '-v3') - self.assertEqual(logger.debug.call_count, 4) - - # running again does not change any values. - with mock.patch('mirrors.management.commands.mirrorresolv.logger') as logger: - call_command('mirrorresolv', '-v3') - self.assertEqual(logger.debug.call_count, 3) + +@mock.patch('socket.getaddrinfo') +def test_ip4_ip6(getaddrinfo, db, mirrorurl): + getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0)), (10, 1, 6, '', ('1a01:3f8:132:1d96::1', 0, 0, 0))] + call_command('mirrorresolv') + mirrorurl.refresh_from_db() + + assert mirrorurl.has_ipv4 == True + assert mirrorurl.has_ipv6 == True + + +@mock.patch('socket.getaddrinfo') +def test_ip4_only(getaddrinfo, db, mirrorurl): + getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0))] + call_command('mirrorresolv') + mirrorurl.refresh_from_db() + + assert mirrorurl.has_ipv4 == True + assert mirrorurl.has_ipv6 == False + +@mock.patch('socket.getaddrinfo') +def test_running_twice(getaddrinfo, db, mirrorurl): + getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0)), (10, 1, 6, '', ('1a01:3f8:132:1d96::1', 0, 0, 0))] + + # Check if values changed + with mock.patch('mirrors.management.commands.mirrorresolv.logger') as logger: + call_command('mirrorresolv', '-v3') + assert logger.debug.call_count == 4 + + # running again does not change any values. + with mock.patch('mirrors.management.commands.mirrorresolv.logger') as logger: + call_command('mirrorresolv', '-v3') + assert logger.debug.call_count == 3 From 858322c86772c73cfc20582b1617ac9d1054d05b Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 12:35:48 +0100 Subject: [PATCH 10/42] mirrors: convert to pytest --- mirrors/tests/test_mirrorcheck.py | 264 ++++++++++++++---------------- 1 file changed, 123 insertions(+), 141 deletions(-) diff --git a/mirrors/tests/test_mirrorcheck.py b/mirrors/tests/test_mirrorcheck.py index c4a6450d..293dc41f 100644 --- a/mirrors/tests/test_mirrorcheck.py +++ b/mirrors/tests/test_mirrorcheck.py @@ -6,150 +6,132 @@ from ssl import CertificateError from socket import timeout, error +import pytest from django.utils.timezone import now from datetime import timedelta - -from django.test import TestCase from django.core.management import call_command - -from mirrors.tests import create_mirror_url -from mirrors.models import MirrorLog, CheckLocation - - -class MirrorCheckTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() - - def tearDown(self): - self.mirror_url.delete() - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_invalid(self, urlopen, Request): - urlopen.return_value.read.return_value = 'data' - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertNotEqual(mirrorlog.error, '') - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_valid(self, urlopen, Request): - urlopen.return_value.read.return_value = str(int(time.time())) - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertEqual(mirrorlog.error, '') - self.assertEqual(mirrorlog.is_success, True) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_valid_olddate(self, urlopen, Request): - urlopen.return_value.read.return_value = str(int(time.time())) - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - date = now() - timedelta(days=600) - MirrorLog.objects.create(url=self.mirror_url, check_time=date) - call_command('mirrorcheck') - self.assertEqual(len(MirrorLog.objects.all()), 1) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_not_found(self, urlopen, Request): - excp = HTTPError('https://archlinux.org/404.txt', 404, 'Not Found', '', None) - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertEqual(mirrorlog.error, str(excp)) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_not_found_variant(self, urlopen, Request): - excp = BadStatusLine('') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertIn('Exception in processing', mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_cert_error(self, urlopen, Request): - excp = CertificateError('certificate error') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertIn('certificate error', mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_general_httpexception(self, urlopen, Request): - excp = URLError('550 No such file', '550.txt') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertIn(excp.reason, mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_socket_timeout(self, urlopen, Request): - excp = timeout('timeout') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertEqual('Connection timed out.', mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_socket_error(self, urlopen, Request): - excp = error('error') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertEqual(str(excp), mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - def test_checklocation(self): - with self.assertRaises(CheckLocation.DoesNotExist) as e: - call_command('mirrorcheck', '-l', '1') - self.assertEqual('CheckLocation matching query does not exist.', str(e.exception)) - - def test_checklocation_model(self): - checkloc = CheckLocation.objects.create(hostname='archlinux.org', - source_ip='1.1.1.1') - with mock.patch('mirrors.management.commands.mirrorcheck.logger') as logger: - call_command('mirrorcheck', '-l', '1') - logger.info.assert_called() - - checkloc.delete() +from mirrors.models import CheckLocation, MirrorLog +from mirrors.tests.conftest import HOSTNAME, PROTOCOL + + +def mocked_request(urlopen, Request, return_value): + urlopen.return_value.read.return_value = return_value + Request.get_host.return_value = HOSTNAME + Request.type.return_value = PROTOCOL + + +def mocked_request_exception(urlopen, Request, excp): + urlopen.return_value.read.side_effect = excp + Request.get_host.return_value = HOSTNAME + Request.type.return_value = PROTOCOL + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_invalid(urlopen, Request, mirrorurl): + mocked_request(urlopen, Request, 'data') + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert mirrorlog.error != '' + assert mirrorlog.is_success == False + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_valid(urlopen, Request, mirrorurl): + mocked_request(urlopen, Request, str(int(time.time()))) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert mirrorlog.error == '' + assert mirrorlog.is_success == True + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_valid_olddate(urlopen, Request, mirrorurl): + mocked_request(urlopen, Request, str(int(time.time()))) + date = now() - timedelta(days=600) + MirrorLog.objects.create(url=mirrorurl, check_time=date) + call_command('mirrorcheck') + assert len(MirrorLog.objects.all()) == 1 + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_not_found(urlopen, Request, mirrorurl): + excp = HTTPError('https://archlinux.org/404.txt', 404, 'Not Found', '', None) + mocked_request_exception(urlopen, Request, excp) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert mirrorlog.error == str(excp) + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_not_found_variant(urlopen, Request, mirrorurl): + excp = BadStatusLine('') + mocked_request_exception(urlopen, Request, excp) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert 'Exception in processing' in mirrorlog.error + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_cert_error(urlopen, Request, mirrorurl): + excp = CertificateError('certificate error') + mocked_request_exception(urlopen, Request, excp) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert 'certificate error' in mirrorlog.error + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_general_httpexception(urlopen, Request, mirrorurl): + excp = URLError('550 No such file', '550.txt') + mocked_request_exception(urlopen, Request, excp) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert excp.reason in mirrorlog.error + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_socket_timeout(urlopen, Request, mirrorurl): + excp = timeout('timeout') + mocked_request_exception(urlopen, Request, excp) + + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert 'Connection timed out.' in mirrorlog.error + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_socket_error(urlopen, Request, mirrorurl): + excp = error('error') + mocked_request_exception(urlopen, Request, excp) + + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert str(excp) in mirrorlog.error + assert mirrorlog.is_success == False + + +def test_checklocation_fail(db): + with pytest.raises(CheckLocation.DoesNotExist) as e: + call_command('mirrorcheck', '-l', '1') + assert 'CheckLocation matching query does not exist.' == str(e.value) + +def test_checklocation_model(checklocation): + with mock.patch('mirrors.management.commands.mirrorcheck.logger') as logger: + call_command('mirrorcheck', '-l', '1') + logger.info.assert_called() From fca832f0b9594866c1b8f56295dba201420159f0 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 15:18:48 +0100 Subject: [PATCH 11/42] mirrors: convert to pytest --- mirrors/tests/conftest.py | 17 ++++ mirrors/tests/test_mirrorlist.py | 110 +++++++++++--------------- mirrors/tests/test_mirrorlocations.py | 27 +++---- 3 files changed, 73 insertions(+), 81 deletions(-) diff --git a/mirrors/tests/conftest.py b/mirrors/tests/conftest.py index 7e8077a5..72bf5947 100644 --- a/mirrors/tests/conftest.py +++ b/mirrors/tests/conftest.py @@ -45,3 +45,20 @@ def mirrorurl(db, mirror, mirrorprotocol, country=COUNTRY, country=country) yield mirror_url mirror_url.delete() + + +@pytest.fixture +def create_mirrorurl(db, mirror, mirrorprotocol): + mirrors = [] + def _create_mirrorurl(country=COUNTRY, url=URL): + mirror_url = MirrorUrl.objects.create(url=url, + protocol=mirrorprotocol, + mirror=mirror, + country=country) + mirrors.append(mirror_url) + return mirror_url + + yield _create_mirrorurl + + for mirror in mirrors: + mirror.delete() diff --git a/mirrors/tests/test_mirrorlist.py b/mirrors/tests/test_mirrorlist.py index abff0e97..b119195f 100644 --- a/mirrors/tests/test_mirrorlist.py +++ b/mirrors/tests/test_mirrorlist.py @@ -1,66 +1,50 @@ -from django.test import TestCase - -from mirrors.tests import create_mirror_url from mirrors.models import Mirror +# TODO(jelle): add test for https/rsync mirrors + + +def test_mirrorlist(client, mirrorurl): + response = client.get('/mirrorlist/') + assert response.status_code == 200 + + +def test_mirrorlist_tier_last(client, mirrorurl): + last_tier = Mirror.TIER_CHOICES[-1][0] + response = client.get('/mirrorlist/tier/{}/'.format(last_tier + 1)) + assert response.status_code == 404 + + +def test_mirrorlist_all(client, mirrorurl): + response = client.get('/mirrorlist/all/') + assert response.status_code == 200 + assert mirrorurl.hostname in response.content.decode() + + +def test_mirrorlist_all_https(client, mirrorurl): + response = client.get('/mirrorlist/all/https/') + assert response.status_code == 200 + assert mirrorurl.hostname in response.content.decode() + + +def test_mirrorlist_all_http(client, mirrorurl): + # First test that without any http mirrors, we get a 404. + response = client.get('/mirrorlist/all/http/') + assert response.status_code == 404 + + +def test_mirrorlist_status(client, mirrorurl): + response = client.get('/mirrorlist/?country=all&use_mirror_status=on') + assert response.status_code == 200 + + +def test_mirrorlist_filter(client, create_mirrorurl): + mirror1 = create_mirrorurl('JP', 'https://jp.org') + mirror2 = create_mirrorurl() + + # First test that we correctly see the above mirror. + response = client.get('/mirrorlist/?country=JP&protocol=https') + assert response.status_code == 200 + assert mirror1.hostname in response.content.decode() -class MirrorListTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() - - def tearDown(self): - self.mirror_url.delete() - - def test_mirrorlist(self): - response = self.client.get('/mirrorlist/') - self.assertEqual(response.status_code, 200) - - def test_mirrorlist_tier_last(self): - last_tier = Mirror.TIER_CHOICES[-1][0] - response = self.client.get('/mirrorlist/tier/{}/'.format(last_tier + 1)) - self.assertEqual(response.status_code, 404) - - def test_mirrorlist_all(self): - response = self.client.get('/mirrorlist/all/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.mirror_url.hostname, response.content.decode()) - - def test_mirrorlist_all_http(self): - response = self.client.get('/mirrorlist/all/http/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.mirror_url.hostname, response.content.decode()) - - def test_mirrorlist_all_https(self): - # First test that without any https mirrors, we get a 404. - response = self.client.get('/mirrorlist/all/https/') - self.assertEqual(response.status_code, 404) - - # Now, after adding an HTTPS mirror, we expect to succeed. - https_mirror_url = create_mirror_url( - name='https_mirror', - protocol='https', - url='https://wikipedia.org') - response = self.client.get('/mirrorlist/all/https/') - self.assertEqual(response.status_code, 200) - https_mirror_url.delete() - - def test_mirrorlist_filter(self): - jp_mirror_url = create_mirror_url( - name='jp_mirror', - country='JP', - protocol='https', - url='https://wikipedia.jp') - - # First test that we correctly see the above mirror. - response = self.client.get('/mirrorlist/?country=JP&protocol=https') - self.assertEqual(response.status_code, 200) - self.assertIn(jp_mirror_url.hostname, response.content.decode()) - - # Now confirm that the US mirror did not show up. - self.assertNotIn(self.mirror_url.hostname, response.content.decode()) - - jp_mirror_url.delete() - - def test_mirrorlist_status(self): - response = self.client.get('/mirrorlist/?country=all&use_mirror_status=on') - self.assertEqual(response.status_code, 200) + # Now confirm that the US mirror did not show up. + assert not mirror2.hostname in response.content.decode() diff --git a/mirrors/tests/test_mirrorlocations.py b/mirrors/tests/test_mirrorlocations.py index d065e2ef..576da0a7 100644 --- a/mirrors/tests/test_mirrorlocations.py +++ b/mirrors/tests/test_mirrorlocations.py @@ -1,18 +1,9 @@ -from django.test import TestCase - -from mirrors.models import CheckLocation - - -class MirrorLocationsTest(TestCase): - def setUp(self): - self.checklocation = CheckLocation.objects.create(hostname='arch.org', - source_ip='8.8.8.8', - country='US') - - def test_mirrorlocations_json(self): - response = self.client.get('/mirrors/locations/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(1, data['version']) - location = data['locations'][0]['country_code'] - self.assertEqual('US', location) +from mirrors.tests.conftest import COUNTRY + +def test_mirrorlocations_json(client, checklocation): + response = client.get('/mirrors/locations/json/') + assert response.status_code == 200 + data = response.json() + assert 1 == data['version'] + location = data['locations'][0]['country_code'] + assert COUNTRY == location From fce216ef334b7f8e6cf2738c08184894561167e5 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 15:21:44 +0100 Subject: [PATCH 12/42] Remove unrequired function --- mirrors/tests/__init__.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/mirrors/tests/__init__.py b/mirrors/tests/__init__.py index 4ea5e1fb..e69de29b 100644 --- a/mirrors/tests/__init__.py +++ b/mirrors/tests/__init__.py @@ -1,13 +0,0 @@ -from mirrors.models import MirrorUrl, MirrorProtocol, Mirror - - -def create_mirror_url(name='mirror1', country='US', - protocol='http', url='https://archlinux.org/'): - mirror = Mirror.objects.create(name=name, - admin_email='admin@archlinux.org') - mirror_protocol = MirrorProtocol.objects.create(protocol=protocol) - mirror_url = MirrorUrl.objects.create(url=url, - protocol=mirror_protocol, - mirror=mirror, - country=country) - return mirror_url From 14d5bfcceb6fce8cc2cbd1427343256baaa3df5f Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 15:22:18 +0100 Subject: [PATCH 13/42] mirrors: ipv6 does not exists everywhere :( --- mirrors/tests/test_mirrorurl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mirrors/tests/test_mirrorurl.py b/mirrors/tests/test_mirrorurl.py index 836fbb80..9af3fea6 100644 --- a/mirrors/tests/test_mirrorurl.py +++ b/mirrors/tests/test_mirrorurl.py @@ -24,7 +24,7 @@ def test_mirror_url_clean(mirrorurl): mirrorurl.clean() # TOOD(jelle): this expects HOSTNAME to resolve, maybe mock assert mirrorurl.has_ipv4 == True - assert mirrorurl.has_ipv6 == True + #assert mirrorurl.has_ipv6 == True def test_mirrorurl_repr(mirrorurl): assert URL in repr(mirrorurl) From 5855cda68bb3c0fd1cce019d60bb9c0081939049 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 15:39:08 +0100 Subject: [PATCH 14/42] releng: convert to pytest fixtures --- README.md | 1 - releng/fixtures/release.json | 17 ------------ releng/tests/conftest.py | 18 ++++++++++++ releng/tests/test_models.py | 42 ++++++++++++---------------- releng/tests/test_views.py | 53 +++++++++++++++--------------------- 5 files changed, 58 insertions(+), 73 deletions(-) delete mode 100644 releng/fixtures/release.json create mode 100644 releng/tests/conftest.py diff --git a/README.md b/README.md index 2f3c050a..611ae988 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,6 @@ packages, you will probably want the following: ./manage.py loaddata main/fixtures/*.json ./manage.py loaddata devel/fixtures/*.json ./manage.py loaddata mirrors/fixtures/*.json - ./manage.py loaddata releng/fixtures/*.json 6. Use the following commands to start a service instance diff --git a/releng/fixtures/release.json b/releng/fixtures/release.json deleted file mode 100644 index 94a4dd5e..00000000 --- a/releng/fixtures/release.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "fields": { - "available": true, - "created": "2017-06-07T19:36:49.569Z", - "info": "public information", - "kernel_version": "4.12", - "last_modified": "2017-06-11T16:53:53.723Z", - "md5_sum": "f029d6004e63464b1b26c62058c4e37e", - "release_date": "2017-06-11", - "sha1_sum": "2c2c8ce676e891ac354cf4a8bac3824a4aae0c90", - "version": "juni" - }, - "model": "releng.release", - "pk": 1 - } -] diff --git a/releng/tests/conftest.py b/releng/tests/conftest.py new file mode 100644 index 00000000..3731ab0f --- /dev/null +++ b/releng/tests/conftest.py @@ -0,0 +1,18 @@ +from datetime import datetime + +import pytest + +from releng.models import Release + + +VERSION = '1.0' +KERNEL_VERSION = '4.18' + + +@pytest.fixture +def release(db): + release = Release.objects.create(release_date=datetime.now(), + version=VERSION, + kernel_version=KERNEL_VERSION) + yield release + release.delete() diff --git a/releng/tests/test_models.py b/releng/tests/test_models.py index 0ed5f1fe..314e8e1f 100644 --- a/releng/tests/test_models.py +++ b/releng/tests/test_models.py @@ -1,34 +1,28 @@ -from django.test import TestCase +def test_feed(client, release): + response = client.get('/feeds/releases/') + assert response.status_code == 200 -from releng.models import Release +def test_absolute_url(release): + assert release.version in release.get_absolute_url() -class RelengTest(TestCase): - fixtures = ['releng/fixtures/release.json'] - def setUp(self): - self.release = Release.objects.first() +def test_iso_url(release): + url = release.iso_url() + ver = release.version + expected = 'iso/{}/archlinux-{}-x86_64.iso'.format(ver, ver) + assert url == expected - def test_feed(self): - response = self.client.get('/feeds/releases/') - self.assertEqual(response.status_code, 200) - def test_absolute_url(self): - self.assertIn(self.release.version, self.release.get_absolute_url()) +def test_info_html(release): + assert release.info in release.info_html() - def test_iso_url(self): - url = self.release.iso_url() - ver = self.release.version - expected = 'iso/{}/archlinux-{}-x86_64.iso'.format(ver, ver) - self.assertEqual(url, expected) - def test_info_html(self): - self.assertIn(self.release.info, self.release.info_html()) +def test_dir_path(release): + dir_path = u'iso/{}/'.format(release.version) + assert dir_path == release.dir_path() - def test_dir_path(self): - dir_path = u'iso/{}/'.format(self.release.version) - self.assertEqual(dir_path, self.release.dir_path()) - def test_sitemap(self): - response = self.client.get('/sitemap-releases.xml') - self.assertEqual(response.status_code, 200) +def test_sitemap(client, release): + response = client.get('/sitemap-releases.xml') + assert response.status_code == 200 diff --git a/releng/tests/test_views.py b/releng/tests/test_views.py index d6e5f59c..b18be30a 100644 --- a/releng/tests/test_views.py +++ b/releng/tests/test_views.py @@ -1,40 +1,31 @@ -from django.test import TestCase +def test_release_json(client, release): + version = release.version + response = client.get('/releng/releases/json/') + assert response.status_code == 200 -from releng.models import Release + data = response.json() + assert data['version'] == 1 + release = data['releases'][0] + assert release['version'] == version -class RelengViewTest(TestCase): - fixtures = ['releng/fixtures/release.json'] +def test_netboot_page(db, client): + response = client.get('/releng/netboot/') + assert response.status_code == 200 - def setUp(self): - self.release = Release.objects.first() - def test_release_json(self): - version = self.release.version - response = self.client.get('/releng/releases/json/') - self.assertEqual(response.status_code, 200) - data = response.json() +def test_netboot_config(db, client): + response = client.get('/releng/netboot/archlinux.ipxe') + assert response.status_code == 200 - self.assertEqual(data['version'], 1) - release = data['releases'][0] - self.assertEqual(release['version'], version) - def test_netboot_page(self): - response = self.client.get('/releng/netboot/') - self.assertEqual(response.status_code, 200) +def test_release_torrent_not_found(client, release): + # TODO: Add torrent data to release fixture + response = client.get('/releng/releases/{}/torrent/'.format(release.version)) + assert response.status_code == 404 - def test_netboot_config(self): - response = self.client.get('/releng/netboot/archlinux.ipxe') - self.assertEqual(response.status_code, 200) - def test_release_torrent_not_found(self): - # TODO: Add torrent data to release fixture - version = self.release.version - response = self.client.get('/releng/releases/{}/torrent/'.format(version)) - self.assertEqual(response.status_code, 404) - - def test_release_details(self): - version = self.release.version - response = self.client.get('/releng/releases/{}/'.format(version)) - self.assertEqual(response.status_code, 200) - self.assertIn(version, response.content.decode('utf-8')) +def test_release_details(client, release): + response = client.get('/releng/releases/{}/'.format(release.version)) + assert response.status_code == 200 + assert release.version in response.content.decode() From 2df95446d09cf8994f2f78c0c6651da9d7f99423 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 16:28:42 +0100 Subject: [PATCH 15/42] main: convert tests to pytest --- main/tests/test_donor_import.py | 107 ++++++++++++++------------ main/tests/test_templatetags_flags.py | 24 ++---- main/tests/test_templatetags_pgp.py | 106 +++++++++++++------------ 3 files changed, 114 insertions(+), 123 deletions(-) diff --git a/main/tests/test_donor_import.py b/main/tests/test_donor_import.py index 0f27eee7..97490fea 100644 --- a/main/tests/test_donor_import.py +++ b/main/tests/test_donor_import.py @@ -6,7 +6,8 @@ from tempfile import mkdtemp from shutil import rmtree -from django.test import TransactionTestCase +import pytest + from django.core.management import call_command from django.core.management.base import CommandError @@ -14,67 +15,71 @@ from main.management.commands.donor_import import Command -class DonorImportTest(TransactionTestCase): +command = Command() + + +def gen_parse_subject(data): + return command.parse_subject(valid.format(data)) + + +def test_parse_subject(): + assert command.parse_subject('garbage') is None + + # Valid + valid = 'Receipt [$25.00] By: John Doe [john.doe@archlinux.org]' + output = command.parse_subject(valid) + assert output == 'John Doe' + - def setUp(self): - self.command = Command() +def test_parse_name(): + assert command.sanitize_name('1244') == '' + assert command.sanitize_name('John Doe') == 'John Doe' + assert command.sanitize_name(' John Doe ') == 'John Doe' + assert command.sanitize_name('John Doe 23') == 'John Doe' - def gen_parse_subject(self, data): - return self.command.parse_subject(valid.format(data)) - def test_parse_subject(self): - self.assertIsNone(self.command.parse_subject('garbage')) +def test_decode_subject(): + text = u'メイル' + subject = Header(text, 'utf-8') + assert command.decode_subject(subject) == text - # Valid - valid = u'Receipt [$25.00] By: John Doe [john.doe@archlinux.org]' - output = self.command.parse_subject(valid) - self.assertEqual(output, u'John Doe') - def test_parse_name(self): - self.assertEqual(self.command.sanitize_name(u'1244'), u'') - self.assertEqual(self.command.sanitize_name(u'John Doe'), u'John Doe') - self.assertEqual(self.command.sanitize_name(u' John Doe '), u'John Doe') - self.assertEqual(self.command.sanitize_name(u'John Doe 23'), u'John Doe') +def test_invalid_args(): + with pytest.raises(CommandError) as e: + call_command('donor_import') + assert 'Error: the following arguments are required' in str(e.value) - def test_decode_subject(self): - text = u'メイル' - subject = Header(text, 'utf-8') - self.assertEqual(self.command.decode_subject(subject), text) - def test_invalid_args(self): - with self.assertRaises(CommandError) as e: - call_command('donor_import') - self.assertIn('Error: the following arguments are required', str(e.exception)) +def test_invalid_path(): + with pytest.raises(CommandError) as e: + call_command('donor_import', '/tmp/non-existant') + assert 'Failed to open maildir' in str(e.value) - def test_invalid_path(self): - with self.assertRaises(CommandError) as e: - call_command('donor_import', '/tmp/non-existant') - self.assertIn('Failed to open maildir', str(e.exception)) - def test_maildir(self): - tmpdir = mkdtemp('archweb') - mdir = tmpdir + '/maildir' +def test_maildir(db): + tmpdir = mkdtemp('archweb') + mdir = tmpdir + '/maildir' - maildir = Maildir(mdir) - msg = Message() - msg['subject'] = 'John Doe' - msg['to'] = 'John Doe ' - maildir.add(msg) + maildir = Maildir(mdir) + msg = Message() + msg['subject'] = 'John Doe' + msg['to'] = 'John Doe ' + maildir.add(msg) - # Invalid - call_command('donor_import', mdir) - self.assertEqual(len(Donor.objects.all()), 0) + # Invalid + call_command('donor_import', mdir) + assert len(Donor.objects.all()) == 0 - # Valid - msg = Message() - msg['subject'] = 'Receipt [$25.00] By: David Doe [david@doe.com]' - msg['to'] = 'John Doe ' - maildir.add(msg) - call_command('donor_import', mdir) - self.assertEqual(len(Donor.objects.all()), 1) + # Valid + msg = Message() + msg['subject'] = 'Receipt [$25.00] By: David Doe [david@doe.com]' + msg['to'] = 'John Doe ' + maildir.add(msg) + call_command('donor_import', mdir) + assert len(Donor.objects.all()) == 1 - # Re-running should result in no new donor - call_command('donor_import', mdir) - self.assertEqual(len(Donor.objects.all()), 1) + # Re-running should result in no new donor + call_command('donor_import', mdir) + assert len(Donor.objects.all()) == 1 - rmtree(tmpdir) + rmtree(tmpdir) diff --git a/main/tests/test_templatetags_flags.py b/main/tests/test_templatetags_flags.py index 7ff0406c..907fa8fa 100644 --- a/main/tests/test_templatetags_flags.py +++ b/main/tests/test_templatetags_flags.py @@ -1,22 +1,10 @@ -from django.test import TestCase - - from main.templatetags.flags import country_flag -from mirrors.models import CheckLocation - - -class FlagsTemplateTest(TestCase): - def setUp(self): - self.checkloc = CheckLocation.objects.create(hostname='arch.org', - source_ip='127.0.0.1', - country='US') +from mirrors.tests.conftest import checklocation - def tearDown(self): - self.checkloc.delete() - def test_country_flag(self): - flag = country_flag(self.checkloc.country) - self.assertIn(self.checkloc.country.name, flag) - self.assertIn(self.checkloc.country.code.lower(), flag) - self.assertEqual(country_flag(None), '') +def test_country_flag(checklocation): + flag = country_flag(checklocation.country) + assert checklocation.country.name in flag + assert checklocation.country.code.lower() in flag + assert country_flag(None) == '' diff --git a/main/tests/test_templatetags_pgp.py b/main/tests/test_templatetags_pgp.py index 39ace88b..c1dafc74 100644 --- a/main/tests/test_templatetags_pgp.py +++ b/main/tests/test_templatetags_pgp.py @@ -1,74 +1,72 @@ -from django.conf import settings -from django.test import TestCase - from main.templatetags.pgp import pgp_key_link, format_key, pgp_fingerprint -class PGPTemplateTest(TestCase): +def test_format_key(): + # 40 len case + pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + pgp_key_len = len(pgp_key) + + output = format_key(pgp_key) + spaces = output.count(' ') + output.count('\xa0') # nbsp + assert pgp_key_len + spaces == len(output) + # 21 - 39 len case + pgp_key = '3E2C81117BFB1108D234DAFZ' + pgp_key_len = len(pgp_key) + len('0x') + assert pgp_key_len == len(format_key(pgp_key)) - def test_format_key(self): - # 40 len case - pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - pgp_key_len = len(pgp_key) + # 8, 20 len case + pgp_key = '3E2C81117BFB1108DEFF' + pgp_key_len = len(pgp_key) + len('0x') + assert pgp_key_len == len(format_key(pgp_key)) - output = format_key(pgp_key) - spaces = output.count(' ') + output.count('\xa0') # nbsp - self.assertEqual(pgp_key_len + spaces, len(output)) + # 0 - 7 len case + pgp_key = 'B1108D' + pgp_key_len = len(pgp_key) + len('0x') + assert pgp_key_len == len(format_key(pgp_key)) - # 21 - 39 len case - pgp_key = '3E2C81117BFB1108D234DAFZ' - pgp_key_len = len(pgp_key) + len('0x') - self.assertEqual(pgp_key_len, len(format_key(pgp_key))) - # 8, 20 len case - pgp_key = '3E2C81117BFB1108DEFF' - pgp_key_len = len(pgp_key) + len('0x') - self.assertEqual(pgp_key_len, len(format_key(pgp_key))) +def assert_pgp_key_link(pgp_key): + output = pgp_key_link(int(pgp_key, 16)) + assert pgp_key[2:] in output + assert "https" in output - # 0 - 7 len case - pgp_key = 'B1108D' - pgp_key_len = len(pgp_key) + len('0x') - self.assertEqual(pgp_key_len, len(format_key(pgp_key))) - def assert_pgp_key_link(self, pgp_key): - output = pgp_key_link(int(pgp_key, 16)) - self.assertIn(pgp_key[2:], output) - self.assertIn("https", output) +def test_pgp_key_link(settings): + assert pgp_key_link("") == "Unknown" - def test_pgp_key_link(self): - self.assertEqual(pgp_key_link(""), "Unknown") + pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + output = pgp_key_link(pgp_key) + assert pgp_key in output + assert "https" in output - pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - output = pgp_key_link(pgp_key) - self.assertIn(pgp_key, output) - self.assertIn("https", output) + output = pgp_key_link(pgp_key, "test") + assert "test" in output + assert "https" in output - output = pgp_key_link(pgp_key, "test") - self.assertIn("test", output) - self.assertIn("https", output) + # Numeric key_id <= 8 + assert_pgp_key_link('0x0023BDC7') - # Numeric key_id <= 8 - self.assert_pgp_key_link('0x0023BDC7') + # Numeric key_id <= 16 + assert_pgp_key_link('0xBDC7FF5E34A12F') - # Numeric key_id <= 16 - self.assert_pgp_key_link('0xBDC7FF5E34A12F') + # Numeric key_id <= 40 + assert_pgp_key_link('0xA10E234343EA8BDC7FF5E34A12F') - # Numeric key_id <= 40 - self.assert_pgp_key_link('0xA10E234343EA8BDC7FF5E34A12F') + pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + server = settings.PGP_SERVER - pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - server = getattr(settings, 'PGP_SERVER') + settings.PGP_SERVER = '' + assert server not in pgp_key_link(pgp_key) - with self.settings(PGP_SERVER=''): - self.assertNotIn(server, pgp_key_link(pgp_key)) - with self.settings(PGP_SERVER_SECURE=False): - pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - self.assertNotIn("https", pgp_key_link(pgp_key)) + settings.PGP_SERVER_SECURE = False + settings.PGP_SERVER = server + pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + assert not "https" in pgp_key_link(pgp_key) - def test_pgp_fingerprint(self): - self.assertEqual(pgp_fingerprint(None), "") - keyid = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - fingerprint = pgp_fingerprint(keyid) - self.assertTrue(len(fingerprint) > len(keyid)) +def test_pgp_fingerprint(): + assert pgp_fingerprint(None) == "" + keyid = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + fingerprint = pgp_fingerprint(keyid) + assert len(fingerprint) > len(keyid) From a620fedab40d753607d0e36f5ded3acc6bcdd436 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 16:42:18 +0100 Subject: [PATCH 16/42] visualize: convert to pytest --- conftest.py | 20 ++++++++++++++++++++ visualize/tests.py | 15 ++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 conftest.py diff --git a/conftest.py b/conftest.py new file mode 100644 index 00000000..accb7416 --- /dev/null +++ b/conftest.py @@ -0,0 +1,20 @@ +import pytest + +from django.core.management import call_command + + + +@pytest.fixture +def arches(db): + call_command('loaddata', 'main/fixtures/arches.json') + + +@pytest.fixture +def repos(db): + call_command('loaddata', 'main/fixtures/repos.json') + + +@pytest.fixture +def package(db): + # TODO(jelle): create own parameter based version + call_command('loaddata', 'main/fixtures/package.json') diff --git a/visualize/tests.py b/visualize/tests.py index 30289c89..ec9ab1a1 100644 --- a/visualize/tests.py +++ b/visualize/tests.py @@ -1,11 +1,4 @@ -from django.test import TestCase - - -class VisualeTest(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_urls(self): - for url in ['', 'by_repo/', 'by_arch/']: - response = self.client.get('/visualize/{}'.format(url)) - self.assertEqual(response.status_code, 200) +def test_urls(client, arches, repos, package): + for url in ['', 'by_repo/', 'by_arch/']: + response = client.get('/visualize/{}'.format(url)) + assert response.status_code == 200 From ac05d5369a03868cc2ad18cac262485ef793f99b Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 18:31:29 +0100 Subject: [PATCH 17/42] public: port to pytest --- conftest.py | 10 ++++++ public/tests.py | 81 +++++++++++++++++++++++++------------------------ 2 files changed, 51 insertions(+), 40 deletions(-) diff --git a/conftest.py b/conftest.py index accb7416..5f91a842 100644 --- a/conftest.py +++ b/conftest.py @@ -18,3 +18,13 @@ def repos(db): def package(db): # TODO(jelle): create own parameter based version call_command('loaddata', 'main/fixtures/package.json') + + +@pytest.fixture +def groups(db): + call_command('loaddata', 'main/fixtures/groups.json') + + +@pytest.fixture +def staff_groups(db): + call_command('loaddata', 'devel/fixtures/staff_groups.json') diff --git a/public/tests.py b/public/tests.py index b826ee53..9be36564 100644 --- a/public/tests.py +++ b/public/tests.py @@ -1,54 +1,55 @@ -from django.test import TestCase +def test_index(client, arches, repos, package, groups, staff_groups): + response = client.get('/') + assert response.status_code == 200 -class PublicTest(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json', 'main/fixtures/groups.json', - 'devel/fixtures/staff_groups.json'] +def test_about(client, arches, repos, package, groups, staff_groups): + response = client.get('/about/') + assert response.status_code == 200 - def test_index(self): - response = self.client.get('/') - self.assertEqual(response.status_code, 200) - def test_about(self): - response = self.client.get('/about/') - self.assertEqual(response.status_code, 200) +def test_art(client, arches, repos, package, groups, staff_groups): + response = client.get('/art/') + assert response.status_code == 200 - def test_art(self): - response = self.client.get('/art/') - self.assertEqual(response.status_code, 200) - def test_svn(self): - response = self.client.get('/svn/') - self.assertEqual(response.status_code, 200) +def test_svn(client, arches, repos, package, groups, staff_groups): + response = client.get('/svn/') + assert response.status_code == 200 - def test_donate(self): - response = self.client.get('/donate/') - self.assertEqual(response.status_code, 200) - def test_download(self): - response = self.client.get('/download/') - self.assertEqual(response.status_code, 200) +def test_donate(client, arches, repos, package, groups, staff_groups): + response = client.get('/donate/') + assert response.status_code == 200 - def test_master_keys(self): - response = self.client.get('/master-keys/') - self.assertEqual(response.status_code, 200) - def test_master_keys_json(self): - response = self.client.get('/master-keys/json/') - self.assertEqual(response.status_code, 200) +def test_download(client, arches, repos, package, groups, staff_groups): + response = client.get('/download/') + assert response.status_code == 200 - def test_feeds(self): - response = self.client.get('/feeds/') - self.assertEqual(response.status_code, 200) - def test_people(self): - response = self.client.get('/people/developers/') - self.assertEqual(response.status_code, 200) +def test_master_keys(client, arches, repos, package, groups, staff_groups): + response = client.get('/master-keys/') + assert response.status_code == 200 - def test_sitemap(self): - sitemaps = ['sitemap', 'sitemap-base'] - for sitemap in sitemaps: - response = self.client.get('/{}.xml'.format(sitemap)) - self.assertEqual(response.status_code, 200) +def test_master_keys_json(client, arches, repos, package, groups, staff_groups): + response = client.get('/master-keys/json/') + assert response.status_code == 200 + + +def test_feeds(client, arches, repos, package, groups, staff_groups): + response = client.get('/feeds/') + assert response.status_code == 200 + + +def test_people(client, arches, repos, package, groups, staff_groups): + response = client.get('/people/developers/') + assert response.status_code == 200 + + +def test_sitemap(client, arches, repos, package, groups, staff_groups): + sitemaps = ['sitemap', 'sitemap-base'] + for sitemap in sitemaps: + response = client.get('/{}.xml'.format(sitemap)) + assert response.status_code == 200 From 7500b1e0aff1792bb6997872da3d31fe5fadfc56 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 20:27:12 +0100 Subject: [PATCH 18/42] news: port to pytest --- news/tests.py | 84 --------------------------------------- news/tests/test_crud.py | 53 ++++++++++++++++++++++++ news/tests/test_models.py | 18 +++++++++ 3 files changed, 71 insertions(+), 84 deletions(-) delete mode 100644 news/tests.py create mode 100644 news/tests/test_crud.py create mode 100644 news/tests/test_models.py diff --git a/news/tests.py b/news/tests.py deleted file mode 100644 index b7cdd2dd..00000000 --- a/news/tests.py +++ /dev/null @@ -1,84 +0,0 @@ -from django.core import mail -from django.test import TestCase, TransactionTestCase -from django.contrib.auth.models import User - - -from news.models import News - - -class NewsTest(TestCase): - - def test_feed(self): - response = self.client.get('/feeds/news/') - self.assertEqual(response.status_code, 200) - - def test_sitemap(self): - response = self.client.get('/sitemap-news.xml') - self.assertEqual(response.status_code, 200) - - def test_news_sitemap(self): - response = self.client.get('/news-sitemap.xml') - self.assertEqual(response.status_code, 200) - - def test_newsitem(self): - response = self.client.get('/news/404', follow=True) - self.assertEqual(response.status_code, 404) - - -class NewsCrud(TransactionTestCase): - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - News.objects.all().delete() - self.user.delete() - - def create(self, title='Bash broken', content='Broken in [testing]', announce=False): - data = { - 'title': title, - 'content': content, - } - if announce: - data['send_announce'] = 'on' - return self.client.post('/news/add/', data, follow=True) - - def testCreateItem(self): - title = 'Bash broken' - response = self.create(title) - self.assertEqual(response.status_code, 200) - - news = News.objects.first() - self.assertEqual(news.author, self.user) - self.assertEqual(news.title, title) - - def testView(self): - self.create() - news = News.objects.first() - - response = self.client.get(news.get_absolute_url()) - self.assertEqual(response.status_code, 200) - - def testRedirectId(self): - self.create() - news = News.objects.first() - - response = self.client.get('/news/{}'.format(news.id), follow=True) - self.assertEqual(response.status_code, 200) - - def testSendAnnounce(self): - title = 'New glibc' - self.create(title, announce=True) - self.assertEqual(len(mail.outbox), 1) - self.assertIn(title, mail.outbox[0].subject) - - def testPreview(self): - response = self.client.post('/news/preview/', {'data': '**body**'}, follow=True) - self.assertEqual(response.status_code, 200) - self.assertEqual('

body

', response.content.decode()) diff --git a/news/tests/test_crud.py b/news/tests/test_crud.py new file mode 100644 index 00000000..07294769 --- /dev/null +++ b/news/tests/test_crud.py @@ -0,0 +1,53 @@ +from news.models import News + +from django.core import mail + + +def create(admin_client, title='Bash broken', content='Broken in [testing]', announce=False): + data = { + 'title': title, + 'content': content, + } + if announce: + data['send_announce'] = 'on' + return admin_client.post('/news/add/', data, follow=True) + + +def test_create_item(db, admin_client, admin_user): + title = 'Bash broken' + response = create(admin_client, title) + assert response.status_code == 200 + + news = News.objects.first() + + assert news.author == admin_user + assert news.title == title + + +def test_view(db, admin_client): + create(admin_client) + news = News.objects.first() + + response = admin_client.get(news.get_absolute_url()) + assert response.status_code == 200 + + +def test_redirect_id(db, admin_client): + create(admin_client) + news = News.objects.first() + + response = admin_client.get('/news/{}'.format(news.id), follow=True) + assert response.status_code == 200 + + +def test_send_announce(db, admin_client): + title = 'New glibc' + create(admin_client, title, announce=True) + assert len(mail.outbox) == 1 + assert title in mail.outbox[0].subject + + +def test_preview(db, admin_client): + response = admin_client.post('/news/preview/', {'data': '**body**'}, follow=True) + assert response.status_code == 200 + assert '

body

' == response.content.decode() diff --git a/news/tests/test_models.py b/news/tests/test_models.py new file mode 100644 index 00000000..5a4178bc --- /dev/null +++ b/news/tests/test_models.py @@ -0,0 +1,18 @@ +def test_feed(db, client): + response = client.get('/feeds/news/') + assert response.status_code == 200 + + +def test_sitemap(db, client): + response = client.get('/sitemap-news.xml') + assert response.status_code == 200 + + +def test_news_sitemap(db, client): + response = client.get('/news-sitemap.xml') + assert response.status_code == 200 + + +def test_newsitem(db, client): + response = client.get('/news/404', follow=True) + assert response.status_code == 404 From 6710663079a0c736a7b87386b7ac4d04e47bfad2 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 22:03:43 +0100 Subject: [PATCH 19/42] packages: port to pytest --- conftest.py | 9 + packages/tests.py | 309 +------------------- packages/tests/test_adoptorphan_packages.py | 47 +++ packages/tests/test_alpm.py | 43 +++ packages/tests/test_opensearch.py | 24 ++ packages/tests/test_package_flag.py | 42 +++ packages/tests/test_package_search.py | 69 +++++ packages/tests/test_search_json.py | 47 +++ packages/tests/test_signoff.py | 9 + 9 files changed, 292 insertions(+), 307 deletions(-) create mode 100644 packages/tests/test_adoptorphan_packages.py create mode 100644 packages/tests/test_alpm.py create mode 100644 packages/tests/test_opensearch.py create mode 100644 packages/tests/test_package_flag.py create mode 100644 packages/tests/test_package_search.py create mode 100644 packages/tests/test_search_json.py create mode 100644 packages/tests/test_signoff.py diff --git a/conftest.py b/conftest.py index 5f91a842..3cdc2650 100644 --- a/conftest.py +++ b/conftest.py @@ -2,6 +2,7 @@ from django.core.management import call_command +from devel.models import UserProfile @pytest.fixture @@ -28,3 +29,11 @@ def groups(db): @pytest.fixture def staff_groups(db): call_command('loaddata', 'devel/fixtures/staff_groups.json') + + +@pytest.fixture +def admin_user_profile(admin_user): + profile = UserProfile.objects.create(user=admin_user, + public_email="public@archlinux.org") + yield profile + profile.delete() diff --git a/packages/tests.py b/packages/tests.py index f2dae8cb..18ea740d 100644 --- a/packages/tests.py +++ b/packages/tests.py @@ -1,315 +1,10 @@ -import unittest - -from django.core import mail -from django.test import TestCase, TransactionTestCase +from django.test import TransactionTestCase from django.contrib.auth.models import User -from main.models import Package, Repo +from main.models import Repo from packages.models import PackageRelation from devel.models import UserProfile -from .alpm import AlpmAPI - - -alpm = AlpmAPI() - - -class AlpmTestCase(unittest.TestCase): - - @unittest.skipUnless(alpm.available, "ALPM is unavailable") - def test_version(self): - version = alpm.version() - self.assertIsNotNone(version) - version = version.split(b'.') - # version is a 3-tuple, e.g., '7.0.2' - self.assertEqual(3, len(version)) - - @unittest.skipUnless(alpm.available, "ALPM is unavailable") - def test_vercmp(self): - self.assertEqual(0, alpm.vercmp("1.0", "1.0")) - self.assertEqual(1, alpm.vercmp("1.1", "1.0")) - - @unittest.skipUnless(alpm.available, "ALPM is unavailable") - def test_compare_versions(self): - self.assertTrue(alpm.compare_versions("1.0", "<=", "2.0")) - self.assertTrue(alpm.compare_versions("1.0", "<", "2.0")) - self.assertFalse(alpm.compare_versions("1.0", ">=", "2.0")) - self.assertFalse(alpm.compare_versions("1.0", ">", "2.0")) - self.assertTrue(alpm.compare_versions("1:1.0", ">", "2.0")) - self.assertFalse(alpm.compare_versions("1.0.2", ">=", "2.1.0")) - - self.assertTrue(alpm.compare_versions("1.0", "=", "1.0")) - self.assertTrue(alpm.compare_versions("1.0", "=", "1.0-1")) - self.assertFalse(alpm.compare_versions("1.0", "!=", "1.0")) - - def test_behavior_when_unavailable(self): - mock_alpm = AlpmAPI() - mock_alpm.available = False - - self.assertIsNone(mock_alpm.version()) - self.assertIsNone(mock_alpm.vercmp("1.0", "1.0")) - self.assertIsNone(mock_alpm.compare_versions("1.0", "=", "1.0")) - - -class PackagesTest(TestCase): - - def test_feed(self): - response = self.client.get('/feeds/packages/') - self.assertEqual(response.status_code, 200) - - def test_sitemap(self): - for sitemap in ['packages', 'package-groups', 'package-files', 'split-packages']: - response = self.client.get('/sitemap-{}.xml'.format(sitemap)) - self.assertEqual(response.status_code, 200) - - -class PackageSearchJson(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_invalid(self): - response = self.client.get('/packages/search/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['limit'], 250) - self.assertEqual(data['results'], []) - self.assertEqual(data['valid'], False) - - def test_reponame(self): - response = self.client.get('/packages/search/json/?repository=core') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(len(data['results']), 5) - self.assertEqual(set([r['pkgname'] for r in data['results']]), - {"coreutils", "glibc", "linux", "pacman", "systemd"}) - - def test_packagename(self): - response = self.client.get('/packages/search/json/?name=linux') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(len(data['results']), 1) - - def test_no_results(self): - response = self.client.get('/packages/search/json/?name=none') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(len(data['results']), 0) - - def test_limit_four(self): - response = self.client.get('/packages/search/json/?limit=4') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['page'], 1) - self.assertEqual(data['num_pages'], 2) - self.assertEqual(data['limit'], 4) - self.assertEqual(len(data['results']), 4) - - def test_second_page(self): - response = self.client.get('/packages/search/json/?limit=4&page=2') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['page'], 2) - self.assertEqual(data['num_pages'], 2) - self.assertEqual(len(data['results']), 1) - - -class PackageSearch(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_invalid(self): - response = self.client.get('/packages/?q=test') - self.assertEqual(response.status_code, 200) - self.assertIn('0 matching packages found', response.content.decode()) - - def test_exact_match(self): - response = self.client.get('/packages/?q=linux') - self.assertEqual(response.status_code, 200) - self.assertIn('1 matching package found', response.content.decode()) - - def test_filter_name(self): - response = self.client.get('/packages/?name=name') - self.assertEqual(response.status_code, 200) - self.assertIn('0 matching packages found', response.content.decode()) - - def test_filter_repo(self): - response = self.client.get('/packages/?repo=Core') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_filter_desc(self): - response = self.client.get('/packages/?desc=kernel') - self.assertEqual(response.status_code, 200) - self.assertIn('1 matching package found', response.content.decode()) - - def test_filter_flagged(self): - response = self.client.get('/packages/?flagged=Flagged') - self.assertEqual(response.status_code, 200) - self.assertIn('0 matching packages found', response.content.decode()) - - def test_filter_not_flagged(self): - response = self.client.get('/packages/?flagged=Not Flagged') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_filter_arch(self): - response = self.client.get('/packages/?arch=any') - self.assertEqual(response.status_code, 200) - self.assertIn('0 matching packages found', response.content.decode()) - - def test_filter_maintainer_orphan(self): - response = self.client.get('/packages/?maintainer=orphan') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_filter_packager_unknown(self): - response = self.client.get('/packages/?packager=unknown') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_sort(self): - response = self.client.get('/packages/?sort=pkgname') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_head(self): - response = self.client.head('/packages/?q=unknown') - self.assertEqual(response.status_code, 200) - - -class OpenSearch(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_packages(self): - response = self.client.get('/opensearch/packages/') - self.assertEqual(response.status_code, 200) - - def test_packages_suggest(self): - response = self.client.get('/opensearch/packages/suggest') - self.assertEqual(response.status_code, 200) - - def test_packages_suggest_lowercase(self): - response = self.client.get('/opensearch/packages/suggest?q=linux') - self.assertEqual(response.status_code, 200) - self.assertIn('linux', response.content.decode()) - - def test_packages_suggest_uppercase(self): - response = self.client.get('/opensearch/packages/suggest?q=LINUX') - self.assertEqual(response.status_code, 200) - self.assertIn('linux', response.content.decode()) - - response = self.client.get('/opensearch/packages/suggest?q=LINux') - self.assertEqual(response.status_code, 200) - self.assertIn('linux', response.content.decode()) - - -class PackageViews(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_arch_differences(self): - response = self.client.get('/packages/differences/') - self.assertEqual(response.status_code, 200) - - -class PackageDisplay(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_packages_detail(self): - response = self.client.get('/packages/core/x86_64/linux/') - self.assertEqual(response.status_code, 200) - - response = self.client.get('/packages/core/x86_64/nope/') - self.assertEqual(response.status_code, 404) - - # Redirect to search - response = self.client.get('/packages/core/x86_64/') - self.assertEqual(response.status_code, 302) - - def test_packages_json(self): - response = self.client.get('/packages/core/x86_64/linux/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['pkgbase'], 'linux') - # TODO verify more of the structure - - def test_packages_files(self): - response = self.client.get('/packages/core/x86_64/linux/files/') - self.assertEqual(response.status_code, 200) - - def test_packages_files_json(self): - response = self.client.get('/packages/core/x86_64/linux/files/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['pkgname'], 'linux') - # TODO verify more of the structure - - def test_packages_download(self): - response = self.client.get('/packages/core/x86_64/linux/download/') - self.assertEqual(response.status_code, 404) - # TODO: Figure out how to fake a mirror - - def test_head(self): - response = self.client.head('/packages/core/x86_64/linux/') - self.assertEqual(response.status_code, 200) - - def test_groups(self): - response = self.client.get('/groups/') - self.assertEqual(response.status_code, 200) - - def test_groups_arch(self): - response = self.client.get('/groups/x86_64/') - self.assertEqual(response.status_code, 200) - - def test_groups_details(self): - response = self.client.get('/groups/x86_64/base/') - self.assertEqual(response.status_code, 404) - # FIXME: add group fixtures. - - -class FlagPackage(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_flag_package(self): - data = { - 'website': '', - 'email': 'nobody@archlinux.org', - 'message': 'new linux version', - } - response = self.client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Package Flagged - linux', response.content.decode()) - self.assertEqual(len(mail.outbox), 1) - self.assertIn('package [linux] marked out-of-date', mail.outbox[0].subject) - - # Flag again, should fail - response = self.client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('has already been flagged out-of-date.', response.content.decode()) - - def test_flag_package_invalid(self): - data = { - 'website': '', - 'email': 'nobody@archlinux.org', - 'message': 'a', - } - response = self.client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Enter a valid and useful out-of-date message', response.content.decode()) - self.assertEqual(len(mail.outbox), 0) - - def test_flag_help(self): - response = self.client.get('/packages/flaghelp/') - self.assertEqual(response.status_code, 200) class UnFlagPackage(TransactionTestCase): diff --git a/packages/tests/test_adoptorphan_packages.py b/packages/tests/test_adoptorphan_packages.py new file mode 100644 index 00000000..5c3c3e38 --- /dev/null +++ b/packages/tests/test_adoptorphan_packages.py @@ -0,0 +1,47 @@ +from main.models import Package, Repo +from packages.models import PackageRelation + + +def request(client, pkgid, adopt=True): + data = { + 'pkgid': pkgid, + } + if adopt: + data['adopt'] = 'adopt' + else: + data['disown'] = 'disown' + return client.post('/packages/update/', data, follow=True) + + + +def test_wrong_request(admin_client, arches, repos, package): + # TODO(jelle): fix + pkg = Package.objects.first() + response = admin_client.post('/packages/update/', {'pkgid': pkg.id, }, follow=True) + assert response.status_code == 200 + assert 'Are you trying to adopt or disown' in response.content.decode() + + +def test_stale_relations(admin_user_profile, admin_client, arches, repos, package): + response = admin_client.get('/packages/stale_relations/') + assert response.status_code == 200 + + +def test_no_permissions(admin_client, admin_user_profile, arches, repos, package): + pkg = Package.objects.first() + + response = request(admin_client, pkg.id) + assert response.status_code == 200 + assert len(PackageRelation.objects.all()) == 0 + + +def test_adopt_package(admin_client, admin_user_profile, arches, repos, package): + admin_user_profile.allowed_repos.add(Repo.objects.get(name='Core')) + pkg = Package.objects.first() + response = request(admin_client, pkg.id) + assert response.status_code == 200 + assert len(PackageRelation.objects.all()) == 1 + + response = request(admin_client, pkg.id, False) + assert response.status_code == 200 + assert len(PackageRelation.objects.all()) == 0 diff --git a/packages/tests/test_alpm.py b/packages/tests/test_alpm.py new file mode 100644 index 00000000..74111d06 --- /dev/null +++ b/packages/tests/test_alpm.py @@ -0,0 +1,43 @@ +import unittest + +from packages.alpm import AlpmAPI + + +alpm = AlpmAPI() + + +@unittest.skipUnless(alpm.available, "ALPM is unavailable") +def test_version(): + version = alpm.version() + assert version is not None + version = version.split(b'.') + # version is a 3-tuple, e.g., '7.0.2' + assert 3 == len(version) + + +@unittest.skipUnless(alpm.available, "ALPM is unavailable") +def test_vercmp(): + assert 0 == alpm.vercmp("1.0", "1.0") + assert 1 == alpm.vercmp("1.1", "1.0") + + +@unittest.skipUnless(alpm.available, "ALPM is unavailable") +def test_compare_versions(): + assert alpm.compare_versions("1.0", "<=", "2.0") == True + assert alpm.compare_versions("1.0", "<", "2.0") == True + assert alpm.compare_versions("1.0", ">=", "2.0") == False + assert alpm.compare_versions("1.0", ">", "2.0") == False + assert alpm.compare_versions("1:1.0", ">", "2.0") == True + assert alpm.compare_versions("1.0.2", ">=", "2.1.0") == False + assert alpm.compare_versions("1.0", "=", "1.0") == True + assert alpm.compare_versions("1.0", "=", "1.0-1") == True + assert alpm.compare_versions("1.0", "!=", "1.0") == False + + +def test_behavior_when_unavailable(): + mock_alpm = AlpmAPI() + mock_alpm.available = False + + assert mock_alpm.version() is None + assert mock_alpm.vercmp("1.0", "1.0") is None + assert mock_alpm.compare_versions("1.0", "=", "1.0") is None diff --git a/packages/tests/test_opensearch.py b/packages/tests/test_opensearch.py new file mode 100644 index 00000000..2a3b66ad --- /dev/null +++ b/packages/tests/test_opensearch.py @@ -0,0 +1,24 @@ +def test_packages(client, arches, repos, package): + response = client.get('/opensearch/packages/') + assert response.status_code == 200 + + +def test_packages_suggest(client, arches, repos, package): + response = client.get('/opensearch/packages/suggest') + assert response.status_code == 200 + + +def test_packages_suggest_lowercase(client, arches, repos, package): + response = client.get('/opensearch/packages/suggest?q=linux') + assert response.status_code == 200 + assert 'linux' in response.content.decode() + + +def test_packages_suggest_uppercase(client, arches, repos, package): + response = client.get('/opensearch/packages/suggest?q=LINUX') + assert response.status_code == 200 + assert 'linux' in response.content.decode() + + response = client.get('/opensearch/packages/suggest?q=LINux') + assert response.status_code == 200 + assert 'linux' in response.content.decode() diff --git a/packages/tests/test_package_flag.py b/packages/tests/test_package_flag.py new file mode 100644 index 00000000..df9e15ab --- /dev/null +++ b/packages/tests/test_package_flag.py @@ -0,0 +1,42 @@ +from django.core import mail + + +def test_flag_package(client, arches, repos, package): + data = { + 'website': '', + 'email': 'nobody@archlinux.org', + 'message': 'new linux version', + } + response = client.post('/packages/core/x86_64/linux/flag/', + data, + follow=True) + assert response.status_code == 200 + assert 'Package Flagged - linux' in response.content.decode() + assert len(mail.outbox) == 1 + assert 'package [linux] marked out-of-date' in mail.outbox[0].subject + + # Flag again, should fail + response = client.post('/packages/core/x86_64/linux/flag/', + data, + follow=True) + assert response.status_code == 200 + assert 'has already been flagged out-of-date.' in response.content.decode() + + +def test_flag_package_invalid(client, arches, repos, package): + data = { + 'website': '', + 'email': 'nobody@archlinux.org', + 'message': 'a', + } + response = client.post('/packages/core/x86_64/linux/flag/', + data, + follow=True) + assert response.status_code == 200 + assert 'Enter a valid and useful out-of-date message' in response.content.decode() + assert len(mail.outbox) == 0 + + +def test_flag_help(client, arches, repos, package): + response = client.get('/packages/flaghelp/') + assert response.status_code == 200 diff --git a/packages/tests/test_package_search.py b/packages/tests/test_package_search.py new file mode 100644 index 00000000..2ef30731 --- /dev/null +++ b/packages/tests/test_package_search.py @@ -0,0 +1,69 @@ +def test_invalid(client, arches, repos, package): + response = client.get('/packages/?q=test') + assert response.status_code == 200 + assert '0 matching packages found' in response.content.decode() + + +def test_exact_match(client, arches, repos, package): + response = client.get('/packages/?q=linux') + assert response.status_code == 200 + assert '1 matching package found' in response.content.decode() + + +def test_filter_name(client, arches, repos, package): + response = client.get('/packages/?name=name') + assert response.status_code == 200 + assert '0 matching packages found' in response.content.decode() + + +def test_filter_repo(client, arches, repos, package): + response = client.get('/packages/?repo=Core') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_filter_desc(client, arches, repos, package): + response = client.get('/packages/?desc=kernel') + assert response.status_code == 200 + assert '1 matching package found' in response.content.decode() + + +def test_filter_flagged(client, arches, repos, package): + response = client.get('/packages/?flagged=Flagged') + assert response.status_code == 200 + assert '0 matching packages found' in response.content.decode() + + +def test_filter_not_flagged(client, arches, repos, package): + response = client.get('/packages/?flagged=Not Flagged') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_filter_arch(client, arches, repos, package): + response = client.get('/packages/?arch=any') + assert response.status_code == 200 + assert '0 matching packages found' in response.content.decode() + + +def test_filter_maintainer_orphan(client, arches, repos, package): + response = client.get('/packages/?maintainer=orphan') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_filter_packager_unknown(client, arches, repos, package): + response = client.get('/packages/?packager=unknown') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_sort(client, arches, repos, package): + response = client.get('/packages/?sort=pkgname') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_head(client, arches, repos, package): + response = client.head('/packages/?q=unknown') + assert response.status_code == 200 diff --git a/packages/tests/test_search_json.py b/packages/tests/test_search_json.py new file mode 100644 index 00000000..a6735eb5 --- /dev/null +++ b/packages/tests/test_search_json.py @@ -0,0 +1,47 @@ +def test_invalid(client, arches, repos, package): + response = client.get('/packages/search/json/') + assert response.status_code == 200 + data = response.json() + assert data['limit'] == 250 + assert data['results'] == [] + assert data['valid'] == False + + +def test_reponame(client, arches, repos, package): + response = client.get('/packages/search/json/?repository=core') + assert response.status_code == 200 + data = response.json() + assert len(data['results']) == 5 + assert set([r['pkgname'] for r in data['results']]) == {"coreutils", "glibc", "linux", "pacman", "systemd"} + +def test_packagename(client, arches, repos, package): + response = client.get('/packages/search/json/?name=linux') + assert response.status_code == 200 + data = response.json() + assert len(data['results']) == 1 + + +def test_no_results(client, arches, repos, package): + response = client.get('/packages/search/json/?name=none') + assert response.status_code == 200 + data = response.json() + assert len(data['results']) == 0 + + +def test_limit_four(client, arches, repos, package): + response = client.get('/packages/search/json/?limit=4') + assert response.status_code == 200 + data = response.json() + assert data['page'] == 1 + assert data['num_pages'] == 2 + assert data['limit'] == 4 + assert len(data['results']) == 4 + + +def test_second_page(client, arches, repos, package): + response = client.get('/packages/search/json/?limit=4&page=2') + assert response.status_code == 200 + data = response.json() + assert data['page'] == 2 + assert data['num_pages'] == 2 + assert len(data['results']) == 1 diff --git a/packages/tests/test_signoff.py b/packages/tests/test_signoff.py new file mode 100644 index 00000000..1085570e --- /dev/null +++ b/packages/tests/test_signoff.py @@ -0,0 +1,9 @@ +def test_signoffs(admin_client, arches, repos, package): + response = admin_client.get('/packages/signoffs/') + assert response.status_code == 200 + + +def test_signoffs_json(admin_client, arches, repos, package): + response = admin_client.get('/packages/signoffs/json/') + assert response.status_code == 200 + assert response.json()['signoff_groups'] == [] From 8245939538a80998a86403c970eca174c6bf4292 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 22:44:40 +0100 Subject: [PATCH 20/42] todolists: port to pytest --- todolists/tests/conftest.py | 30 +++++++++++ todolists/tests/test_models.py | 52 +++++-------------- .../tests/test_templatetags_todolists.py | 29 ++--------- 3 files changed, 46 insertions(+), 65 deletions(-) create mode 100644 todolists/tests/conftest.py diff --git a/todolists/tests/conftest.py b/todolists/tests/conftest.py new file mode 100644 index 00000000..6dca6813 --- /dev/null +++ b/todolists/tests/conftest.py @@ -0,0 +1,30 @@ +import pytest + +from main.models import Package +from todolists.models import Todolist, TodolistPackage + + +NAME = 'Boost rebuild' +DESCRIPTION = 'Boost 1.66 rebuild' +RAW = 'linux' + + +@pytest.fixture +def todolist(admin_user, arches, repos, package): + todolist = Todolist.objects.create(name=NAME, + description=DESCRIPTION, + creator=admin_user, + raw=RAW) + yield todolist + todolist.delete() + + +@pytest.fixture +def todolistpackage(admin_user, todolist): + pkg = Package.objects.first() + todopkg = TodolistPackage.objects.create(pkg=pkg, pkgname=pkg.pkgname, + pkgbase=pkg.pkgbase, arch=pkg.arch, + repo=pkg.repo, user=admin_user, + todolist=todolist) + yield todopkg + todopkg.delete() diff --git a/todolists/tests/test_models.py b/todolists/tests/test_models.py index 4e629f37..ccfed3f6 100644 --- a/todolists/tests/test_models.py +++ b/todolists/tests/test_models.py @@ -1,45 +1,19 @@ -from django.contrib.auth.models import User -from django.test import TestCase +def test_stripped_description(todolist): + todolist.description = 'Boost rebuild ' + desc = todolist.stripped_description + assert desc.endswith(' ') == False -from main.models import Package -from todolists.models import Todolist, TodolistPackage +def test_get_absolute_url(todolist): + assert '/todo/' in todolist.get_absolute_url() -class TestTodolist(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] +def test_get_full_url(todolist): + url = todolist.get_full_url() + assert 'https://example.com/todo/' in url - def setUp(self): - self.user = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.todolist = Todolist.objects.create(name='Boost rebuild', - description='Boost 1.66 rebuid', - creator=self.user, - raw='linux') - def tearDown(self): - self.todolist.delete() - self.user.delete() - - def test_stripped_description(self): - self.todolist.description = 'Boost rebuild ' - desc = self.todolist.stripped_description - self.assertFalse(desc.endswith(' ')) - - def test_get_absolute_url(self): - self.assertIn('/todo/', self.todolist.get_absolute_url()) - - def test_get_full_url(self): - url = self.todolist.get_full_url() - self.assertIn('https://example.com/todo/', url) - - def test_packages(self): - pkg = Package.objects.first() - todopkg = TodolistPackage.objects.create(pkg=pkg, pkgname=pkg.pkgname, - pkgbase=pkg.pkgbase, arch=pkg.arch, - repo=pkg.repo, user=self.user, - todolist=self.todolist) - pkgs = self.todolist.packages() - self.assertEqual(len(pkgs), 1) - self.assertEqual(pkgs[0], todopkg) +def test_packages(admin_user, todolist, todolistpackage): + pkgs = todolist.packages() + assert len(pkgs) == 1 + assert pkgs[0] == todolistpackage diff --git a/todolists/tests/test_templatetags_todolists.py b/todolists/tests/test_templatetags_todolists.py index 93cdbf94..cb547425 100644 --- a/todolists/tests/test_templatetags_todolists.py +++ b/todolists/tests/test_templatetags_todolists.py @@ -1,29 +1,6 @@ -from django.contrib.auth.models import User -from django.test import TestCase - - -from main.models import Package -from todolists.models import Todolist, TodolistPackage from todolists.templatetags.todolists import todopkg_details_link -class TestTodolist(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - self.user = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.todolist = Todolist.objects.create(name='Boost rebuild', - description='Boost 1.66 rebuid', - creator=self.user, - raw='linux') - - def test_details_link(self): - pkg = Package.objects.first() - todopkg = TodolistPackage.objects.create(pkg=pkg, pkgname=pkg.pkgname, - pkgbase=pkg.pkgbase, arch=pkg.arch, - repo=pkg.repo, user=self.user, - todolist=self.todolist) - link = todopkg_details_link(todopkg) - self.assertIn('View package details for {}'.format(todopkg.pkg.pkgname), link) +def test_details_link(todolistpackage): + link = todopkg_details_link(todolistpackage) + assert 'View package details for {}'.format(todolistpackage.pkg.pkgname) in link From 6e7829d0f7f4f8a2afb51f4308016b9ac94cd70b Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 22:45:08 +0100 Subject: [PATCH 21/42] packages; port to pytest --- packages/tests/test_packagedisplay.py | 58 +++++++++++++++++++++++++++ packages/tests/test_views.py | 14 +++++++ 2 files changed, 72 insertions(+) create mode 100644 packages/tests/test_packagedisplay.py create mode 100644 packages/tests/test_views.py diff --git a/packages/tests/test_packagedisplay.py b/packages/tests/test_packagedisplay.py new file mode 100644 index 00000000..c11750ea --- /dev/null +++ b/packages/tests/test_packagedisplay.py @@ -0,0 +1,58 @@ +def test_packages_detail(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/') + assert response.status_code == 200 + + response = client.get('/packages/core/x86_64/nope/') + assert response.status_code == 404 + + # Redirect to search + response = client.get('/packages/core/x86_64/') + assert response.status_code == 302 + + +def test_packages_json(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/json/') + assert response.status_code == 200 + data = response.json() + assert data['pkgbase'] == 'linux' + # TODO verify more of the structure + + +def test_packages_files(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/files/') + assert response.status_code == 200 + + +def test_packages_files_json(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/files/json/') + assert response.status_code == 200 + data = response.json() + assert data['pkgname'] == 'linux' + # TODO verify more of the structure + + +def test_packages_download(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/download/') + assert response.status_code == 404 + # TODO: Figure out how to fake a mirror + + +def test_head(client, arches, repos, package): + response = client.head('/packages/core/x86_64/linux/') + assert response.status_code == 200 + + +def test_groups(client, arches, repos, package): + response = client.get('/groups/') + assert response.status_code == 200 + + +def test_groups_arch(client, arches, repos, package): + response = client.get('/groups/x86_64/') + assert response.status_code == 200 + + +def test_groups_details(client, arches, repos, package): + response = client.get('/groups/x86_64/base/') + assert response.status_code == 404 + # FIXME: add group fixtures. diff --git a/packages/tests/test_views.py b/packages/tests/test_views.py new file mode 100644 index 00000000..a5452311 --- /dev/null +++ b/packages/tests/test_views.py @@ -0,0 +1,14 @@ +def test_feed(db, client): + response = client.get('/feeds/packages/') + assert response.status_code == 200 + + +def test_sitemap(db, client): + for sitemap in ['packages', 'package-groups', 'package-files', 'split-packages']: + response = client.get('/sitemap-{}.xml'.format(sitemap)) + assert response.status_code == 200 + + +def test_arch_differences(client, arches, repos, package): + response = client.get('/packages/differences/') + assert response.status_code == 200 From ba55137f4bbe69fce3b5736d12283982bb62e812 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 9 Mar 2019 23:02:21 +0100 Subject: [PATCH 22/42] devel: port to pytest --- devel/tests/test_pgp_import.py | 51 +++++++++++++------------- devel/tests/test_rematch_developers.py | 13 ++----- devel/tests/test_templatetags.py | 10 +---- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/devel/tests/test_pgp_import.py b/devel/tests/test_pgp_import.py index f01e73a3..f7f4e67b 100644 --- a/devel/tests/test_pgp_import.py +++ b/devel/tests/test_pgp_import.py @@ -1,8 +1,9 @@ from unittest.mock import patch +import pytest + from django.core.management import call_command from django.core.management.base import CommandError -from django.test import TransactionTestCase CREATED = 1541685162 @@ -19,28 +20,26 @@ ] -class PGPImportTest(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json'] - - def test_pgp_import_error(self): - with self.assertRaises(CommandError) as e: - call_command('pgp_import') - self.assertIn('keyring_path', str(e.exception)) - - @patch('devel.management.commands.pgp_import.call_gpg') - def test_pgp_import_garbage_data(self, mock_call_gpg): - mock_call_gpg.return_value = 'barf' - with patch('devel.management.commands.pgp_import.logger') as logger: - call_command('pgp_import', '/tmp') - logger.info.assert_called() - logger.info.assert_any_call('created %d, updated %d signatures', 0, 0) - logger.info.assert_any_call('created %d, updated %d keys', 0, 0) - - @patch('devel.management.commands.pgp_import.call_gpg') - def test_pgp_import(self, mock_call_gpg): - mock_call_gpg.return_value = '\n'.join(SIG_DATA) - with patch('devel.management.commands.pgp_import.logger') as logger: - call_command('pgp_import', '/tmp') - logger.info.assert_called() - logger.info.assert_any_call('created %d, updated %d signatures', 0, 0) - logger.info.assert_any_call('created %d, updated %d keys', 1, 0) +def test_pgp_import_error(arches, repos): + with pytest.raises(CommandError) as e: + call_command('pgp_import') + assert 'keyring_path' in str(e.value) + + +@patch('devel.management.commands.pgp_import.call_gpg') +def test_pgp_import_garbage_data(mock_call_gpg, arches, repos): + mock_call_gpg.return_value = 'barf' + with patch('devel.management.commands.pgp_import.logger') as logger: + call_command('pgp_import', '/tmp') + logger.info.assert_called() + logger.info.assert_any_call('created %d, updated %d signatures', 0, 0) + logger.info.assert_any_call('created %d, updated %d keys', 0, 0) + +@patch('devel.management.commands.pgp_import.call_gpg') +def test_pgp_import(mock_call_gpg, arches, repos): + mock_call_gpg.return_value = '\n'.join(SIG_DATA) + with patch('devel.management.commands.pgp_import.logger') as logger: + call_command('pgp_import', '/tmp') + logger.info.assert_called() + logger.info.assert_any_call('created %d, updated %d signatures', 0, 0) + logger.info.assert_any_call('created %d, updated %d keys', 1, 0) diff --git a/devel/tests/test_rematch_developers.py b/devel/tests/test_rematch_developers.py index 07daf50f..8dbbdfdf 100644 --- a/devel/tests/test_rematch_developers.py +++ b/devel/tests/test_rematch_developers.py @@ -1,14 +1,9 @@ from unittest.mock import patch - from django.core.management import call_command -from django.test import TransactionTestCase - -class RematchDeveloperTest(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json'] - def test_rematch_developers(self): - with patch('devel.management.commands.rematch_developers.logger') as logger: - call_command('rematch_developers') - logger.info.assert_called() +def test_rematch_developers(arches, repos): + with patch('devel.management.commands.rematch_developers.logger') as logger: + call_command('rematch_developers') + logger.info.assert_called() diff --git a/devel/tests/test_templatetags.py b/devel/tests/test_templatetags.py index e5d9782a..47de68dd 100644 --- a/devel/tests/test_templatetags.py +++ b/devel/tests/test_templatetags.py @@ -1,11 +1,5 @@ -from django.contrib.auth.models import User -from django.test import TestCase - from devel.templatetags.group import in_group -class DevelTemplatetagsTest(TestCase): - def test_in_group(self): - user = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.assertEqual(in_group(user, 'none'), False) +def test_in_group(admin_user): + assert in_group(admin_user, 'none') == False From 9cf6c4c2e2cee225f6dadae0f0889cf8f3d239df Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Mon, 29 Jul 2019 21:36:12 +0200 Subject: [PATCH 23/42] Add pytest integration files --- .coveragerc | 1 + .gitignore | 1 + .travis.yml | 6 +++--- Makefile | 32 ++++++++++++++++++++++++++++++++ pytest.ini | 2 ++ 5 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 Makefile create mode 100644 pytest.ini diff --git a/.coveragerc b/.coveragerc index 02b787e9..4664e2bc 100644 --- a/.coveragerc +++ b/.coveragerc @@ -7,5 +7,6 @@ omit = **/tests/*.py env* settings.py + conftest.py local_settings.py /home/travis/virtualenv* diff --git a/.gitignore b/.gitignore index e047ef4a..b6abcfbc 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ env/ # coverage .coverage +htmlcov diff --git a/.travis.yml b/.travis.yml index 03bb6f46..c06a474a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,9 +6,9 @@ cache: pip install: "pip install -r requirements.txt && pip install coveralls pylint" script: - - python manage.py collectstatic --noinput - - coverage run --rcfile .coveragerc manage.py test - - pylint devel main mirrors news packages releng templates todolists visualize *.py + - make collectstatic + - make lint + - make coverage after_success: - coveralls diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..baa6a826 --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +PYTHON>=python +PYTEST?=pytest +PYTEST_OPTIONS+= +PYTEST_INPUT?=. +PYTEST_COVERAGE_OPTIONS+=--cov-report=term-missing --cov-report=html:htmlcov --cov=. +PYTEST_PDB?=0 +PYTEST_PDB_OPTIONS?=--pdb --pdbcls=IPython.terminal.debugger:TerminalPdb + + +ifeq (${PYTEST_PDB},1) +PYTEST_OPTIONS+= ${PYTEST_PDB_OPTIONS} +else +test-pdb: PYTEST_OPTIONS+= ${PYTEST_PDB_OPTIONS} +endif +test-pdb: test + + +.PHONY: test lint + +lint: + pylint devel main mirrors news packages releng templates todolists visualize *.py + +collecstatic: + python manage.py collecstatic --noinput + +test: test-py + +test-py coverage: + ${PYTEST} ${PYTEST_INPUT} ${PYTEST_OPTIONS} ${PYTEST_COVERAGE_OPTIONS} + +open-coverage: coverage + ${BROWSER} htmlcov/index.html diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..4e22ea20 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +DJANGO_SETTINGS_MODULE = settings From 04835d48cd0a8fef7fe7d72fe0e991388d9296ce Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 4 Aug 2019 18:27:50 +0200 Subject: [PATCH 24/42] Add pylint disable for import --- main/tests/test_templatetags_flags.py | 1 + 1 file changed, 1 insertion(+) diff --git a/main/tests/test_templatetags_flags.py b/main/tests/test_templatetags_flags.py index 907fa8fa..ce1ccacc 100644 --- a/main/tests/test_templatetags_flags.py +++ b/main/tests/test_templatetags_flags.py @@ -1,5 +1,6 @@ from main.templatetags.flags import country_flag +# pylint: disable=W0611 from mirrors.tests.conftest import checklocation From 0f30d7147892005acd176791ed48f2b93cbfb513 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 4 Aug 2019 21:58:57 +0200 Subject: [PATCH 25/42] Update tests --- .coveragerc | 1 + conftest.py | 4 +- packages/tests.py | 160 -------------------- packages/tests/__init__.py | 0 packages/tests/test_adoptorphan_packages.py | 1 - packages/tests/test_unflag.py | 34 +++++ public/{tests.py => tests/test_views.py} | 0 visualize/{tests.py => tests/test_urls.py} | 0 8 files changed, 38 insertions(+), 162 deletions(-) delete mode 100644 packages/tests.py create mode 100644 packages/tests/__init__.py create mode 100644 packages/tests/test_unflag.py rename public/{tests.py => tests/test_views.py} (100%) rename visualize/{tests.py => tests/test_urls.py} (100%) diff --git a/.coveragerc b/.coveragerc index 4664e2bc..bd4aa6c5 100644 --- a/.coveragerc +++ b/.coveragerc @@ -10,3 +10,4 @@ omit = conftest.py local_settings.py /home/travis/virtualenv* + manage.py diff --git a/conftest.py b/conftest.py index 3cdc2650..8e5e1c06 100644 --- a/conftest.py +++ b/conftest.py @@ -2,6 +2,7 @@ from django.core.management import call_command +from main.models import Repo from devel.models import UserProfile @@ -31,8 +32,9 @@ def staff_groups(db): call_command('loaddata', 'devel/fixtures/staff_groups.json') +# TODO: test with non-admin user fixture @pytest.fixture -def admin_user_profile(admin_user): +def admin_user_profile(admin_user, arches, repos): profile = UserProfile.objects.create(user=admin_user, public_email="public@archlinux.org") yield profile diff --git a/packages/tests.py b/packages/tests.py deleted file mode 100644 index 18ea740d..00000000 --- a/packages/tests.py +++ /dev/null @@ -1,160 +0,0 @@ -from django.test import TransactionTestCase -from django.contrib.auth.models import User - -from main.models import Repo -from packages.models import PackageRelation -from devel.models import UserProfile - - - -class UnFlagPackage(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.profile = UserProfile.objects.create(user=self.user, - public_email="{}@awesome.com".format(self.user.username)) - self.profile.allowed_repos.add(Repo.objects.get(name='Core')) - self.profile.save() - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - self.profile.delete() - self.user.delete() - PackageRelation.objects.all().delete() - - def flag_package(self): - data = { - 'website': '', - 'email': 'nobody@archlinux.org', - 'message': 'new linux version', - } - response = self.client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) - self.assertEqual(response.status_code, 200) - - def test_unflag_package_404(self): - response = self.client.get('/packages/core/x86_64/fooobar/unflag/') - self.assertEqual(response.status_code, 404) - - response = self.client.get('/packages/core/x86_64/fooobar/unflag/all/') - self.assertEqual(response.status_code, 404) - - def test_unflag_package(self): - self.flag_package() - response = self.client.get('/packages/core/x86_64/linux/unflag/', follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Flag linux as out-of-date', response.content.decode()) - - def test_unflag_all_package(self): - self.flag_package() - response = self.client.get('/packages/core/x86_64/linux/unflag/all/', follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Flag linux as out-of-date', response.content.decode()) - - -class AdoptOrphanPackage(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.profile = UserProfile.objects.create(user=self.user, - public_email="{}@awesome.com".format(self.user.username)) - self.profile.allowed_repos.add(Repo.objects.get(name='Core')) - self.profile.save() - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - self.profile.delete() - self.user.delete() - PackageRelation.objects.all().delete() - - def request(self, pkgid, adopt=True): - data = { - 'pkgid': pkgid, - } - if adopt: - data['adopt'] = 'adopt' - else: - data['disown'] = 'disown' - return self.client.post('/packages/update/', data, follow=True) - - def test_adopt_package(self): - pkg = Package.objects.first() - response = self.request(pkg.id) - self.assertEqual(response.status_code, 200) - self.assertEqual(len(PackageRelation.objects.all()), 1) - - response = self.request(pkg.id, False) - self.assertEqual(response.status_code, 200) - self.assertEqual(len(PackageRelation.objects.all()), 0) - - def test_no_permissions(self): - self.profile.allowed_repos.set([]) - self.profile.save() - pkg = Package.objects.first() - - response = self.request(pkg.id) - self.assertEqual(response.status_code, 200) - self.assertEqual(len(PackageRelation.objects.all()), 0) - - def test_wrong_request(self): - pkg = Package.objects.first() - response = self.client.post('/packages/update/', {'pkgid': pkg.id, }, follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Are you trying to adopt or disown', response.content.decode()) - - def test_stale_relations(self): - response = self.client.get('/packages/stale_relations/') - self.assertEqual(response.status_code, 200) - - -class SignOffTest(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.profile = UserProfile.objects.create(user=self.user, - public_email="{}@awesome.com".format(self.user.username)) - self.profile.allowed_repos.add(Repo.objects.get(name='Core')) - self.profile.save() - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - self.profile.delete() - self.user.delete() - PackageRelation.objects.all().delete() - - def test_signoffs(self): - response = self.client.get('/packages/signoffs/') - self.assertEqual(response.status_code, 200) - - def test_signoffs_json(self): - response = self.client.get('/packages/signoffs/json/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json()['signoff_groups'], []) - - -# vim: set ts=4 sw=4 et: diff --git a/packages/tests/__init__.py b/packages/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/tests/test_adoptorphan_packages.py b/packages/tests/test_adoptorphan_packages.py index 5c3c3e38..1f086049 100644 --- a/packages/tests/test_adoptorphan_packages.py +++ b/packages/tests/test_adoptorphan_packages.py @@ -13,7 +13,6 @@ def request(client, pkgid, adopt=True): return client.post('/packages/update/', data, follow=True) - def test_wrong_request(admin_client, arches, repos, package): # TODO(jelle): fix pkg = Package.objects.first() diff --git a/packages/tests/test_unflag.py b/packages/tests/test_unflag.py new file mode 100644 index 00000000..077fbc32 --- /dev/null +++ b/packages/tests/test_unflag.py @@ -0,0 +1,34 @@ +def assert_flag_package(client): + data = { + 'website': '', + 'email': 'nobody@archlinux.org', + 'message': 'new linux version', + } + + # TODO: hardcoded package name + response = client.post('/packages/core/x86_64/linux/flag/', + data, + follow=True) + assert response.status_code == 200 + + +def test_unflag_package_404(admin_user_profile, admin_client): + response = admin_client.get('/packages/core/x86_64/fooobar/unflag/') + assert response.status_code == 404 + + response = admin_client.get('/packages/core/x86_64/fooobar/unflag/all/') + assert response.status_code == 404 + + +def test_unflag_package(admin_user_profile, admin_client, package): + assert_flag_package(admin_client) + response = admin_client.get('/packages/core/x86_64/linux/unflag/', follow=True) + assert response.status_code == 200 + assert 'Flag linux as out-of-date' in response.content.decode() + + +def test_unflag_all_package(admin_user_profile, admin_client, package): + assert_flag_package(admin_client) + response = admin_client.get('/packages/core/x86_64/linux/unflag/all/', follow=True) + assert response.status_code == 200 + assert 'Flag linux as out-of-date' in response.content.decode() diff --git a/public/tests.py b/public/tests/test_views.py similarity index 100% rename from public/tests.py rename to public/tests/test_views.py diff --git a/visualize/tests.py b/visualize/tests/test_urls.py similarity index 100% rename from visualize/tests.py rename to visualize/tests/test_urls.py From aaaaab99cebb1373a795aaca540c84f8e7c10ab4 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 4 Aug 2019 22:03:45 +0200 Subject: [PATCH 26/42] disable coverage reporting for the django debug toolbar --- urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/urls.py b/urls.py index 1bfbc7f4..034e1640 100644 --- a/urls.py +++ b/urls.py @@ -110,7 +110,7 @@ ]) # django-toolbar -if settings.DEBUG_TOOLBAR: +if settings.DEBUG_TOOLBAR: # pragma: no cover import debug_toolbar urlpatterns.extend([ path('__debug__/', include(debug_toolbar.urls)), From 60667ccc7d665b1246de7e1712f38f9e2079d6e8 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 4 Aug 2019 22:13:06 +0200 Subject: [PATCH 27/42] todolists: increase coverage for todolist models --- todolists/tests/test_models.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/todolists/tests/test_models.py b/todolists/tests/test_models.py index ccfed3f6..db62cc96 100644 --- a/todolists/tests/test_models.py +++ b/todolists/tests/test_models.py @@ -1,3 +1,6 @@ +from todolists.tests.conftest import NAME, RAW + + def test_stripped_description(todolist): todolist.description = 'Boost rebuild ' desc = todolist.stripped_description @@ -17,3 +20,15 @@ def test_packages(admin_user, todolist, todolistpackage): pkgs = todolist.packages() assert len(pkgs) == 1 assert pkgs[0] == todolistpackage + + +def test_str(admin_user, todolist): + assert NAME in str(todolist) + + +def test_todolist_str(admin_user, todolist, todolistpackage): + assert todolistpackage.pkgname in str(todolistpackage) + + +def test_status_css_class(admin_user, todolist, todolistpackage): + assert todolistpackage.status_css_class() == 'incomplete' From df32e88423bfd191f3157d912c0cd9f7fafa57d8 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 4 Aug 2019 22:15:56 +0200 Subject: [PATCH 28/42] mirrors: add test for "smart" protocol --- mirrors/tests/test_mirrorlist.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mirrors/tests/test_mirrorlist.py b/mirrors/tests/test_mirrorlist.py index b119195f..03f0f8f6 100644 --- a/mirrors/tests/test_mirrorlist.py +++ b/mirrors/tests/test_mirrorlist.py @@ -32,6 +32,11 @@ def test_mirrorlist_all_http(client, mirrorurl): assert response.status_code == 404 +def test_mirrorlist_all_smart(client, mirrorurl): + response = client.get('/mirrorlist/all/smart/', follow=True) + assert response.status_code == 404 + + def test_mirrorlist_status(client, mirrorurl): response = client.get('/mirrorlist/?country=all&use_mirror_status=on') assert response.status_code == 200 From 4bb9496128c45b98ce2671fd837b99f52f124cb4 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 4 Aug 2019 22:20:27 +0200 Subject: [PATCH 29/42] public: add logged in index view --- public/tests/test_views.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/tests/test_views.py b/public/tests/test_views.py index 9be36564..4c82ceac 100644 --- a/public/tests/test_views.py +++ b/public/tests/test_views.py @@ -3,6 +3,11 @@ def test_index(client, arches, repos, package, groups, staff_groups): assert response.status_code == 200 +def test_index_logged_in(admin_client, arches, repos, package, groups, staff_groups): + response = admin_client.get('/') + assert response.status_code == 200 + + def test_about(client, arches, repos, package, groups, staff_groups): response = client.get('/about/') assert response.status_code == 200 From 40325d1a8ee6d008fb1013ed5204e22bacbf1f71 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 4 Aug 2019 22:23:09 +0200 Subject: [PATCH 30/42] Add test for non existing dependencies --- devel/tests/test_reports.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/devel/tests/test_reports.py b/devel/tests/test_reports.py index 2906d940..1fea1c4c 100644 --- a/devel/tests/test_reports.py +++ b/devel/tests/test_reports.py @@ -58,3 +58,7 @@ def test_reports_mismatched_signature(self): def test_reports_signature_time(self): response = self.client.get('/devel/reports/signature-time', follow=True) self.assertEqual(response.status_code, 200) + + def test_non_existing_dependencies(self): + response = self.client.get('/devel/reports/non-existing-dependencies', follow=True) + self.assertEqual(response.status_code, 200) From 9de5aff084b1374109beb96c3ade95d72ff10ae1 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sun, 4 Aug 2019 22:24:05 +0200 Subject: [PATCH 31/42] conftest: remove unused import --- conftest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/conftest.py b/conftest.py index 8e5e1c06..702ca2fd 100644 --- a/conftest.py +++ b/conftest.py @@ -2,7 +2,6 @@ from django.core.management import call_command -from main.models import Repo from devel.models import UserProfile From cbe2caa72a2b03a33f44051009043d6a7249cf3f Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Mon, 5 Aug 2019 21:07:03 +0200 Subject: [PATCH 32/42] Fix typo in makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index baa6a826..74f429b1 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,8 @@ test-pdb: test lint: pylint devel main mirrors news packages releng templates todolists visualize *.py -collecstatic: - python manage.py collecstatic --noinput +collectstatic: + python manage.py collectstatic --noinput test: test-py From f6c4674cc5f729784abadd984c0f0bf75d356eb9 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Mon, 5 Aug 2019 21:12:17 +0200 Subject: [PATCH 33/42] Hardcore settins for testing --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 74f429b1..7f574ace 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ collectstatic: test: test-py test-py coverage: - ${PYTEST} ${PYTEST_INPUT} ${PYTEST_OPTIONS} ${PYTEST_COVERAGE_OPTIONS} + DJANGO_SETTINGS_MODULE=settings ${PYTEST} ${PYTEST_INPUT} ${PYTEST_OPTIONS} ${PYTEST_COVERAGE_OPTIONS} open-coverage: coverage ${BROWSER} htmlcov/index.html From 932e43b9ec92e33d8de692df6c098ff111a82e70 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Mon, 5 Aug 2019 21:30:46 +0200 Subject: [PATCH 34/42] Also install pytest-django --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c06a474a..b49a7a35 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: python python: - "3.7" cache: pip -install: "pip install -r requirements.txt && pip install coveralls pylint" +install: "pip install -r requirements.txt && pip install coveralls pylint pytest pytest-django" script: - make collectstatic From c7476597fcf81b2cbade4d9f34db3391c0b55ff3 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Mon, 5 Aug 2019 21:35:22 +0200 Subject: [PATCH 35/42] reroll options --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7f574ace..4519b54b 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ collectstatic: test: test-py test-py coverage: - DJANGO_SETTINGS_MODULE=settings ${PYTEST} ${PYTEST_INPUT} ${PYTEST_OPTIONS} ${PYTEST_COVERAGE_OPTIONS} + ${PYTEST} ${PYTEST_OPTIONS} ${PYTEST_COVERAGE_OPTIONS} ${PYTEST_INPUT} open-coverage: coverage ${BROWSER} htmlcov/index.html From 3621de4130c3a53882143033aed21f99ce0fb474 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Mon, 5 Aug 2019 21:40:00 +0200 Subject: [PATCH 36/42] ok wtf --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4519b54b..e06917db 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ collectstatic: test: test-py test-py coverage: - ${PYTEST} ${PYTEST_OPTIONS} ${PYTEST_COVERAGE_OPTIONS} ${PYTEST_INPUT} + DJANGO_SETTINGS_MODULE=settings ${PYTEST} ${PYTEST_OPTIONS} ${PYTEST_COVERAGE_OPTIONS} ${PYTEST_INPUT} open-coverage: coverage ${BROWSER} htmlcov/index.html From 1d54e2ee6c18227259c5f15e362983dc4c154a7d Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Mon, 5 Aug 2019 21:42:57 +0200 Subject: [PATCH 37/42] forgot pytest -cov --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b49a7a35..28880324 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: python python: - "3.7" cache: pip -install: "pip install -r requirements.txt && pip install coveralls pylint pytest pytest-django" +install: "pip install -r requirements.txt && pip install coveralls pylint pytest pytest-cov pytest-django" script: - make collectstatic From 91140ade58a38daa5afb10b8cd99972652e4b694 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Tue, 6 Aug 2019 18:21:56 +0200 Subject: [PATCH 38/42] Add requirements_test.txt file for test depenendencies --- .travis.yml | 2 +- README.md | 5 ++++- requirements_test.txt | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 requirements_test.txt diff --git a/.travis.yml b/.travis.yml index 28880324..ec4afab7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: python python: - "3.7" cache: pip -install: "pip install -r requirements.txt && pip install coveralls pylint pytest pytest-cov pytest-django" +install: "pip install -r requirements.txt && pip install -r requirements_test.txt" script: - make collectstatic diff --git a/README.md b/README.md index 611ae988..faab8c17 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,10 @@ In local\_settings.py add entries to set EMAIL\_HOST to 'localhost' and EMAIL\_P # Running tests and coverage +Install the test dependencies: + + pip install -r requirements_text.txt + To the unittests execute the following commands: ./manage.py collectstatic --noinput @@ -102,7 +106,6 @@ To the unittests execute the following commands: Running coverage: - pip install coverage coverage run --omit='env*' --source='.' manage.py test coverage report diff --git a/requirements_test.txt b/requirements_test.txt new file mode 100644 index 00000000..ff768e2f --- /dev/null +++ b/requirements_test.txt @@ -0,0 +1,6 @@ +coveralls +pylint +pytest +pytest-cov +pytest-django + From 84a37ec989ef9f51e72fc014485671c8d56904f9 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Tue, 6 Aug 2019 20:58:49 +0200 Subject: [PATCH 39/42] port todolists to pytest --- Makefile | 2 +- conftest.py | 22 +++++ todolists/tests/conftest.py | 2 + todolists/tests/test_views.py | 171 ++++++++++++++-------------------- 4 files changed, 97 insertions(+), 100 deletions(-) diff --git a/Makefile b/Makefile index e06917db..1e244ded 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ endif test-pdb: test -.PHONY: test lint +.PHONY: test lint coverage lint: pylint devel main mirrors news packages releng templates todolists visualize *.py diff --git a/conftest.py b/conftest.py index 702ca2fd..704a8477 100644 --- a/conftest.py +++ b/conftest.py @@ -1,10 +1,17 @@ import pytest +from django.contrib.auth.models import Group from django.core.management import call_command from devel.models import UserProfile +USERNAME = 'joeuser' +FIRSTNAME = 'Joe' +LASTNAME = 'User' +EMAIL = 'user1@example.com' + + @pytest.fixture def arches(db): call_command('loaddata', 'main/fixtures/arches.json') @@ -18,7 +25,10 @@ def repos(db): @pytest.fixture def package(db): # TODO(jelle): create own parameter based version + from main.models import Package + print(list(Package.objects.all())) call_command('loaddata', 'main/fixtures/package.json') + print(list(Package.objects.all())) @pytest.fixture @@ -38,3 +48,15 @@ def admin_user_profile(admin_user, arches, repos): public_email="public@archlinux.org") yield profile profile.delete() + + +@pytest.fixture +def user_client(client, django_user_model, groups): + user = django_user_model.objects.create_user(username=USERNAME, password=USERNAME) + profile = UserProfile.objects.create(user=user, + public_email="{}@archlinux.org".format(user.username)) + user.groups.add(Group.objects.get(name='Developers')) + client.login(username=USERNAME, password=USERNAME) + yield client + profile.delete() + user.delete() diff --git a/todolists/tests/conftest.py b/todolists/tests/conftest.py index 6dca6813..dba17410 100644 --- a/todolists/tests/conftest.py +++ b/todolists/tests/conftest.py @@ -5,6 +5,7 @@ NAME = 'Boost rebuild' +SLUG = 'boost-rebuild' DESCRIPTION = 'Boost 1.66 rebuild' RAW = 'linux' @@ -13,6 +14,7 @@ def todolist(admin_user, arches, repos, package): todolist = Todolist.objects.create(name=NAME, description=DESCRIPTION, + slug=SLUG, creator=admin_user, raw=RAW) yield todolist diff --git a/todolists/tests/test_views.py b/todolists/tests/test_views.py index 8c605bc3..1b886901 100644 --- a/todolists/tests/test_views.py +++ b/todolists/tests/test_views.py @@ -1,103 +1,76 @@ -from django.contrib.auth.models import User -from django.test import TestCase +from todolists.models import Todolist, TodolistPackage -from todolists.models import Todolist, TodolistPackage +def assert_create_todo(client): + response = client.post('/todo/add/', { + 'name': 'Foo rebuild', + 'description': 'The Foo Rebuild, please read the instructions', + 'raw': 'linux', + }, follow=True) + assert response.status_code == 200 + + +def test_todolist_overview(user_client, todolist): + response = user_client.get('/todo/') + assert response.status_code == 200 + assert todolist.name in response.content.decode() + + +def test_todolist_detail(todolist, user_client): + response = user_client.get(todolist.get_absolute_url()) + assert response.status_code == 200 + assert todolist.name in response.content.decode() + + +def test_todolist_json(todolist, user_client): + response = user_client.get(todolist.get_absolute_url() + 'json') + assert response.status_code == 200 + data = response.json() + assert data['name'] == todolist.name + + +def test_create_todolist(user_client): + assert_create_todo(user_client) + assert Todolist.objects.count() == 1 + Todolist.objects.all().delete() + + +def test_flag_pkg(user_client, arches, repos, package): + assert_create_todo(user_client) + + todolist = Todolist.objects.first() + package = todolist.packages().first() + assert package.status == TodolistPackage.INCOMPLETE + + response = user_client.get('/todo/{}/flag/{}/'.format(todolist.slug, package.id)) + assert response.status_code == 302 + + package = todolist.packages().first() + assert package.status == TodolistPackage.COMPLETE + + Todolist.objects.all().delete() + +def test_edit(user_client, arches, repos, package): + assert_create_todo(user_client) + + todolist = Todolist.objects.first() + assert todolist.packages().count() == 1 + + response = user_client.post('/todo/{}/edit/'.format(todolist.slug), { + 'name': 'Foo rebuild', + 'description': 'The Foo Rebuild, please read the instructions', + 'raw': 'linux\nglibc', + }) + assert response.status_code == 302 + todolist = Todolist.objects.first() + assert todolist.packages().count() == 2 + + Todolist.objects.all().delete() +def test_delete(user_client, arches, repos, package): + assert_create_todo(user_client) -class TestTodolist(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - self.user = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.todolist = Todolist.objects.create(name='Boost rebuild', - description='Boost 1.66 rebuid', - creator=self.user, - slug='boost-rebuild', - raw='linux') - - def test_todolist_overview(self): - response = self.client.get('/todo/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.todolist.name, response.content.decode()) - - def test_todolist_detail(self): - response = self.client.get(self.todolist.get_absolute_url()) - self.assertEqual(response.status_code, 200) - self.assertIn(self.todolist.name, response.content.decode()) - - def test_todolist_json(self): - response = self.client.get(self.todolist.get_absolute_url() + 'json') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['name'], self.todolist.name) - - -class TestTodolistAdmin(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser("admin", - "admin@archlinux.org", - password) - - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - Todolist.objects.all().delete() - self.user.delete() - - def create_todo(self): - return self.client.post('/todo/add/', { - 'name': 'Foo rebuild', - 'description': 'The Foo Rebuild, please read the instructions', - 'raw': 'linux', - }) - - def test_create_todolist(self): - response = self.create_todo() - self.assertEqual(response.status_code, 302) - self.assertEqual(len(Todolist.objects.all()), 1) - - def test_flag_pkg(self): - response = self.create_todo() - self.assertEqual(response.status_code, 302) - - todolist = Todolist.objects.first() - package = todolist.packages().first() - self.assertEqual(package.status, TodolistPackage.INCOMPLETE) - - response = self.client.get('/todo/{}/flag/{}/'.format(todolist.slug, package.id)) - self.assertEqual(response.status_code, 302) - - package = todolist.packages().first() - self.assertEqual(package.status, TodolistPackage.COMPLETE) - - def test_edit(self): - response = self.create_todo() - self.assertEqual(response.status_code, 302) - todolist = Todolist.objects.first() - self.assertEqual(len(todolist.packages().all()), 1) - - response = self.client.post('/todo/{}/edit/'.format(todolist.slug), { - 'name': 'Foo rebuild', - 'description': 'The Foo Rebuild, please read the instructions', - 'raw': 'linux\nglibc', - }) - self.assertEqual(response.status_code, 302) - todolist = Todolist.objects.first() - self.assertEqual(len(todolist.packages().all()), 2) - - def test_delete(self): - response = self.create_todo() - self.assertEqual(response.status_code, 302) - todolist = Todolist.objects.first() - response = self.client.post('/todo/{}/delete'.format(todolist.slug)) - self.assertEqual(response.status_code, 301) + todolist = Todolist.objects.first() + response = user_client.post('/todo/{}/delete'.format(todolist.slug)) + assert response.status_code == 301 + Todolist.objects.all().delete() From 08a396221e738578c5fc0659d14117f3ef73e4a6 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 23 May 2020 16:03:01 +0200 Subject: [PATCH 40/42] Remove unused test function --- main/tests/test_donor_import.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/main/tests/test_donor_import.py b/main/tests/test_donor_import.py index 97490fea..fbb01572 100644 --- a/main/tests/test_donor_import.py +++ b/main/tests/test_donor_import.py @@ -18,10 +18,6 @@ command = Command() -def gen_parse_subject(data): - return command.parse_subject(valid.format(data)) - - def test_parse_subject(): assert command.parse_subject('garbage') is None From 8b21e12d325c39543db0482ccf1b4da19c5089b7 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 23 May 2020 17:04:37 +0200 Subject: [PATCH 41/42] Port planet tests to pytest --- planet/tests/test_command.py | 81 +++++++++++++++++++++++------------- planet/tests/test_views.py | 16 +++---- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/planet/tests/test_command.py b/planet/tests/test_command.py index e93ce51a..ce4b70a1 100644 --- a/planet/tests/test_command.py +++ b/planet/tests/test_command.py @@ -1,7 +1,7 @@ import time from unittest import mock -from django.test import TestCase +import pytest from planet.models import Feed, FeedItem from planet.management.commands.update_planet import Command @@ -14,6 +14,7 @@ class Result(dict): def get(self, value): return getattr(self, value) + class Entry(dict): title = 'title' description = 'lorem ipsum' @@ -26,58 +27,82 @@ def get(self, value): return getattr(self, value) -class UpdatePlanetTest(TestCase): +@pytest.fixture +def command(): + yield Command() + + +@pytest.fixture +def feed(db): + return Feed(title='test', website='http://archlinux.org', + website_rss='http://archlinux.org/feed.rss') + + +class MockParse: + @staticmethod + def parse(): + return {} + + +@pytest.fixture +def mock_parse(monkeypatch): + def mock_get(*args, **kwargs): + return MockParse() - def setUp(self): - self.command = Command() - self.feed = Feed(title='test', website='http://archlinux.org', - website_rss='http://archlinux.org/feed.rss') + monkeypatch.setattr(feedparser, "parse", mock_get) - # Test when feedparser receives an exception and returns no status - @mock.patch('feedparser.parse') - def test_parse_feed_wrong(self, parse): + +# Test when feedparser receives an exception and returns no status +def test_parse_feed_wrong(feed, command): + with mock.patch('feedparser.parse') as parse: parse.return_value = {} - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_feed_304(self, parse): + +def test_parse_feed_304(feed, command): + with mock.patch('feedparser.parse') as parse: parse.return_value = {'status': 304} - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_feed_unknown(self, parse): + +def test_parse_feed_unknown(feed, command): + with mock.patch('feedparser.parse') as parse: parse.return_value = {'status': 201} - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_entries_empty(self, parse): + +def test_parse_entries_empty(feed, command): + with mock.patch('feedparser.parse') as parse: parse.return_value = Result() - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_entries_not_published(self, parse): + +def test_parse_entries_not_published(feed, command): + with mock.patch('feedparser.parse') as parse: value = Result() entry = Entry() entry.published_parsed = None value.entries = [entry] parse.return_value = value - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_entries(self, parse): + +def test_parse_entries(feed, command): + with mock.patch('feedparser.parse') as parse: value = Result() value.entries = [Entry()] parse.return_value = value - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 1 - @mock.patch('feedparser.parse') - def test_parse_entries_atom(self, parse): + +def test_parse_entries_atom(feed, command): + with mock.patch('feedparser.parse') as parse: value = Result() entry = Entry() entry.published_parsed = None @@ -85,5 +110,5 @@ def test_parse_entries_atom(self, parse): value.entries = [entry] parse.return_value = value - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 1 diff --git a/planet/tests/test_views.py b/planet/tests/test_views.py index b09c9e6b..864ff583 100644 --- a/planet/tests/test_views.py +++ b/planet/tests/test_views.py @@ -1,12 +1,8 @@ -from django.test import TestCase +def test_feed(db, client): + response = client.get('/feeds/planet/') + assert response.status_code == 200 -class PlanetTest(TestCase): - - def test_feed(self): - response = self.client.get('/feeds/planet/') - self.assertEqual(response.status_code, 200) - - def test_planet(self): - response = self.client.get('/planet/') - self.assertEqual(response.status_code, 200) +def test_planet(db, client): + response = client.get('/planet/') + assert response.status_code == 200 From 3d4827c0232766a26267b73b602c571ae7acfeda Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 23 May 2020 23:09:55 +0200 Subject: [PATCH 42/42] Port remainder to pytest --- conftest.py | 30 +- devel/tests/test_devel.py | 48 +--- devel/tests/test_reporead.py | 161 ++++++----- devel/tests/test_reports.py | 125 ++++---- devel/tests/test_user.py | 300 +++++++++++--------- mirrors/tests/conftest.py | 21 +- mirrors/tests/test_mirrorrsync.py | 39 ++- packages/tests/test_adoptorphan_packages.py | 18 +- packages/tests/test_unflag.py | 22 +- todolists/tests/test_models.py | 4 +- 10 files changed, 391 insertions(+), 377 deletions(-) diff --git a/conftest.py b/conftest.py index 704a8477..064f0e17 100644 --- a/conftest.py +++ b/conftest.py @@ -23,12 +23,9 @@ def repos(db): @pytest.fixture -def package(db): - # TODO(jelle): create own parameter based version - from main.models import Package - print(list(Package.objects.all())) +def package(db, arches, repos): + # TODO: convert to create_package with standard parameters call_command('loaddata', 'main/fixtures/package.json') - print(list(Package.objects.all())) @pytest.fixture @@ -41,22 +38,23 @@ def staff_groups(db): call_command('loaddata', 'devel/fixtures/staff_groups.json') -# TODO: test with non-admin user fixture @pytest.fixture -def admin_user_profile(admin_user, arches, repos): - profile = UserProfile.objects.create(user=admin_user, - public_email="public@archlinux.org") +def user(django_user_model): + user = django_user_model.objects.create_user(username=USERNAME, password=USERNAME) + yield user + user.delete() + + +@pytest.fixture +def userprofile(user): + profile = UserProfile.objects.create(user=user, + public_email=f'{user.username}@archlinux.org') yield profile profile.delete() @pytest.fixture -def user_client(client, django_user_model, groups): - user = django_user_model.objects.create_user(username=USERNAME, password=USERNAME) - profile = UserProfile.objects.create(user=user, - public_email="{}@archlinux.org".format(user.username)) +def user_client(client, user, userprofile, groups): user.groups.add(Group.objects.get(name='Developers')) client.login(username=USERNAME, password=USERNAME) - yield client - profile.delete() - user.delete() + return client diff --git a/devel/tests/test_devel.py b/devel/tests/test_devel.py index c8a28c1a..6835456b 100644 --- a/devel/tests/test_devel.py +++ b/devel/tests/test_devel.py @@ -1,42 +1,14 @@ -from django.test import TransactionTestCase -from django.contrib.auth.models import User, Group -from devel.models import UserProfile +def test_clock(user_client): + response = user_client.get('/devel/clock/') + assert response.status_code == 200 -class DevelView(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] +def test_profile(user_client): + response = user_client.get('/devel/profile/') + assert response.status_code == 200 + # Test changing - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - for name in ['Developers', 'Retired Developers']: - Group.objects.create(name=name) - self.user.groups.add(Group.objects.get(name='Developers')) - self.user.save() - self.profile = UserProfile.objects.create(user=self.user, - public_email="{}@awesome.com".format(self.user.username)) - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - def tearDown(self): - self.profile.delete() - self.user.delete() - Group.objects.all().delete() - - def test_clock(self): - response = self.client.get('/devel/clock/') - self.assertEqual(response.status_code, 200) - - def test_profile(self): - response = self.client.get('/devel/profile/') - self.assertEqual(response.status_code, 200) - # Test changing - - def test_stats(self): - response = self.client.get('/devel/stats/') - self.assertEqual(response.status_code, 200) +def test_stats(user_client): + response = user_client.get('/devel/stats/') + assert response.status_code == 200 diff --git a/devel/tests/test_reporead.py b/devel/tests/test_reporead.py index 0ffe3a17..d6eefd86 100644 --- a/devel/tests/test_reporead.py +++ b/devel/tests/test_reporead.py @@ -2,10 +2,10 @@ from unittest.mock import patch from datetime import datetime +import pytest from django.core.management import call_command from django.core.management.base import CommandError -from django.test import TransactionTestCase from django.utils import timezone @@ -13,82 +13,95 @@ from packages.models import FlagRequest -# Django's TestCase is wrapped in transaction, therefore use TransactionTestCase -class RepoReadTest(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json'] +@pytest.fixture +def create_pkg(arches, repos): + packages = [] - def create_pkg(self, repo=None, pkgver='4.10.1', pkgrel='1'): + def _create_pkg(repo=None, pkgver='4.10.1', pkgrel='1'): if not repo: repo = Repo.objects.get(name__iexact='core') arch = Arch.objects.get(name__iexact='any') now = datetime.now(tz=timezone.utc) - return Package.objects.create(arch=arch, repo=repo, pkgname='systemd', - pkgbase='systemd', pkgver=pkgver, - pkgrel=pkgrel, pkgdesc='Linux kernel', - compressed_size=10, installed_size=20, - last_update=now, created=now) - - def test_invalid_args(self): - with self.assertRaises(CommandError) as e: - call_command('reporead') - self.assertIn('missing arch and file.', str(e.exception)) - - with self.assertRaises(CommandError) as e: - call_command('reporead', 'x86_64') - self.assertIn('Package database file is required.', str(e.exception)) - - with self.assertRaises(CommandError) as e: - call_command('reporead', 'x86_64', 'nothing.db.tar.gz') - self.assertIn('Specified package database file does not exist.', str(e.exception)) - - def test_invalid_arch(self): - with self.assertRaises(CommandError) as e: - call_command('reporead', 'armv64', 'devel/fixtures/core.db.tar.gz') - self.assertEqual('Specified architecture armv64 is not currently known.', str(e.exception)) - - def test_read_packages(self): - with patch('devel.management.commands.reporead.logger') as logger: - call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') - logger.info.assert_called() - - # Verify contents - with tarfile.open('devel/fixtures/core.db.tar.gz') as tar: - files = [name.replace('core.db/', '') for name in tar.getnames() if name != 'core.db' and not 'desc' in name] - - packages = Package.objects.all() - import_packages = ["{}-{}-{}".format(pkg.pkgname, pkg.pkgver, pkg.pkgrel) for pkg in packages] - self.assertCountEqual(files, import_packages) - - def test_flagoutofdate(self): - pkg = self.create_pkg() - FlagRequest.objects.create(pkgbase=pkg.pkgbase, repo=pkg.repo, - pkgver=pkg.pkgver, epoch=pkg.epoch, - ip_address='1.1.1.1') - - with patch('devel.management.commands.reporead.logger') as logger: - call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') - logger.info.assert_called() - - self.assertEqual(len(FlagRequest.objects.all()), 0) - - def test_flagoutofdate_staging(self): - staging = Repo.objects.get(name__iexact='staging') - - pkg = self.create_pkg() - staging_pkg = self.create_pkg(repo=staging, pkgrel='2') - - FlagRequest.objects.create(pkgbase=pkg.pkgbase, repo=pkg.repo, - pkgver=pkg.pkgver, epoch=pkg.epoch, - ip_address='1.1.1.1') - FlagRequest.objects.create(pkgbase=staging_pkg.pkgbase, repo=staging_pkg.repo, - pkgver=staging_pkg.pkgver, epoch=staging_pkg.epoch, - ip_address='1.1.1.1') - - with patch('devel.management.commands.reporead.logger') as logger: - call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') - logger.info.assert_called() - - objects = FlagRequest.objects.all() - self.assertEqual(len(objects), 1) - self.assertEqual(objects[0].pkgver, staging_pkg.pkgver) + package = Package.objects.create(arch=arch, repo=repo, pkgname='systemd', + pkgbase='systemd', pkgver=pkgver, + pkgrel=pkgrel, pkgdesc='Linux kernel', + compressed_size=10, installed_size=20, + last_update=now, created=now) + packages.append(package) + return package + + yield _create_pkg + + for package in packages: + package.delete() + + +def test_invalid_args(): + with pytest.raises(CommandError) as excinfo: + call_command('reporead') + assert 'missing arch and file.' in str(excinfo) + + with pytest.raises(CommandError) as excinfo: + call_command('reporead', 'x86_64') + assert 'Package database file is required.' in str(excinfo) + + with pytest.raises(CommandError) as excinfo: + call_command('reporead', 'x86_64', 'nothing.db.tar.gz') + assert 'Specified package database file does not exist.' in str(excinfo) + + +def test_invalid_arch(transactional_db, arches, repos): + with pytest.raises(CommandError) as excinfo: + call_command('reporead', 'armv64', 'devel/fixtures/core.db.tar.gz') + assert 'Specified architecture armv64 is not currently known.' in str(excinfo) + + +# TODO: create pacman repo db with a pytest fixture +def test_read_packages(transactional_db, arches, repos): + with patch('devel.management.commands.reporead.logger') as logger: + call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') + logger.info.assert_called() + + # Verify contents + with tarfile.open('devel/fixtures/core.db.tar.gz') as tar: + files = [name.replace('core.db/', '') for name in tar.getnames() if name != 'core.db' and not 'desc' in name] + + packages = Package.objects.all() + import_packages = ["{}-{}-{}".format(pkg.pkgname, pkg.pkgver, pkg.pkgrel) for pkg in packages] + assert len(files) == len(import_packages) + + +def test_flagoutofdate(transactional_db, create_pkg): + pkg = create_pkg() + FlagRequest.objects.create(pkgbase=pkg.pkgbase, repo=pkg.repo, + pkgver=pkg.pkgver, epoch=pkg.epoch, + ip_address='1.1.1.1') + + with patch('devel.management.commands.reporead.logger') as logger: + call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') + logger.info.assert_called() + + assert not len(FlagRequest.objects.all()) + + +def test_flagoutofdate_staging(transactional_db, create_pkg): + staging = Repo.objects.get(name__iexact='staging') + + pkg = create_pkg() + staging_pkg = create_pkg(repo=staging, pkgrel='2') + + FlagRequest.objects.create(pkgbase=pkg.pkgbase, repo=pkg.repo, + pkgver=pkg.pkgver, epoch=pkg.epoch, + ip_address='1.1.1.1') + FlagRequest.objects.create(pkgbase=staging_pkg.pkgbase, repo=staging_pkg.repo, + pkgver=staging_pkg.pkgver, epoch=staging_pkg.epoch, + ip_address='1.1.1.1') + + with patch('devel.management.commands.reporead.logger') as logger: + call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') + logger.info.assert_called() + + objects = FlagRequest.objects.all() + assert len(objects) == 1 + assert objects[0].pkgver == staging_pkg.pkgver diff --git a/devel/tests/test_reports.py b/devel/tests/test_reports.py index 1fea1c4c..0e37f519 100644 --- a/devel/tests/test_reports.py +++ b/devel/tests/test_reports.py @@ -1,64 +1,61 @@ -from django.test import TransactionTestCase -from django.contrib.auth.models import User - - -class DeveloperReport(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - self.user.delete() - - def test_overview(self): - response = self.client.get('/devel/') - self.assertEqual(response.status_code, 200) - - def test_reports_old(self): - response = self.client.get('/devel/reports/old', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_outofdate(self): - response = self.client.get('/devel/reports/long-out-of-date', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_big(self): - response = self.client.get('/devel/reports/big', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_badcompression(self): - response = self.client.get('/devel/reports/badcompression', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_uncompressed_man(self): - response = self.client.get('/devel/reports/uncompressed-man', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_uncompressed_info(self): - response = self.client.get('/devel/reports/uncompressed-info', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_unneeded_orphans(self): - response = self.client.get('/devel/reports/unneeded-orphans', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_mismatched_signature(self): - response = self.client.get('/devel/reports/mismatched-signature', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_signature_time(self): - response = self.client.get('/devel/reports/signature-time', follow=True) - self.assertEqual(response.status_code, 200) - - def test_non_existing_dependencies(self): - response = self.client.get('/devel/reports/non-existing-dependencies', follow=True) - self.assertEqual(response.status_code, 200) +import pytest + + +@pytest.fixture +def report_client(user_client, arches, repos, package): + return user_client + + +def test_overview(report_client): + response = report_client.get('/devel/') + assert response.status_code == 200 + + +def test_reports_old(report_client): + response = report_client.get('/devel/reports/old', follow=True) + assert response.status_code == 200 + + +def test_reports_outofdate(report_client): + response = report_client.get('/devel/reports/long-out-of-date', follow=True) + assert response.status_code == 200 + + +def test_reports_big(report_client): + response = report_client.get('/devel/reports/big', follow=True) + assert response.status_code == 200 + + +def test_reports_badcompression(report_client): + response = report_client.get('/devel/reports/badcompression', follow=True) + assert response.status_code == 200 + + +def test_reports_uncompressed_man(report_client): + response = report_client.get('/devel/reports/uncompressed-man', follow=True) + assert response.status_code == 200 + + +def test_reports_uncompressed_info(report_client): + response = report_client.get('/devel/reports/uncompressed-info', follow=True) + assert response.status_code == 200 + + +def test_reports_unneeded_orphans(report_client): + response = report_client.get('/devel/reports/unneeded-orphans', follow=True) + assert response.status_code == 200 + + +def test_reports_mismatched_signature(report_client): + response = report_client.get('/devel/reports/mismatched-signature', follow=True) + assert response.status_code == 200 + + +def test_reports_signature_time(report_client): + response = report_client.get('/devel/reports/signature-time', follow=True) + assert response.status_code == 200 + + +def test_non_existing_dependencies(report_client): + response = report_client.get('/devel/reports/non-existing-dependencies', follow=True) + assert response.status_code == 200 diff --git a/devel/tests/test_user.py b/devel/tests/test_user.py index 91c0b1e6..6f434824 100644 --- a/devel/tests/test_user.py +++ b/devel/tests/test_user.py @@ -1,135 +1,177 @@ -from django.contrib.auth.models import User -from django.test import TestCase +import pytest + +from django.contrib.auth.models import User from devel.utils import UserFinder from devel.models import UserProfile -class DevelTest(TestCase): - def test_index(self): - response = self.client.get('/devel/') - self.assertEqual(response.status_code, 302) - self.assertEqual(response.has_header('Location'), True) - self.assertEqual(response['location'], - '/login/?next=/devel/') - - def test_profile(self): - response = self.client.get('/devel/profile/') - self.assertEqual(response.status_code, 302) - self.assertEqual(response.has_header('Location'), True) - self.assertEqual(response['location'], - '/login/?next=/devel/profile/') - - def test_newuser(self): - response = self.client.get('/devel/newuser/') - self.assertEqual(response.status_code, 302) - self.assertEqual(response.has_header('Location'), True) - self.assertEqual(response['location'], - '/login/?next=/devel/newuser/') - - def test_mirrors(self): - response = self.client.get('/mirrors/') - self.assertEqual(response.status_code, 200) - - def test_admin_log(self): - User.objects.create_superuser('admin', 'admin@archlinux.org', 'admin') - response = self.client.post('/login/', {'username': 'admin', 'password': 'admin'}) - response = self.client.get('/devel/admin_log', follow=True) - self.assertEqual(response.status_code, 200) - -class FindUserTest(TestCase): - - def setUp(self): - self.finder = UserFinder() - - self.user1 = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.user2 = User.objects.create(username="john", first_name="John", - last_name="", email="user2@example.com") - self.user3 = User.objects.create(username="bjones", first_name="Bob", - last_name="Jones", email="user3@example.com") - - for user in (self.user1, self.user2, self.user3): - email_addr = "%s@awesome.com" % user.username - UserProfile.objects.create(user=user, public_email=email_addr) - - self.user4 = User.objects.create(username="tim1", first_name="Tim", - last_name="One", email="tim@example.com") - self.user5 = User.objects.create(username="tim2", first_name="Tim", - last_name="Two", email="timtwo@example.com") - - def test_not_matching(self): - self.assertIsNone(self.finder.find(None)) - self.assertIsNone(self.finder.find("")) - self.assertIsNone(self.finder.find("Bogus")) - self.assertIsNone(self.finder.find("Bogus ")) - self.assertIsNone(self.finder.find("")) - self.assertIsNone(self.finder.find("bogus@example.com")) - self.assertIsNone(self.finder.find("Unknown Packager")) - - def test_by_email(self): - self.assertEqual(self.user1, - self.finder.find("XXX YYY ")) - self.assertEqual(self.user2, - self.finder.find("YYY ZZZ ")) - - def test_by_profile_email(self): - self.assertEqual(self.user1, - self.finder.find("XXX ")) - self.assertEqual(self.user2, - self.finder.find("YYY ")) - self.assertEqual(self.user3, - self.finder.find("ZZZ ")) - - def test_by_name(self): - self.assertEqual(self.user1, - self.finder.find("Joe User ")) - self.assertEqual(self.user1, - self.finder.find("Joe User")) - self.assertEqual(self.user2, - self.finder.find("John ")) - self.assertEqual(self.user2, - self.finder.find("John")) - self.assertEqual(self.user3, - self.finder.find("Bob Jones ")) - - def test_by_invalid(self): - self.assertEqual(self.user1, - self.finder.find("Joe User ")) - self.assertEqual(self.user3, - self.finder.find("Bob Jones ")) - - def test_ambiguous(self): - self.assertEqual(self.user4, - self.finder.find("Tim One ")) - self.assertEqual(self.user5, - self.finder.find("Tim Two ")) - self.assertIsNone(self.finder.find("Tim ")) - - def test_find_by_username(self): - self.assertEqual(self.finder.find_by_username(None), None) - self.assertEqual(self.finder.find_by_username('noone'), None) - self.assertEqual(self.finder.find_by_username(self.user1.username), self.user1) - # Test cache - self.assertEqual(self.finder.find_by_username(self.user1.username), self.user1) - - def test_find_by_email(self): - self.assertEqual(self.finder.find_by_email(None), None) - self.assertEqual(self.finder.find_by_email('bar@bar.com'), None) - self.assertEqual(self.finder.find_by_email(self.user1.email), self.user1) - # Test cache - self.assertEqual(self.finder.find_by_email(self.user1.email), self.user1) + +def test_index(client): + response = client.get('/devel/') + assert response.status_code == 302 + assert response.has_header('Location') + assert response['location'] == '/login/?next=/devel/' + + +def test_profile(client): + response = client.get('/devel/profile/') + assert response.status_code == 302 + assert response.has_header('Location') + assert response['location'] == '/login/?next=/devel/profile/' + + +def test_newuser(client): + response = client.get('/devel/newuser/') + assert response.status_code == 302 + assert response.has_header('Location') + assert response['location'] == '/login/?next=/devel/newuser/' + + +def test_mirrors(client, db): + response = client.get('/mirrors/') + assert response.status_code == 200 + + +def test_admin_log(admin_client): + response = admin_client.get('/devel/admin_log', follow=True) + assert response.status_code == 200 + + +@pytest.fixture +def user1(django_user_model): + user1 = django_user_model.objects.create(username="joeuser", first_name="Joe", + last_name="User", email="user1@example.com") + email_addr = "%s@awesome.com" % user1.username + profile = UserProfile.objects.create(user=user1, public_email=email_addr) + yield user1 + profile.delete() + user1.delete() + + +@pytest.fixture +def create_user(django_user_model): + users = [] + + def _create_user(username, firstname, lastname="", email="", public_email=""): + user = User.objects.create(username=username, first_name=firstname, + last_name=lastname, email=email) + profile = None + + if public_email: + profile = UserProfile.objects.create(user=user, public_email=public_email) + + users.append((user, profile)) + return user + + yield _create_user + + for user, prof in users: + if prof: + prof.delete() + user.delete() + + +@pytest.fixture() +def users(create_user): + create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + create_user('john', 'John', '', 'user2@example.com', 'john@awesome.com') + create_user('bjones', 'Bob', 'Jones', 'user3@example.com', 'bjones@awesome.com') + + create_user('tin1', 'Tim', 'One', 'tim@example.com') + create_user('tin2', 'Tim', 'Two', 'timtwo@example.com') + + +@pytest.fixture() +def finder(): + return UserFinder() + + +def test_not_matching(finder, users): + + assert not finder.find(None) + assert not finder.find("") + assert not finder.find("Bogus") + assert not finder.find("Bogus ") + assert not finder.find("") + assert not finder.find("bogus@example.com") + assert not finder.find("Unknown Packager") + + +def test_by_email(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + user2 = create_user('john', 'John', '', 'user2@example.com', 'john@example.com') + + assert user1 == finder.find("XXX YYY ") + assert user2 == finder.find("YYY ZZZ ") + + +def test_by_profile_email(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + user2 = create_user('john', 'John', '', 'user2@example.com', 'john@awesome.com') + user3 = create_user('bjones', 'Bob', 'Jones', 'user3@example.com', 'bjones@awesome.com') + + assert user1 == finder.find("XXX ") + assert user2 == finder.find("YYY ") + assert user3 == finder.find("ZZZ ") + + +def test_by_name(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + user2 = create_user('john', 'John', '', 'user2@example.com', 'john@awesome.com') + user3 = create_user('bjones', 'Bob', 'Jones', 'user3@example.com', 'bjones@awesome.com') + + assert user1 == finder.find("Joe User ") + assert user1 == finder.find("Joe User") + assert user2 == finder.find("John ") + assert user2 == finder.find("John") + assert user3 == finder.find("Bob Jones ") + + +def test_by_invalid(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + + assert user1 == finder.find("Joe User ") + assert user3 == finder.find("Bob Jones ") + + +def test_ambiguous(finder, create_user): + user4 = create_user('tin1', 'Tim', 'One', 'tim@example.com') + user5 = create_user('tin2', 'Tim', 'Two', 'timtwo@example.com') + assert user4 == finder.find("Tim One ") + assert user5 == finder.find("Tim Two ") + assert not finder.find("Tim ") + + +def test_find_by_username(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + + assert not finder.find_by_username(None) + assert not finder.find_by_username('noone') + assert user1 == finder.find_by_username(user1.username) + # Test cache + assert user1 == finder.find_by_username(user1.username) + + +def test_find_by_email(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + + assert not finder.find_by_email(None) + assert not finder.find_by_email('bar@bar.com') + assert user1 == finder.find_by_username(user1.username) + # Test cache + assert user1 == finder.find_by_username(user1.username) # vim: set ts=4 sw=4 et: diff --git a/mirrors/tests/conftest.py b/mirrors/tests/conftest.py index 72bf5947..24028d8d 100644 --- a/mirrors/tests/conftest.py +++ b/mirrors/tests/conftest.py @@ -14,10 +14,10 @@ @pytest.fixture def mirror(db, name=NAME, admin_email=ADMIN_EMAIL): - mirror = Mirror.objects.create(name=name, - admin_email=admin_email) - yield mirror - mirror.delete() + mirror = Mirror.objects.create(name=name, + admin_email=admin_email) + yield mirror + mirror.delete() @pytest.fixture @@ -39,17 +39,18 @@ def mirrorprotocol(db, protocol=PROTOCOL): @pytest.fixture def mirrorurl(db, mirror, mirrorprotocol, country=COUNTRY, url=URL): - mirror_url = MirrorUrl.objects.create(url=url, - protocol=mirrorprotocol, - mirror=mirror, - country=country) - yield mirror_url - mirror_url.delete() + mirror_url = MirrorUrl.objects.create(url=url, + protocol=mirrorprotocol, + mirror=mirror, + country=country) + yield mirror_url + mirror_url.delete() @pytest.fixture def create_mirrorurl(db, mirror, mirrorprotocol): mirrors = [] + def _create_mirrorurl(country=COUNTRY, url=URL): mirror_url = MirrorUrl.objects.create(url=url, protocol=mirrorprotocol, diff --git a/mirrors/tests/test_mirrorrsync.py b/mirrors/tests/test_mirrorrsync.py index 31dc325d..9f18fedd 100644 --- a/mirrors/tests/test_mirrorrsync.py +++ b/mirrors/tests/test_mirrorrsync.py @@ -1,30 +1,23 @@ -from django.test import TransactionTestCase +import pytest -from mirrors.models import MirrorRsync, Mirror +from mirrors.models import MirrorRsync -TEST_IPV6 = "2a0b:4342:1a31:410::" -TEST_IPV4 = "8.8.8.8" +def test_invalid(transactional_db, mirror): + with pytest.raises(ValueError) as excinfo: + MirrorRsync.objects.create(ip="8.8.8.8.8", mirror=mirror) + assert 'IPv4 Address with more than 4 bytes' in str(excinfo) -class MirrorRsyncTest(TransactionTestCase): - def setUp(self): - self.mirror = Mirror.objects.create(name='rmirror', - admin_email='foo@bar.com') - def tearDown(self): - self.mirror.delete() +def test_ipv6(transactional_db, mirror): + ipv6 = "2a0b:4342:1a31:410::" + mirrorrsync = MirrorRsync.objects.create(ip=ipv6, mirror=mirror) + assert str(mirrorrsync) == ipv6 + mirrorrsync.delete() - def test_ipv6(self): - mirrorrsync = MirrorRsync.objects.create(ip=TEST_IPV6, mirror=self.mirror) - self.assertEqual(str(mirrorrsync), TEST_IPV6) - mirrorrsync.delete() - def test_ipv4(self): - mirrorrsync = MirrorRsync.objects.create(ip=TEST_IPV4, mirror=self.mirror) - self.assertEqual(str(mirrorrsync), TEST_IPV4) - mirrorrsync.delete() - - def test_invalid(self): - with self.assertRaises(ValueError) as e: - MirrorRsync.objects.create(ip="8.8.8.8.8", mirror=self.mirror) - self.assertIn('IPv4 Address with more than 4 bytes', str(e.exception)) +def test_ipv4(transactional_db, mirror): + ipv4 = "8.8.8.8" + mirrorrsync = MirrorRsync.objects.create(ip=ipv4, mirror=mirror) + assert str(mirrorrsync) == ipv4 + mirrorrsync.delete() diff --git a/packages/tests/test_adoptorphan_packages.py b/packages/tests/test_adoptorphan_packages.py index 1f086049..8d9bda9b 100644 --- a/packages/tests/test_adoptorphan_packages.py +++ b/packages/tests/test_adoptorphan_packages.py @@ -14,33 +14,33 @@ def request(client, pkgid, adopt=True): def test_wrong_request(admin_client, arches, repos, package): - # TODO(jelle): fix + # TODO(jelle): fix pkg = Package.objects.first() response = admin_client.post('/packages/update/', {'pkgid': pkg.id, }, follow=True) assert response.status_code == 200 assert 'Are you trying to adopt or disown' in response.content.decode() -def test_stale_relations(admin_user_profile, admin_client, arches, repos, package): - response = admin_client.get('/packages/stale_relations/') +def test_stale_relations(user_client, arches, repos, package): + response = user_client.get('/packages/stale_relations/') assert response.status_code == 200 -def test_no_permissions(admin_client, admin_user_profile, arches, repos, package): +def test_no_permissions(user_client, arches, repos, package): pkg = Package.objects.first() - response = request(admin_client, pkg.id) + response = request(user_client, pkg.id) assert response.status_code == 200 assert len(PackageRelation.objects.all()) == 0 -def test_adopt_package(admin_client, admin_user_profile, arches, repos, package): - admin_user_profile.allowed_repos.add(Repo.objects.get(name='Core')) +def test_adopt_package(user_client, userprofile, arches, repos, package): + userprofile.allowed_repos.add(Repo.objects.get(name='Core')) pkg = Package.objects.first() - response = request(admin_client, pkg.id) + response = request(user_client, pkg.id) assert response.status_code == 200 assert len(PackageRelation.objects.all()) == 1 - response = request(admin_client, pkg.id, False) + response = request(user_client, pkg.id, False) assert response.status_code == 200 assert len(PackageRelation.objects.all()) == 0 diff --git a/packages/tests/test_unflag.py b/packages/tests/test_unflag.py index 077fbc32..16724bb1 100644 --- a/packages/tests/test_unflag.py +++ b/packages/tests/test_unflag.py @@ -6,29 +6,27 @@ def assert_flag_package(client): } # TODO: hardcoded package name - response = client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) + response = client.post('/packages/core/x86_64/linux/flag/', data, follow=True) assert response.status_code == 200 -def test_unflag_package_404(admin_user_profile, admin_client): - response = admin_client.get('/packages/core/x86_64/fooobar/unflag/') +def test_unflag_package_404(user_client): + response = user_client.get('/packages/core/x86_64/fooobar/unflag/') assert response.status_code == 404 - response = admin_client.get('/packages/core/x86_64/fooobar/unflag/all/') + response = user_client.get('/packages/core/x86_64/fooobar/unflag/all/') assert response.status_code == 404 -def test_unflag_package(admin_user_profile, admin_client, package): - assert_flag_package(admin_client) - response = admin_client.get('/packages/core/x86_64/linux/unflag/', follow=True) +def test_unflag_package(user_client, package): + assert_flag_package(user_client) + response = user_client.get('/packages/core/x86_64/linux/unflag/', follow=True) assert response.status_code == 200 assert 'Flag linux as out-of-date' in response.content.decode() -def test_unflag_all_package(admin_user_profile, admin_client, package): - assert_flag_package(admin_client) - response = admin_client.get('/packages/core/x86_64/linux/unflag/all/', follow=True) +def test_unflag_all_package(user_client, package): + assert_flag_package(user_client) + response = user_client.get('/packages/core/x86_64/linux/unflag/all/', follow=True) assert response.status_code == 200 assert 'Flag linux as out-of-date' in response.content.decode() diff --git a/todolists/tests/test_models.py b/todolists/tests/test_models.py index db62cc96..61ed458d 100644 --- a/todolists/tests/test_models.py +++ b/todolists/tests/test_models.py @@ -1,10 +1,10 @@ -from todolists.tests.conftest import NAME, RAW +from todolists.tests.conftest import NAME def test_stripped_description(todolist): todolist.description = 'Boost rebuild ' desc = todolist.stripped_description - assert desc.endswith(' ') == False + assert not desc.endswith(' ') def test_get_absolute_url(todolist):