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

Allow sanic test client to bind to a random port #1376

Merged
merged 1 commit into from
Mar 4, 2019
Merged

Allow sanic test client to bind to a random port #1376

merged 1 commit into from
Mar 4, 2019

Conversation

relud
Copy link
Contributor

@relud relud commented Oct 19, 2018

I like to run tests with detox, but using sanic.Sanic.test_client causes issues because of multiple servers trying to simultaneously bind to sanic.testing.PORT.

This solves that problem by having SanicTestClient use socket to bind to a random port when port=None.

@sjsadowski
Copy link
Contributor

Hi Daniel - flake8 is fussing because of your line length. Can you fix so the checks will pass?

@codecov-io
Copy link

codecov-io commented Oct 20, 2018

Codecov Report

Merging #1376 into master will increase coverage by 0.09%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master   #1376      +/-   ##
=========================================
+ Coverage   91.31%   91.4%   +0.09%     
=========================================
  Files          18      18              
  Lines        1773    1781       +8     
  Branches      336     337       +1     
=========================================
+ Hits         1619    1628       +9     
  Misses        130     130              
+ Partials       24      23       -1
Impacted Files Coverage Δ
sanic/testing.py 95.29% <100%> (+0.48%) ⬆️
sanic/app.py 92.25% <0%> (+0.23%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 348964f...76dcea0. Read the comment docs.

@relud
Copy link
Contributor Author

relud commented Oct 20, 2018

Whoops, missed that. Should be all fixed up now.

@sjsadowski sjsadowski added this to the 19.03 milestone Oct 20, 2018
## Using a random port

If you need to test using a random port instead of the default with
`SanicTestClient`, you can do so by specifying `port=None`
Copy link
Contributor

Choose a reason for hiding this comment

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

From a general usability standpoint, wouldn't it be good to reverse the behavior?
i.e. the port param defaults to None and picks a random port, however, you can specify a port and use for running test cases. IMHO, this would be more readable and easy to understand.

As an additional option, we can even add an ENV variable TEST_CLIENT_PORT and use that to provide a much dynamic port assignment.

Copy link
Contributor

Choose a reason for hiding this comment

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

I like this idea but unless other people pipe up on it I think adding this functionality and changing the default can be addressed separately

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I think changing the default functionality should come with a different PR

Copy link
Contributor

@abuckenheimer abuckenheimer left a comment

Choose a reason for hiding this comment

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

thanks for the PR! I'd like to suggest a test that the default port functionality remains the same (i.e. response url points to port 42101) and that you add somewhere in the docs what range the random port falls in (I think its 1024 to 65535?).

sanic/testing.py Outdated
self.app = app
self.port = port

async def _local_request(self, method, uri, cookies=None, *args, **kwargs):
async def _local_request(
self, method, uri, sock=None, cookies=None, *args, **kwargs
Copy link
Contributor

Choose a reason for hiding this comment

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

My main issue here is that this function signature now has duplicate information, it seems like if we have all the information we need in the caller to infer the url then it should be the callers responsibility for doing so.The easiest way to do that would be self.port = sock.getsockname()[1] after 92, lazily setting the port should be fine but it may be worth thinking about. Another option though is we have a short circuit on 23 for uri's that look like urls, we could similarly do uri = "http://{sock[0]}:{sock[1]}{uri}".format(sock=sock.getaddrname(), uri=uri) at after 92 as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like the idea, but setting self.port causes multiple requests to bind the same port, which may fail if the OS assigned the random port to something else between requests. I think it would be better to set self.sock to None in __init__ and set and unset it from _collect_request() below.

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 could similarly do uri = "http://{sock[0]}:{sock[1]}{uri}".format(sock=sock.getaddrname(), uri=uri) at after 92 as well.

I ended up going with that, more or less

## Using a random port

If you need to test using a random port instead of the default with
`SanicTestClient`, you can do so by specifying `port=None`
Copy link
Contributor

Choose a reason for hiding this comment

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

I like this idea but unless other people pipe up on it I think adding this functionality and changing the default can be addressed separately

@ahopkins
Copy link
Member

@relud Are you still pursuing this one?

As for the question of changing the functionality, or whether there should be something separate (TEST_CLIENT_PORT for example), I would lean towards making it an opt in feature and not changing the default.

@relud
Copy link
Contributor Author

relud commented Dec 28, 2018

@ahopkins yes, I'm still pursuing this, I just haven't had time to @abuckenheimer's request because of a very busy december. I'm planning to add the requested test and documentation next week after Tuesday.

@ahopkins
Copy link
Member

🤘 Happy New Year 🥳

@Nelapa
Copy link

Nelapa commented Jan 16, 2019

Vote for PR, feature crashes our CI pipelines too.

@sjsadowski sjsadowski closed this Mar 3, 2019
@sjsadowski sjsadowski reopened this Mar 3, 2019
@sjsadowski
Copy link
Contributor

I'm moving to 19.6, hopefully we can get the changes requested implemented in the PR by then.

@relud if you do get this done before 10-Mar ping me directly so I can get people to review and I'll merge it if the reviewers are satisifed.

@relud
Copy link
Contributor Author

relud commented Mar 4, 2019

@sjsadowski I believe this has now been updated to address reviews.

@seemethere seemethere added needs review the PR appears ready but requires a review and removed pending close: abandoned labels Mar 4, 2019
@sjsadowski sjsadowski merged commit d581315 into sanic-org:master Mar 4, 2019
@seemethere seemethere removed the needs review the PR appears ready but requires a review label Mar 4, 2019
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.

8 participants