adamspd / django-appointment

A Django app for managing appointment scheduling with ease and flexibility.
Apache License 2.0
89 stars 30 forks source link

order dependant tests in appointment.tests.utils.test_db_helpers #163

Closed deronnax closed 1 month ago

deronnax commented 3 months ago

On the main branch:

./manage.py test appointment.tests.utils.test_db_helpers  --shuffle
Using shuffle seed: 4356288042 (generated)
Found 87 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...........................................E.......2024-03-27 02:06:11,934 - appointment.logger_config - INFO - Scheduling email reminder for appointment 1 at 2024-03-26 09:00:00+01:00
.................F....F...2024-03-27 02:06:25,464 - appointment.logger_config - INFO - Rescheduling is allowed for service Test Service -> Reschedule count: 0, Reschedule limit: 0
.2024-03-27 02:06:26,213 - appointment.logger_config - INFO - Rescheduling is allowed but no specific limit set for service Test Service -> Reschedule count: 0, Reschedule limit: 3
.2024-03-27 02:06:26,947 - appointment.logger_config - INFO - Rescheduling is allowed for service Test Service -> Reschedule count: 4, Reschedule limit: 3
.2024-03-27 02:06:27,704 - appointment.logger_config - INFO - Rescheduling is allowed but no specific limit set for service Test Service -> Reschedule count: 2, Reschedule limit: 3
2024-03-27 02:06:27,705 - appointment.logger_config - INFO - Rescheduling is allowed but no specific limit set for service Test Service -> Reschedule count: 3, Reschedule limit: 3
.2024-03-27 02:06:28,384 - appointment.logger_config - INFO - New appointment created: {'id': 1, 'client_name': 'Tester2', 'client_email': 'tester2@gmail.com', 'start_time': '1900-01-01 09:00', 'end_time': '1900-01-01 10:00', 'service_name': 'Test Service', 'address': '123 Main St', 'want_reminder': True, 'additional_info': 'Additional Test Info', 'paid': False, 'amount_to_pay': 100, 'id_request': '171150158838388516e2e264025104d8c93e8144a07168c8c'}
Missing conf: []
2024-03-27 02:06:28,384 - appointment.logger_config - INFO - Scheduling email reminder for appointment 1 at 2024-03-26 09:00:00+01:00
......
======================================================================
ERROR: test_calculate_slots_on_working_day_without_appointments (appointment.tests.utils.test_db_helpers.TestCalculateStaffSlots)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/mathieu/dev/django-appointment/appointment/tests/utils/test_db_helpers.py", line 109, in test_calculate_slots_on_working_day_without_appointments
    slots = calculate_staff_slots(self.working_date, self.staff_member1)
  File "/Users/mathieu/dev/django-appointment/appointment/utils/db_helpers.py", line 75, in calculate_staff_slots
    buffer_duration_minutes = get_staff_member_buffer_time(staff_member, date)
  File "/Users/mathieu/dev/django-appointment/appointment/utils/db_helpers.py", line 538, in get_staff_member_buffer_time
    _, _, _, buff_time = get_times_from_config(date)
  File "/Users/mathieu/dev/django-appointment/appointment/utils/db_helpers.py", line 593, in get_times_from_config
    start_time = datetime.datetime.combine(date, datetime.time(hour=config.lead_time.hour,
AttributeError: 'NoneType' object has no attribute 'hour'

======================================================================
FAIL: test_staff_member_buffer_time_with_global_setting (appointment.tests.utils.test_db_helpers.TestStaffMemberTimeFunctions)
Test buffer time when staff member-specific setting is None.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/mathieu/.pyenv/versions/3.10.13/lib/python3.10/unittest/mock.py", line 1379, in patched
    return func(*newargs, **newkeywargs)
  File "/Users/mathieu/dev/django-appointment/appointment/tests/utils/test_db_helpers.py", line 814, in test_staff_member_buffer_time_with_global_setting
    self.assertEqual(buffer_time, 60)  # Global setting
AssertionError: 90.0 != 60

======================================================================
FAIL: test_staff_member_slot_duration_with_global_setting (appointment.tests.utils.test_db_helpers.TestStaffMemberTimeFunctions)
Test slot duration when staff member-specific setting is None.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/mathieu/.pyenv/versions/3.10.13/lib/python3.10/unittest/mock.py", line 1379, in patched
    return func(*newargs, **newkeywargs)
  File "/Users/mathieu/dev/django-appointment/appointment/tests/utils/test_db_helpers.py", line 826, in test_staff_member_slot_duration_with_global_setting
    self.assertEqual(slot_duration, 30)  # Global setting
AssertionError: 45.0 != 30

----------------------------------------------------------------------
Ran 87 tests in 47.532s

FAILED (failures=2, errors=1)
Used shuffle seed: 4356288042 (generated)
Destroying test database for alias 'default'...

You can reproduce these failures by re-running the test suite shuffled with the same seed: ./manage.py test appointment.tests.utils.test_db_helpers --shuffle 4356288042.

I notice that objects created in setUp sometime are mutated elsewhere, that might be a cause.

adamspd commented 3 months ago

I didn't know there was a --shuffle option.

I will experiment with it and try to understand what it does. As it turns out, there's still a lot I don't know about Django, thanks ! I will work on that issue to resolve it.

deronnax commented 3 months ago

--shuffle shuffles (randomizes) the test run order, which is otherwise deterministic. Because of this determinist order, developers tend to rely on this order and assume certains behaviors, partucularly about objects created in setUp, modified in some tests and then tests somewhere else. But that's a fault: tests should be Isolated (self-sufficient), and hence order independant (see the FIRST test principle).

Also, did you know about the --parallel [n] options? It split the test suite in [n] subprocesses, which roughly divides the test suite run time by the number of logical core of your machine. Very handy. But it also obviously change the test run order grouping from the "normal" non-parallel run, and I get a bunch of random failures when I use it. But when I don't use it, the test suite takes 5 times the duration.

I see you are French, so we could schedule a call, there I could of things I could tell you about Django (I am no expert but I have been fiddling with it for a while).

adamspd commented 3 months ago

No, I didn't really check, it just occurred to me that it would have been great, but I never looked to see if it existed. I'll look into it a bit more.

I see you are French, so we could schedule a call, there I could of things I could tell you about Django (I am no expert but I have been fiddling with it for a while).

I'm not an expert either 😂 but I've been playing with it for about 5 years now. We certainly can when you have time, and thanks for the explanation, it will be put in good use.

deronnax commented 3 months ago

I sent you a message on the contact form of your website ;)