Merge pull request 'added tests' (#15) from tests into main
continuous-integration/drone/push Build is failing Details

Reviewed-on: #15
This commit is contained in:
jens 2020-11-08 14:48:47 +00:00
commit 31662a5273
9 changed files with 82 additions and 18 deletions

View File

@ -8,8 +8,16 @@ platform:
arch: amd64 arch: amd64
steps: steps:
- name: test - name: install deps
commands: commands:
- dnf install -y python3 python3-pip - dnf install -y python3 python3-pip
- pip3 install -U Django - pip3 install -U Django coverage flake8 pylint django-coverage-plugin pylint-django
- python3 manage.py test - name: run unittests
commands:
- coverage run --source='.' manage.py test --noinput --parallel
- name: run flake8
commands:
- flake8
- name: run pylint
commands:
- pylint --rcfile=.pylintrc -- **/*.py

3
.gitignore vendored
View File

@ -102,3 +102,6 @@ venv.bak/
# mypy # mypy
.mypy_cache/ .mypy_cache/
.DS_Store

14
.pylintrc Normal file
View File

@ -0,0 +1,14 @@
[MASTER]
load-plugins=pylint_django
[FORMAT]
max-line-length=120
[MESSAGES CONTROL]
disable=missing-docstring,unnecessary-pass
[DESIGN]
max-parents=13
[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,"[a-zA-Z]+_set{1,2}",save,delete

View File

@ -64,6 +64,7 @@ TEMPLATES = [
'django.contrib.auth.context_processors.auth', 'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
], ],
'debug': DEBUG,
}, },
}, },
] ]
@ -100,6 +101,10 @@ AUTH_PASSWORD_VALIDATORS = [
}, },
] ]
# enabling this may speed up testing
# PASSWORD_HASHERS = [
# 'django.contrib.auth.hashers.MD5PasswordHasher',
# ]
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/ # https://docs.djangoproject.com/en/2.1/topics/i18n/

View File

@ -9,7 +9,6 @@ class PantryItemInLine(admin.TabularInline):
extra = 1 extra = 1
class LocationInLine(admin.TabularInline): class LocationInLine(admin.TabularInline):
model = Location model = Location
extra = 1 extra = 1
@ -17,11 +16,15 @@ class LocationInLine(admin.TabularInline):
def upper_case_name(obj): def upper_case_name(obj):
return obj.name.upper() return obj.name.upper()
upper_case_name.short_description = 'Name' upper_case_name.short_description = 'Name'
def capitalize_name(obj): def capitalize_name(obj):
return obj.name.capitalize() return obj.name.capitalize()
upper_case_name.short_description = 'Name' upper_case_name.short_description = 'Name'
@ -65,7 +68,7 @@ class PantryItemAdmin(admin.ModelAdmin):
inlines = [PantryItemInLine] inlines = [PantryItemInLine]
# TODO: make category a model # TODO: make category a model
#autocomplete_fields = ['category',] # autocomplete_fields = ['category',]
fields = ( fields = (
'name', 'name',
'category', 'category',
@ -93,6 +96,7 @@ class ShoppingListItemAdmin(PantryItemAdmin):
'info', 'info',
) )
admin.site.register(PantryItem, PantryItemAdmin) admin.site.register(PantryItem, PantryItemAdmin)
admin.site.register(ShoppingListItem, ShoppingListItemAdmin) admin.site.register(ShoppingListItem, ShoppingListItemAdmin)
admin.site.register(PantryItemLine, PantryItemLineAdmin) admin.site.register(PantryItemLine, PantryItemLineAdmin)

View File

@ -57,7 +57,7 @@ class PantryItem(models.Model):
# if expiry duration is set the expiration date for a pantryitemline will be set to now + duration on save # if expiry duration is set the expiration date for a pantryitemline will be set to now + duration on save
# represents days # represents days
expiry_duration = models.IntegerField(null=True, blank=True) expiry_duration = models.IntegerField(null=True, blank=True)
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
unit = models.ForeignKey(Unit, on_delete=models.PROTECT, null=True) unit = models.ForeignKey(Unit, on_delete=models.PROTECT, null=True)
info = models.CharField(max_length=200, null=True, blank=True) info = models.CharField(max_length=200, null=True, blank=True)
# location is saved on a per item base, not itemline # location is saved on a per item base, not itemline
@ -78,7 +78,7 @@ class PantryItemLine(models.Model):
pantry_item = models.ForeignKey(PantryItem, on_delete=models.PROTECT) pantry_item = models.ForeignKey(PantryItem, on_delete=models.PROTECT)
quantity = models.IntegerField(default=1) quantity = models.IntegerField(default=1)
expiry_date = models.DateField(null=True, blank=True) expiry_date = models.DateField(null=True, blank=True)
size = models.IntegerField(default=1) #, decimal_places=3, max_digits=32) size = models.IntegerField(default=1)
info = models.CharField(max_length=200, null=True, blank=True) info = models.CharField(max_length=200, null=True, blank=True)
def unit(self): def unit(self):
@ -88,5 +88,5 @@ class PantryItemLine(models.Model):
return reverse('pantryitemlinedetail', kwargs={'pk': self.pk}) return reverse('pantryitemlinedetail', kwargs={'pk': self.pk})
def __str__(self): def __str__(self):
return ' '.join([str(x) for x in [self.pantry_item.name, self.quantity, 'X', self.size, self.pantry_item.unit]]) return ' '.join([str(x) for x in [self.pantry_item.name, self.quantity, 'X',
self.size, self.pantry_item.unit]])

View File

@ -1,3 +1,25 @@
from django.test import TestCase from django.test import TestCase
from django.test import Client
# Create your tests here. from inventory.models import PantryItem, Category
class PantryItemTestCase(TestCase):
""" simple test case for a model"""
def setUp(self):
cat = Category.objects.create(name="UNCATEGORIZED")
PantryItem.objects.create(name="testitem", category=cat)
def test_pantryitem_looksok(self):
"""Pantryitems to string is ok"""
testitem = PantryItem.objects.get(name="testitem")
self.assertEqual(str(testitem), 'testitem')
class InterFaceTestCase(TestCase):
"""Simple test case for the web interface"""
def test_consume_view_exists(self):
client = Client()
response = client.get('/consume/')
self.assertTrue(b"TODO" not in response.content)

View File

@ -1,7 +1,5 @@
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render
from django.http import HttpResponse
from django.views import generic from django.views import generic
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from django.db.models import F, Sum, Q from django.db.models import F, Sum, Q
@ -26,9 +24,10 @@ class Shoppinglist(generic.ListView):
""" """
Return pantryitems for which we have None itemlines or Itemlines whith a total quantitly less than required Return pantryitems for which we have None itemlines or Itemlines whith a total quantitly less than required
""" """
return PantryItem.objects.annotate(total_quantity=Sum(F('pantryitemline__quantity') * return PantryItem.objects.annotate(
F('pantryitemline__size'))).filter(Q(min_quantity__gt=F('total_quantity')) | Q(pantryitemline=None, total_quantity=Sum(F('pantryitemline__quantity') *
min_quantity__gt=0)) F('pantryitemline__size'))
).filter(Q(min_quantity__gt=F('total_quantity')) | Q(pantryitemline=None, min_quantity__gt=0))
class Expirations(generic.ListView): class Expirations(generic.ListView):

9
setup.cfg Normal file
View File

@ -0,0 +1,9 @@
[flake8]
max-line-length = 120
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules,venv
[coverage:run]
include = '.'
omit = *migrations*, *tests*
plugins =
django_coverage_plugin