From 9b2c89f7048755060d5d379d5f475344ebb8b736 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 29 Apr 2025 08:06:04 +0530 Subject: [PATCH 01/25] chore: drop redundant test_records.json --- .../setup/doctype/employee/test_records.json | 38 ------------------- 1 file changed, 38 deletions(-) delete mode 100644 erpnext/setup/doctype/employee/test_records.json diff --git a/erpnext/setup/doctype/employee/test_records.json b/erpnext/setup/doctype/employee/test_records.json deleted file mode 100644 index dfd3eed6ea5..00000000000 --- a/erpnext/setup/doctype/employee/test_records.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department - _TC", - "doctype": "Employee", - "first_name": "_Test Employee", - "gender": "Female", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test@example.com" - }, - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department 1 - _TC", - "doctype": "Employee", - "first_name": "_Test Employee 1", - "gender": "Male", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test1@example.com" - }, - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department 1 - _TC", - "doctype": "Employee", - "first_name": "_Test Employee 2", - "gender": "Male", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test2@example.com" - } -] \ No newline at end of file From 520a54db0c720520eb7c4d27c1c90db2f2bf1b68 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 29 Apr 2025 08:39:37 +0530 Subject: [PATCH 02/25] chore: drop test records for sales person --- .../doctype/sales_person/test_records.json | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 erpnext/setup/doctype/sales_person/test_records.json diff --git a/erpnext/setup/doctype/sales_person/test_records.json b/erpnext/setup/doctype/sales_person/test_records.json deleted file mode 100644 index 536552a0c34..00000000000 --- a/erpnext/setup/doctype/sales_person/test_records.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "doctype": "Sales Person", - "employee": "_T-Employee-00001", - "is_group": 0, - "parent_sales_person": "Sales Team", - "sales_person_name": "_Test Sales Person" - }, - { - "doctype": "Sales Person", - "employee": "_T-Employee-00002", - "is_group": 0, - "parent_sales_person": "Sales Team", - "sales_person_name": "_Test Sales Person 1" - }, - { - "doctype": "Sales Person", - "employee": "_T-Employee-00003", - "is_group": 0, - "parent_sales_person": "Sales Team", - "sales_person_name": "_Test Sales Person 2" - } -] \ No newline at end of file From c585bdb316e8a2ec8f9cfd3064c31189edb4cb80 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 29 Apr 2025 12:33:49 +0530 Subject: [PATCH 03/25] chore: setup test data in class initialization --- .../sales_invoice/test_sales_invoice.py | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index dcd465e51a4..4d09f8e2977 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -87,12 +87,87 @@ class TestSalesInvoice(IntegrationTestCase): def setUpClass(cls): super().setUpClass() cls.enterClassContext(cls.change_settings("Selling Settings", validate_selling_price=0)) + cls.make_employees() + cls.make_sales_person() unlink_payment_on_cancel_of_invoice() @classmethod def tearDownClass(self): unlink_payment_on_cancel_of_invoice(0) + @classmethod + def make_employees(cls): + records = [ + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department - _TC", + "doctype": "Employee", + "first_name": "_Test Employee", + "gender": "Female", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test@example.com", + }, + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department 1 - _TC", + "doctype": "Employee", + "first_name": "_Test Employee 1", + "gender": "Male", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test1@example.com", + }, + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department 1 - _TC", + "doctype": "Employee", + "first_name": "_Test Employee 2", + "gender": "Male", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test2@example.com", + }, + ] + for x in records: + if not frappe.db.exists("Employee", {"first_name": x.get("first_name")}): + frappe.get_doc(x).insert() + + @classmethod + def make_sales_person(cls): + records = [ + { + "doctype": "Sales Person", + "employee": "_T-Employee-00001", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person", + }, + { + "doctype": "Sales Person", + "employee": "_T-Employee-00002", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person 1", + }, + { + "doctype": "Sales Person", + "employee": "_T-Employee-00003", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person 2", + }, + ] + for x in records: + if not frappe.db.exists("Sales Person", {"sales_person_name": x.get("sales_person_name")}): + frappe.get_doc(x).insert() + def test_sales_invoice_qty(self): si = create_sales_invoice(qty=0, do_not_save=True) with self.assertRaises(InvalidQtyError): From fb4ca8c3862c2bb4cd397cf1deb44d0db02cb898 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 29 Apr 2025 16:29:03 +0530 Subject: [PATCH 04/25] chore: remove sales team from SI test records --- .../doctype/sales_invoice/test_records.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_records.json b/erpnext/accounts/doctype/sales_invoice/test_records.json index 61e5219c80c..814c6757d38 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_records.json +++ b/erpnext/accounts/doctype/sales_invoice/test_records.json @@ -55,20 +55,6 @@ ], "plc_conversion_rate": 1.0, "price_list_currency": "INR", - "sales_team": [ - { - "allocated_percentage": 65.5, - "doctype": "Sales Team", - "parentfield": "sales_team", - "sales_person": "_Test Sales Person 1" - }, - { - "allocated_percentage": 34.5, - "doctype": "Sales Team", - "parentfield": "sales_team", - "sales_person": "_Test Sales Person 2" - } - ], "selling_price_list": "_Test Price List", "territory": "_Test Territory" }, From 8d089218b5052214416fb1f96ae661aebe5a3009 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 3 May 2025 11:54:17 +0530 Subject: [PATCH 05/25] chore: drop test suite for 'Sales Person' - there are no tests it is only used to trigger dependent data creation --- erpnext/setup/doctype/sales_person/test_sales_person.py | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 erpnext/setup/doctype/sales_person/test_sales_person.py diff --git a/erpnext/setup/doctype/sales_person/test_sales_person.py b/erpnext/setup/doctype/sales_person/test_sales_person.py deleted file mode 100644 index 650b1d27c25..00000000000 --- a/erpnext/setup/doctype/sales_person/test_sales_person.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -EXTRA_TEST_RECORD_DEPENDENCIES = ["Employee"] - -import frappe - -IGNORE_TEST_RECORD_DEPENDENCIES = ["Item Group"] From f7f3269c682ce5761107beeb148eef271c532287 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 4 May 2025 08:00:02 +0530 Subject: [PATCH 06/25] refactor(test): "Lead" test suite working locally --- erpnext/crm/doctype/lead/test_lead.py | 61 ++++++++++++++++++++-- erpnext/crm/doctype/lead/test_records.json | 34 ------------ 2 files changed, 57 insertions(+), 38 deletions(-) delete mode 100644 erpnext/crm/doctype/lead/test_records.json diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index 7c7b4320b6a..2431d3478ef 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -11,14 +11,67 @@ from erpnext.crm.utils import get_linked_prospect class TestLead(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_leads() + + @classmethod + def make_leads(cls): + records = [ + { + "doctype": "Lead", + "email_id": "test_lead@example.com", + "lead_name": "_Test Lead", + "status": "Open", + "territory": "_Test Territory", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead1@example.com", + "lead_name": "_Test Lead 1", + "status": "Open", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead2@example.com", + "lead_name": "_Test Lead 2", + "status": "Lead", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead3@example.com", + "lead_name": "_Test Lead 3", + "status": "Converted", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead4@example.com", + "lead_name": "_Test Lead 4", + "company_name": "_Test Lead 4", + "status": "Open", + "naming_series": "_T-Lead-", + }, + ] + cls.leads = [] + for x in records: + if not frappe.db.exists("Lead", {"email_id": x.get("email_id")}): + cls.leads.append(frappe.get_doc(x).insert()) + else: + cls.leads.append(frappe.get_doc("Lead", {"email_id": x.get("email_id")})) + def test_make_customer(self): from erpnext.crm.doctype.lead.lead import make_customer frappe.delete_doc_if_exists("Customer", "_Test Lead") - customer = make_customer("_T-Lead-00001") + customer = make_customer(self.leads[0].name) self.assertEqual(customer.doctype, "Customer") - self.assertEqual(customer.lead_name, "_T-Lead-00001") + self.assertEqual(customer.lead_name, self.leads[0].name) customer.company = "_Test Company" customer.customer_group = "_Test Customer Group" @@ -42,9 +95,9 @@ class TestLead(IntegrationTestCase): def test_make_customer_from_organization(self): from erpnext.crm.doctype.lead.lead import make_customer - customer = make_customer("_T-Lead-00002") + customer = make_customer(self.leads[1].name) self.assertEqual(customer.doctype, "Customer") - self.assertEqual(customer.lead_name, "_T-Lead-00002") + self.assertEqual(customer.lead_name, self.leads[1].name) customer.company = "_Test Company" customer.customer_group = "_Test Customer Group" diff --git a/erpnext/crm/doctype/lead/test_records.json b/erpnext/crm/doctype/lead/test_records.json deleted file mode 100644 index 3158add0f23..00000000000 --- a/erpnext/crm/doctype/lead/test_records.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "doctype": "Lead", - "email_id": "test_lead@example.com", - "lead_name": "_Test Lead", - "status": "Open", - "territory": "_Test Territory" - }, - { - "doctype": "Lead", - "email_id": "test_lead1@example.com", - "lead_name": "_Test Lead 1", - "status": "Open" - }, - { - "doctype": "Lead", - "email_id": "test_lead2@example.com", - "lead_name": "_Test Lead 2", - "status": "Lead" - }, - { - "doctype": "Lead", - "email_id": "test_lead3@example.com", - "lead_name": "_Test Lead 3", - "status": "Converted" -}, -{ - "doctype": "Lead", - "email_id": "test_lead4@example.com", - "lead_name": "_Test Lead 4", - "company_name": "_Test Lead 4", - "status": "Open" -} -] From b77e608264a1bc5ffdc2cf6b7ded65c28a52fa45 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 4 May 2025 08:06:12 +0530 Subject: [PATCH 07/25] refactor(test): idempotent Opportunity test suite --- .../doctype/opportunity/test_opportunity.py | 47 +++++++++++++++++++ .../crm/doctype/opportunity/test_records.json | 16 ------- 2 files changed, 47 insertions(+), 16 deletions(-) delete mode 100644 erpnext/crm/doctype/opportunity/test_records.json diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py index b21f87d17ba..3111bcd4cda 100644 --- a/erpnext/crm/doctype/opportunity/test_opportunity.py +++ b/erpnext/crm/doctype/opportunity/test_opportunity.py @@ -13,6 +13,53 @@ from erpnext.crm.utils import get_linked_communication_list class TestOpportunity(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_leads() + cls.make_opportunities() + + @classmethod + def make_leads(cls): + records = [ + { + "doctype": "Lead", + "email_id": "test_lead@example.com", + "lead_name": "_Test Lead", + "status": "Open", + "territory": "_Test Territory", + "naming_series": "_T-Lead-", + }, + ] + cls.leads = [] + for x in records: + if not frappe.db.exists("Lead", {"email_id": x.get("email_id")}): + cls.leads.append(frappe.get_doc(x).insert()) + else: + cls.leads.append(frappe.get_doc("Lead", {"email_id": x.get("email_id")})) + + @classmethod + def make_opportunities(cls): + records = [ + { + "doctype": "Opportunity", + "name": "_Test Opportunity 1", + "opportunity_from": "Lead", + "enquiry_type": "Sales", + "party_name": cls.leads[0].name, + "transaction_date": "2013-12-12", + "items": [ + {"item_name": "Test Item", "description": "Some description", "qty": 5, "rate": 100} + ], + } + ] + cls.opportunities = [] + for x in records: + if not frappe.db.exists("Opportunity", {"name": x.get("name")}): + cls.opportunities.append(frappe.get_doc(x).insert()) + else: + cls.opportunities.append(frappe.get_doc("Opportunity", {"party_name": x.get("party_name")})) + def test_opportunity_status(self): doc = make_opportunity(with_items=0) quotation = make_quotation(doc.name) diff --git a/erpnext/crm/doctype/opportunity/test_records.json b/erpnext/crm/doctype/opportunity/test_records.json deleted file mode 100644 index f7e8350f308..00000000000 --- a/erpnext/crm/doctype/opportunity/test_records.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "doctype": "Opportunity", - "name": "_Test Opportunity 1", - "opportunity_from": "Lead", - "enquiry_type": "Sales", - "party_name": "_T-Lead-00001", - "transaction_date": "2013-12-12", - "items": [{ - "item_name": "Test Item", - "description": "Some description", - "qty": 5, - "rate": 100 - }] - } -] From 3ecc39a51faee0fa460e511ea0a8705a231921bc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 4 May 2025 08:43:40 +0530 Subject: [PATCH 08/25] refactor(test): make 'Activity Cost' idempotent --- .../activity_cost/test_activity_cost.py | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/erpnext/projects/doctype/activity_cost/test_activity_cost.py b/erpnext/projects/doctype/activity_cost/test_activity_cost.py index 03db2fe6d5a..a3eb176693a 100644 --- a/erpnext/projects/doctype/activity_cost/test_activity_cost.py +++ b/erpnext/projects/doctype/activity_cost/test_activity_cost.py @@ -9,13 +9,41 @@ from erpnext.projects.doctype.activity_cost.activity_cost import DuplicationErro class TestActivityCost(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_employees() + + @classmethod + def make_employees(cls): + records = [ + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department - _TC", + "doctype": "Employee", + "first_name": "_Test Employee", + "gender": "Female", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test@example.com", + }, + ] + cls.employees = [] + for x in records: + if not frappe.db.exists("Employee", {"first_name": x.get("first_name")}): + cls.employees.append(frappe.get_doc(x).insert()) + else: + cls.employees.append(frappe.get_doc("Employee", {"first_name": x.get("first_name")})) + def test_duplication(self): frappe.db.sql("delete from `tabActivity Cost`") activity_cost1 = frappe.new_doc("Activity Cost") activity_cost1.update( { - "employee": "_T-Employee-00001", - "employee_name": "_Test Employee", + "employee": self.employees[0].name, + "employee_name": self.employees[0].first_name, "activity_type": "_Test Activity Type 1", "billing_rate": 100, "costing_rate": 50, From eda7595179357542db379374051b254afbba2848 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 4 May 2025 20:26:29 +0530 Subject: [PATCH 09/25] refactor(test): make tests for queries and Project deterministic --- .../projects/doctype/project/test_project.py | 23 +++++++++++++++++++ .../doctype/project/test_records.json | 7 ------ 2 files changed, 23 insertions(+), 7 deletions(-) delete mode 100644 erpnext/projects/doctype/project/test_records.json diff --git a/erpnext/projects/doctype/project/test_project.py b/erpnext/projects/doctype/project/test_project.py index 901f7beabf1..b76f27a66ca 100644 --- a/erpnext/projects/doctype/project/test_project.py +++ b/erpnext/projects/doctype/project/test_project.py @@ -23,6 +23,29 @@ class UnitTestProject(UnitTestCase): class TestProject(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_projects() + + @classmethod + def make_projects(cls): + records = [ + { + "doctype": "Project", + "company": "_Test Company", + "project_name": "_Test Project", + "status": "Open", + } + ] + + cls.projects = [] + for x in records: + if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): + cls.projects.append(frappe.get_doc(x).insert()) + else: + cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) + def test_project_with_template_having_no_parent_and_depend_tasks(self): project_name = "Test Project with Template - No Parent and Dependend Tasks" frappe.db.sql(""" delete from tabTask where project = %s """, project_name) diff --git a/erpnext/projects/doctype/project/test_records.json b/erpnext/projects/doctype/project/test_records.json deleted file mode 100644 index 49021da4b7c..00000000000 --- a/erpnext/projects/doctype/project/test_records.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "company": "_Test Company", - "project_name": "_Test Project", - "status": "Open" - } -] \ No newline at end of file From 9526f9d835f16355397c334fa6922ac8e0ac3739 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 5 May 2025 07:29:06 +0530 Subject: [PATCH 10/25] refactor(test): deterministic 'Queries' test suite --- erpnext/controllers/tests/test_queries.py | 124 +++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/tests/test_queries.py b/erpnext/controllers/tests/test_queries.py index 124a351212a..69ec12ebd47 100644 --- a/erpnext/controllers/tests/test_queries.py +++ b/erpnext/controllers/tests/test_queries.py @@ -14,12 +14,132 @@ def add_default_params(func, doctype): return partial(func, doctype=doctype, txt="", searchfield="name", start=0, page_len=20, filters=None) -EXTRA_TEST_RECORD_DEPENDENCIES = ["Employee", "Lead", "Item", "BOM", "Project", "Account"] +EXTRA_TEST_RECORD_DEPENDENCIES = ["Item", "BOM", "Account"] class TestQueries(IntegrationTestCase): # All tests are based on self.globalTestRecords[doctype] + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_employees() + cls.make_leads() + cls.make_projects() + + @classmethod + def make_employees(cls): + records = [ + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department - _TC", + "doctype": "Employee", + "first_name": "_Test Employee", + "gender": "Female", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test@example.com", + }, + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department 1 - _TC", + "doctype": "Employee", + "first_name": "_Test Employee 1", + "gender": "Male", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test1@example.com", + }, + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department 1 - _TC", + "doctype": "Employee", + "first_name": "_Test Employee 2", + "gender": "Male", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test2@example.com", + }, + ] + cls.employees = [] + for x in records: + if not frappe.db.exists("Employee", {"first_name": x.get("first_name")}): + cls.employees.append(frappe.get_doc(x).insert()) + else: + cls.employees.append(frappe.get_doc("Employee", {"first_name": x.get("first_name")})) + + @classmethod + def make_leads(cls): + records = [ + { + "doctype": "Lead", + "email_id": "test_lead@example.com", + "lead_name": "_Test Lead", + "status": "Open", + "territory": "_Test Territory", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead1@example.com", + "lead_name": "_Test Lead 1", + "status": "Open", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead2@example.com", + "lead_name": "_Test Lead 2", + "status": "Lead", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead3@example.com", + "lead_name": "_Test Lead 3", + "status": "Converted", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead4@example.com", + "lead_name": "_Test Lead 4", + "company_name": "_Test Lead 4", + "status": "Open", + "naming_series": "_T-Lead-", + }, + ] + cls.leads = [] + for x in records: + if not frappe.db.exists("Lead", {"email_id": x.get("email_id")}): + cls.leads.append(frappe.get_doc(x).insert()) + else: + cls.leads.append(frappe.get_doc("Lead", {"email_id": x.get("email_id")})) + + @classmethod + def make_projects(cls): + records = [ + { + "doctype": "Project", + "company": "_Test Company", + "project_name": "_Test Project", + "status": "Open", + } + ] + + cls.projects = [] + for x in records: + if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): + cls.projects.append(frappe.get_doc(x).insert()) + else: + cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) + def assert_nested_in(self, item, container): self.assertIn(item, [vals for tuples in container for vals in tuples]) @@ -105,7 +225,7 @@ class TestQueries(IntegrationTestCase): { "user": user.name, "doctype": "Employee", - "docname": "_T-Employee-00001", + "docname": self.employees[0].name, "is_default": 1, "apply_to_all_doctypes": 1, "applicable_doctypes": [], From 78b026a4cab477f5fae693578503fdb7c42bd9dc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 5 May 2025 08:28:03 +0530 Subject: [PATCH 11/25] refactor(test): deterministic 'Budget' test suite --- .../accounts/doctype/budget/test_budget.py | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py index 013d36691db..12365516e2a 100644 --- a/erpnext/accounts/doctype/budget/test_budget.py +++ b/erpnext/accounts/doctype/budget/test_budget.py @@ -11,10 +11,64 @@ from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journ from erpnext.accounts.utils import get_fiscal_year from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order -EXTRA_TEST_RECORD_DEPENDENCIES = ["Monthly Distribution"] - class TestBudget(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_monthly_distribution() + cls.make_projects() + + @classmethod + def make_monthly_distribution(cls): + records = [ + { + "doctype": "Monthly Distribution", + "distribution_id": "_Test Distribution", + "fiscal_year": "_Test Fiscal Year 2013", + "percentages": [ + {"month": "January", "percentage_allocation": "8"}, + {"month": "February", "percentage_allocation": "8"}, + {"month": "March", "percentage_allocation": "8"}, + {"month": "April", "percentage_allocation": "8"}, + {"month": "May", "percentage_allocation": "8"}, + {"month": "June", "percentage_allocation": "8"}, + {"month": "July", "percentage_allocation": "8"}, + {"month": "August", "percentage_allocation": "8"}, + {"month": "September", "percentage_allocation": "8"}, + {"month": "October", "percentage_allocation": "8"}, + {"month": "November", "percentage_allocation": "10"}, + {"month": "December", "percentage_allocation": "10"}, + ], + } + ] + cls.monthly_distribution = [] + for x in records: + if not frappe.db.exists("Monthly Distribution", {"distribution_id": x.get("distribution_id")}): + cls.monthly_distribution.append(frappe.get_doc(x).insert()) + else: + cls.monthly_distribution.append( + frappe.get_doc("Monthly Distribution", {"distribution_id": x.get("distribution_id")}) + ) + + @classmethod + def make_projects(cls): + records = [ + { + "doctype": "Project", + "company": "_Test Company", + "project_name": "_Test Project", + "status": "Open", + } + ] + + cls.projects = [] + for x in records: + if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): + cls.projects.append(frappe.get_doc(x).insert()) + else: + cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) + def test_monthly_budget_crossed_ignore(self): set_total_expense_zero(nowdate(), "cost_center") From 66381f52ed9e0c2b392e2c276568512795f17c23 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 5 May 2025 08:28:43 +0530 Subject: [PATCH 12/25] chore: drop empty test suite for 'Monthly Distribution' data from test records are moved to 'Budget' test suite --- .../monthly_distribution/test_records.json | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 erpnext/accounts/doctype/monthly_distribution/test_records.json diff --git a/erpnext/accounts/doctype/monthly_distribution/test_records.json b/erpnext/accounts/doctype/monthly_distribution/test_records.json deleted file mode 100644 index 8dbf210ce65..00000000000 --- a/erpnext/accounts/doctype/monthly_distribution/test_records.json +++ /dev/null @@ -1,44 +0,0 @@ -[{ - "doctype": "Monthly Distribution", - "distribution_id": "_Test Distribution", - "fiscal_year": "_Test Fiscal Year 2013", - "percentages": [ - { - "month": "January", - "percentage_allocation": "8" - }, { - "month": "February", - "percentage_allocation": "8" - }, { - "month": "March", - "percentage_allocation": "8" - }, { - "month": "April", - "percentage_allocation": "8" - }, { - "month": "May", - "percentage_allocation": "8" - }, { - "month": "June", - "percentage_allocation": "8" - }, { - "month": "July", - "percentage_allocation": "8" - }, { - "month": "August", - "percentage_allocation": "8" - }, { - "month": "September", - "percentage_allocation": "8" - }, { - "month": "October", - "percentage_allocation": "8" - }, { - "month": "November", - "percentage_allocation": "10" - }, { - "month": "December", - "percentage_allocation": "10" - } - ] -}] From 80f7c507ba2be1b2f64794114e779182fccc02ca Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 5 May 2025 08:53:53 +0530 Subject: [PATCH 13/25] refactor(test): make 'Timesheet' test suite deterministic --- .../doctype/timesheet/test_timesheet.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 311fe3da140..767cff08db6 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -13,6 +13,29 @@ from erpnext.setup.doctype.employee.test_employee import make_employee class TestTimesheet(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_projects() + + @classmethod + def make_projects(cls): + records = [ + { + "doctype": "Project", + "company": "_Test Company", + "project_name": "_Test Project", + "status": "Open", + } + ] + + cls.projects = [] + for x in records: + if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): + cls.projects.append(frappe.get_doc(x).insert()) + else: + cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) + def setUp(self): frappe.db.delete("Timesheet") From 50551c1069287ae4bcc1c85bd12fcee036b98a53 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 5 May 2025 09:31:39 +0530 Subject: [PATCH 14/25] refactor(test): deterministic test suite for Task --- erpnext/projects/doctype/task/test_task.py | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index 082b474c07a..6d166c78088 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -10,6 +10,29 @@ from erpnext.projects.doctype.task.task import CircularReferenceError class TestTask(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_projects() + + @classmethod + def make_projects(cls): + records = [ + { + "doctype": "Project", + "company": "_Test Company", + "project_name": "_Test Project", + "status": "Open", + } + ] + + cls.projects = [] + for x in records: + if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): + cls.projects.append(frappe.get_doc(x).insert()) + else: + cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) + def test_circular_reference(self): task1 = create_task("_Test Task 1", add_days(nowdate(), -15), add_days(nowdate(), -10)) task2 = create_task("_Test Task 2", add_days(nowdate(), 11), add_days(nowdate(), 15), task1.name) From 8a3a9b985b5afb1100d45217fbf746a122e43295 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 5 May 2025 09:40:40 +0530 Subject: [PATCH 15/25] refactor(test): deterministic test suite for 'Maintenance Schedule' --- .../test_maintenance_schedule.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py index 34c6e955240..206c9687c31 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py +++ b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py @@ -16,6 +16,30 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_i class TestMaintenanceSchedule(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.make_sales_person() + + @classmethod + def make_sales_person(cls): + records = [ + { + "doctype": "Sales Person", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person", + }, + ] + cls.sales_person = [] + for x in records: + if not frappe.db.exists("Sales Person", {"sales_person_name": x.get("sales_person_name")}): + cls.sales_person.append(frappe.get_doc(x).insert()) + else: + cls.sales_person.append( + frappe.get_doc("Sales Person", {"sales_person_name": x.get("sales_person_name")}) + ) + def test_events_should_be_created_and_deleted(self): ms = make_maintenance_schedule() ms.generate_schedule() @@ -136,7 +160,7 @@ class TestMaintenanceSchedule(IntegrationTestCase): self.assertFalse(ms.validate_items_table_change()) # After Save ms.items[0].serial_no = "TEST001" - ms.items[0].sales_person = "_Test Sales Person" + ms.items[0].sales_person = self.sales_person[0].name ms.items[0].no_of_visits = 2 self.assertTrue(ms.validate_items_table_change()) ms.save() From 4a4e314899c771af818cc1146cd842ccc7186a97 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 5 May 2025 11:15:33 +0530 Subject: [PATCH 16/25] chore: handle duplicate data on sales invoice setup --- .../doctype/sales_invoice/test_sales_invoice.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 4d09f8e2977..081c6e7437d 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -135,9 +135,12 @@ class TestSalesInvoice(IntegrationTestCase): "user_id": "test2@example.com", }, ] + cls.employees = [] for x in records: if not frappe.db.exists("Employee", {"first_name": x.get("first_name")}): - frappe.get_doc(x).insert() + cls.employees.append(frappe.get_doc(x).insert()) + else: + cls.employees.append(frappe.get_doc("Employee", {"first_name": x.get("first_name")})) @classmethod def make_sales_person(cls): @@ -164,9 +167,14 @@ class TestSalesInvoice(IntegrationTestCase): "sales_person_name": "_Test Sales Person 2", }, ] + cls.sales_person = [] for x in records: if not frappe.db.exists("Sales Person", {"sales_person_name": x.get("sales_person_name")}): - frappe.get_doc(x).insert() + cls.sales_person.append(frappe.get_doc(x).insert()) + else: + cls.sales_person.append( + frappe.get_doc("Sales Person", {"sales_person_name": x.get("sales_person_name")}) + ) def test_sales_invoice_qty(self): si = create_sales_invoice(qty=0, do_not_save=True) From 543ba51009f63a132b2c2fe99a767e27bb72e675 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:08:34 +0530 Subject: [PATCH 17/25] refactor(test): create ERPNext specific test suite and move data initialization there --- .../accounts/doctype/budget/test_budget.py | 54 +----------------- erpnext/tests/utils.py | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+), 52 deletions(-) diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py index 12365516e2a..6fa655c0a36 100644 --- a/erpnext/accounts/doctype/budget/test_budget.py +++ b/erpnext/accounts/doctype/budget/test_budget.py @@ -3,72 +3,22 @@ import unittest import frappe -from frappe.tests import IntegrationTestCase from frappe.utils import now_datetime, nowdate from erpnext.accounts.doctype.budget.budget import BudgetError, get_actual_expense from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry from erpnext.accounts.utils import get_fiscal_year from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order +from erpnext.tests.utils import ERPNextTestSuite -class TestBudget(IntegrationTestCase): +class TestBudget(ERPNextTestSuite): @classmethod def setUpClass(cls): super().setUpClass() cls.make_monthly_distribution() cls.make_projects() - @classmethod - def make_monthly_distribution(cls): - records = [ - { - "doctype": "Monthly Distribution", - "distribution_id": "_Test Distribution", - "fiscal_year": "_Test Fiscal Year 2013", - "percentages": [ - {"month": "January", "percentage_allocation": "8"}, - {"month": "February", "percentage_allocation": "8"}, - {"month": "March", "percentage_allocation": "8"}, - {"month": "April", "percentage_allocation": "8"}, - {"month": "May", "percentage_allocation": "8"}, - {"month": "June", "percentage_allocation": "8"}, - {"month": "July", "percentage_allocation": "8"}, - {"month": "August", "percentage_allocation": "8"}, - {"month": "September", "percentage_allocation": "8"}, - {"month": "October", "percentage_allocation": "8"}, - {"month": "November", "percentage_allocation": "10"}, - {"month": "December", "percentage_allocation": "10"}, - ], - } - ] - cls.monthly_distribution = [] - for x in records: - if not frappe.db.exists("Monthly Distribution", {"distribution_id": x.get("distribution_id")}): - cls.monthly_distribution.append(frappe.get_doc(x).insert()) - else: - cls.monthly_distribution.append( - frappe.get_doc("Monthly Distribution", {"distribution_id": x.get("distribution_id")}) - ) - - @classmethod - def make_projects(cls): - records = [ - { - "doctype": "Project", - "company": "_Test Company", - "project_name": "_Test Project", - "status": "Open", - } - ] - - cls.projects = [] - for x in records: - if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): - cls.projects.append(frappe.get_doc(x).insert()) - else: - cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) - def test_monthly_budget_crossed_ignore(self): set_total_expense_zero(nowdate(), "cost_center") diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py index 7ed84514f52..a5f8cda1f3a 100644 --- a/erpnext/tests/utils.py +++ b/erpnext/tests/utils.py @@ -5,6 +5,7 @@ from typing import Any, NewType import frappe from frappe.core.doctype.report.report import get_report_module_dotted_path +from frappe.tests import IntegrationTestCase ReportFilters = dict[str, Any] ReportName = NewType("ReportName", str) @@ -114,3 +115,59 @@ def if_lending_app_not_installed(function): return return wrapper + + +class ERPNextTestSuite(IntegrationTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + @classmethod + def make_monthly_distribution(cls): + records = [ + { + "doctype": "Monthly Distribution", + "distribution_id": "_Test Distribution", + "fiscal_year": "_Test Fiscal Year 2013", + "percentages": [ + {"month": "January", "percentage_allocation": "8"}, + {"month": "February", "percentage_allocation": "8"}, + {"month": "March", "percentage_allocation": "8"}, + {"month": "April", "percentage_allocation": "8"}, + {"month": "May", "percentage_allocation": "8"}, + {"month": "June", "percentage_allocation": "8"}, + {"month": "July", "percentage_allocation": "8"}, + {"month": "August", "percentage_allocation": "8"}, + {"month": "September", "percentage_allocation": "8"}, + {"month": "October", "percentage_allocation": "8"}, + {"month": "November", "percentage_allocation": "10"}, + {"month": "December", "percentage_allocation": "10"}, + ], + } + ] + cls.monthly_distribution = [] + for x in records: + if not frappe.db.exists("Monthly Distribution", {"distribution_id": x.get("distribution_id")}): + cls.monthly_distribution.append(frappe.get_doc(x).insert()) + else: + cls.monthly_distribution.append( + frappe.get_doc("Monthly Distribution", {"distribution_id": x.get("distribution_id")}) + ) + + @classmethod + def make_projects(cls): + records = [ + { + "doctype": "Project", + "company": "_Test Company", + "project_name": "_Test Project", + "status": "Open", + } + ] + + cls.projects = [] + for x in records: + if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): + cls.projects.append(frappe.get_doc(x).insert()) + else: + cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) From 26915c622f51e431cd46f4351113393c8b79f536 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:10:26 +0530 Subject: [PATCH 18/25] refactor(test): move SI test data creation to erpnext test suite --- .../sales_invoice/test_sales_invoice.py | 84 +------------------ erpnext/tests/utils.py | 81 ++++++++++++++++++ 2 files changed, 83 insertions(+), 82 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 081c6e7437d..367f3f82ccd 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -48,6 +48,7 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ) from erpnext.stock.get_item_details import get_item_tax_map from erpnext.stock.utils import get_incoming_rate, get_stock_balance +from erpnext.tests.utils import ERPNextTestSuite class UnitTestSalesInvoice(UnitTestCase): @@ -59,7 +60,7 @@ class UnitTestSalesInvoice(UnitTestCase): pass -class TestSalesInvoice(IntegrationTestCase): +class TestSalesInvoice(ERPNextTestSuite): def setUp(self): from erpnext.stock.doctype.stock_ledger_entry.test_stock_ledger_entry import create_items @@ -95,87 +96,6 @@ class TestSalesInvoice(IntegrationTestCase): def tearDownClass(self): unlink_payment_on_cancel_of_invoice(0) - @classmethod - def make_employees(cls): - records = [ - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department - _TC", - "doctype": "Employee", - "first_name": "_Test Employee", - "gender": "Female", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test@example.com", - }, - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department 1 - _TC", - "doctype": "Employee", - "first_name": "_Test Employee 1", - "gender": "Male", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test1@example.com", - }, - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department 1 - _TC", - "doctype": "Employee", - "first_name": "_Test Employee 2", - "gender": "Male", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test2@example.com", - }, - ] - cls.employees = [] - for x in records: - if not frappe.db.exists("Employee", {"first_name": x.get("first_name")}): - cls.employees.append(frappe.get_doc(x).insert()) - else: - cls.employees.append(frappe.get_doc("Employee", {"first_name": x.get("first_name")})) - - @classmethod - def make_sales_person(cls): - records = [ - { - "doctype": "Sales Person", - "employee": "_T-Employee-00001", - "is_group": 0, - "parent_sales_person": "Sales Team", - "sales_person_name": "_Test Sales Person", - }, - { - "doctype": "Sales Person", - "employee": "_T-Employee-00002", - "is_group": 0, - "parent_sales_person": "Sales Team", - "sales_person_name": "_Test Sales Person 1", - }, - { - "doctype": "Sales Person", - "employee": "_T-Employee-00003", - "is_group": 0, - "parent_sales_person": "Sales Team", - "sales_person_name": "_Test Sales Person 2", - }, - ] - cls.sales_person = [] - for x in records: - if not frappe.db.exists("Sales Person", {"sales_person_name": x.get("sales_person_name")}): - cls.sales_person.append(frappe.get_doc(x).insert()) - else: - cls.sales_person.append( - frappe.get_doc("Sales Person", {"sales_person_name": x.get("sales_person_name")}) - ) - def test_sales_invoice_qty(self): si = create_sales_invoice(qty=0, do_not_save=True) with self.assertRaises(InvalidQtyError): diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py index a5f8cda1f3a..f62da50672b 100644 --- a/erpnext/tests/utils.py +++ b/erpnext/tests/utils.py @@ -171,3 +171,84 @@ class ERPNextTestSuite(IntegrationTestCase): cls.projects.append(frappe.get_doc(x).insert()) else: cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) + + @classmethod + def make_employees(cls): + records = [ + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department - _TC", + "doctype": "Employee", + "first_name": "_Test Employee", + "gender": "Female", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test@example.com", + }, + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department 1 - _TC", + "doctype": "Employee", + "first_name": "_Test Employee 1", + "gender": "Male", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test1@example.com", + }, + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department 1 - _TC", + "doctype": "Employee", + "first_name": "_Test Employee 2", + "gender": "Male", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test2@example.com", + }, + ] + cls.employees = [] + for x in records: + if not frappe.db.exists("Employee", {"first_name": x.get("first_name")}): + cls.employees.append(frappe.get_doc(x).insert()) + else: + cls.employees.append(frappe.get_doc("Employee", {"first_name": x.get("first_name")})) + + @classmethod + def make_sales_person(cls): + records = [ + { + "doctype": "Sales Person", + "employee": "_T-Employee-00001", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person", + }, + { + "doctype": "Sales Person", + "employee": "_T-Employee-00002", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person 1", + }, + { + "doctype": "Sales Person", + "employee": "_T-Employee-00003", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person 2", + }, + ] + cls.sales_person = [] + for x in records: + if not frappe.db.exists("Sales Person", {"sales_person_name": x.get("sales_person_name")}): + cls.sales_person.append(frappe.get_doc(x).insert()) + else: + cls.sales_person.append( + frappe.get_doc("Sales Person", {"sales_person_name": x.get("sales_person_name")}) + ) From a55a86f300431811fad1aa1434c8f6e3d97d4ac6 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:12:50 +0530 Subject: [PATCH 19/25] refactor(test): Queries test suite to use ERPNextTestSuite --- erpnext/controllers/tests/test_queries.py | 116 +--------------------- erpnext/tests/utils.py | 48 +++++++++ 2 files changed, 50 insertions(+), 114 deletions(-) diff --git a/erpnext/controllers/tests/test_queries.py b/erpnext/controllers/tests/test_queries.py index 69ec12ebd47..9e92d7ce638 100644 --- a/erpnext/controllers/tests/test_queries.py +++ b/erpnext/controllers/tests/test_queries.py @@ -8,6 +8,7 @@ from frappe.custom.doctype.property_setter.property_setter import make_property_ from frappe.tests import IntegrationTestCase from erpnext.controllers import queries +from erpnext.tests.utils import ERPNextTestSuite def add_default_params(func, doctype): @@ -17,7 +18,7 @@ def add_default_params(func, doctype): EXTRA_TEST_RECORD_DEPENDENCIES = ["Item", "BOM", "Account"] -class TestQueries(IntegrationTestCase): +class TestQueries(ERPNextTestSuite): # All tests are based on self.globalTestRecords[doctype] @classmethod @@ -27,119 +28,6 @@ class TestQueries(IntegrationTestCase): cls.make_leads() cls.make_projects() - @classmethod - def make_employees(cls): - records = [ - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department - _TC", - "doctype": "Employee", - "first_name": "_Test Employee", - "gender": "Female", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test@example.com", - }, - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department 1 - _TC", - "doctype": "Employee", - "first_name": "_Test Employee 1", - "gender": "Male", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test1@example.com", - }, - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department 1 - _TC", - "doctype": "Employee", - "first_name": "_Test Employee 2", - "gender": "Male", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test2@example.com", - }, - ] - cls.employees = [] - for x in records: - if not frappe.db.exists("Employee", {"first_name": x.get("first_name")}): - cls.employees.append(frappe.get_doc(x).insert()) - else: - cls.employees.append(frappe.get_doc("Employee", {"first_name": x.get("first_name")})) - - @classmethod - def make_leads(cls): - records = [ - { - "doctype": "Lead", - "email_id": "test_lead@example.com", - "lead_name": "_Test Lead", - "status": "Open", - "territory": "_Test Territory", - "naming_series": "_T-Lead-", - }, - { - "doctype": "Lead", - "email_id": "test_lead1@example.com", - "lead_name": "_Test Lead 1", - "status": "Open", - "naming_series": "_T-Lead-", - }, - { - "doctype": "Lead", - "email_id": "test_lead2@example.com", - "lead_name": "_Test Lead 2", - "status": "Lead", - "naming_series": "_T-Lead-", - }, - { - "doctype": "Lead", - "email_id": "test_lead3@example.com", - "lead_name": "_Test Lead 3", - "status": "Converted", - "naming_series": "_T-Lead-", - }, - { - "doctype": "Lead", - "email_id": "test_lead4@example.com", - "lead_name": "_Test Lead 4", - "company_name": "_Test Lead 4", - "status": "Open", - "naming_series": "_T-Lead-", - }, - ] - cls.leads = [] - for x in records: - if not frappe.db.exists("Lead", {"email_id": x.get("email_id")}): - cls.leads.append(frappe.get_doc(x).insert()) - else: - cls.leads.append(frappe.get_doc("Lead", {"email_id": x.get("email_id")})) - - @classmethod - def make_projects(cls): - records = [ - { - "doctype": "Project", - "company": "_Test Company", - "project_name": "_Test Project", - "status": "Open", - } - ] - - cls.projects = [] - for x in records: - if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): - cls.projects.append(frappe.get_doc(x).insert()) - else: - cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) - def assert_nested_in(self, item, container): self.assertIn(item, [vals for tuples in container for vals in tuples]) diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py index f62da50672b..7dedd637d3c 100644 --- a/erpnext/tests/utils.py +++ b/erpnext/tests/utils.py @@ -252,3 +252,51 @@ class ERPNextTestSuite(IntegrationTestCase): cls.sales_person.append( frappe.get_doc("Sales Person", {"sales_person_name": x.get("sales_person_name")}) ) + + @classmethod + def make_leads(cls): + records = [ + { + "doctype": "Lead", + "email_id": "test_lead@example.com", + "lead_name": "_Test Lead", + "status": "Open", + "territory": "_Test Territory", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead1@example.com", + "lead_name": "_Test Lead 1", + "status": "Open", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead2@example.com", + "lead_name": "_Test Lead 2", + "status": "Lead", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead3@example.com", + "lead_name": "_Test Lead 3", + "status": "Converted", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead4@example.com", + "lead_name": "_Test Lead 4", + "company_name": "_Test Lead 4", + "status": "Open", + "naming_series": "_T-Lead-", + }, + ] + cls.leads = [] + for x in records: + if not frappe.db.exists("Lead", {"email_id": x.get("email_id")}): + cls.leads.append(frappe.get_doc(x).insert()) + else: + cls.leads.append(frappe.get_doc("Lead", {"email_id": x.get("email_id")})) From b2fd354d4162e8c4c9309316c069da2ddd20b356 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:14:25 +0530 Subject: [PATCH 20/25] refactor(test): Lead with use ERPNextTestSuite --- erpnext/crm/doctype/lead/test_lead.py | 51 ++------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index 2431d3478ef..b1b4e162b32 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -8,62 +8,15 @@ from frappe.utils import random_string, today from erpnext.crm.doctype.lead.lead import make_opportunity from erpnext.crm.utils import get_linked_prospect +from erpnext.tests.utils import ERPNextTestSuite -class TestLead(IntegrationTestCase): +class TestLead(ERPNextTestSuite): @classmethod def setUpClass(cls): super().setUpClass() cls.make_leads() - @classmethod - def make_leads(cls): - records = [ - { - "doctype": "Lead", - "email_id": "test_lead@example.com", - "lead_name": "_Test Lead", - "status": "Open", - "territory": "_Test Territory", - "naming_series": "_T-Lead-", - }, - { - "doctype": "Lead", - "email_id": "test_lead1@example.com", - "lead_name": "_Test Lead 1", - "status": "Open", - "naming_series": "_T-Lead-", - }, - { - "doctype": "Lead", - "email_id": "test_lead2@example.com", - "lead_name": "_Test Lead 2", - "status": "Lead", - "naming_series": "_T-Lead-", - }, - { - "doctype": "Lead", - "email_id": "test_lead3@example.com", - "lead_name": "_Test Lead 3", - "status": "Converted", - "naming_series": "_T-Lead-", - }, - { - "doctype": "Lead", - "email_id": "test_lead4@example.com", - "lead_name": "_Test Lead 4", - "company_name": "_Test Lead 4", - "status": "Open", - "naming_series": "_T-Lead-", - }, - ] - cls.leads = [] - for x in records: - if not frappe.db.exists("Lead", {"email_id": x.get("email_id")}): - cls.leads.append(frappe.get_doc(x).insert()) - else: - cls.leads.append(frappe.get_doc("Lead", {"email_id": x.get("email_id")})) - def test_make_customer(self): from erpnext.crm.doctype.lead.lead import make_customer From 1271ba3672ca023feb80b241e60231c5d5837bef Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:16:52 +0530 Subject: [PATCH 21/25] refactor(test): Opportunity will use ERPNextTestSuite --- .../doctype/opportunity/test_opportunity.py | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py index 3111bcd4cda..db9866d9b89 100644 --- a/erpnext/crm/doctype/opportunity/test_opportunity.py +++ b/erpnext/crm/doctype/opportunity/test_opportunity.py @@ -10,34 +10,18 @@ from erpnext.crm.doctype.lead.lead import make_customer from erpnext.crm.doctype.lead.test_lead import make_lead from erpnext.crm.doctype.opportunity.opportunity import make_quotation from erpnext.crm.utils import get_linked_communication_list +from erpnext.tests.utils import ERPNextTestSuite -class TestOpportunity(IntegrationTestCase): +class TestOpportunity(ERPNextTestSuite): @classmethod def setUpClass(cls): super().setUpClass() + # Only first lead is required + # TODO: dynamically generate limited test records cls.make_leads() cls.make_opportunities() - @classmethod - def make_leads(cls): - records = [ - { - "doctype": "Lead", - "email_id": "test_lead@example.com", - "lead_name": "_Test Lead", - "status": "Open", - "territory": "_Test Territory", - "naming_series": "_T-Lead-", - }, - ] - cls.leads = [] - for x in records: - if not frappe.db.exists("Lead", {"email_id": x.get("email_id")}): - cls.leads.append(frappe.get_doc(x).insert()) - else: - cls.leads.append(frappe.get_doc("Lead", {"email_id": x.get("email_id")})) - @classmethod def make_opportunities(cls): records = [ From fbdbcdd8c01f9385869e1d0813f694cdd67a03c7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:19:30 +0530 Subject: [PATCH 22/25] refactor(test): Activity Cost to use ERPNextTestSuite --- .../activity_cost/test_activity_cost.py | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/erpnext/projects/doctype/activity_cost/test_activity_cost.py b/erpnext/projects/doctype/activity_cost/test_activity_cost.py index a3eb176693a..470b21cca87 100644 --- a/erpnext/projects/doctype/activity_cost/test_activity_cost.py +++ b/erpnext/projects/doctype/activity_cost/test_activity_cost.py @@ -6,37 +6,16 @@ import frappe from frappe.tests import IntegrationTestCase from erpnext.projects.doctype.activity_cost.activity_cost import DuplicationError +from erpnext.tests.utils import ERPNextTestSuite -class TestActivityCost(IntegrationTestCase): +class TestActivityCost(ERPNextTestSuite): @classmethod def setUpClass(cls): super().setUpClass() + # TODO: only 1 employee is required cls.make_employees() - @classmethod - def make_employees(cls): - records = [ - { - "company": "_Test Company", - "date_of_birth": "1980-01-01", - "date_of_joining": "2010-01-01", - "department": "_Test Department - _TC", - "doctype": "Employee", - "first_name": "_Test Employee", - "gender": "Female", - "naming_series": "_T-Employee-", - "status": "Active", - "user_id": "test@example.com", - }, - ] - cls.employees = [] - for x in records: - if not frappe.db.exists("Employee", {"first_name": x.get("first_name")}): - cls.employees.append(frappe.get_doc(x).insert()) - else: - cls.employees.append(frappe.get_doc("Employee", {"first_name": x.get("first_name")})) - def test_duplication(self): frappe.db.sql("delete from `tabActivity Cost`") activity_cost1 = frappe.new_doc("Activity Cost") From 835d08ab00130b81288f0940ce3d038a793ea92e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:21:55 +0530 Subject: [PATCH 23/25] refactor(test): Project will use ERPNextTestSuite --- .../projects/doctype/project/test_project.py | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/erpnext/projects/doctype/project/test_project.py b/erpnext/projects/doctype/project/test_project.py index b76f27a66ca..2c88b88ff4e 100644 --- a/erpnext/projects/doctype/project/test_project.py +++ b/erpnext/projects/doctype/project/test_project.py @@ -9,6 +9,7 @@ from erpnext.projects.doctype.project_template.test_project_template import make from erpnext.projects.doctype.task.test_task import create_task from erpnext.selling.doctype.sales_order.sales_order import make_project as make_project_from_so from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order +from erpnext.tests.utils import ERPNextTestSuite IGNORE_TEST_RECORD_DEPENDENCIES = ["Sales Order"] @@ -22,30 +23,12 @@ class UnitTestProject(UnitTestCase): pass -class TestProject(IntegrationTestCase): +class TestProject(ERPNextTestSuite): @classmethod def setUpClass(cls): super().setUpClass() cls.make_projects() - @classmethod - def make_projects(cls): - records = [ - { - "doctype": "Project", - "company": "_Test Company", - "project_name": "_Test Project", - "status": "Open", - } - ] - - cls.projects = [] - for x in records: - if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): - cls.projects.append(frappe.get_doc(x).insert()) - else: - cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) - def test_project_with_template_having_no_parent_and_depend_tasks(self): project_name = "Test Project with Template - No Parent and Dependend Tasks" frappe.db.sql(""" delete from tabTask where project = %s """, project_name) From bc7cc6eac0b3c69f89f779f463c034ae64720407 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:22:50 +0530 Subject: [PATCH 24/25] refactor(test): Project will use ERPNextTestSuite --- erpnext/projects/doctype/task/test_task.py | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index 6d166c78088..7a93585e832 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -7,32 +7,15 @@ from frappe.tests import IntegrationTestCase from frappe.utils import add_days, getdate, nowdate from erpnext.projects.doctype.task.task import CircularReferenceError +from erpnext.tests.utils import ERPNextTestSuite -class TestTask(IntegrationTestCase): +class TestTask(ERPNextTestSuite): @classmethod def setUpClass(cls): super().setUpClass() cls.make_projects() - @classmethod - def make_projects(cls): - records = [ - { - "doctype": "Project", - "company": "_Test Company", - "project_name": "_Test Project", - "status": "Open", - } - ] - - cls.projects = [] - for x in records: - if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): - cls.projects.append(frappe.get_doc(x).insert()) - else: - cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) - def test_circular_reference(self): task1 = create_task("_Test Task 1", add_days(nowdate(), -15), add_days(nowdate(), -10)) task2 = create_task("_Test Task 2", add_days(nowdate(), 11), add_days(nowdate(), 15), task1.name) From afc46a77f61b071ca3f38a00b82f75442993a4b8 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 7 May 2025 12:23:49 +0530 Subject: [PATCH 25/25] refactor(test): Timesheet will use ERPNextTestSuite --- .../doctype/timesheet/test_timesheet.py | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 767cff08db6..f9c631b00a8 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -10,32 +10,15 @@ from frappe.utils import add_to_date, now_datetime, nowdate from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.projects.doctype.timesheet.timesheet import OverlapError, make_sales_invoice from erpnext.setup.doctype.employee.test_employee import make_employee +from erpnext.tests.utils import ERPNextTestSuite -class TestTimesheet(IntegrationTestCase): +class TestTimesheet(ERPNextTestSuite): @classmethod def setUpClass(cls): super().setUpClass() cls.make_projects() - @classmethod - def make_projects(cls): - records = [ - { - "doctype": "Project", - "company": "_Test Company", - "project_name": "_Test Project", - "status": "Open", - } - ] - - cls.projects = [] - for x in records: - if not frappe.db.exists("Project", {"project_name": x.get("project_name")}): - cls.projects.append(frappe.get_doc(x).insert()) - else: - cls.projects.append(frappe.get_doc("Project", {"project_name": x.get("project_name")})) - def setUp(self): frappe.db.delete("Timesheet")