-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Support for custom clients #83
Comments
Good proposal, I think this is a simple and good way to start. I got a few comments and edge-cases though:
class HttpLocust(Locust):
client_class = HttpClient
class ThriftLocust(Locust):
client_class = ThriftClient A mixed version would require something like this: class User(TaskSet):
@task
def index(self):
self.get_client().get("/") # fetches default client (HTTP)
self.get_client("thrift").someServiceCall() So the question is rather; should we support mixed-client behaviours? This is obviously not a common use-case, but on the other hand I don't think it would polute things too much either.
|
Do we really need the "client_class" attribute and the get_client() method? Can't the implementor handle this on his own:
(We can provide a default HttpLocust that does this, and a default HttpClient) |
Good idea! +1 for @mthurlin's suggestion. I don't believe Locust should involved in the creation and managing of the client(s) needed to test a system. As long as the clients report back of what they do (num requests, response times, failure rate etc), we should be fine. Adding a possibility for metadata as @Jahaja is suggestions sounds good. We currently are designing Locust around request/response based scenarios but that may expand so enabling room for metadata seems nice. |
I think that the absolutely most common use case is still going to be HTTP testing. Therefore, I think it would be bad to make changes that in those cases would add some boilerplate code like: class MyLocust(Locust):
def init(self, *args, **kwargs):
super(MyLocust, self).__init__(*args, **kwargs)
self.client = HttpClient(self) One solution to this would be that we would continue to automatically supply each Locust instance with an instance of HttpSession under the client attribute. However, this would make the HTTP client implementation "special", and all other clients "second class citizens", which I don't think would be good either. Therefore I'm still leaning more to the idea where we provide some simple helper method (and attribute that defaults to the HTTP client) that can be easily overridden. As to the mixed client issue, one could still use the (slightly hackish) method of just instantiating an additional client in the init method for those rare cases. For the metadata I think that it could be good to start by keeping it simple and just use the Type (change name from method) as the available metadata. Unless we have a good idea on how it should work, and some real use-cases it would solve. |
Why not have
No boilerplate necessary for end-users, but HTTP doesn't become "special" (except for the fact that we provide a default implementation). |
That's true. 😊 🌴 +1 from me too then :) |
A big 👍 from me for the class HttpLocust(Locust):
def init(self, *args, **kwargs):
super(HttpLocust, self).__init__(*args, **kwargs)
self.client = HttpClient(self) solution and having a Making the overwrite of |
As discussed in #83, removed HttpSession instantiation on the Locust.client attribute from base Locust class, and introduced new HttpLocust class with this functionality. Added warning when trying to access the client attribute on a "bare" Locust instance. Updated documentation.
Fixed! |
@heyman / @cgbystrom :Could you please give me an example or explanation on how to write locust load test with custom client ( WebSocket Server in my case ). I saw the explanation given in locust documentation but I dint get how exactly the functions |
Support for custom clients
This is a proposal for how we could implement official support for custom request/response based clients.
Reasoning
The reason we would like to do this is both to officially support testing of other request/response based systems than HTTP, but also to provide the ability to swap out the current requests based (http://docs.python-requests.org/) HTTP client, in favor for some other HTTP client. For example, if you're running extremely large load tests where you're doing tenths of thousands of requests per second, the overhead python-requests comes with can actually have a quite large impact.
Proposal
I've given this some thought, but it's most likely not optimal. However it's good to start somewhere, so you can see it as a starting point for a discussion on how to best implement this :).
One would specify the client class on the locust class(es) like this:
We would modify the Locust base class to something like this (which will allow one to either just set client_class on the Locust class, or override the get_client() method):
The client classes should then expect to get an instance of a Locust subclass to their init method (which can be used to read Locust.host etc.), and the client is also responsible for fire:ing request_success and request_failure events when it does requests (which of course should be clearly documented).
Finally, we should also change the HTTP specific labels that we have in the UI (I think it might only be "Method", which we could rename to "Type").
So, what do you think? ping @cgbystrom @Jahaja
The text was updated successfully, but these errors were encountered: