diff --git a/InvenTree/InvenTree/api_tester.py b/InvenTree/InvenTree/api_tester.py index 81eebe436a..a65c6ae18b 100644 --- a/InvenTree/InvenTree/api_tester.py +++ b/InvenTree/InvenTree/api_tester.py @@ -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: diff --git a/InvenTree/InvenTree/test_api.py b/InvenTree/InvenTree/test_api.py index 0b43f44cd0..e34cd362e9 100644 --- a/InvenTree/InvenTree/test_api.py +++ b/InvenTree/InvenTree/test_api.py @@ -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 diff --git a/InvenTree/InvenTree/tests.py b/InvenTree/InvenTree/tests.py index 0f5b04f512..bc90bb063d 100644 --- a/InvenTree/InvenTree/tests.py +++ b/InvenTree/InvenTree/tests.py @@ -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): diff --git a/InvenTree/build/test_api.py b/InvenTree/build/test_api.py index af6d7a0781..bb15aaec8b 100644 --- a/InvenTree/build/test_api.py +++ b/InvenTree/build/test_api.py @@ -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) diff --git a/InvenTree/build/test_build.py b/InvenTree/build/test_build.py index 38c20c331b..8c293bf5d6 100644 --- a/InvenTree/build/test_build.py +++ b/InvenTree/build/test_build.py @@ -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): diff --git a/InvenTree/common/tests.py b/InvenTree/common/tests.py index f77b32ca0e..ce6f1bf283 100644 --- a/InvenTree/common/tests.py +++ b/InvenTree/common/tests.py @@ -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") diff --git a/InvenTree/company/test_api.py b/InvenTree/company/test_api.py index 6f3e9e5bf2..aa33385d2c 100644 --- a/InvenTree/company/test_api.py +++ b/InvenTree/company/test_api.py @@ -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') diff --git a/InvenTree/company/tests.py b/InvenTree/company/tests.py index cb42653afc..ae0ab87e5d 100644 --- a/InvenTree/company/tests.py +++ b/InvenTree/company/tests.py @@ -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""" diff --git a/InvenTree/label/tests.py b/InvenTree/label/tests.py index 605d706181..88e4fad4f0 100644 --- a/InvenTree/label/tests.py +++ b/InvenTree/label/tests.py @@ -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): diff --git a/InvenTree/order/test_api.py b/InvenTree/order/test_api.py index 976f198cad..631b54caaf 100644 --- a/InvenTree/order/test_api.py +++ b/InvenTree/order/test_api.py @@ -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""" diff --git a/InvenTree/order/test_sales_order.py b/InvenTree/order/test_sales_order.py index 98db41ff42..9050ad8704 100644 --- a/InvenTree/order/test_sales_order.py +++ b/InvenTree/order/test_sales_order.py @@ -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""" diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 1aabf5ffb8..d3b0408eaf 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -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: diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index fedbc55b84..1c83be1a4a 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -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""" diff --git a/InvenTree/part/test_bom_import.py b/InvenTree/part/test_bom_import.py index 73410ea350..d7d3367bb8 100644 --- a/InvenTree/part/test_bom_import.py +++ b/InvenTree/part/test_bom_import.py @@ -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( diff --git a/InvenTree/part/test_category.py b/InvenTree/part/test_category.py index 8044dddf7e..f484314415 100644 --- a/InvenTree/part/test_category.py +++ b/InvenTree/part/test_category.py @@ -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.""" diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py index d6b191be13..aaeb4d9085 100644 --- a/InvenTree/part/test_part.py +++ b/InvenTree/part/test_part.py @@ -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. diff --git a/InvenTree/part/test_pricing.py b/InvenTree/part/test_pricing.py index dcd2fdc4aa..e470b2389d 100644 --- a/InvenTree/part/test_pricing.py +++ b/InvenTree/part/test_pricing.py @@ -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""" diff --git a/InvenTree/plugin/test_plugin.py b/InvenTree/plugin/test_plugin.py index 953915841d..c8d51f4944 100644 --- a/InvenTree/plugin/test_plugin.py +++ b/InvenTree/plugin/test_plugin.py @@ -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.""" diff --git a/InvenTree/stock/test_api.py b/InvenTree/stock/test_api.py index 68fb75baaf..dc645e9eae 100644 --- a/InvenTree/stock/test_api.py +++ b/InvenTree/stock/test_api.py @@ -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, ) diff --git a/InvenTree/stock/tests.py b/InvenTree/stock/tests.py index 675cadadd2..e4c4914dd6 100644 --- a/InvenTree/stock/tests.py +++ b/InvenTree/stock/tests.py @@ -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()