From 811f13d3b9e2a76df11623b830342e0868332b3e Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 6 Jan 2025 23:02:46 +0530 Subject: [PATCH 1/4] test(fix): create missing test fixtures --- hrms/hr/report/leave_ledger/test_leave_ledger.py | 1 + hrms/payroll/doctype/salary_slip/test_salary_slip.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/hrms/hr/report/leave_ledger/test_leave_ledger.py b/hrms/hr/report/leave_ledger/test_leave_ledger.py index 4eae16d113..3a8998cd99 100644 --- a/hrms/hr/report/leave_ledger/test_leave_ledger.py +++ b/hrms/hr/report/leave_ledger/test_leave_ledger.py @@ -48,6 +48,7 @@ def setUp(self): # create leave type self.earned_leave = "Test Earned Leave" self.casual_leave = "_Test Leave Type" + create_leave_type(leave_type=self.casual_leave) self.create_earned_leave_allocation() self.create_casual_leave_allocation() diff --git a/hrms/payroll/doctype/salary_slip/test_salary_slip.py b/hrms/payroll/doctype/salary_slip/test_salary_slip.py index a3ab575da8..2163572d14 100644 --- a/hrms/payroll/doctype/salary_slip/test_salary_slip.py +++ b/hrms/payroll/doctype/salary_slip/test_salary_slip.py @@ -5,6 +5,7 @@ import random import frappe +from frappe.core.doctype.user_permission.test_user_permission import create_user from frappe.model.document import Document from frappe.tests import IntegrationTestCase, change_settings from frappe.utils import ( @@ -2168,6 +2169,8 @@ def make_leave_application( half_day_date=None, submit=True, ): + create_user("test@example.com") + leave_application = frappe.get_doc( dict( doctype="Leave Application", From d2920e855262f277251e403a1bb86e618005e91c Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 6 Jan 2025 23:26:01 +0530 Subject: [PATCH 2/4] test(fix): Leave Ledger - skip weekly offs in test holiday list for deterministic results - weekly off dates will vary every year, testing against dynamic holiday list isn't necessary for leave ledger --- hrms/hr/report/leave_ledger/test_leave_ledger.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hrms/hr/report/leave_ledger/test_leave_ledger.py b/hrms/hr/report/leave_ledger/test_leave_ledger.py index 3a8998cd99..bd969af06b 100644 --- a/hrms/hr/report/leave_ledger/test_leave_ledger.py +++ b/hrms/hr/report/leave_ledger/test_leave_ledger.py @@ -33,16 +33,19 @@ def setUp(self): self.year_start = getdate(get_year_start(self.date)) self.year_end = getdate(get_year_ending(self.date)) - self.holiday_list = make_holiday_list( - "_Test Emp Balance Holiday List", self.year_start, self.year_end + holiday_list = make_holiday_list( + "_Test Emp Balance Holiday List", + self.year_start, + self.year_end, + add_weekly_offs=False, ) - - # create employee 1 & 2 self.employee_1 = frappe.get_doc( - "Employee", make_employee("test_emp_1@example.com", company="_Test Company") + "Employee", + make_employee("test_emp_1@example.com", company="_Test Company", holiday_list=holiday_list), ) self.employee_2 = frappe.get_doc( - "Employee", make_employee("test_emp_2@example.com", company="_Test Company") + "Employee", + make_employee("test_emp_2@example.com", company="_Test Company", holiday_list=holiday_list), ) # create leave type From e26b49d9542e6d9445c9c1f8fdd77426f79315c8 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 6 Jan 2025 23:56:40 +0530 Subject: [PATCH 3/4] test(fix): set correct holiday list - tests generate holiday list as per current year. Those who assert against hardcoded dates from previous years fail as holidays from prev year aren't applicable anymore - set that year's holiday list for tests that check against exact dates --- hrms/hr/report/leave_ledger/test_leave_ledger.py | 1 + hrms/payroll/doctype/salary_slip/test_salary_slip.py | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/hrms/hr/report/leave_ledger/test_leave_ledger.py b/hrms/hr/report/leave_ledger/test_leave_ledger.py index bd969af06b..7d405c2274 100644 --- a/hrms/hr/report/leave_ledger/test_leave_ledger.py +++ b/hrms/hr/report/leave_ledger/test_leave_ledger.py @@ -51,6 +51,7 @@ def setUp(self): # create leave type self.earned_leave = "Test Earned Leave" self.casual_leave = "_Test Leave Type" + create_leave_type(leave_type=self.earned_leave) create_leave_type(leave_type=self.casual_leave) self.create_earned_leave_allocation() diff --git a/hrms/payroll/doctype/salary_slip/test_salary_slip.py b/hrms/payroll/doctype/salary_slip/test_salary_slip.py index 2163572d14..ab71525bd0 100644 --- a/hrms/payroll/doctype/salary_slip/test_salary_slip.py +++ b/hrms/payroll/doctype/salary_slip/test_salary_slip.py @@ -372,8 +372,16 @@ def test_payment_days_based_on_leave_application(self): self.assertEqual(ss.payment_days, days_in_month - no_of_holidays - 3.75) @change_settings("Payroll Settings", {"payroll_based_on": "Leave"}) - def test_payment_days_calculation_for_varying_leave_ranges(self): - emp_id = make_employee("test_payment_days_based_on_leave_application@salary.com") + def test_payment_days_calculation_for_lwp_on_month_boundaries(self): + """Tests LWP calculation leave applications created on month boundaries""" + holiday_list = make_holiday_list( + "Test Holiday List", + "2024-01-01", + "2024-12-31", + ) + emp_id = make_employee( + "test_payment_days_based_on_leave_application@salary.com", holiday_list=holiday_list + ) make_leave_application(emp_id, "2024-06-28", "2024-07-03", "Leave Without Pay") # 3 days in July make_leave_application(emp_id, "2024-07-10", "2024-07-13", "Leave Without Pay") # 4 days in July From 689e9d837fa675e8a148da5de08b67120f5b7ed8 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 7 Jan 2025 00:52:55 +0530 Subject: [PATCH 4/4] test(refactor): use consistent dates in all salary withholding tests - currently 1 test uses hardcoded dates from 2024, while others use dynamic dates from current year, leading to missing salary structure assignment validations - use the same dates in all tests, no need to test this against dynamic data --- .../test_salary_withholding.py | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/hrms/payroll/doctype/salary_withholding/test_salary_withholding.py b/hrms/payroll/doctype/salary_withholding/test_salary_withholding.py index d79a084611..230b3859df 100644 --- a/hrms/payroll/doctype/salary_withholding/test_salary_withholding.py +++ b/hrms/payroll/doctype/salary_withholding/test_salary_withholding.py @@ -3,7 +3,7 @@ import frappe from frappe.tests import IntegrationTestCase -from frappe.utils import get_first_day, get_year_start, getdate +from frappe.utils import getdate from erpnext.setup.doctype.employee.test_employee import make_employee @@ -11,6 +11,12 @@ from hrms.payroll.doctype.payroll_entry.test_payroll_entry import make_payroll_entry from hrms.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure +COMPANY_NAME = "_Test Company" +MONTH_1_START = getdate("2024-01-01") +MONTH_1_END = getdate("2024-01-31") +MONTH_2_START = getdate("2024-02-01") +MONTH_2_END = getdate("2024-02-29") + class TestSalaryWithholding(IntegrationTestCase): def setUp(self): @@ -26,28 +32,36 @@ def setUp(self): ]: frappe.db.delete(dt) - self.company = frappe.get_doc("Company", "_Test Company") - self.employee1 = make_employee("employee1@example.com", company=self.company, designation="Engineer") - self.employee2 = make_employee("employee2@example.com", company=self.company, designation="Engineer") + self.company = frappe.get_doc("Company", COMPANY_NAME) + self.employee1 = make_employee("employee1@example.com", company=COMPANY_NAME, designation="Engineer") + self.employee2 = make_employee("employee2@example.com", company=COMPANY_NAME, designation="Engineer") - self.today = getdate() - year_start = get_year_start(self.today) - make_salary_structure("Test Withholding", "Monthly", employee=self.employee1, from_date=year_start) - make_salary_structure("Test Withholding", "Monthly", employee=self.employee2, from_date=year_start) + make_salary_structure( + "Test Withholding", + "Monthly", + company=COMPANY_NAME, + employee=self.employee1, + from_date=MONTH_1_START, + ) + make_salary_structure( + "Test Withholding", + "Monthly", + company=COMPANY_NAME, + employee=self.employee2, + from_date=MONTH_1_START, + ) def test_set_withholding_cycles_and_to_date(self): - from_date = getdate("2024-06-01") - to_date = getdate("2024-07-31") - withholding = create_salary_withholding(self.employee1, from_date, 2) + withholding = create_salary_withholding(self.employee1, MONTH_1_START, 2) - self.assertEqual(withholding.to_date, to_date) - self.assertEqual(withholding.cycles[0].from_date, from_date) - self.assertEqual(withholding.cycles[0].to_date, getdate("2024-06-30")) - self.assertEqual(withholding.cycles[1].from_date, getdate("2024-07-01")) - self.assertEqual(withholding.cycles[1].to_date, to_date) + self.assertEqual(withholding.to_date, MONTH_2_END) + self.assertEqual(withholding.cycles[0].from_date, MONTH_1_START) + self.assertEqual(withholding.cycles[0].to_date, MONTH_1_END) + self.assertEqual(withholding.cycles[1].from_date, MONTH_2_START) + self.assertEqual(withholding.cycles[1].to_date, MONTH_2_END) def test_salary_withholding(self): - withholding = create_salary_withholding(self.employee1, get_first_day(self.today), 2) + withholding = create_salary_withholding(self.employee1, MONTH_1_START, 2) withholding.submit() payroll_entry = self._make_payroll_entry() @@ -61,7 +75,7 @@ def test_salary_withholding(self): self.assertEqual(withholding.status, "Withheld") def test_release_withheld_salaries(self): - withholding = create_salary_withholding(self.employee1, get_first_day(self.today), 2) + withholding = create_salary_withholding(self.employee1, MONTH_1_START, 2) withholding.submit() def test_run_payroll_for_cycle(withholding_cycle): @@ -106,7 +120,7 @@ def test_run_payroll_for_cycle(withholding_cycle): self.assertEqual(payroll_employee.is_salary_withheld, 1) def _make_payroll_entry(self, date: str | None = None): - dates = get_start_end_dates("Monthly", date or self.today) + dates = get_start_end_dates("Monthly", date or MONTH_1_START) return make_payroll_entry( start_date=dates.start_date, end_date=dates.end_date, @@ -117,7 +131,7 @@ def _make_payroll_entry(self, date: str | None = None): def _submit_bank_entry(self, bank_entry: dict): bank_entry.cheque_no = "123456" - bank_entry.cheque_date = self.today + bank_entry.cheque_date = MONTH_1_START bank_entry.submit() def _get_payroll_employee_row(self, payroll_entry: dict) -> dict | None: