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

Limit on Locust subclasses #1248

Closed
neophyte57 opened this issue Jan 29, 2020 · 3 comments
Closed

Limit on Locust subclasses #1248

neophyte57 opened this issue Jan 29, 2020 · 3 comments
Labels

Comments

@neophyte57
Copy link

Hi, I have reviewed issue 573 (#573) and am following the recommendation: to have multiple HttpLocust subclasses and a corresponding TaskSet subclass for each HttpLocust subclass in my Locust file. But when I run Locust (version 0.13.5), this is the behavior I get

Arrangement of Locust file Behavior
combined_test21.py Both task sets executed
combined_test123.py Task sets #2 and #3 executed
combined_test231.py Task sets #3 and #1 executed
combined_test0231.py Task sets #0 and #2 executed
combined_test2310.py Task sets #2 and #3 executed

The number in the Python file name indicates the included test case #s (e.g. "combined_test0231.py" has the pair of TaskSet and HttpLocust classes for test case #0, followed by the pair for test case #2, etc.). I run the test within the Docker image locustio/locust:0.13.5 like this:

locust -f combined_test123.py --no-web -c 2 -r 1

So from my analysis, it seems at most two HttpLocust subclasses are executed. I was so surprised by this that I reviewed the Locust code (

locusts = dict(filter(is_locust, vars(imported).items()))
) and then my code. Yes, my classes satisfy the is_locust function (
def is_locust(tup):
)

Note that these combined_test******.py files are actually the result of a "cat XXXXXXX.py YYYYYYYY.py > combined_test******.py" so the individual .py files are valid Locust files that are able to execute properly by themselves.

What am I doing wrong? Thanks.

@heyman
Copy link
Member

heyman commented Jan 30, 2020

So from my analysis, it seems at most two HttpLocust subclasses are executed.

Since you're using -c 2 locust will only be simulating two users (instances of Locust classes).

If you want simulate users that can execute many different TaskSets, you should have a single Locust subclass with a task_set that has multiple TaskSet subclasses as tasks.

Here's an example:

from locust import Locust, TaskSet, task, constant

class Tasks1(TaskSet):
    @task
    def some_task(self):
        print("task 1")
    
    @task
    def stop(self):
        self.interrupt()

class Tasks2(TaskSet):
    @task
    def some_task(self):
        print("task 2")
    
    @task
    def stop(self):
        self.interrupt()

class Tasks3(TaskSet):
    @task
    def some_task(self):
        print("task 3")
    
    @task
    def stop(self):
        self.interrupt()

class MyLocust(Locust):
    wait_time = constant(1)
    class task_set(TaskSet):
        tasks = {
            Tasks1: 1, 
            Tasks2: 1, 
            Tasks3: 1,
        }

For more info see: https://docs.locust.io/en/stable/writing-a-locustfile.html#tasksets-can-be-nested

@neophyte57
Copy link
Author

Thanks for the timely response. Yes, the reason for the observed behavior makes sense … doh!

Why I use the "cat" command is because I am converting these test cases from a different tool so I wanted to keep the same folder and file organization. I've been doing some experimenting based on your response and it seems I can cat the individual Locust files together, define a new HttpLocust class with a nested TaskSet that defines the distribution of TaskSets (directly or via configuration) and then when running Locust, specify this new HttpLocust class, like this:

`
class OverallUnauthenticatedUser(HttpLocust):

class task_set(TaskSet):
    tasks = {
        TC1Behavior: Configuration.get_weight('TC1'), 
        TC2Behavior: 20, 
        TC3Behavior: 30,
        TC4Behavior: 40
    }
         
host = 'https://portal.foobar.ca/' 

`

FYI, Configuration is my own class. I didn't add the stop method in each TaskSet (e.g. TC1Behavior) and it seems to run the way I want to. By not defining, could this cause some problem?

@heyman
Copy link
Member

heyman commented Jan 31, 2020

I didn't add the stop method in each TaskSet (e.g. TC1Behavior) and it seems to run the way I want to. By not defining, could this cause some problem?

If your sub TaskSets never call the interrupt() method, it means that a once a simulated user starts executing one of those TaskSets, it'll keep running tasks from that TaskSet forever (until it's stopped) and never exit from it and pick a new sub TaskSet.

@heyman heyman closed this as completed Jan 31, 2020
@heyman heyman added the invalid label Jan 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants