Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
fw:locust [2014/08/08 07:25] alfred [Install] |
fw:locust [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 2: | Línea 2: | ||
| Is a load testing tool in which you define user behaviour and the system launches a lot of non-real users accessing your web page. | Is a load testing tool in which you define user behaviour and the system launches a lot of non-real users accessing your web page. | ||
| + | * Docs: [[http://docs.locust.io/en/latest/]] | ||
| ===== Basic things ===== | ===== Basic things ===== | ||
| ==== Install ==== | ==== Install ==== | ||
| Línea 7: | Línea 8: | ||
| $ pip install locustio | $ pip install locustio | ||
| </code> | </code> | ||
| - | ==== Basic example ==== | + | ==== Basic things in Locust ==== |
| + | We define several tasks (functions that take one argument, a Locus class instance). We set them on a ''TaskSet'' class, using the ''tasks'' attribute. This class defines the user behaviour. The engine which move all of this is the ''Locust'' class, it indicates the "limits" (of time, with min_wait and max_wait) for the user. \\ | ||
| + | |||
| + | ''HttpLocust'' is a ''Locust'' class that allows HTTP requests. | ||
| + | |||
| + | The ''Locust'' class represents a user then, the system, will create a lot of locust instances (one for each user simulated). It contains... | ||
| + | * ''task_set'' attribute, which will be set with a ''TaskSet'' instance that defines the user behaviour. | ||
| + | * ''min_wait'' and ''max_wait'' attributes, milliseconds that a simulated user will wait between executing each task. If they are not set, locust will wait a second to execute it again (both have 1000 as default). | ||
| + | * ''host'', you can specify it on the command line using the –host option. It tells the host to be loaded. | ||
| + | * ''weight'' tells the frequency of use, for example, ''WebUserLocust'' will be executed three times ''MobileUserLocust''. | ||
| + | <code python> | ||
| + | class WebUserLocust(Locust): | ||
| + | weight = 3 | ||
| + | .... | ||
| + | |||
| + | class MobileUserLocust(Locust): | ||
| + | weight = 1 | ||
| + | .... | ||
| + | </code> | ||
| + | The ''TaskSet'' represents the user behaviour. It's a collection of tasks (actions). If we were loadtesting an auction website this tasks would be like “loading the start page”, “searching for some product” and “making a bid”. | ||
| + | |||
| + | In a load test, each TaskSet will pick one of it’s tasks and call it. It will then wait a number of milliseconds, chosen at random between min_wait and max_wait attributes. Then it will again pick a new task which will be called, then wait again, and so on. | ||
| + | |||
| + | === Examples === | ||
| + | This... | ||
| + | <code python> | ||
| + | from locust import HttpLocust, TaskSet | ||
| + | |||
| + | def login(l): | ||
| + | l.client.post("/login", {"username":"ellen_key", "password":"education"}) | ||
| + | |||
| + | def index(l): | ||
| + | l.client.get("/") | ||
| + | |||
| + | def profile(l): | ||
| + | l.client.get("/profile") | ||
| + | |||
| + | class UserBehavior(TaskSet): | ||
| + | tasks = {index:2, profile:1} | ||
| + | |||
| + | def on_start(self): | ||
| + | login(self) | ||
| + | |||
| + | class WebsiteUser(HttpLocust): | ||
| + | task_set = UserBehavior | ||
| + | min_wait=5000 | ||
| + | max_wait=9000 | ||
| + | </code> | ||
| + | Is the same than... | ||
| + | <code python> | ||
| + | from locust import HttpLocust, TaskSet, task | ||
| + | |||
| + | class UserBehavior(TaskSet): | ||
| + | def on_start(self): | ||
| + | """ on_start is called when a Locust start before any task is scheduled """ | ||
| + | self.login() | ||
| + | |||
| + | def login(self): | ||
| + | self.client.post("/login", {"username":"ellen_key", "password":"education"}) | ||
| + | |||
| + | @task(2) | ||
| + | def index(self): | ||
| + | self.client.get("/") | ||
| + | |||
| + | @task(1) | ||
| + | def profile(self): | ||
| + | self.client.get("/profile") | ||
| + | |||
| + | class WebsiteUser(HttpLocust): | ||
| + | task_set = UserBehavior | ||
| + | min_wait=5000 | ||
| + | max_wait=9000 | ||
| + | </code> | ||
| ==== Executing Locust ==== | ==== Executing Locust ==== | ||
| + | In the same path than the locust file: | ||
| + | <code> | ||
| + | locust | ||
| + | </code> | ||
| + | Or in different path: | ||
| + | <code> | ||
| + | locust -f ../locust_files/my_locust_file.py | ||
| + | </code> | ||
| + | Running two locust in the same file (weight attribute will define the frequency of calling). | ||
| + | <code> | ||
| + | locust -f locust_file.py WebUserLocust MobileUserLocust | ||
| + | </code> | ||
| + | === Running multiple processes === | ||
| + | * It's recommended to install zeromq: ''$ pip install pyzmq'' | ||
| + | * You can find more about this subject [[http://docs.locust.io/en/latest/running-locust-distributed.html|here]]. | ||
| + | |||
| + | |||
| + | You'll need a master: | ||
| + | <code> | ||
| + | locust -f ../locust_files/my_locust_file.py --master | ||
| + | </code> | ||
| + | And an arbitrary number of slave processes: | ||
| + | <code> | ||
| + | locust -f ../locust_files/my_locust_file.py --slave | ||
| + | </code> | ||
| + | Or with multiple machines: | ||
| + | <code> | ||
| + | locust -f ../locust_files/my_locust_file.py --slave --master-host=192.168.0.100 | ||
| + | </code> | ||
| ==== Accessing to the web interface ==== | ==== Accessing to the web interface ==== | ||
| You only need to access the url: [[http://127.0.0.1:8089]] | You only need to access the url: [[http://127.0.0.1:8089]] | ||
| + | |||
| + | ===== More things... ===== | ||
| + | ==== The TaskSet class ==== | ||
| + | === Declaring tasks with the task decorator === | ||
| + | <code python> | ||
| + | from locust import Locust, TaskSet, task | ||
| + | |||
| + | class MyTaskSet(TaskSet): | ||
| + | @task | ||
| + | def my_task(self): | ||
| + | print "Locust instance (%r) executing my_task" % (self.locust) | ||
| + | |||
| + | class MyLocust(Locust): | ||
| + | task_set = MyTaskSet | ||
| + | </code> | ||
| + | Or defining weight (task2 will be executed twice than task): | ||
| + | <code python> | ||
| + | from locust import Locust, TaskSet, task | ||
| + | |||
| + | class MyTaskSet(TaskSet): | ||
| + | min_wait = 5000 | ||
| + | max_wait = 15000 | ||
| + | |||
| + | @task(3) | ||
| + | def task1(self): | ||
| + | pass | ||
| + | |||
| + | @task(6) | ||
| + | def task2(self): | ||
| + | pass | ||
| + | |||
| + | class MyLocust(Locust): | ||
| + | task_set = MyTaskSet | ||
| + | </code> | ||
| + | |||
| + | === Set an dictionary to tasks attribute === | ||
| + | The next dictionary will assign two tasks, each one with their weight. | ||
| + | <code python> | ||
| + | class MyTaskSet(TaskSet): | ||
| + | tasks = {my_task: 3, another_task:1} | ||
| + | </code> | ||
| + | |||
| + | === The on_start function === | ||
| + | A TaskSet class can declare an on_start function. That function is called when a simulated user starts executing tasks in that TaskSet. | ||
| + | |||
| + | === Nesting TaskSets === | ||
| + | We can define a ''TaskSet'' as a task. Then it will represent a group of sub-task which are executed in that way. | ||
| + | |||
| + | It could be useful to represent a user that makes actions over the web (like enter in a web, then browse films and watch one, then navigate in the blog and comment and comment again, then navigate again, then browse films...). | ||
| + | |||
| + | A nested class set could call the ''self.interrupt()'' function. It interrupts the action in that class set. | ||
| + | |||
| + | === Nested sub-tasks examples === | ||
| + | |||
| + | <code python> | ||
| + | class ForumPage(TaskSet): | ||
| + | @task(20) | ||
| + | def read_thread(self): | ||
| + | pass | ||
| + | |||
| + | @task(1) | ||
| + | def new_thread(self): | ||
| + | pass | ||
| + | |||
| + | @task(5) | ||
| + | def stop(self): | ||
| + | self.interrupt() | ||
| + | |||
| + | class UserBehaviour(TaskSet): | ||
| + | tasks = {ForumPage:10} | ||
| + | |||
| + | @task | ||
| + | def index(self): | ||
| + | pass | ||
| + | </code> | ||
| + | <code python> | ||
| + | class MyTaskSet(TaskSet): | ||
| + | @task | ||
| + | class SubTaskSet(TaskSet): | ||
| + | @task | ||
| + | def my_task(self): | ||
| + | pass | ||
| + | </code> | ||
| + | ==== Hacer nuestro propio cliente ==== | ||
| + | Haremos un cliente "específico" para la tarea de deseemos. Este heredará de la clase ''Locust'' y usará el código que deseemos. Luego, para definir las acciones del test de carga heredaremos de esa clase; esta contendrá el taskset. Ver [[http://docs.locust.io/en/latest/testing-other-systems.html|aquí]], donde tenemos un código ''XmlRpcClient'' y una clase ''Locust'' que lo usa, la ''XmlRpcLocust''. | ||
| + | |||
| + | ==== The HTTPClient ==== | ||
| + | * [[http://docs.locust.io/en/latest/writing-a-locustfile.html#using-the-http-client]] | ||