mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Unit test speed improvements (#4463)
* Unit test speed improvements - Move from insantiating data in setUp to setUpTestData * Update UserMixin class for API testing * Bunch of test updates * Further test updates * Test fixes * Add allowances for exchange rate server not responding * Fixes for group role test
This commit is contained in:
parent
9c594ed52b
commit
2dfea9b825
@ -33,56 +33,69 @@ class UserMixin:
|
||||
# Set list of roles automatically associated with the user
|
||||
roles = []
|
||||
|
||||
def setUp(self):
|
||||
"""Setup for all tests."""
|
||||
super().setUp()
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Run setup for all tests in a given class"""
|
||||
super().setUpTestData()
|
||||
|
||||
# Create a user to log in with
|
||||
self.user = get_user_model().objects.create_user(
|
||||
username=self.username,
|
||||
password=self.password,
|
||||
email=self.email
|
||||
cls.user = get_user_model().objects.create_user(
|
||||
username=cls.username,
|
||||
password=cls.password,
|
||||
email=cls.email
|
||||
)
|
||||
|
||||
# Create a group for the user
|
||||
self.group = Group.objects.create(name='my_test_group')
|
||||
self.user.groups.add(self.group)
|
||||
cls.group = Group.objects.create(name='my_test_group')
|
||||
cls.user.groups.add(cls.group)
|
||||
|
||||
if self.superuser:
|
||||
self.user.is_superuser = True
|
||||
if cls.superuser:
|
||||
cls.user.is_superuser = True
|
||||
|
||||
if self.is_staff:
|
||||
self.user.is_staff = True
|
||||
if cls.is_staff:
|
||||
cls.user.is_staff = True
|
||||
|
||||
self.user.save()
|
||||
cls.user.save()
|
||||
|
||||
# Assign all roles if set
|
||||
if self.roles == 'all':
|
||||
self.assignRole(assign_all=True)
|
||||
if cls.roles == 'all':
|
||||
cls.assignRole(group=cls.group, assign_all=True)
|
||||
|
||||
# else filter the roles
|
||||
else:
|
||||
for role in self.roles:
|
||||
self.assignRole(role)
|
||||
for role in cls.roles:
|
||||
cls.assignRole(role=role, group=cls.group)
|
||||
|
||||
def setUp(self):
|
||||
"""Run setup for individual test methods"""
|
||||
|
||||
if self.auto_login:
|
||||
self.client.login(username=self.username, password=self.password)
|
||||
|
||||
def assignRole(self, role=None, assign_all: bool = False):
|
||||
@classmethod
|
||||
def assignRole(cls, role=None, assign_all: bool = False, group=None):
|
||||
"""Set the user roles for the registered user.
|
||||
|
||||
Arguments:
|
||||
role: Role of the format 'rule.permission' e.g. 'part.add'
|
||||
assign_all: Set to True to assign *all* roles
|
||||
group: The group to assign roles to (or leave None to use the group assigned to this class)
|
||||
"""
|
||||
|
||||
if group is None:
|
||||
group = cls.group
|
||||
|
||||
if type(assign_all) is not bool:
|
||||
# Raise exception if common mistake is made!
|
||||
raise TypeError('assign_all must be a boolean value')
|
||||
raise TypeError('assignRole: assign_all must be a boolean value')
|
||||
|
||||
if not role and not assign_all:
|
||||
raise ValueError('assignRole: either role must be provided, or assign_all must be set')
|
||||
|
||||
if not assign_all and role:
|
||||
rule, perm = role.split('.')
|
||||
|
||||
for ruleset in self.group.rule_sets.all():
|
||||
for ruleset in group.rule_sets.all():
|
||||
|
||||
if assign_all or ruleset.name == rule:
|
||||
|
||||
|
@ -8,7 +8,7 @@ from rest_framework import status
|
||||
|
||||
from InvenTree.api_tester import InvenTreeAPITestCase
|
||||
from InvenTree.helpers import InvenTreeTestCase
|
||||
from users.models import RuleSet
|
||||
from users.models import RuleSet, update_group_roles
|
||||
|
||||
|
||||
class HTMLAPITests(InvenTreeTestCase):
|
||||
@ -126,6 +126,10 @@ class APITests(InvenTreeAPITestCase):
|
||||
"""
|
||||
url = reverse('api-user-roles')
|
||||
|
||||
# Delete all rules
|
||||
self.group.rule_sets.all().delete()
|
||||
update_group_roles(self.group)
|
||||
|
||||
response = self.client.get(url, format='json')
|
||||
|
||||
# Not logged in, so cannot access user role data
|
||||
|
@ -390,10 +390,10 @@ class TestMPTT(TestCase):
|
||||
'location',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Setup for all tests."""
|
||||
super().setUp()
|
||||
|
||||
super().setUpTestData()
|
||||
StockLocation.objects.rebuild()
|
||||
|
||||
def test_self_as_parent(self):
|
||||
|
@ -731,38 +731,42 @@ class BuildOverallocationTest(BuildAPITest):
|
||||
Using same Build ID=1 as allocation test above.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Basic operation as part of test suite setup"""
|
||||
super().setUp()
|
||||
super().setUpTestData()
|
||||
|
||||
self.assignRole('build.add')
|
||||
self.assignRole('build.change')
|
||||
cls.assignRole('build.add')
|
||||
cls.assignRole('build.change')
|
||||
|
||||
self.build = Build.objects.get(pk=1)
|
||||
self.url = reverse('api-build-finish', kwargs={'pk': self.build.pk})
|
||||
cls.build = Build.objects.get(pk=1)
|
||||
cls.url = reverse('api-build-finish', kwargs={'pk': cls.build.pk})
|
||||
|
||||
StockItem.objects.create(part=Part.objects.get(pk=50), quantity=30)
|
||||
|
||||
# Keep some state for use in later assertions, and then overallocate
|
||||
self.state = {}
|
||||
self.allocation = {}
|
||||
for i, bi in enumerate(self.build.part.bom_items.all()):
|
||||
rq = self.build.required_quantity(bi, None) + i + 1
|
||||
cls.state = {}
|
||||
cls.allocation = {}
|
||||
|
||||
for i, bi in enumerate(cls.build.part.bom_items.all()):
|
||||
rq = cls.build.required_quantity(bi, None) + i + 1
|
||||
si = StockItem.objects.filter(part=bi.sub_part, quantity__gte=rq).first()
|
||||
|
||||
self.state[bi.sub_part] = (si, si.quantity, rq)
|
||||
cls.state[bi.sub_part] = (si, si.quantity, rq)
|
||||
BuildItem.objects.create(
|
||||
build=self.build,
|
||||
build=cls.build,
|
||||
stock_item=si,
|
||||
quantity=rq,
|
||||
)
|
||||
|
||||
# create and complete outputs
|
||||
self.build.create_build_output(self.build.quantity)
|
||||
outputs = self.build.build_outputs.all()
|
||||
self.build.complete_build_output(outputs[0], self.user)
|
||||
cls.build.create_build_output(cls.build.quantity)
|
||||
outputs = cls.build.build_outputs.all()
|
||||
cls.build.complete_build_output(outputs[0], cls.user)
|
||||
|
||||
def test_setup(self):
|
||||
"""Validate expected state after set-up."""
|
||||
|
||||
# Validate expected state after set-up.
|
||||
self.assertEqual(self.build.incomplete_outputs.count(), 0)
|
||||
self.assertEqual(self.build.complete_outputs.count(), 1)
|
||||
self.assertEqual(self.build.completed, self.build.quantity)
|
||||
|
@ -29,7 +29,8 @@ class BuildTestBase(TestCase):
|
||||
'users',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Initialize data to use for these tests.
|
||||
|
||||
The base Part 'assembly' has a BOM consisting of three parts:
|
||||
@ -45,27 +46,29 @@ class BuildTestBase(TestCase):
|
||||
|
||||
"""
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
# Create a base "Part"
|
||||
self.assembly = Part.objects.create(
|
||||
cls.assembly = Part.objects.create(
|
||||
name="An assembled part",
|
||||
description="Why does it matter what my description is?",
|
||||
assembly=True,
|
||||
trackable=True,
|
||||
)
|
||||
|
||||
self.sub_part_1 = Part.objects.create(
|
||||
cls.sub_part_1 = Part.objects.create(
|
||||
name="Widget A",
|
||||
description="A widget",
|
||||
component=True
|
||||
)
|
||||
|
||||
self.sub_part_2 = Part.objects.create(
|
||||
cls.sub_part_2 = Part.objects.create(
|
||||
name="Widget B",
|
||||
description="A widget",
|
||||
component=True
|
||||
)
|
||||
|
||||
self.sub_part_3 = Part.objects.create(
|
||||
cls.sub_part_3 = Part.objects.create(
|
||||
name="Widget C",
|
||||
description="A widget",
|
||||
component=True,
|
||||
@ -73,63 +76,63 @@ class BuildTestBase(TestCase):
|
||||
)
|
||||
|
||||
# Create BOM item links for the parts
|
||||
self.bom_item_1 = BomItem.objects.create(
|
||||
part=self.assembly,
|
||||
sub_part=self.sub_part_1,
|
||||
cls.bom_item_1 = BomItem.objects.create(
|
||||
part=cls.assembly,
|
||||
sub_part=cls.sub_part_1,
|
||||
quantity=5
|
||||
)
|
||||
|
||||
self.bom_item_2 = BomItem.objects.create(
|
||||
part=self.assembly,
|
||||
sub_part=self.sub_part_2,
|
||||
cls.bom_item_2 = BomItem.objects.create(
|
||||
part=cls.assembly,
|
||||
sub_part=cls.sub_part_2,
|
||||
quantity=3,
|
||||
optional=True
|
||||
)
|
||||
|
||||
# sub_part_3 is trackable!
|
||||
self.bom_item_3 = BomItem.objects.create(
|
||||
part=self.assembly,
|
||||
sub_part=self.sub_part_3,
|
||||
cls.bom_item_3 = BomItem.objects.create(
|
||||
part=cls.assembly,
|
||||
sub_part=cls.sub_part_3,
|
||||
quantity=2
|
||||
)
|
||||
|
||||
ref = generate_next_build_reference()
|
||||
|
||||
# Create a "Build" object to make 10x objects
|
||||
self.build = Build.objects.create(
|
||||
cls.build = Build.objects.create(
|
||||
reference=ref,
|
||||
title="This is a build",
|
||||
part=self.assembly,
|
||||
part=cls.assembly,
|
||||
quantity=10,
|
||||
issued_by=get_user_model().objects.get(pk=1),
|
||||
)
|
||||
|
||||
# Create some build output (StockItem) objects
|
||||
self.output_1 = StockItem.objects.create(
|
||||
part=self.assembly,
|
||||
cls.output_1 = StockItem.objects.create(
|
||||
part=cls.assembly,
|
||||
quantity=3,
|
||||
is_building=True,
|
||||
build=self.build
|
||||
build=cls.build
|
||||
)
|
||||
|
||||
self.output_2 = StockItem.objects.create(
|
||||
part=self.assembly,
|
||||
cls.output_2 = StockItem.objects.create(
|
||||
part=cls.assembly,
|
||||
quantity=7,
|
||||
is_building=True,
|
||||
build=self.build,
|
||||
build=cls.build,
|
||||
)
|
||||
|
||||
# Create some stock items to assign to the build
|
||||
self.stock_1_1 = StockItem.objects.create(part=self.sub_part_1, quantity=3)
|
||||
self.stock_1_2 = StockItem.objects.create(part=self.sub_part_1, quantity=100)
|
||||
cls.stock_1_1 = StockItem.objects.create(part=cls.sub_part_1, quantity=3)
|
||||
cls.stock_1_2 = StockItem.objects.create(part=cls.sub_part_1, quantity=100)
|
||||
|
||||
self.stock_2_1 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
self.stock_2_2 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
self.stock_2_3 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
self.stock_2_4 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
self.stock_2_5 = StockItem.objects.create(part=self.sub_part_2, quantity=5)
|
||||
cls.stock_2_1 = StockItem.objects.create(part=cls.sub_part_2, quantity=5)
|
||||
cls.stock_2_2 = StockItem.objects.create(part=cls.sub_part_2, quantity=5)
|
||||
cls.stock_2_3 = StockItem.objects.create(part=cls.sub_part_2, quantity=5)
|
||||
cls.stock_2_4 = StockItem.objects.create(part=cls.sub_part_2, quantity=5)
|
||||
cls.stock_2_5 = StockItem.objects.create(part=cls.sub_part_2, quantity=5)
|
||||
|
||||
self.stock_3_1 = StockItem.objects.create(part=self.sub_part_3, quantity=1000)
|
||||
cls.stock_3_1 = StockItem.objects.create(part=cls.sub_part_3, quantity=1000)
|
||||
|
||||
|
||||
class BuildTest(BuildTestBase):
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Tests for mechanisms in common."""
|
||||
|
||||
import json
|
||||
import time
|
||||
from datetime import timedelta
|
||||
from http import HTTPStatus
|
||||
|
||||
@ -921,7 +922,16 @@ class CurrencyAPITests(InvenTreeAPITestCase):
|
||||
# Delete any existing exchange rate data
|
||||
Rate.objects.all().delete()
|
||||
|
||||
self.post(reverse('api-currency-refresh'))
|
||||
# Updating via the external exchange may not work every time
|
||||
for _idx in range(5):
|
||||
self.post(reverse('api-currency-refresh'))
|
||||
|
||||
# There should be some new exchange rate objects now
|
||||
self.assertTrue(Rate.objects.all().exists())
|
||||
# There should be some new exchange rate objects now
|
||||
if Rate.objects.all().exists():
|
||||
# Exit early
|
||||
return
|
||||
|
||||
# Delay and try again
|
||||
time.sleep(10)
|
||||
|
||||
raise TimeoutError("Could not refresh currency exchange data after 5 attempts")
|
||||
|
@ -17,11 +17,14 @@ class CompanyTest(InvenTreeAPITestCase):
|
||||
'purchase_order.change',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Perform initialization for the unit test class"""
|
||||
super().setUp()
|
||||
|
||||
self.acme = Company.objects.create(name='ACME', description='Supplier', is_customer=False, is_supplier=True)
|
||||
super().setUpTestData()
|
||||
|
||||
# Create some company objects to work with
|
||||
cls.acme = Company.objects.create(name='ACME', description='Supplier', is_customer=False, is_supplier=True)
|
||||
Company.objects.create(name='Drippy Cup Co.', description='Customer', is_customer=True, is_supplier=False)
|
||||
Company.objects.create(name='Sippy Cup Emporium', description='Another supplier')
|
||||
|
||||
|
@ -26,8 +26,12 @@ class CompanySimpleTest(TestCase):
|
||||
'price_breaks',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Perform initialization for the tests in this class"""
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
Company.objects.create(name='ABC Co.',
|
||||
description='Seller of ABC products',
|
||||
website='www.abc-sales.com',
|
||||
@ -35,10 +39,10 @@ class CompanySimpleTest(TestCase):
|
||||
is_customer=False,
|
||||
is_supplier=True)
|
||||
|
||||
self.acme0001 = SupplierPart.objects.get(SKU='ACME0001')
|
||||
self.acme0002 = SupplierPart.objects.get(SKU='ACME0002')
|
||||
self.zerglphs = SupplierPart.objects.get(SKU='ZERGLPHS')
|
||||
self.zergm312 = SupplierPart.objects.get(SKU='ZERGM312')
|
||||
cls.acme0001 = SupplierPart.objects.get(SKU='ACME0001')
|
||||
cls.acme0002 = SupplierPart.objects.get(SKU='ACME0002')
|
||||
cls.zerglphs = SupplierPart.objects.get(SKU='ZERGLPHS')
|
||||
cls.zergm312 = SupplierPart.objects.get(SKU='ZERGM312')
|
||||
|
||||
def test_company_model(self):
|
||||
"""Tests for the company model data"""
|
||||
|
@ -27,9 +27,10 @@ class LabelTest(InvenTreeAPITestCase):
|
||||
'stock'
|
||||
]
|
||||
|
||||
def setUp(self) -> None:
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Ensure that some label instances exist as part of init routine"""
|
||||
super().setUp()
|
||||
super().setUpTestData()
|
||||
apps.get_app_config('label').create_labels()
|
||||
|
||||
def test_default_labels(self):
|
||||
|
@ -1408,25 +1408,33 @@ class SalesOrderLineItemTest(OrderTest):
|
||||
|
||||
LIST_URL = reverse('api-so-line-list')
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Init routine for this unit test class"""
|
||||
super().setUp()
|
||||
super().setUpTestData()
|
||||
|
||||
# List of salable parts
|
||||
parts = Part.objects.filter(salable=True)
|
||||
|
||||
lines = []
|
||||
|
||||
# Create a bunch of SalesOrderLineItems for each order
|
||||
for idx, so in enumerate(models.SalesOrder.objects.all()):
|
||||
|
||||
for part in parts:
|
||||
models.SalesOrderLineItem.objects.create(
|
||||
order=so,
|
||||
part=part,
|
||||
quantity=(idx + 1) * 5,
|
||||
reference=f"Order {so.reference} - line {idx}",
|
||||
lines.append(
|
||||
models.SalesOrderLineItem(
|
||||
order=so,
|
||||
part=part,
|
||||
quantity=(idx + 1) * 5,
|
||||
reference=f"Order {so.reference} - line {idx}",
|
||||
)
|
||||
)
|
||||
|
||||
self.url = reverse('api-so-line-list')
|
||||
# Bulk create
|
||||
models.SalesOrderLineItem.objects.bulk_create(lines)
|
||||
|
||||
cls.url = reverse('api-so-line-list')
|
||||
|
||||
def test_so_line_list(self):
|
||||
"""Test list endpoint"""
|
||||
|
@ -25,33 +25,34 @@ class SalesOrderTest(TestCase):
|
||||
'users',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Initial setup for this set of unit tests"""
|
||||
# Create a Company to ship the goods to
|
||||
self.customer = Company.objects.create(name="ABC Co", description="My customer", is_customer=True)
|
||||
cls.customer = Company.objects.create(name="ABC Co", description="My customer", is_customer=True)
|
||||
|
||||
# Create a Part to ship
|
||||
self.part = Part.objects.create(name='Spanner', salable=True, description='A spanner that I sell')
|
||||
cls.part = Part.objects.create(name='Spanner', salable=True, description='A spanner that I sell')
|
||||
|
||||
# Create some stock!
|
||||
self.Sa = StockItem.objects.create(part=self.part, quantity=100)
|
||||
self.Sb = StockItem.objects.create(part=self.part, quantity=200)
|
||||
cls.Sa = StockItem.objects.create(part=cls.part, quantity=100)
|
||||
cls.Sb = StockItem.objects.create(part=cls.part, quantity=200)
|
||||
|
||||
# Create a SalesOrder to ship against
|
||||
self.order = SalesOrder.objects.create(
|
||||
customer=self.customer,
|
||||
cls.order = SalesOrder.objects.create(
|
||||
customer=cls.customer,
|
||||
reference='SO-1234',
|
||||
customer_reference='ABC 55555'
|
||||
)
|
||||
|
||||
# Create a Shipment against this SalesOrder
|
||||
self.shipment = SalesOrderShipment.objects.create(
|
||||
order=self.order,
|
||||
cls.shipment = SalesOrderShipment.objects.create(
|
||||
order=cls.order,
|
||||
reference='SO-001',
|
||||
)
|
||||
|
||||
# Create a line item
|
||||
self.line = SalesOrderLineItem.objects.create(quantity=50, order=self.order, part=self.part)
|
||||
cls.line = SalesOrderLineItem.objects.create(quantity=50, order=cls.order, part=cls.part)
|
||||
|
||||
def test_so_reference(self):
|
||||
"""Unit tests for sales order generation"""
|
||||
|
@ -2357,12 +2357,12 @@ class PartPricing(common.models.MetaMixin):
|
||||
|
||||
if self.scheduled_for_update:
|
||||
# Ignore if the pricing is already scheduled to be updated
|
||||
logger.info(f"Pricing for {p} already scheduled for update - skipping")
|
||||
logger.debug(f"Pricing for {p} already scheduled for update - skipping")
|
||||
return
|
||||
|
||||
if counter > 25:
|
||||
# Prevent infinite recursion / stack depth issues
|
||||
logger.info(counter, f"Skipping pricing update for {p} - maximum depth exceeded")
|
||||
logger.debug(counter, f"Skipping pricing update for {p} - maximum depth exceeded")
|
||||
return
|
||||
|
||||
try:
|
||||
|
@ -1893,15 +1893,16 @@ class PartAPIAggregationTest(InvenTreeAPITestCase):
|
||||
'part.change',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create test data as part of setup routine"""
|
||||
super().setUp()
|
||||
super().setUpTestData()
|
||||
|
||||
# Ensure the part "variant" tree is correctly structured
|
||||
Part.objects.rebuild()
|
||||
|
||||
# Add a new part
|
||||
self.part = Part.objects.create(
|
||||
cls.part = Part.objects.create(
|
||||
name='Banana',
|
||||
description='This is a banana',
|
||||
category=PartCategory.objects.get(pk=1),
|
||||
@ -1910,12 +1911,12 @@ class PartAPIAggregationTest(InvenTreeAPITestCase):
|
||||
# Create some stock items associated with the part
|
||||
|
||||
# First create 600 units which are OK
|
||||
StockItem.objects.create(part=self.part, quantity=100)
|
||||
StockItem.objects.create(part=self.part, quantity=200)
|
||||
StockItem.objects.create(part=self.part, quantity=300)
|
||||
StockItem.objects.create(part=cls.part, quantity=100)
|
||||
StockItem.objects.create(part=cls.part, quantity=200)
|
||||
StockItem.objects.create(part=cls.part, quantity=300)
|
||||
|
||||
# Now create another 400 units which are LOST
|
||||
StockItem.objects.create(part=self.part, quantity=400, status=StockStatus.LOST)
|
||||
StockItem.objects.create(part=cls.part, quantity=400, status=StockStatus.LOST)
|
||||
|
||||
def get_part_data(self):
|
||||
"""Helper function for retrieving part data"""
|
||||
|
@ -17,26 +17,35 @@ class BomUploadTest(InvenTreeAPITestCase):
|
||||
'part.change',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create BOM data as part of setup routine"""
|
||||
super().setUp()
|
||||
super().setUpTestData()
|
||||
|
||||
self.part = Part.objects.create(
|
||||
cls.part = Part.objects.create(
|
||||
name='Assembly',
|
||||
description='An assembled part',
|
||||
assembly=True,
|
||||
component=False,
|
||||
)
|
||||
|
||||
parts = []
|
||||
|
||||
for i in range(10):
|
||||
Part.objects.create(
|
||||
name=f"Component {i}",
|
||||
IPN=f"CMP_{i}",
|
||||
description="A subcomponent that can be used in a BOM",
|
||||
component=True,
|
||||
assembly=False,
|
||||
parts.append(
|
||||
Part(
|
||||
name=f"Component {i}",
|
||||
IPN=f"CMP_{i}",
|
||||
description="A subcomponent that can be used in a BOM",
|
||||
component=True,
|
||||
assembly=False,
|
||||
lft=0, rght=0,
|
||||
level=0, tree_id=0,
|
||||
)
|
||||
)
|
||||
|
||||
Part.objects.bulk_create(parts)
|
||||
|
||||
def post_bom(self, filename, file_data, clear_existing=None, expected_code=None, content_type='text/plain'):
|
||||
"""Helper function for submitting a BOM file"""
|
||||
bom_file = SimpleUploadedFile(
|
||||
|
@ -19,15 +19,19 @@ class CategoryTest(TestCase):
|
||||
'params',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Extract some interesting categories for time-saving"""
|
||||
self.electronics = PartCategory.objects.get(name='Electronics')
|
||||
self.mechanical = PartCategory.objects.get(name='Mechanical')
|
||||
self.resistors = PartCategory.objects.get(name='Resistors')
|
||||
self.capacitors = PartCategory.objects.get(name='Capacitors')
|
||||
self.fasteners = PartCategory.objects.get(name='Fasteners')
|
||||
self.ic = PartCategory.objects.get(name='IC')
|
||||
self.transceivers = PartCategory.objects.get(name='Transceivers')
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
cls.electronics = PartCategory.objects.get(name='Electronics')
|
||||
cls.mechanical = PartCategory.objects.get(name='Mechanical')
|
||||
cls.resistors = PartCategory.objects.get(name='Resistors')
|
||||
cls.capacitors = PartCategory.objects.get(name='Capacitors')
|
||||
cls.fasteners = PartCategory.objects.get(name='Fasteners')
|
||||
cls.ic = PartCategory.objects.get(name='IC')
|
||||
cls.transceivers = PartCategory.objects.get(name='Transceivers')
|
||||
|
||||
def test_parents(self):
|
||||
"""Test that the parent fields are properly set, based on the test fixtures."""
|
||||
|
@ -134,14 +134,16 @@ class PartTest(TestCase):
|
||||
'part_pricebreaks'
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create some Part instances as part of init routine"""
|
||||
super().setUp()
|
||||
|
||||
self.r1 = Part.objects.get(name='R_2K2_0805')
|
||||
self.r2 = Part.objects.get(name='R_4K7_0603')
|
||||
super().setUpTestData()
|
||||
|
||||
self.c1 = Part.objects.get(name='C_22N_0805')
|
||||
cls.r1 = Part.objects.get(name='R_2K2_0805')
|
||||
cls.r2 = Part.objects.get(name='R_4K7_0603')
|
||||
|
||||
cls.c1 = Part.objects.get(name='C_22N_0805')
|
||||
|
||||
Part.objects.rebuild()
|
||||
|
||||
@ -529,15 +531,16 @@ class PartSubscriptionTests(InvenTreeTestCase):
|
||||
'part',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create category and part data as part of setup routine"""
|
||||
super().setUp()
|
||||
super().setUpTestData()
|
||||
|
||||
# electronics / IC / MCU
|
||||
self.category = PartCategory.objects.get(pk=4)
|
||||
# Electronics / IC / MCU
|
||||
cls.category = PartCategory.objects.get(pk=4)
|
||||
|
||||
self.part = Part.objects.create(
|
||||
category=self.category,
|
||||
cls.part = Part.objects.create(
|
||||
category=cls.category,
|
||||
name='STM32F103',
|
||||
description='Currently worth a lot of money',
|
||||
is_template=True,
|
||||
@ -629,14 +632,16 @@ class BaseNotificationIntegrationTest(InvenTreeTestCase):
|
||||
'stock'
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Add an email address as part of initialization"""
|
||||
super().setUp()
|
||||
# Add Mailadress
|
||||
EmailAddress.objects.create(user=self.user, email='test@testing.com')
|
||||
super().setUpTestData()
|
||||
|
||||
# Add email address
|
||||
EmailAddress.objects.create(user=cls.user, email='test@testing.com')
|
||||
|
||||
# Define part that will be tested
|
||||
self.part = Part.objects.get(name='R_2K2_0805')
|
||||
cls.part = Part.objects.get(name='R_2K2_0805')
|
||||
|
||||
def _notification_run(self, run_class=None):
|
||||
"""Run a notification test suit through.
|
||||
|
@ -20,6 +20,8 @@ class PartPricingTests(InvenTreeTestCase):
|
||||
def setUp(self):
|
||||
"""Setup routines"""
|
||||
|
||||
super().setUp()
|
||||
|
||||
self.generate_exchange_rates()
|
||||
|
||||
# Create a new part for performing pricing calculations
|
||||
@ -29,8 +31,6 @@ class PartPricingTests(InvenTreeTestCase):
|
||||
assembly=True
|
||||
)
|
||||
|
||||
return super().setUp()
|
||||
|
||||
def create_price_breaks(self):
|
||||
"""Create some price breaks for the part, in various currencies"""
|
||||
|
||||
|
@ -66,25 +66,29 @@ class PluginTagTests(TestCase):
|
||||
class InvenTreePluginTests(TestCase):
|
||||
"""Tests for InvenTreePlugin."""
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Setup for all tests."""
|
||||
self.plugin = InvenTreePlugin()
|
||||
|
||||
super().setUpTestData()
|
||||
|
||||
cls.plugin = InvenTreePlugin()
|
||||
|
||||
class NamedPlugin(InvenTreePlugin):
|
||||
"""a named plugin."""
|
||||
NAME = 'abc123'
|
||||
|
||||
self.named_plugin = NamedPlugin()
|
||||
cls.named_plugin = NamedPlugin()
|
||||
|
||||
class SimpleInvenTreePlugin(InvenTreePlugin):
|
||||
NAME = 'SimplePlugin'
|
||||
|
||||
self.plugin_simple = SimpleInvenTreePlugin()
|
||||
cls.plugin_simple = SimpleInvenTreePlugin()
|
||||
|
||||
class OldInvenTreePlugin(InvenTreePlugin):
|
||||
PLUGIN_SLUG = 'old'
|
||||
|
||||
self.plugin_old = OldInvenTreePlugin()
|
||||
cls.plugin_old = OldInvenTreePlugin()
|
||||
|
||||
class NameInvenTreePlugin(InvenTreePlugin):
|
||||
NAME = 'Aplugin'
|
||||
@ -97,8 +101,8 @@ class InvenTreePluginTests(TestCase):
|
||||
WEBSITE = 'https://aa.bb/cc'
|
||||
LICENSE = 'MIT'
|
||||
|
||||
self.plugin_name = NameInvenTreePlugin()
|
||||
self.plugin_sample = SampleIntegrationPlugin()
|
||||
cls.plugin_name = NameInvenTreePlugin()
|
||||
cls.plugin_sample = SampleIntegrationPlugin()
|
||||
|
||||
class VersionInvenTreePlugin(InvenTreePlugin):
|
||||
NAME = 'Version'
|
||||
@ -106,7 +110,7 @@ class InvenTreePluginTests(TestCase):
|
||||
MIN_VERSION = '0.1.0'
|
||||
MAX_VERSION = '0.1.3'
|
||||
|
||||
self.plugin_version = VersionInvenTreePlugin()
|
||||
cls.plugin_version = VersionInvenTreePlugin()
|
||||
|
||||
def test_basic_plugin_init(self):
|
||||
"""Check if a basic plugin intis."""
|
||||
|
@ -50,9 +50,10 @@ class StockLocationTest(StockAPITestCase):
|
||||
|
||||
list_url = reverse('api-location-list')
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Setup for all tests."""
|
||||
super().setUp()
|
||||
super().setUpTestData()
|
||||
|
||||
# Add some stock locations
|
||||
StockLocation.objects.create(name='top', description='top category')
|
||||
@ -1413,30 +1414,32 @@ class StockMergeTest(StockAPITestCase):
|
||||
|
||||
URL = reverse('api-stock-merge')
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Setup for all tests."""
|
||||
super().setUp()
|
||||
|
||||
self.part = part.models.Part.objects.get(pk=25)
|
||||
self.loc = StockLocation.objects.get(pk=1)
|
||||
self.sp_1 = company.models.SupplierPart.objects.get(pk=100)
|
||||
self.sp_2 = company.models.SupplierPart.objects.get(pk=101)
|
||||
super().setUpTestData()
|
||||
|
||||
self.item_1 = StockItem.objects.create(
|
||||
part=self.part,
|
||||
supplier_part=self.sp_1,
|
||||
cls.part = part.models.Part.objects.get(pk=25)
|
||||
cls.loc = StockLocation.objects.get(pk=1)
|
||||
cls.sp_1 = company.models.SupplierPart.objects.get(pk=100)
|
||||
cls.sp_2 = company.models.SupplierPart.objects.get(pk=101)
|
||||
|
||||
cls.item_1 = StockItem.objects.create(
|
||||
part=cls.part,
|
||||
supplier_part=cls.sp_1,
|
||||
quantity=100,
|
||||
)
|
||||
|
||||
self.item_2 = StockItem.objects.create(
|
||||
part=self.part,
|
||||
supplier_part=self.sp_2,
|
||||
cls.item_2 = StockItem.objects.create(
|
||||
part=cls.part,
|
||||
supplier_part=cls.sp_2,
|
||||
quantity=100,
|
||||
)
|
||||
|
||||
self.item_3 = StockItem.objects.create(
|
||||
part=self.part,
|
||||
supplier_part=self.sp_2,
|
||||
cls.item_3 = StockItem.objects.create(
|
||||
part=cls.part,
|
||||
supplier_part=cls.sp_2,
|
||||
quantity=50,
|
||||
)
|
||||
|
||||
|
@ -30,19 +30,20 @@ class StockTestBase(InvenTreeTestCase):
|
||||
'stock_tests',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Setup for all tests."""
|
||||
super().setUp()
|
||||
super().setUpTestData()
|
||||
|
||||
# Extract some shortcuts from the fixtures
|
||||
self.home = StockLocation.objects.get(name='Home')
|
||||
self.bathroom = StockLocation.objects.get(name='Bathroom')
|
||||
self.diningroom = StockLocation.objects.get(name='Dining Room')
|
||||
cls.home = StockLocation.objects.get(name='Home')
|
||||
cls.bathroom = StockLocation.objects.get(name='Bathroom')
|
||||
cls.diningroom = StockLocation.objects.get(name='Dining Room')
|
||||
|
||||
self.office = StockLocation.objects.get(name='Office')
|
||||
self.drawer1 = StockLocation.objects.get(name='Drawer_1')
|
||||
self.drawer2 = StockLocation.objects.get(name='Drawer_2')
|
||||
self.drawer3 = StockLocation.objects.get(name='Drawer_3')
|
||||
cls.office = StockLocation.objects.get(name='Office')
|
||||
cls.drawer1 = StockLocation.objects.get(name='Drawer_1')
|
||||
cls.drawer2 = StockLocation.objects.get(name='Drawer_2')
|
||||
cls.drawer3 = StockLocation.objects.get(name='Drawer_3')
|
||||
|
||||
# Ensure the MPTT objects are correctly rebuild
|
||||
Part.objects.rebuild()
|
||||
|
Loading…
Reference in New Issue
Block a user