Add some more unit testing for the builds

This commit is contained in:
Oliver Walters 2020-04-27 21:28:44 +10:00
parent 35f48ed899
commit cb3fe0fc35
4 changed files with 193 additions and 7 deletions

View File

@ -205,10 +205,12 @@ When running unit tests, enforce usage of sqlite3 database,
so that the tests can be run in RAM without any setup requirements
"""
if 'test' in sys.argv:
eprint('Running tests - Using sqlite3 memory database')
eprint('InvenTree: Running tests - Using sqlite3 memory database')
DATABASES['default'] = {
# Ensure sqlite3 backend is being used
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test_db.sqlite3'
# Doesn't matter what the database is called, it is executed in RAM
'NAME': 'ram_test_db.sqlite3',
}
# Database backend selection

View File

@ -371,11 +371,12 @@ class Build(MPTTModel):
parts = []
for item in self.part.bom_items.all().prefetch_related('sub_part'):
part = {'part': item.sub_part,
'per_build': item.quantity,
'quantity': item.quantity * self.quantity,
'allocated': self.getAllocatedQuantity(item.sub_part)
}
part = {
'part': item.sub_part,
'per_build': item.quantity,
'quantity': item.quantity * self.quantity,
'allocated': self.getAllocatedQuantity(item.sub_part)
}
parts.append(part)

View File

@ -0,0 +1,181 @@
# -*- coding: utf-8 -*-
from django.test import TestCase
from django.core.exceptions import ValidationError
from django.db import transaction
from django.db.utils import IntegrityError
from build.models import Build, BuildItem
from stock.models import StockItem
from part.models import Part, BomItem
from InvenTree import status_codes as status
class BuildTest(TestCase):
"""
Run some tests to ensure that the Build model is working properly.
"""
def setUp(self):
"""
Initialize data to use for these tests.
"""
# Create a base "Part"
self.assembly = Part.objects.create(
name="An assembled part",
description="Why does it matter what my description is?",
assembly=True
)
self.sub_part_1 = Part.objects.create(
name="Widget A",
description="A widget",
component=True
)
self.sub_part_2 = Part.objects.create(
name="Widget B",
description="A widget",
component=True
)
# Create BOM item links for the parts
BomItem.objects.create(
part=self.assembly,
sub_part=self.sub_part_1,
quantity=10
)
BomItem.objects.create(
part=self.assembly,
sub_part=self.sub_part_2,
quantity=25
)
# Create a "Build" object to make 10x objects
self.build = Build.objects.create(
title="This is a build",
part=self.assembly,
quantity=10
)
# Create some stock items to assign to the build
self.stock_1_1 = StockItem.objects.create(part=self.sub_part_1, quantity=1000)
self.stock_1_2 = StockItem.objects.create(part=self.sub_part_1, quantity=100)
self.stock_2_1 = StockItem.objects.create(part=self.sub_part_2, quantity=5000)
def test_init(self):
# Perform some basic tests before we start the ball rolling
self.assertEqual(StockItem.objects.count(), 3)
self.assertEqual(self.build.status, status.BuildStatus.PENDING)
self.assertFalse(self.build.isFullyAllocated())
self.assertFalse(self.build.isPartFullyAllocated(self.sub_part_1))
self.assertFalse(self.build.isPartFullyAllocated(self.sub_part_2))
self.assertEqual(self.build.getRequiredQuantity(self.sub_part_1), 100)
self.assertEqual(self.build.getRequiredQuantity(self.sub_part_2), 250)
self.assertTrue(self.build.can_build)
self.assertFalse(self.build.is_complete)
def test_duplicate_bom_line(self):
# Try to add a duplicate BOM item - it should fail!
with self.assertRaises(IntegrityError):
BomItem.objects.create(
part=self.assembly,
sub_part=self.sub_part_1,
quantity=99
)
def allocate_stock(self, q11, q12, q21):
# Assign stock to this build
BuildItem.objects.create(
build=self.build,
stock_item=self.stock_1_1,
quantity=q11
)
BuildItem.objects.create(
build=self.build,
stock_item=self.stock_1_2,
quantity=q12
)
BuildItem.objects.create(
build=self.build,
stock_item=self.stock_2_1,
quantity=q21
)
with transaction.atomic():
with self.assertRaises(IntegrityError):
BuildItem.objects.create(
build=self.build,
stock_item=self.stock_2_1,
quantity=99
)
self.assertEqual(BuildItem.objects.count(), 3)
def test_partial_allocation(self):
self.allocate_stock(50, 50, 200)
self.assertFalse(self.build.isFullyAllocated())
self.assertTrue(self.build.isPartFullyAllocated(self.sub_part_1))
self.assertFalse(self.build.isPartFullyAllocated(self.sub_part_2))
def test_cancel(self):
self.allocate_stock(50, 50, 200)
self.build.cancelBuild(None)
self.assertEqual(BuildItem.objects.count(), 0)
def test_complete(self):
self.allocate_stock(50, 50, 250)
self.assertTrue(self.build.isFullyAllocated())
self.build.completeBuild(None, None, None)
self.assertEqual(self.build.status, status.BuildStatus.COMPLETE)
# the original BuildItem objects should have been deleted!
self.assertEqual(BuildItem.objects.count(), 0)
# Four new stock items should have been created!
# - One for the build output
# - Three for the split items assigned to the build
self.assertEqual(StockItem.objects.count(), 7)
# Stock should have been subtracted from the original items
self.assertEqual(StockItem.objects.get(pk=1).quantity, 950)
self.assertEqual(StockItem.objects.get(pk=2).quantity, 50)
self.assertEqual(StockItem.objects.get(pk=3).quantity, 4750)
# New stock items created and assigned to the build
self.assertEqual(StockItem.objects.get(pk=4).quantity, 50)
self.assertEqual(StockItem.objects.get(pk=4).build_order, self.build)
self.assertEqual(StockItem.objects.get(pk=4).status, status.StockStatus.ASSIGNED_TO_BUILD)
self.assertEqual(StockItem.objects.get(pk=5).quantity, 50)
self.assertEqual(StockItem.objects.get(pk=5).build_order, self.build)
self.assertEqual(StockItem.objects.get(pk=5).status, status.StockStatus.ASSIGNED_TO_BUILD)
self.assertEqual(StockItem.objects.get(pk=6).quantity, 250)
self.assertEqual(StockItem.objects.get(pk=6).build_order, self.build)
self.assertEqual(StockItem.objects.get(pk=6).status, status.StockStatus.ASSIGNED_TO_BUILD)
# And a new stock item created for the build output
self.assertEqual(StockItem.objects.get(pk=7).quantity, 10)
self.assertEqual(StockItem.objects.get(pk=7).build, self.build)

View File

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
from django.test import TestCase
from django.core.exceptions import ValidationError