Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resignation tests kerstens fork #569

Conversation

Theophile-Madet
Copy link
Contributor

No description provided.

kerstenkenan and others added 28 commits September 29, 2024 12:16
…dability

First attempt ;) for getting the shift calendar more readable.
…or-logs

Collapsing also for the log view
First suggestion for ShiftAttendance entry in contributing
…fixes

Little translations corrections (hint from Vicky) conc. automated mails.
@kerstenkenan
Copy link
Contributor

kerstenkenan commented Nov 1, 2024

Hi @Theophile-Madet, I'm sorry to disturb you. But I'm completely stuck with the tests, which you preformulated. I don't get the changed object in the updateview and deleteview. The refresh_from_db() is not working and I really googled a lot what the problem could be. I filled all data-fields in the client post at the updateview, as you can see, which was working for one guy at StackOverFlow. Also if I try to print(response.context["form"].errors I get NONE. Could you have a look, especially at test_edit_view.py? I think it has something with the redirectment to do, which both updateview and deleteview have.

The form and service tests should be fine now. They are all green (puh ;) ).

@Theophile-Madet
Copy link
Contributor Author

So, the problem is that test_membershipResignationEditView_cancellationDateUpdate_payOutDayUpdated fails, because the pay_out_day is not updated, right?

I think it's because MembershipResignationEditView does not update pay_out_day.
The form tries to update it in those lines:

tapir/tapir/coop/forms.py

Lines 302 to 304 in a19c55d

self.cleaned_data["pay_out_day"] = cancellation_date + relativedelta(
day=31, month=12, years=3
)

But pay_out_day is not a field of MembershipResignationForm, so the lines do nothing. The form will look in cleaned_data only for the fields that are part of the form. The solution would be to do that change in the view rather than the form.

There is a similar test for the create view: test_membershipResignationCreateView_resignationTypeBuyBack_payOutDayIsSetCorrectly. That one works, because it calls MembershipResignationService.update_shifts_and_shares(), which does update the pay_out_day.

update_shifts_and_shares should probably be renamed to show that it updates pay_out_day, or that update should be moved to another function.

Let me know if that helps, or if you meant another problem.

Also, should I already look at the other tests? I only checked test_membershipResignationEditView_cancellationDateUpdate_payOutDayUpdated for now.

@Theophile-Madet Theophile-Madet marked this pull request as ready for review November 11, 2024 16:12
Copy link
Contributor Author

@Theophile-Madet Theophile-Madet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting closer, I left more comments.

)
self.assertEqual(share.end_date, resignation.cancellation_date)

def test_update_shifts_shiftsAndShiftAttendance_cancelled(self):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test fails on my machine. The shift from shift = ShiftFactory.create() is generated in the past, so it doesn't get affected by update_shifts. You can fix it by setting the start_time of the shift in the future relative to self.NOW

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not fixed.

tapir/coop/tests/membership_resignation/test_edit_view.py Outdated Show resolved Hide resolved
tapir/coop/services/MembershipResignationService.py Outdated Show resolved Hide resolved
tapir/coop/services/MembershipResignationService.py Outdated Show resolved Hide resolved
tapir/coop/tests/membership_resignation/test_service.py Outdated Show resolved Hide resolved
tapir/coop/tests/membership_resignation/test_service.py Outdated Show resolved Hide resolved
tapir/coop/tests/membership_resignation/test_service.py Outdated Show resolved Hide resolved
tapir/coop/tests/membership_resignation/test_service.py Outdated Show resolved Hide resolved
tapir/coop/tests/membership_resignation/test_service.py Outdated Show resolved Hide resolved
@kerstenkenan
Copy link
Contributor

For #569 (comment)
Strange if I do: self.assertEqual(created_resignation.id, int(log_entry.values["id"])) I get the error AttributeError: 'MembershipResignationUpdateLogEntry' object has no attribute 'values. But if I do self.assertEqual(created_resignation.id, log_entry.id) everything works fine. In the deleteview it work your way. Have you an idea why here not?

@Theophile-Madet
Copy link
Contributor Author

For #569 (comment)
Strange if I do: self.assertEqual(created_resignation.id, int(log_entry.values["id"])) I get the error AttributeError: 'MembershipResignationUpdateLogEntry' object has no attribute 'values. But if I do self.assertEqual(created_resignation.id, log_entry.id) everything works fine. In the deleteview it work your way. Have you an idea why here not?

I must have mixed up the UpdateLogEntry with the other types of log entries. It's true that UdpateLogEntry don't have values.

self.assertEqual(created_resignation.id, log_entry.id) works but doesn't make sense: we're checking that the ID of the resignation object is the same as the ID of the log entry. They are probably both 1 because each tests starts with a fresh database. So the first ID for each object type will be 1.

Since this is an UpdateModelLogEntry, we want to check that it contains the appropriate values in old_values and new_values.
Something like self.assertEqual("Reason before edit", log_entry.old_values["cancellation_reason]) and self.assertEqual("Reason afteredit", log_entry.new_values["cancellation_reason])

@kerstenkenan
Copy link
Contributor

Salut @Theophile-Madet, I made several new fixes, renaming, separating test in more funcs .... . The only thing I don't get done is the case with assert_called_once_with (#569 (comment)). It's maybe just a syntax thing, but I have no clue how to do it. I tried several approaches, but no-one worked. Maybe it's easier if you have the code directly instead of comments? Hope the other topics are covered.

Copy link
Contributor Author

@Theophile-Madet Theophile-Madet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I re-opened 2 conversations that were closed but the problem was not fixed, and left a few extra comments. I find less and less comments to write, so that means we're getting closer and closer.

About test_membershipResignationCreateView_default_changesApplied, I think I found what was confusing you: the order of the test function parameters are reversed (the two mock_...). I think the test should look like this:

@patch.object(MembershipResignationService, "delete_shareowner_membershippauses")
    @patch.object(
        MembershipResignationService, "update_shifts_and_shares_and_pay_out_day"
    )
    def test_membershipResignationCreateView_default_changesApplied(
        self,
        mock_update_shifts_and_shares_and_pay_out_day: Mock,
        mock_delete_shareowner_membershippauses: Mock,
    ):
        resignation, actor = self.create_default_resignation()
        self.assertEqual(1, MembershipResignation.objects.count())
        mock_delete_shareowner_membershippauses.assert_called_once_with(resignation)
        mock_update_shifts_and_shares_and_pay_out_day.assert_called_once_with(
            resignation=resignation
        )

@@ -58,9 +62,10 @@ def update_shifts(tapir_user: TapirUser, resignation: MembershipResignation):
)

for attendance_template in ShiftAttendanceTemplate.objects.filter(
user=tapir_user
user=tapir_user,
slot_template__shift_template__start_date__gte=start_date,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't filter relative to the start date of the shift template: if a member registers to a shift template that started for example on 15/06/23, then resigns on the 15/11/24, we still want to cancel that attendance template.

Copy link
Contributor

@kerstenkenan kerstenkenan Nov 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What did you mean then by this: #569 (comment)?
I didn't get quiet well yet how the shift-system works in total.

)
self.assertEqual(share.end_date, resignation.cancellation_date)

def test_update_shifts_shiftsAndShiftAttendance_cancelled(self):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not fixed.

tapir/coop/services/MembershipResignationService.py Outdated Show resolved Hide resolved
ShiftAttendance.State.CANCELLED,
)

def test_updateShifts_shiftsBeforeResignation_notCancelled(self):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there is confusion about the start_date of ShiftTemplate: it's the date from which the ShiftTemplate should start generating shifts. So it's not relevant to resignations: no matter what the ShiftTemplate.start_date is, if the resigning member is registered to ShiftTemplate, they should get unregistered from that ShiftTemplate

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought to achieve this topic (#569 (comment)), with the start_date of the ShiftTemplate. Is it more the Shift start_time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the only time to check is the time of the Shift: shifts that are before the resignation should not get affected.
The start_date of the ShiftTemplate is irrelevant.

@kerstenkenan
Copy link
Contributor

I re-opened 2 conversations that were closed but the problem was not fixed, and left a few extra comments. I find less and less comments to write, so that means we're getting closer and closer.

About test_membershipResignationCreateView_default_changesApplied, I think I found what was confusing you: the order of the test function parameters are reversed (the two mock_...). I think the test should look like this:

@patch.object(MembershipResignationService, "delete_shareowner_membershippauses")
    @patch.object(
        MembershipResignationService, "update_shifts_and_shares_and_pay_out_day"
    )
    def test_membershipResignationCreateView_default_changesApplied(
        self,
        mock_update_shifts_and_shares_and_pay_out_day: Mock,
        mock_delete_shareowner_membershippauses: Mock,
    ):
        resignation, actor = self.create_default_resignation()
        self.assertEqual(1, MembershipResignation.objects.count())
        mock_delete_shareowner_membershippauses.assert_called_once_with(resignation)
        mock_update_shifts_and_shares_and_pay_out_day.assert_called_once_with(
            resignation=resignation
        )

Nothing helps, if I do your version, I get the error:

 AssertionError: expected call not found.
E Expected: update_shifts_and_shares_and_pay_out_day(<MembershipResignation: MembershipResignation object (1)>)
E  Actual: update_shifts_and_shares_and_pay_out_day(resignation=<MembershipResignation: MembershipResignation object (1)>)

If I do it reverse:

      mock_delete_shareowner_membershippauses.assert_called_once_with(
            resignation,
        )
        mock_update_shifts_and_shares_and_pay_out_day.assert_called_once_with(
            tapir_user=actor, resignation=resignation
        )

I get the same error:

 AssertionError: expected call not found.
E Expected: update_shifts_and_shares_and_pay_out_day(<MembershipResignation: MembershipResignation object (1)>)
E  Actual: update_shifts_and_shares_and_pay_out_day(resignation=<MembershipResignation: MembershipResignation object (1)>)

@Theophile-Madet
Copy link
Contributor Author

The first logs that you copy show that you are not running my version of the test. We can see that because the logs says Expected: update_...(<object>), but the code says mock_update_...(resignation=object).
Did you check the order of the test function parameters as I said?

The second logs you copied also do not correspond to the code snippet you copied. We can see that because the code say mock_update[...].assert_called_once_with(tapir_user=..., resignation=...), but the log says Expected: update_...(resignation=...).

To help you I need the code and the logs that come with that code. If they don't fit nothing makes sense.

@kerstenkenan
Copy link
Contributor

kerstenkenan commented Nov 17, 2024

Hi @Theophile-Madet, I got the assert_called_once_with-issue done, even though I still not understand, why one func works with parameter name and the other not 😵‍💫. Only thing, which is left I think is this: #569 (comment).
I'm not firm enough how the Shift-System works in total, so maybe you can give me a hint, what start-date/time I should take for your suggest: #569 (comment)?

@@ -42,7 +44,6 @@ def update_shifts_and_shares_and_pay_out_day(resignation: MembershipResignation)
for _ in shares
]
ShareOwnership.objects.bulk_create(shares_to_create)
shares.update(end_date=resignation.cancellation_date)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need here a cancellation date for the transferred shares, right? They begin from scratch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true, transfered shares should not have an end date.

@@ -87,8 +89,8 @@ def test_updateShiftsAndSharesAndPayOutDay_SharesAndPayOutDayForResignationTypeT
).count(),
shares_after_update.count(),
)
for share in shares_after_update.all():
self.assertEqual(share.end_date, resignation.cancellation_date)
# for share in shares_after_update.all():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Therefore we don't need this test?!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"This test" is the entire test_updateShiftsAndSharesAndPayOutDay_SharesAndPayOutDayForResignationTypeTransfer_transferredAndSet function, that we do need.

Instead of removing self.assertEqual(share.end_date, resignation.cancellation_date), let's replace it with self.assertEqual(share.end_date, None)

Copy link
Contributor Author

@Theophile-Madet Theophile-Madet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • About assert_called_once_with: the assert has to be the same as the logic code. If in the service the function is called with the parameter name, then assert_called_once_with has to be with the parameter name too. If the service calls the function without the parameter name, then assert_called_once_with has to be called without parameter name either.
  • test_updateShifts_shiftsAndShiftAttendance_cancelled still needs fixing: the start_time of the Shift must be set explicitely to make sure that the random generation doesn't put the shift in the past. See this comment
  • I answered your comment about the shift start time.

@@ -42,7 +44,6 @@ def update_shifts_and_shares_and_pay_out_day(resignation: MembershipResignation)
for _ in shares
]
ShareOwnership.objects.bulk_create(shares_to_create)
shares.update(end_date=resignation.cancellation_date)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true, transfered shares should not have an end date.

@@ -87,8 +89,8 @@ def test_updateShiftsAndSharesAndPayOutDay_SharesAndPayOutDayForResignationTypeT
).count(),
shares_after_update.count(),
)
for share in shares_after_update.all():
self.assertEqual(share.end_date, resignation.cancellation_date)
# for share in shares_after_update.all():
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"This test" is the entire test_updateShiftsAndSharesAndPayOutDay_SharesAndPayOutDayForResignationTypeTransfer_transferredAndSet function, that we do need.

Instead of removing self.assertEqual(share.end_date, resignation.cancellation_date), let's replace it with self.assertEqual(share.end_date, None)

MembershipResignationService.update_shifts_and_shares_and_pay_out_day(
resignation_one
)
MembershipResignationService.update_shifts_and_shares_and_pay_out_day(
resignation_two
)
share_owner.refresh_from_db()
ic(share_owner.num_shares())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed

ShiftAttendance.State.CANCELLED,
)

def test_updateShifts_shiftsBeforeResignation_notCancelled(self):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the only time to check is the time of the Shift: shifts that are before the resignation should not get affected.
The start_date of the ShiftTemplate is irrelevant.

@kerstenkenan
Copy link
Contributor

Hi @Theophile-Madet, accomplished #569 (comment)
Concerning assert_called_once_with: both update_shifts_and_shares_and_pay_out_day(resignation: MembershipResignation) and delete_end_dates(resignation: MembershipResignation) are declared with parameter-names. I'm done with this stupid function!!! I changed really everything for the last 2 days in the parameters and if I write

mock_update_shifts_and_shares_and_pay_out_day.assert_called_once_with(
                resignation=resignation
            )

I get the error:

Expected: update_shifts_and_shares_and_pay_out_day()
Actual: update_shifts_and_shares_and_pay_out_day(resignation=<MembershipResignation: MembershipResignation object (1)>)

And if I write it without parameter mock_update_shifts_and_shares_and_pay_out_day.assert_called_once_with(), I get the the same error:

Expected: update_shifts_and_shares_and_pay_out_day()
E             Actual: update_shifts_and_shares_and_pay_out_day(resignation=<MembershipResignation: MembershipResignation object (1)>)

and also If I write mock_update_shifts_and_shares_and_pay_out_day.assert_called_once_with(resignation=resignation, tapir_user=actor) I get the same irrational error.
I change the test to just mock_update_shifts_and_shares_and_pay_out_day.assert_called_once() and the test passes. I'm sorry but if you want to have assert_called_once_with() func, you will have to do it yourself. I have no more ideas!

@kerstenkenan
Copy link
Contributor

kerstenkenan commented Nov 17, 2024

I customized the Shift-start_time, please have a look on test_updateShifts_shiftsAndShiftAttendance_cancelled() and test_updateShifts_shiftsBeforeResignation_notCancelled() in test_service.py if this is the behaviour you intended.

@Theophile-Madet
Copy link
Contributor Author

You keep getting the same error with assert_called_once_with because you're not reading the solution I give you. This, once again, feels disrespectful.
I told you twice, here and here, that the order of the parameter of the test function is wrong.

The current order is

    @patch.object(MembershipResignationService, "delete_shareowner_membershippauses")
    @patch.object(
        MembershipResignationService, "update_shifts_and_shares_and_pay_out_day"
    )
    def test_membershipResignationCreateView_default_changesApplied(
        self,
        mock_delete_shareowner_membershippauses: Mock,
        mock_update_shifts_and_shares_and_pay_out_day: Mock,
    ):

The correct order is

    @patch.object(MembershipResignationService, "delete_shareowner_membershippauses")
    @patch.object(
        MembershipResignationService, "update_shifts_and_shares_and_pay_out_day"
    )
    def test_membershipResignationCreateView_default_changesApplied(
        self,
        mock_update_shifts_and_shares_and_pay_out_day: Mock,
        mock_delete_shareowner_membershippauses: Mock,
    ):

Because the order is wrong, the variable called mock_update_shifts_and_shares_and_pay_out_day actually refers to the function delete_shareowner_membershippauses.

@Theophile-Madet
Copy link
Contributor Author

test_updateShifts_shiftsAndShiftAttendance_cancelled and test_updateShifts_shiftsBeforeResignation_notCancelled are fine.

@kerstenkenan
Copy link
Contributor

kerstenkenan commented Nov 18, 2024

Hi @Theophile-Madet, please believe me, that I was not intended to be disrespectful to you! It was just that I hanging in a stuck-line. I still don't understand, why mock_update_shifts_and_shares_and_pay_out_day.assert_called_once_with(resignation=resignation) comes with a parameter-name and mock_delete_shareowner_membershippauses.assert_called_once_with(resignation)not. But what I also found was the problem, that I didnt' grab the second variable (actor) returned from self.create_default_resignation(). So now it should hopefully work 😬

@Theophile-Madet
Copy link
Contributor Author

mock_update_shifts_and_shares_and_pay_out_day.assert_called_once_with(resignation=resignation) comes with parameter name because the logic code calls the function with the parameter name, see

MembershipResignationService.update_shifts_and_shares_and_pay_out_day(
resignation=membership_resignation
)

mock_delete_shareowner_membershippauses.assert_called_once_with(resignation) comes without parameter name because the logic code calls the functgion without parameter name, see

MembershipResignationService.delete_shareowner_membershippauses(
membership_resignation
)

That's what I was explaining here:

About assert_called_once_with: the assert has to be the same as the logic code. If in the service the function is called with the parameter name, then assert_called_once_with has to be with the parameter name too. If the service calls the function without the parameter name, then assert_called_once_with has to be called without parameter name either.

@kerstenkenan
Copy link
Contributor

I'm very sorry I looked at the wrong place, I really had a "Brett vor dem Kopf". I looked all the time at MembershipResignationService.py and not at membership_resignation.py. Everything ok now. Merging?

@Theophile-Madet Theophile-Madet merged commit 075c872 into SuperCoopBerlin:resignation_tests Nov 18, 2024
1 check passed
Theophile-Madet added a commit that referenced this pull request Nov 19, 2024
* WIP resignation tests

* Added base test for the membership resignation create view.

* WIP tests.

* Membership resignation edit view tests.

* Membership resignation detail and delete views tests.

* 1st try for TestMembershipResignationForm.

* Resignation tests kerstens fork (#569)

* First suggestion for ShiftAttendance entry in contributing

* First attempt ;) for getting the shift calendar more readable.

* Collasping also for the log view

* Fixed hopefully all changes requests.

* Fixed text for ShiftAttendance.

* Fixed collapsing list.

* Deleted all "filter-button" classes.

* Set seletc2-width to 100%.

* Last fixes with flexbox ;)

* Align title to center with flexbox.

* Translations corrections (hint from Vicky).

* Fixes in opening hours.

* Missing po-file

* Restored 24h time

* Sorry for fuzzied po-file. Removed.

* Translations fixes

* Update translations.

* Search for Nonetype im form test.

* test_membershipResignationForm_is_valid & test_validate_shareOwner_function

* Form tests done.

* Form tests work, but view tests still fails.

* Updateview-tests ready

* Changed service-function update_shifts_and_shares_and_pay_out_day in all placed

* Several fixes for all resignation-tests.

* More fixes for resignation-tests.

* Even more fixes for resignation-tests 1.0

* Even more fixes for resignation-tests 1.1

* Even more fixes for resignation-tests 1.2

* Even more fixes for resignation-tests 1.3

* Even more fixes for resignation-tests 1.4

* Even more fixes for resignation-tests 1.5

* Even more fixes for resignation-tests 1.6

---------

Co-authored-by: Kersten Weise <[email protected]>
Co-authored-by: Kersten Weise <[email protected]>

* Fixed migration conflict after merge,
Improved view names,
Cleanup in test_create_view.py
Removed test_create_membershipresignation.py that contains only duplicates of test_create_view.py

* Cleanup in test_delete_view.py,
More view name updates.

* Cleanup in test_edit_view.py

* Cleanup in test_form.py

* Cleanup in test_service.py

* Post-rename fix.

* Switched ShareOwnership.transferred_from to OneToOneField to make sure a share can't be transferred twice.

* UI improvements around resignation cancellations.

* Translation file update.

---------

Co-authored-by: Kersten Weise <[email protected]>
Co-authored-by: Kersten Weise <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants