-
-
Notifications
You must be signed in to change notification settings - Fork 252
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
tests: boxes: Add tests for saving drafts. #1495
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally this looks fine to me. I left some comments on things that came to mind. I don't know enough about the codebase yet to give an approval, but given that the test is green and it looks to me like it's testing something useful, I probably would approve it if I had to :P
hope that helps :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take another look later, but wanted to get this comment out that I'd drafted previously, before mentoring had started.
8a3f2b4
to
96bdbba
Compare
Updated to add the |
tests/ui_tools/test_boxes.py
Outdated
assert not write_box.model.save_draft.called | ||
assert not write_box.view.controller.save_draft_confirmation_popup.called |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: Should we prefer using?
write_box.model.save_draft.assert_not_called()
write_box.view.controller.save_draft_confirmation_popup.assert_not_called()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are equivalent - or should be!
However, the great thing about using assert
and the core called
style values are:
- pytest can dig through levels of code using
assert
, if they fail called
and similar results are values, not assertions in a function
The most useful aspect here though, is that this form can be more easily extracted into parametrize blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, the parametrization part makes sense. Should we stick to using .called from now on?
LGTM! Great work @Niloth-p 👍 I'm trying to see if we can simplify the conditionals in the test by adding more to the parameterize, but I'm not sure. |
96bdbba
to
7981b32
Compare
Thank you for catching those details, @rsashank! Great review, that was very helpful. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Niloth-p I was just mid-review yesterday, so just posting the notes I made and a few more, since I note you updated this already :)
tests/ui_tools/test_boxes.py
Outdated
mocked_saved_drafts = [ | ||
case(None, id="no_saved_draft_exists"), | ||
case( | ||
StreamComposition( | ||
type="stream", | ||
to="Random Stream", | ||
content="Random stream draft", | ||
subject="Topic name", | ||
read_by_sender=True, | ||
), | ||
id="saved_stream_draft_exists", | ||
), | ||
case( | ||
PrivateComposition( | ||
type="private", | ||
to=[5140], | ||
content="Random private draft", | ||
read_by_sender=True, | ||
), | ||
id="saved_private_draft_exists", | ||
), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate the intent to reduce repetition here.
That said, normally I would convert the input into a pytest fixture, which would mean you could skip the parametrize on the test function and put the name of the fixture in the list of test parameters.
Another advantage of converting this into a fixture, which we haven't done as much to date, is that you should be able to extract common mocking or other setup too.
(note that it's fine to have the fixture local to this file (ie. not conftest.py
), if it is specific to this set of tests)
tests/ui_tools/test_boxes.py
Outdated
draft_composition = StreamComposition( | ||
type="stream", | ||
to="Current Stream", | ||
content="Random message", | ||
subject="Topic", | ||
read_by_sender=True, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be worth noting here, and also asserting (and in the other test) that the draft_composition
is not equal to the current draft_saved_in_current_session
- ie. it explicitly does not cover that case, at least right now.
That kind of assert can be useful to demonstrate that the test is doing what it is supposed to do.
Given the above, we may also want to add a test for the behavior of if the draft exists and matches separately.
tests/ui_tools/test_boxes.py
Outdated
if draft_saved_in_current_session is not None: | ||
write_box.view.controller.save_draft_confirmation_popup.assert_called_once_with( | ||
draft_composition | ||
) | ||
else: | ||
write_box.model.save_draft.assert_called_once_with(draft_composition) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per Sashank's comment, it would be preferable to include these in the parametrize.
tests/ui_tools/test_boxes.py
Outdated
assert not write_box.model.save_draft.called | ||
assert not write_box.view.controller.save_draft_confirmation_popup.called |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are equivalent - or should be!
However, the great thing about using assert
and the core called
style values are:
- pytest can dig through levels of code using
assert
, if they fail called
and similar results are values, not assertions in a function
The most useful aspect here though, is that this form can be more easily extracted into parametrize blocks.
tests/ui_tools/test_boxes.py
Outdated
if not is_every_recipient_valid: | ||
write_box.model.save_draft.assert_not_called() | ||
write_box.view.controller.save_draft_confirmation_popup.assert_not_called() | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To simplify this, since the test has a nested if
, I'm wondering if it would be cleaner to extract this first part into a separate test?
That avoids a parametrize over is_every_recipient_valid.
8e3b967
to
88584cd
Compare
Test functions added: - 2 test functions for stream compositions - when a draft previously exists, call the confirmation popup - when new draft matches saved draft, do not save again - 3 test functions for private compositions - valid recipients, - invalid recipients, - new draft matches already saved draft Fixtures added for: - list saved drafts - list stream compositions - list private compositions - setup for private draft tests - setup for stream draft tests Factories added: - composition factory (generates both stream and private compositions) - saved draft factory
88584cd
to
696eba6
Compare
@Niloth-p I have tried simplifying and typing your code a bit in https://github.com/zormit/zulip-terminal/tree/1495-save-draft/pr (713bf50, in case I change the branch). What do you think? I'm still not fully happy with all the layers of indirection, probably it can be simplified even more, but this might give you an idea. I have to stop for now, so I'm sending you this idea, please take it if you like it. (edit: I realized tests are not even all passing, but that seems fixable :)) |
Use different recipients for saved drafts and new drafts, in the composition factory.
Check new drafts with - same content, different recipients (already exists) - same recipients, different content (newly added) Previously, we were using different recipients in the composition factory, to differentiate the new draft from the saved draft. Now, it has been extended to allow creating different content as well.
@zormit Thank you lots for making those changes yourself! That does look much better. Sorry for the delay in replying back, I'd absorbed your commits right away, but hadn't managed to type out a reply here. If you find this interesting, please feel free to push your own PR with other improvements and add me as a co-author, that could help get it merged too, as I've done several iterations on this previously, and have been struggling to identify good code and bad code here. So, no, I'm not really clear on how we can further reduce the indirection, my apologies. I can think of several ways to change the tests, but I have no idea what improves it and what worsens it. If someone is able to guide me with 1 liners like the commit messages, I'll try my best to implement it and get back. Being new to the complexities of testing, when I come across best practices and guidance, I'm not sure to what extent I should be following them, that I realise I might have overdone it here to the point of complexity, and I'm still not clear enough on all the tradeoffs, so please do let me know how we can proceed from here. Also, I'm not sure how many commits this is supposed to be. I was initially under the impression this should be a single commit, since it's just tests, and we wouldn't want to be tracking the additions incrementally. But, after the suggestion from @neiljp to break down the refactoring commits of lint-hotkeys, I've been wondering whether we should break this down too. Do we need to? I've added some newer test cases. But I'm not sure if we want to be that thorough or if it bulks up the testing time unnecessarily. |
Github will report the tests as failed, because I've kept my addition separate from Moritz's commits, but they'll pass if they're squashed. So, please ignore them. |
What does this PR do, and why?
Add 2 test functions:
Test for an existing saved draft for each of the test cases.
Test for:
This does not test the
_tidy_valid_recipients_and_notify_invalid_ones
or thesession_draft_message
functions. They're mocked. Tests for them would need to be added separately.External discussion & connections
topic
SAVE_AS_DRAFT
keypress test for write box. #950How did you test this?
Self-review checklist for each commit