Closed cyberw closed 4 years ago
Hmm, catch_response=True
+ resp.failure()
doesn't raise an exception? Maybe I'm misunderstanding your post?
The following code works perfectly fine for me (with either HttpLocust or FastHttpLocust):
from locust import HttpLocust, task, constant
from locust.contrib.fasthttp import FastHttpLocust
class TestUser(HttpLocust):
host = "http://127.0.0.1:8089"
wait_time = constant(1)
@task
def test_task(self):
with self.client.post("/non-existing", catch_response=True) as resp:
resp.failure("Noooo, fail!")
print("request failed")
return
print("end of task (should never run)")
Command line output:
~/projects/locust master ❯ locust -f examples/issue_1335.py -c 1 -r 1 -t 3 --headless
[2020-04-17 16:57:44,237] MacBook-Air.localdomain/INFO/locust.main: Run time limit set to 3 seconds
[2020-04-17 16:57:44,237] MacBook-Air.localdomain/INFO/locust.main: Starting Locust 1.0.0
[2020-04-17 16:57:44,238] MacBook-Air.localdomain/INFO/locust.runners: Hatching and swarming 1 users at the rate 1 users/s (0 users already running)...
[2020-04-17 16:57:44,238] MacBook-Air.localdomain/INFO/locust.runners: All locusts hatched: TestUser: 1 (0 already running)
Name # reqs # fails Avg Min Max | Median req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------
Aggregated 0 0(0.00%) 0 0 0 | 0 0.00 0.00
request failed
request failed
Name # reqs # fails Avg Min Max | Median req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
POST /non-existing 2 2(100.00%) 5 4 6 | 5 0.00 0.00
--------------------------------------------------------------------------------------------------------------------------------------------
Aggregated 2 2(100.00%) 5 4 6 | 5 0.00 0.00
request failed
[2020-04-17 16:57:47,080] MacBook-Air.localdomain/INFO/locust.main: Time limit reached. Stopping Locust.
[2020-04-17 16:57:47,080] MacBook-Air.localdomain/INFO/locust.main: Shutting down (exit code 1), bye.
[2020-04-17 16:57:47,080] MacBook-Air.localdomain/INFO/locust.main: Cleaning up runner...
[2020-04-17 16:57:47,081] MacBook-Air.localdomain/INFO/locust.main: Running teardowns...
Name # reqs # fails Avg Min Max | Median req/s failures/s
--------------------------------------------------------------------------------------------------------------------------------------------
POST /non-existing 3 3(100.00%) 5 4 6 | 5 1.48 1.48
--------------------------------------------------------------------------------------------------------------------------------------------
Aggregated 3 3(100.00%) 5 4 6 | 5 1.48 1.48
Percentage of the requests completed within given times
Type Name # reqs 50% 66% 75% 80% 90% 95% 98% 99% 99.9% 99.99% 100%
------------------------------------------------------------------------------------------------------------------------------------------------------
POST /non-existing 3 5 5 7 7 7 7 7 7 7 7 7
------------------------------------------------------------------------------------------------------------------------------------------------------
None Aggregated 3 5 5 7 7 7 7 7 7 7 7 7
Error report
# occurrences Error
--------------------------------------------------------------------------------------------------------------------------------------------
3 POST /non-existing: "CatchResponseError('Noooo, fail!')"
--------------------------------------------------------------------------------------------------------------------------------------------
Oh, right, I'm totally misremembering. It is possible to do the first thing I posted, just not the second one. For example, doing this:
def t1(self):
with self.client.get("/", catch_response=True) as resp:
resp.failure("foo")
resp.success()
... will log two requests, one failure, and one success.
... and that is bad because it makes it hard to build a more advanced client/user (for example, one that does custom error checking, but allows the error to be overridden/removed in cases where an error is expected)
Ah, I see what you mean! Definitely agree. Only the last call to either success()
or failure()
should count.
I have a failing test for it now. I'll set up a PR.
Probably we should also change it from being a method call to being a property.
I don't think it they should be properties. I think it's useful to be able to pass a message to the failure()
method.
PR submitted!
Because resp.failure() immediately logs a failure
trows an exception, it is kind of hard to work with.edit: I was confused, this first thing is entirely possible today
For instance, if you want to tag the request as a failure and then break out of the task entirely, you cant really do that in a straight forward way.I would like to be able to do this:or even this (particularly useful when you have wrapped the request method and it does some kind of error checking internally, which you may want to override sometimes):
Probably we should also change it from being a method call to being a property.
Because this is potentially a breaking change for some testplans I would like to do it for 1.0