Skip to content
This repository has been archived by the owner on Mar 20, 2024. It is now read-only.

Refactor parse_commands to add tests. #149

Merged
merged 9 commits into from
Mar 15, 2018
Merged

Refactor parse_commands to add tests. #149

merged 9 commits into from
Mar 15, 2018

Conversation

alexrs
Copy link

@alexrs alexrs commented Mar 13, 2018

This PR address #143. This is a first step in making Homu testable.

A small refactor has been done, extracting the logic in parse_commands to its own functions, to be able to mock the state and add tests.


This change is Reviewable

Copy link
Member

@jdm jdm left a comment

Choose a reason for hiding this comment

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

Solid effort to test the behaviour of the particular handlers! What's the plan for getting parse_commands under test?

self.assertFalse(sha_cmp('f25', 'f259660b128ae59133dff123998ee9b643aff050'))

if __name__ == '__main__':
unittest.main()
Copy link
Member

Choose a reason for hiding this comment

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

Let's run these tests on TravisCI by modifying .travis.yml.

Copy link
Author

Choose a reason for hiding this comment

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

It seems to be failing with Python 3.5 https://travis-ci.org/servo/homu/jobs/353098303#L696

Copy link
Member

Choose a reason for hiding this comment

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

What if you update https://github.com/servo/homu/blob/master/setup.py#L13 to only allow versions that are <1.0? That was released yesterday and significantly changes the library, so we probably don't want to blindly allow it; it also introduced the dateutil import that's breaking here.

Copy link
Author

Choose a reason for hiding this comment

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

After some research, I just discovered why some tests are failing. Apparently, the method assert_called_once was introduced in Python 3.6. In Python 3.5 any method starting assert_ but not implemented seems to raise an AttributeError but before Python 3.5, we're just calling a mocked method like any other (that doesn't exist in this case, but it doesn't matter). Any suggestion for a replacement of assert_called_once?

Copy link
Member

Choose a reason for hiding this comment

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

Can you use assert_called_once_with instead?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, it works now! 🎉

def test_sha_or_blank_return_blank(self):
self.assertEqual(sha_or_blank('f5d@12'), '')

def test_sha_cpm_equal(self):
Copy link
Member

Choose a reason for hiding this comment

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

cmp, not cpm

homu/main.py Outdated
# TODO: We don't need partials here.
# I guess that we can use partials, as the
# only parameter that changes is the AuthState.
# We need to refactor this.
Copy link
Member

Choose a reason for hiding this comment

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

It's not clear what this comment adds to the code.

homu/main.py Outdated
state.save()


def treeclosed_equal(state, word):
Copy link
Member

Choose a reason for hiding this comment

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

Let's call this set_treeclosed

homu/main.py Outdated
def retry(state, realtime):
state.set_status('')
if realtime:
# TODO: useless realtime. It's already in the if condition.
Copy link
Member

Choose a reason for hiding this comment

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

Let's address this by taking it out.

Copy link
Author

Choose a reason for hiding this comment

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

There are several places where we make this check. Are we going to call any of the methods when realtime is not true?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we definitely call parse_commands when realtime is not true.

@patch('homu.main.PullReqState')
def test_review_approved_approver_me(self, MockPullReqState):
state = MockPullReqState()
self.assertFalse(review_approved(['r=me', 'approved'], 'r=me', state, True, 'user', 'user', 0, '', []))
Copy link
Member

Choose a reason for hiding this comment

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

We should have tests for non-realtime behavior as well.

state = MockPullReqState()
state.title = 'WIP work in progress'
self.assertFalse(review_approved(['r+', 'approved'], 'r+', state, True, 'user', 'user', 0, '', []))
state.add_comment.assert_called_once_with(':clipboard: Looks like this PR is still in progress, ignoring approval')
Copy link
Member

Choose a reason for hiding this comment

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

We'll want some asserts that the rest of the state isn't updated when this happens.

state = MockPullReqState()
state.title = 'TODO work in progress'
self.assertFalse(review_approved(['r+', 'approved'], 'r+', state, True, 'user', 'user', 0, '', []))
state.add_comment.assert_called_once_with(':clipboard: Looks like this PR is still in progress, ignoring approval')
Copy link
Member

Choose a reason for hiding this comment

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

This seems like it could be merged with the previous test to reduce duplication.

self.assertFalse(state.try_)
state.set_status.assert_called_once_with('')
state.save.assert_called_once()
state.add_comment.assert_called_once_with(":bulb: This pull request was already approved, no need to approve it again.\n\n- This pull request is currently being tested. If there's no response from the continuous integration service, you may use `retry` to trigger a build again.")
Copy link
Member

Choose a reason for hiding this comment

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

It might be nice to have these strings in a common variable that can be used in the implementation and the test.

state.repo_label = 'label'
state.status = 'pending'
states = {}
states[state.repo_label] = {'label': state}
Copy link
Member

Choose a reason for hiding this comment

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

It's not clear to me what this line is for. I see an iteration over states in review_approved, but no code checks a label property as far as I can see. The same question applies for all of the other tests that set it.

Copy link
Author

Choose a reason for hiding this comment

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

states[state.repo_label] should return a dict, because we call states[state.repo_label].values() in review_approved. What matters in this test is the state object. label is just an arbitrary name.

@alexrs
Copy link
Author

alexrs commented Mar 13, 2018

Thanks for the thorough review! I'll address all these comments ASAP!

@alexrs
Copy link
Author

alexrs commented Mar 15, 2018

Hey! Is there anything else I have to fix for this PR? I think we shouldn't add more code to it (apart from fixes to the current code). In a future PR, I'd like to remove the global configuration (global_cfg), extract the DB logic to its own class and wrap it to be able to mock it, which will also remove db_query_lock.
Once we have done that, we will be able to test parse_commands. What do you think about this approach?

@jdm
Copy link
Member

jdm commented Mar 15, 2018

This looks like a useful step forward. Thanks for working on it!
@bors-servo r+

@bors-servo
Copy link

📌 Commit cd5b1b5 has been approved by jdm

@bors-servo
Copy link

⌛ Testing commit cd5b1b5 with merge 2467053...

bors-servo pushed a commit that referenced this pull request Mar 15, 2018
Refactor parse_commands to add tests.

This PR address #143. This is a first step in making Homu testable.

A small refactor has been done, extracting the logic in `parse_commands` to its own functions, to be able to mock the state and add tests.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/homu/149)
<!-- Reviewable:end -->
@bors-servo
Copy link

☀️ Test successful - status-travis
Approved by: jdm
Pushing 2467053 to master...

@bors-servo bors-servo merged commit cd5b1b5 into servo:master Mar 15, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants