mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Add some more unit testing for the builds
This commit is contained in:
parent
35f48ed899
commit
cb3fe0fc35
@ -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
|
so that the tests can be run in RAM without any setup requirements
|
||||||
"""
|
"""
|
||||||
if 'test' in sys.argv:
|
if 'test' in sys.argv:
|
||||||
eprint('Running tests - Using sqlite3 memory database')
|
eprint('InvenTree: Running tests - Using sqlite3 memory database')
|
||||||
DATABASES['default'] = {
|
DATABASES['default'] = {
|
||||||
|
# Ensure sqlite3 backend is being used
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'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
|
# Database backend selection
|
||||||
|
@ -371,11 +371,12 @@ class Build(MPTTModel):
|
|||||||
parts = []
|
parts = []
|
||||||
|
|
||||||
for item in self.part.bom_items.all().prefetch_related('sub_part'):
|
for item in self.part.bom_items.all().prefetch_related('sub_part'):
|
||||||
part = {'part': item.sub_part,
|
part = {
|
||||||
'per_build': item.quantity,
|
'part': item.sub_part,
|
||||||
'quantity': item.quantity * self.quantity,
|
'per_build': item.quantity,
|
||||||
'allocated': self.getAllocatedQuantity(item.sub_part)
|
'quantity': item.quantity * self.quantity,
|
||||||
}
|
'allocated': self.getAllocatedQuantity(item.sub_part)
|
||||||
|
}
|
||||||
|
|
||||||
parts.append(part)
|
parts.append(part)
|
||||||
|
|
||||||
|
181
InvenTree/build/test_build.py
Normal file
181
InvenTree/build/test_build.py
Normal 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)
|
@ -1,3 +1,5 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
Loading…
Reference in New Issue
Block a user