From 66e7942efd7fd615c36e537c87dfd78ca07cb9c3 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Mon, 6 Apr 2020 16:43:49 +1200 Subject: [PATCH 01/37] Rename Locust to User --- .../custom_xmlrpc_client/xmlrpc_locustfile.py | 4 +- locust/__init__.py | 2 +- locust/contrib/fasthttp.py | 4 +- locust/core.py | 8 +-- locust/inspectlocust.py | 4 +- locust/main.py | 6 +- locust/test/test_locust_class.py | 36 +++++------ locust/test/test_main.py | 8 +-- locust/test/test_old_wait_api.py | 26 ++++---- locust/test/test_runners.py | 62 +++++++++---------- locust/test/test_stats.py | 8 +-- locust/test/test_task_sequence_class.py | 6 +- locust/test/test_taskratio.py | 8 +-- locust/test/test_wait_time.py | 30 ++++----- locust/test/test_web.py | 18 +++--- 15 files changed, 115 insertions(+), 115 deletions(-) diff --git a/examples/custom_xmlrpc_client/xmlrpc_locustfile.py b/examples/custom_xmlrpc_client/xmlrpc_locustfile.py index f55e4a3812..3acca957b8 100644 --- a/examples/custom_xmlrpc_client/xmlrpc_locustfile.py +++ b/examples/custom_xmlrpc_client/xmlrpc_locustfile.py @@ -1,7 +1,7 @@ import time from xmlrpc.client import ServerProxy, Fault -from locust import Locust, task, between +from locust import User, task, between class XmlRpcClient(ServerProxy): @@ -31,7 +31,7 @@ def wrapper(*args, **kwargs): return wrapper -class XmlRpcLocust(Locust): +class XmlRpcLocust(User): """ This is the abstract Locust class which should be subclassed. It provides an XML-RPC client that can be used to make XML-RPC requests that will be tracked in Locust's statistics. diff --git a/locust/__init__.py b/locust/__init__.py index 15da43b588..867392eb79 100644 --- a/locust/__init__.py +++ b/locust/__init__.py @@ -1,4 +1,4 @@ -from .core import HttpLocust, Locust, TaskSet, TaskSequence, task, seq_task +from .core import HttpLocust, User, TaskSet, TaskSequence, task, seq_task from .exception import InterruptTaskSet, ResponseError, RescheduleTaskImmediately from .wait_time import between, constant, constant_pacing from .event import Events diff --git a/locust/contrib/fasthttp.py b/locust/contrib/fasthttp.py index 379bf4fb32..c490fbcbb5 100644 --- a/locust/contrib/fasthttp.py +++ b/locust/contrib/fasthttp.py @@ -16,7 +16,7 @@ from geventhttpclient.useragent import UserAgent, CompatRequest, CompatResponse, ConnectionError from geventhttpclient.response import HTTPConnectionClosed -from locust.core import Locust +from locust.core import User from locust.exception import LocustError, CatchResponseError, ResponseError from locust.env import Environment @@ -47,7 +47,7 @@ def _construct_basic_auth_str(username, password): return 'Basic ' + b64encode(b':'.join((username, password))).strip().decode("ascii") -class FastHttpLocust(Locust): +class FastHttpLocust(User): """ FastHttpLocust uses a different HTTP client (geventhttpclient) compared to HttpLocust (python-requests). It's significantly faster, but not as capable. diff --git a/locust/core.py b/locust/core.py index 50a4aec431..41e435b62b 100644 --- a/locust/core.py +++ b/locust/core.py @@ -214,7 +214,7 @@ def __init__(self, parent): if isinstance(parent, TaskSet): self.locust = parent.locust - elif isinstance(parent, Locust): + elif isinstance(parent, User): self.locust = parent else: raise LocustError("TaskSet should be called with Locust instance or TaskSet instance as first argument") @@ -447,7 +447,7 @@ def __new__(mcs, classname, bases, class_dict): return type.__new__(mcs, classname, bases, class_dict) -class Locust(object, metaclass=LocustMeta): +class User(object, metaclass=LocustMeta): """ Represents a "user" which is to be hatched and attack the system that is to be load tested. @@ -517,7 +517,7 @@ class ForumPage(TaskSet): _greenlet = None def __init__(self, environment): - super(Locust, self).__init__() + super(User, self).__init__() # check if deprecated wait API is used deprecation.check_for_deprecated_wait_api(self) self.environment = environment @@ -588,7 +588,7 @@ def stop(self, gevent_group, force=False): return False -class HttpLocust(Locust): +class HttpLocust(User): """ Represents an HTTP "user" which is to be hatched and attack the system that is to be load tested. diff --git a/locust/inspectlocust.py b/locust/inspectlocust.py index 7bd6654da6..522d8954a5 100644 --- a/locust/inspectlocust.py +++ b/locust/inspectlocust.py @@ -1,6 +1,6 @@ import inspect -from .core import Locust, TaskSet +from .core import User, TaskSet from .log import console_logger @@ -37,7 +37,7 @@ def get_task_ratio_dict(tasks, total=False, parent_ratio=1.0): for locust, ratio in ratio_percent.items(): d = {"ratio":ratio} if inspect.isclass(locust): - if issubclass(locust, (Locust, TaskSet)): + if issubclass(locust, (User, TaskSet)): T = locust.tasks if total: d["tasks"] = get_task_ratio_dict(T, total, ratio) diff --git a/locust/main.py b/locust/main.py index 837b431272..ab4efd072a 100644 --- a/locust/main.py +++ b/locust/main.py @@ -13,7 +13,7 @@ from .event import Events from .argument_parser import parse_locustfile_option, parse_options -from .core import HttpLocust, Locust +from .core import HttpLocust, User from .env import Environment from .inspectlocust import get_task_ratio_dict, print_task_ratio from .log import console_logger, setup_logging @@ -23,7 +23,7 @@ from .util.timespan import parse_timespan from .web import WebUI -_internals = [Locust, HttpLocust] +_internals = [User, HttpLocust] version = locust.__version__ @@ -34,7 +34,7 @@ def is_locust(tup): name, item = tup return bool( inspect.isclass(item) - and issubclass(item, Locust) + and issubclass(item, User) and item.abstract == False ) diff --git a/locust/test/test_locust_class.py b/locust/test/test_locust_class.py index 042ae666be..f52a05e08b 100644 --- a/locust/test/test_locust_class.py +++ b/locust/test/test_locust_class.py @@ -3,7 +3,7 @@ from gevent.pool import Group from locust import InterruptTaskSet, ResponseError -from locust.core import HttpLocust, Locust, TaskSet, task +from locust.core import HttpLocust, TaskSet, task, User from locust.env import Environment from locust.exception import (CatchResponseError, LocustError, RescheduleTask, RescheduleTaskImmediately, StopLocust) @@ -16,10 +16,10 @@ class TestTaskSet(LocustTestCase): def setUp(self): super(TestTaskSet, self).setUp() - class User(Locust): + class MyUser(User): host = "127.0.0.1" self.environment = Environment() - self.locust = User(self.environment) + self.locust = MyUser(self.environment) def test_task_ratio(self): t1 = lambda l: None @@ -39,12 +39,12 @@ def test_tasks_missing_gives_user_friendly_exception(self): class MyTasks(TaskSet): tasks = None - class User(Locust): + class MyUser(User): wait_time = constant(0) tasks = [MyTasks] _catch_exceptions = False - l = MyTasks(User(self.environment)) + l = MyTasks(MyUser(self.environment)) self.assertRaisesRegex(Exception, "No tasks defined.*", l.run) l.tasks = [] self.assertRaisesRegex(Exception, "No tasks defined.*", l.run) @@ -78,7 +78,7 @@ def t4(self): self.assertEqual(t4_count, 13) def test_tasks_on_locust(self): - class MyLocust(Locust): + class MyLocust(User): @task(2) def t1(self): pass @@ -90,7 +90,7 @@ def t2(self): self.assertEqual(3, len([t for t in l.tasks if t.__name__ == MyLocust.t2.__name__])) def test_tasks_on_abstract_locust(self): - class AbstractLocust(Locust): + class AbstractLocust(User): abstract = True @task(2) def t1(self): @@ -105,7 +105,7 @@ def t2(self): def test_taskset_on_abstract_locust(self): v = [0] - class AbstractLocust(Locust): + class AbstractLocust(User): abstract = True @task class task_set(TaskSet): @@ -122,7 +122,7 @@ class MyLocust(AbstractLocust): def test_task_decorator_on_taskset(self): state = [0] - class MyLocust(Locust): + class MyLocust(User): wait_time = constant(0) @task def t1(self): @@ -204,7 +204,7 @@ def on_stop(self): def t2(self): self.locust.t2_executed = True - class MyUser(Locust): + class MyUser(User): t2_executed = False on_stop_executed = False @@ -391,7 +391,7 @@ def on_start(self): else: self.interrupt(reschedule=False) - class MyLocust(Locust): + class MyLocust(User): host = "" tasks = [SubTaskSet] @@ -419,7 +419,7 @@ def stop(self): class RootTaskSet(TaskSet): tasks = [SubTaskSet] - class MyLocust(Locust): + class MyLocust(User): host = "" tasks = [RootTaskSet] @@ -431,7 +431,7 @@ class MyLocust(Locust): class TestLocustClass(LocustTestCase): def test_locust_on_start(self): - class MyLocust(Locust): + class MyLocust(User): t1_executed = False t2_executed = False @@ -452,7 +452,7 @@ def t2(self): self.assertTrue(l.t2_executed) def test_locust_on_stop(self): - class MyLocust(Locust): + class MyLocust(User): on_stop_executed = False t2_executed = True @@ -470,7 +470,7 @@ def t2(self): self.assertTrue(l.t2_executed) def test_locust_start(self): - class TestUser(Locust): + class TestUser(User): wait_time = constant(0.1) test_state = 0 @task @@ -491,7 +491,7 @@ def t(self): timeout.cancel() def test_locust_graceful_stop(self): - class TestUser(Locust): + class TestUser(User): wait_time = constant(0) test_state = 0 @task @@ -518,7 +518,7 @@ def t(self): self.assertEqual(2, user.test_state) def test_locust_forced_stop(self): - class TestUser(Locust): + class TestUser(User): wait_time = constant(0) test_state = 0 @task @@ -648,7 +648,7 @@ def t1(self): self.client.get("/") self.interrupt() - class MyLocust(Locust): + class MyLocust(User): host = "http://127.0.0.1:%i" % self.port tasks = [MyTaskSet] diff --git a/locust/test/test_main.py b/locust/test/test_main.py index afe8bf3110..3047816557 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -3,14 +3,14 @@ from locust import main from locust.argument_parser import parse_options from locust.main import create_environment -from locust.core import HttpLocust, Locust, TaskSet +from locust.core import HttpLocust, User, TaskSet from .testcases import LocustTestCase from .mock_locustfile import mock_locustfile class TestLoadLocustfile(LocustTestCase): def test_is_locust(self): - self.assertFalse(main.is_locust(("Locust", Locust))) + self.assertFalse(main.is_locust(("Locust", User))) self.assertFalse(main.is_locust(("HttpLocust", HttpLocust))) self.assertFalse(main.is_locust(("random_dict", {}))) self.assertFalse(main.is_locust(("random_list", []))) @@ -21,13 +21,13 @@ class MyTaskSet(TaskSet): class MyHttpLocust(HttpLocust): tasks = [MyTaskSet] - class MyLocust(Locust): + class MyLocust(User): tasks = [MyTaskSet] self.assertTrue(main.is_locust(("MyHttpLocust", MyHttpLocust))) self.assertTrue(main.is_locust(("MyLocust", MyLocust))) - class ThriftLocust(Locust): + class ThriftLocust(User): abstract = True self.assertFalse(main.is_locust(("ThriftLocust", ThriftLocust))) diff --git a/locust/test/test_old_wait_api.py b/locust/test/test_old_wait_api.py index 57a6e2386d..35f06854d5 100644 --- a/locust/test/test_old_wait_api.py +++ b/locust/test/test_old_wait_api.py @@ -1,7 +1,7 @@ import warnings from locust import InterruptTaskSet, ResponseError -from locust.core import HttpLocust, Locust, TaskSet, task +from locust.core import HttpLocust, User, TaskSet, task from locust.exception import (CatchResponseError, LocustError, RescheduleTask, RescheduleTaskImmediately) from locust.wait_time import between, constant @@ -15,11 +15,11 @@ def setUp(self): def test_wait_function(self): with warnings.catch_warnings(record=True) as w: - class User(Locust): + class MyUser(User): wait_function = lambda self: 5000 class MyTaskSet(TaskSet): pass - taskset = MyTaskSet(User(self.environment)) + taskset = MyTaskSet(MyUser(self.environment)) self.assertEqual(5, taskset.wait_time()) self.assertEqual(1, len(w)) self.assertTrue(issubclass(w[0].category, DeprecationWarning)) @@ -27,11 +27,11 @@ class MyTaskSet(TaskSet): def test_wait_function_on_taskset(self): with warnings.catch_warnings(record=True) as w: - class User(Locust): + class MyUser(User): pass class MyTaskSet(TaskSet): wait_function = lambda self: 5000 - taskset = MyTaskSet(User(self.environment)) + taskset = MyTaskSet(MyUser(self.environment)) self.assertEqual(5, taskset.wait_time()) self.assertEqual(1, len(w)) self.assertTrue(issubclass(w[0].category, DeprecationWarning)) @@ -39,14 +39,14 @@ class MyTaskSet(TaskSet): def test_min_max_wait(self): with warnings.catch_warnings(record=True) as w: - class User(Locust): + class MyUser(User): min_wait = 1000 max_wait = 1000 class TS(TaskSet): @task def t(self): pass - taskset = TS(User(self.environment)) + taskset = TS(MyUser(self.environment)) self.assertEqual(1, taskset.wait_time()) self.assertEqual(1, len(w)) self.assertTrue(issubclass(w[0].category, DeprecationWarning)) @@ -56,14 +56,14 @@ def t(self): def test_zero_min_max_wait(self): return with warnings.catch_warnings(record=True) as w: - class User(Locust): + class MyUser(User): min_wait = 0 max_wait = 0 class TS(TaskSet): @task def t(self): pass - taskset = TS(User(self.environment)) + taskset = TS(MyUser(self.environment)) self.assertEqual(0, taskset.wait_time()) self.assertEqual(1, len(w)) self.assertTrue(issubclass(w[0].category, DeprecationWarning)) @@ -72,7 +72,7 @@ def t(self): def test_min_max_wait_combined_with_wait_time(self): with warnings.catch_warnings(record=True) as w: - class User(Locust): + class MyUser(User): min_wait = 1000 max_wait = 1000 class TS(TaskSet): @@ -80,7 +80,7 @@ class TS(TaskSet): @task def t(self): pass - taskset = TS(User(self.environment)) + taskset = TS(MyUser(self.environment)) self.assertEqual(3, taskset.wait_time()) self.assertEqual(1, len(w)) self.assertTrue(issubclass(w[0].category, DeprecationWarning)) @@ -89,7 +89,7 @@ def t(self): def test_min_max_wait_on_taskset(self): with warnings.catch_warnings(record=True) as w: - class User(Locust): + class MyUser(User): wait_time = constant(3) class TS(TaskSet): min_wait = 1000 @@ -97,7 +97,7 @@ class TS(TaskSet): @task def t(self): pass - taskset = TS(User(self.environment)) + taskset = TS(MyUser(self.environment)) self.assertEqual(3, taskset.wait_time()) self.assertEqual(1, len(w)) self.assertTrue(issubclass(w[0].category, DeprecationWarning)) diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index 956fdf89aa..3a1b110aff 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -7,7 +7,7 @@ import mock from locust import runners from locust.main import create_environment -from locust.core import Locust, TaskSet, task +from locust.core import User, TaskSet, task from locust.env import Environment from locust.exception import LocustError, RPCError, StopLocust from locust.rpc import Message @@ -102,7 +102,7 @@ def test_cpu_warning(self): _monitor_interval = runners.CPU_MONITOR_INTERVAL runners.CPU_MONITOR_INTERVAL = 2.0 try: - class CpuLocust(Locust): + class CpuLocust(User): wait_time = constant(0.001) @task def cpu_task(self): @@ -122,7 +122,7 @@ def cpu_task(self): def test_weight_locusts(self): maxDiff = 2048 - class BaseLocust(Locust): + class BaseLocust(User): pass class L1(BaseLocust): weight = 101 @@ -137,7 +137,7 @@ class L3(BaseLocust): self.assert_locust_class_distribution({L1:11, L2:10, L3:10}, runner.weight_locusts(31)) def test_weight_locusts_fewer_amount_than_locust_classes(self): - class BaseLocust(Locust): + class BaseLocust(User): pass class L1(BaseLocust): weight = 101 @@ -152,7 +152,7 @@ class L3(BaseLocust): def test_kill_locusts(self): triggered = [False] - class BaseLocust(Locust): + class BaseLocust(User): wait_time = constant(1) @task class task_set(TaskSet): @@ -171,12 +171,12 @@ def trigger(self): self.assertTrue(triggered[0]) def test_start_event(self): - class User(Locust): + class MyUser(User): wait_time = constant(1) task_run_count = 0 @task def my_task(self): - User.task_run_count += 1 + MyUser.task_run_count += 1 test_start_run = [0] @@ -185,15 +185,15 @@ def on_test_start(*args, **kwargs): test_start_run[0] += 1 environment.events.test_start.add_listener(on_test_start) - runner = LocalLocustRunner(environment, locust_classes=[User]) + runner = LocalLocustRunner(environment, locust_classes=[MyUser]) runner.start(locust_count=3, hatch_rate=3, wait=False) runner.hatching_greenlet.get(timeout=3) self.assertEqual(1, test_start_run[0]) - self.assertEqual(3, User.task_run_count) + self.assertEqual(3, MyUser.task_run_count) def test_stop_event(self): - class User(Locust): + class MyUser(User): wait_time = constant(1) @task def my_task(self): @@ -205,21 +205,21 @@ def on_test_stop(*args, **kwargs): test_stop_run[0] += 1 environment.events.test_stop.add_listener(on_test_stop) - runner = LocalLocustRunner(environment, locust_classes=[User]) + runner = LocalLocustRunner(environment, locust_classes=[MyUser]) runner.start(locust_count=3, hatch_rate=3, wait=False) self.assertEqual(0, test_stop_run[0]) runner.stop() self.assertEqual(1, test_stop_run[0]) def test_change_user_count_during_hatching(self): - class User(Locust): + class MyUser(User): wait_time = constant(1) @task def my_task(self): pass environment = Environment(options=mocked_options()) - runner = LocalLocustRunner(environment, [User]) + runner = LocalLocustRunner(environment, [MyUser]) runner.start(locust_count=10, hatch_rate=5, wait=False) sleep(0.6) runner.start(locust_count=5, hatch_rate=5, wait=False) @@ -228,7 +228,7 @@ def my_task(self): runner.quit() def test_reset_stats(self): - class User(Locust): + class MyUser(User): wait_time = constant(0) @task class task_set(TaskSet): @@ -243,7 +243,7 @@ def my_task(self): sleep(2) environment = Environment(reset_stats=True, options=mocked_options()) - runner = LocalLocustRunner(environment, locust_classes=[User]) + runner = LocalLocustRunner(environment, locust_classes=[MyUser]) runner.start(locust_count=6, hatch_rate=12, wait=False) sleep(0.25) self.assertGreaterEqual(runner.stats.get("/test", "GET").num_requests, 3) @@ -252,7 +252,7 @@ def my_task(self): runner.quit() def test_no_reset_stats(self): - class User(Locust): + class MyUser(User): wait_time = constant(0) @task class task_set(TaskSet): @@ -267,7 +267,7 @@ def my_task(self): sleep(2) environment = Environment(reset_stats=False, options=mocked_options()) - runner = LocalLocustRunner(environment, locust_classes=[User]) + runner = LocalLocustRunner(environment, locust_classes=[MyUser]) runner.start(locust_count=6, hatch_rate=12, wait=False) sleep(0.25) self.assertGreaterEqual(runner.stats.get("/test", "GET").num_requests, 3) @@ -287,7 +287,7 @@ def setUp(self): #self._worker_report_event_handlers = [h for h in events.worker_report._handlers] self.environment.options = mocked_options() - class MyTestLocust(Locust): + class MyTestLocust(User): pass def tearDown(self): @@ -551,7 +551,7 @@ class MyTaskSet(TaskSet): def my_task(self): pass - class MyTestLocust(Locust): + class MyTestLocust(User): tasks = [MyTaskSet] wait_time = constant(0.1) @@ -634,7 +634,7 @@ def test_spawn_locusts_in_stepload_mode(self): self.assertEqual(10, num_clients, "Total number of locusts that would have been spawned for second step is not 10") def test_exception_in_task(self): - class MyLocust(Locust): + class MyLocust(User): @task def will_error(self): raise HeyAnException(":(") @@ -672,7 +672,7 @@ def will_error(self): def will_stop(self): raise StopLocust() - class MyLocust(Locust): + class MyLocust(User): wait_time = constant(0.01) tasks = [MyTaskSet] @@ -721,7 +721,7 @@ def get_runner(self, environment=None, locust_classes=[]): return WorkerLocustRunner(environment, locust_classes, master_host="localhost", master_port=5557) def test_worker_stop_timeout(self): - class MyTestLocust(Locust): + class MyTestLocust(User): _test_state = 0 wait_time = constant(0) @task @@ -762,7 +762,7 @@ def on_test_start(**kw): self.assertFalse(test_start_run[0]) def test_worker_without_stop_timeout(self): - class MyTestLocust(Locust): + class MyTestLocust(User): _test_state = 0 wait_time = constant(0) @task @@ -799,7 +799,7 @@ def the_task(self): self.assertEqual(1, MyTestLocust._test_state) def test_change_user_count_during_hatching(self): - class User(Locust): + class MyUser(User): wait_time = constant(1) @task def my_task(self): @@ -809,7 +809,7 @@ def my_task(self): options = mocked_options() options.stop_timeout = None environment = Environment(options=options) - worker = self.get_runner(environment=environment, locust_classes=[User]) + worker = self.get_runner(environment=environment, locust_classes=[MyUser]) client.mocked_send(Message("hatch", { "hatch_rate": 5, @@ -851,7 +851,7 @@ def my_task(self): gevent.sleep(short_time) MyTaskSet.state = "third" # should only run when run time + stop_timeout is > short_time * 2 - class MyTestLocust(Locust): + class MyTestLocust(User): tasks = [MyTaskSet] wait_time = constant(0) @@ -898,7 +898,7 @@ def on_start(self): def my_task(self): MyTaskSet.my_task_run = True - class MyTestLocust(Locust): + class MyTestLocust(User): tasks = [MyTaskSet] wait_time = constant(0) @@ -919,7 +919,7 @@ class MyTaskSet(TaskSet): def my_task(self): pass - class MyTestLocust(Locust): + class MyTestLocust(User): tasks = [MyTaskSet] wait_time = between(1, 1) @@ -950,7 +950,7 @@ def a_task(self): class MyTaskSet(TaskSet): tasks = [MySubTaskSet] - class MyTestLocust(Locust): + class MyTestLocust(User): tasks = [MyTaskSet] wait_time = constant(0) @@ -978,7 +978,7 @@ def a_task(self): state[0] = 1 self.interrupt(reschedule=False) - class MyTestLocust(Locust): + class MyTestLocust(User): tasks = [MySubTaskSet] wait_time = constant(3) @@ -1009,7 +1009,7 @@ def my_task(self): gevent.sleep(short_time) MyTaskSet.state = "third" # should only run when run time + stop_timeout is > short_time * 2 - class MyTestLocust(Locust): + class MyTestLocust(User): tasks = [MyTaskSet] wait_time = constant(0) diff --git a/locust/test/test_stats.py b/locust/test/test_stats.py index 4b8a6a45b7..cb98d297d1 100644 --- a/locust/test/test_stats.py +++ b/locust/test/test_stats.py @@ -5,7 +5,7 @@ import gevent import locust -from locust.core import HttpLocust, TaskSet, task, Locust +from locust.core import HttpLocust, TaskSet, task, User from locust.env import Environment from locust.inspectlocust import get_task_ratio_dict from locust.rpc.protocol import Message @@ -291,17 +291,17 @@ class TestWriteStatCSVs(LocustTestCase): def setUp(self): super().setUp() - class User(Locust): + class MyUser(User): setup_run_count = 0 task_run_count = 0 locust_error_count = 0 wait_time = locust.wait_time.constant(1) @task def my_task(self): - User.task_run_count += 1 + MyUser.task_run_count += 1 self.environment = Environment(options=mocked_options()) - locust.runners.locust_runner = locust.runners.LocalLocustRunner(self.environment, [User]) + locust.runners.locust_runner = locust.runners.LocalLocustRunner(self.environment, [MyUser]) self.remove_file_if_exists(self.STATS_FILENAME) self.remove_file_if_exists(self.STATS_HISTORY_FILENAME) self.remove_file_if_exists(self.STATS_FAILURES_FILENAME) diff --git a/locust/test/test_task_sequence_class.py b/locust/test/test_task_sequence_class.py index 3d848d2b11..1624adaf29 100644 --- a/locust/test/test_task_sequence_class.py +++ b/locust/test/test_task_sequence_class.py @@ -1,5 +1,5 @@ from locust import InterruptTaskSet, ResponseError -from locust.core import HttpLocust, Locust, TaskSequence, seq_task, task +from locust.core import HttpLocust, User, TaskSequence, seq_task, task from locust.exception import (CatchResponseError, LocustError, RescheduleTask, RescheduleTaskImmediately) from locust.wait_time import between, constant @@ -10,10 +10,10 @@ class TestTaskSet(LocustTestCase): def setUp(self): super(TestTaskSet, self).setUp() - class User(Locust): + class MyUser(User): host = "127.0.0.1" wait_time = between(0.001, 0.1) - self.locust = User(self.environment) + self.locust = MyUser(self.environment) def test_task_sequence_with_list(self): def t1(l): diff --git a/locust/test/test_taskratio.py b/locust/test/test_taskratio.py index db63f1ea62..3822f7ec0e 100644 --- a/locust/test/test_taskratio.py +++ b/locust/test/test_taskratio.py @@ -1,6 +1,6 @@ import unittest -from locust.core import Locust, TaskSet, task +from locust.core import User, TaskSet, task from locust.inspectlocust import get_task_ratio_dict @@ -21,7 +21,7 @@ def task1(self): def task2(self): pass - class User(Locust): + class MyUser(User): tasks = [Tasks] ratio_dict = get_task_ratio_dict(Tasks.tasks, total=True) @@ -47,11 +47,11 @@ def task1(self): def task3(self): pass - class UnlikelyLocust(Locust): + class UnlikelyLocust(User): weight = 1 tasks = [Tasks] - class MoreLikelyLocust(Locust): + class MoreLikelyLocust(User): weight = 3 tasks = [Tasks] diff --git a/locust/test/test_wait_time.py b/locust/test/test_wait_time.py index 5fa2918d50..d3dd41bda2 100644 --- a/locust/test/test_wait_time.py +++ b/locust/test/test_wait_time.py @@ -1,7 +1,7 @@ import random import time -from locust.core import Locust, TaskSet +from locust.core import User, TaskSet from locust.exception import MissingWaitTimeError from locust.wait_time import between, constant, constant_pacing @@ -10,14 +10,14 @@ class TestWaitTime(LocustTestCase): def test_between(self): - class User(Locust): + class MyUser(User): wait_time = between(3, 9) class TaskSet1(TaskSet): pass class TaskSet2(TaskSet): wait_time = between(20.0, 21.0) - u = User(self.environment) + u = MyUser(self.environment) ts1 = TaskSet1(u) ts2 = TaskSet2(u) for i in range(100): @@ -33,32 +33,32 @@ class TaskSet2(TaskSet): self.assertLessEqual(w, 21) def test_constant(self): - class User(Locust): + class MyUser(User): wait_time = constant(13) class TaskSet1(TaskSet): pass - self.assertEqual(13, User(self.environment).wait_time()) - self.assertEqual(13, TaskSet1(User(self.environment)).wait_time()) + self.assertEqual(13, MyUser(self.environment).wait_time()) + self.assertEqual(13, TaskSet1(MyUser(self.environment)).wait_time()) def test_constant_zero(self): - class User(Locust): + class MyUser(User): wait_time = constant(0) class TaskSet1(TaskSet): pass - self.assertEqual(0, User(self.environment).wait_time()) - self.assertEqual(0, TaskSet1(User(self.environment)).wait_time()) + self.assertEqual(0, MyUser(self.environment).wait_time()) + self.assertEqual(0, TaskSet1(MyUser(self.environment)).wait_time()) start_time = time.time() - TaskSet1(User(self.environment)).wait() + TaskSet1(MyUser(self.environment)).wait() self.assertLess(time.time() - start_time, 0.002) def test_constant_pacing(self): - class User(Locust): + class MyUser(User): wait_time = constant_pacing(0.1) class TS(TaskSet): pass - ts = TS(User(self.environment)) + ts = TS(MyUser(self.environment)) - ts2 = TS(User(self.environment)) + ts2 = TS(MyUser(self.environment)) previous_time = time.time() for i in range(7): @@ -71,9 +71,9 @@ class TS(TaskSet): _ = ts2.wait_time() def test_missing_wait_time(self): - class User(Locust): + class MyUser(User): pass class TS(TaskSet): pass - self.assertRaises(MissingWaitTimeError, lambda: TS(User(self.environment)).wait_time()) + self.assertRaises(MissingWaitTimeError, lambda: TS(MyUser(self.environment)).wait_time()) diff --git a/locust/test/test_web.py b/locust/test/test_web.py index 20c91b06b5..f8b2b4955b 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -10,7 +10,7 @@ from locust import constant from locust.argument_parser import get_parser -from locust.core import Locust, TaskSet, task +from locust.core import User, TaskSet, task from locust.env import Environment from locust.runners import LocustRunner from locust.web import WebUI @@ -183,7 +183,7 @@ def test_exceptions_csv(self): self.assertEqual(2, int(rows[1][0]), "Exception count should be 2") def test_swarm_host_value_specified(self): - class MyLocust(Locust): + class MyLocust(User): wait_time = constant(1) @task(1) def my_task(self): @@ -198,7 +198,7 @@ def my_task(self): self.assertEqual(self.environment.host, "https://localhost") def test_swarm_host_value_not_specified(self): - class MyLocust(Locust): + class MyLocust(User): wait_time = constant(1) @task(1) def my_task(self): @@ -213,7 +213,7 @@ def my_task(self): self.assertEqual(self.environment.host, None) def test_host_value_from_locust_class(self): - class MyLocust(Locust): + class MyLocust(User): host = "http://example.com" self.environment.runner.locust_classes = [MyLocust] response = requests.get("http://127.0.0.1:%i/" % self.web_port) @@ -222,9 +222,9 @@ class MyLocust(Locust): self.assertNotIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) def test_host_value_from_multiple_locust_classes(self): - class MyLocust(Locust): + class MyLocust(User): host = "http://example.com" - class MyLocust2(Locust): + class MyLocust2(User): host = "http://example.com" self.environment.runner.locust_classes = [MyLocust, MyLocust2] response = requests.get("http://127.0.0.1:%i/" % self.web_port) @@ -233,9 +233,9 @@ class MyLocust2(Locust): self.assertNotIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) def test_host_value_from_multiple_locust_classes_different_hosts(self): - class MyLocust(Locust): + class MyLocust(User): host = None - class MyLocust2(Locust): + class MyLocust2(User): host = "http://example.com" self.environment.runner.locust_classes = [MyLocust, MyLocust2] response = requests.get("http://127.0.0.1:%i/" % self.web_port) @@ -244,7 +244,7 @@ class MyLocust2(Locust): self.assertIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) def test_swarm_in_step_load_mode(self): - class MyLocust(Locust): + class MyLocust(User): wait_time = constant(1) @task(1) def my_task(self): From 26573d8f3501f02b8584e1c3848ca7b955c47cdf Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Mon, 6 Apr 2020 16:52:58 +1200 Subject: [PATCH 02/37] Rename client to users where applicable --- locust/argument_parser.py | 20 ++++++++++---------- locust/main.py | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/locust/argument_parser.py b/locust/argument_parser.py index ec36c3118e..3706bc4214 100644 --- a/locust/argument_parser.py +++ b/locust/argument_parser.py @@ -198,20 +198,20 @@ def setup_parser_arguments(parser): action='store_true', help="Disable the web interface, and instead start running the test immediately. Requires -c and -t to be specified." ) - # Number of clients + # Number of users parser.add_argument( - '-c', '--clients', + '-u', '--users', type=int, - dest='num_clients', + dest='num_users', default=1, - help="Number of concurrent Locust users. Only used together with --no-web" + help="Number of concurrent users. Only used together with --no-web" ) - # Client hatch rate + # User hatch rate parser.add_argument( '-r', '--hatch-rate', type=float, default=1, - help="The rate per second in which clients are spawned. Only used together with --no-web" + help="The rate per second in which users are spawned. Only used together with --no-web" ) # Time limit of the test run parser.add_argument( @@ -230,14 +230,14 @@ def setup_parser_arguments(parser): parser.add_argument( '--step-load', action='store_true', - help="Enable Step Load mode to monitor how performance metrics varies when user load increases. Requires --step-clients and --step-time to be specified." + help="Enable Step Load mode to monitor how performance metrics varies when user load increases. Requires --step-users and --step-time to be specified." ) - # Number of clients to incease by Step + # Number of users to incease by Step parser.add_argument( - '--step-clients', + '--step-users', type=int, default=1, - help="Client count to increase by step in Step Load mode. Only used together with --step-load" + help="User count to increase by step in Step Load mode. Only used together with --step-load" ) # Time limit of each step parser.add_argument( diff --git a/locust/main.py b/locust/main.py index ab4efd072a..a2235882af 100644 --- a/locust/main.py +++ b/locust/main.py @@ -248,9 +248,9 @@ def timelimit_stop(): if not options.worker: # start the test if options.step_time: - runner.start_stepload(options.num_clients, options.hatch_rate, options.step_clients, options.step_time) + runner.start_stepload(options.num_users, options.hatch_rate, options.step_users, options.step_time) else: - runner.start(options.num_clients, options.hatch_rate) + runner.start(options.num_users, options.hatch_rate) if options.run_time: spawn_run_time_limit_greenlet() From c6207d382fcd9d575e28beea1cfcb946d790d625 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Mon, 6 Apr 2020 17:05:03 +1200 Subject: [PATCH 03/37] Correct the usage in tests --- locust/test/test_parser.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/locust/test/test_parser.py b/locust/test/test_parser.py index f55a7a3893..185af77d6b 100644 --- a/locust/test/test_parser.py +++ b/locust/test/test_parser.py @@ -57,7 +57,7 @@ class TestArgumentParser(LocustTestCase): def test_parse_options(self): options = parse_options(args=[ "-f", "locustfile.py", - "-c", "100", + "-u", "100", "-r", "10", "-t", "5m", "--reset-stats", @@ -65,7 +65,7 @@ def test_parse_options(self): "MyLocustClass", ]) self.assertEqual("locustfile.py", options.locustfile) - self.assertEqual(100, options.num_clients) + self.assertEqual(100, options.num_users) self.assertEqual(10, options.hatch_rate) self.assertEqual("5m", options.run_time) self.assertTrue(options.reset_stats) @@ -78,7 +78,7 @@ def test_parse_locustfile(self): with mock_locustfile() as mocked: locustfile = parse_locustfile_option(args=[ "-f", mocked.file_path, - "-c", "100", + "-u", "100", "-r", "10", "-t", "5m", "--reset-stats", @@ -96,7 +96,7 @@ def test_unknown_command_line_arg(self): with mock.patch("sys.stderr", new=StringIO()): parse_options(args=[ "-f", "something.py", - "-c", "100", + "-u", "100", "-r", "10", "-t", "5m", "--reset-stats", @@ -119,11 +119,11 @@ def _(parser, **kw): ) options = parse_options(args=[ - "-c", "666", + "-u", "666", "--custom-bool-arg", "--custom-string-arg", "HEJ", ]) - self.assertEqual(666, options.num_clients) + self.assertEqual(666, options.num_users) self.assertEqual("HEJ", options.custom_string_arg) self.assertTrue(options.custom_bool_arg) From 0777fba358b7ce6a82ad07ec808235cde220142c Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Fri, 17 Apr 2020 08:20:29 +1200 Subject: [PATCH 04/37] Rename clients options to users and suppress the existing ones --- locust/argument_parser.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/locust/argument_parser.py b/locust/argument_parser.py index 231c0c8815..48007a7e42 100644 --- a/locust/argument_parser.py +++ b/locust/argument_parser.py @@ -129,18 +129,28 @@ def setup_parser_arguments(parser): ) # Number of Locust users parser.add_argument( - '-c', '--clients', + '-u', '--users', type=int, - dest='num_clients', + dest='num_users', default=1, help="Number of concurrent Locust users. Only used together with --headless" ) + parser.add_argument( + '-u', '--users', + action='store_true', + help=configargparse.SUPPRESS + ) + parser.add_argument( + '-c', '--clients', + action='store_true', + help=configargparse.SUPPRESS + ) # User hatch rate parser.add_argument( '-r', '--hatch-rate', type=float, default=1, - help="The rate per second in which clients are spawned. Only used together with --headless" + help="The rate per second in which users are spawned. Only used together with --headless" ) # Time limit of the test run parser.add_argument( @@ -299,12 +309,17 @@ def setup_parser_arguments(parser): action='store_true', help="Enable Step Load mode to monitor how performance metrics varies when user load increases. Requires --step-clients and --step-time to be specified." ) - # Number of clients to incease by Step + # Number of users to increase by Step step_load_group.add_argument( - '--step-clients', + '--step-users', type=int, default=1, - help="Client count to increase by step in Step Load mode. Only used together with --step-load" + help="User count to increase by step in Step Load mode. Only used together with --step-load" + ) + step_load_group.add_argument( + '--step-clients', + action='store_true', + help=configargparse.SUPPRESS ) # Time limit of each step step_load_group.add_argument( From 01a733f884c31b9b7839b2651016ad42ebc3de24 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Fri, 17 Apr 2020 08:20:41 +1200 Subject: [PATCH 05/37] More renaming from locust to user --- locust/__init__.py | 2 +- locust/core.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/locust/__init__.py b/locust/__init__.py index fbe6b363c2..556bff81e8 100644 --- a/locust/__init__.py +++ b/locust/__init__.py @@ -1,4 +1,4 @@ -from .core import HttpLocust, Locust, TaskSet, task +from .core import HttpLocust, User, TaskSet, task from .event import Events from .exception import InterruptTaskSet, ResponseError, RescheduleTaskImmediately from .sequential_taskset import SequentialTaskSet diff --git a/locust/core.py b/locust/core.py index 9ed70de49d..ff22a5fb3e 100644 --- a/locust/core.py +++ b/locust/core.py @@ -367,7 +367,7 @@ def execute_task(self, task, *args, **kwargs): task(self.locust, *args, **kwargs) -class LocustMeta(type): +class UserMeta(type): """ Meta class for the main Locust class. It's used to allow Locust classes to specify task execution ratio using an {task:int} dict, or a [(task0,int), ..., (taskN,int)] list. @@ -387,7 +387,7 @@ def __new__(mcs, classname, bases, class_dict): return type.__new__(mcs, classname, bases, class_dict) -class User(object, metaclass=LocustMeta): +class User(object, metaclass=UserMeta): """ Represents a "user" which is to be hatched and attack the system that is to be load tested. From 7db61c7346b26ebb9220f1de618e79690f69d743 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Fri, 17 Apr 2020 10:12:44 +1200 Subject: [PATCH 06/37] More renaming --- locust/test/test_runners.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index ae157cad84..98831a9bc1 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -231,14 +231,14 @@ def on_test_stop(*args, **kwargs): self.assertEqual(1, test_stop_run[0]) def test_stop_event_stop_and_quit(self): - class User(Locust): + class MyUser(User): wait_time = constant(1) @task def my_task(self): pass test_stop_run = [0] - environment = Environment(locust_classes=[User]) + environment = Environment(locust_classes=[MyUser]) def on_test_stop(*args, **kwargs): test_stop_run[0] += 1 environment.events.test_stop.add_listener(on_test_stop) @@ -257,7 +257,7 @@ class MyUser(User): def my_task(self): pass - environment = Environment(locust_classes=[User]) + environment = Environment(locust_classes=[MyUser]) runner = LocalLocustRunner(environment) runner.start(locust_count=10, hatch_rate=5, wait=False) sleep(0.6) From c783824e8876fc9cbb3c4316b58d3004df213dc3 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Fri, 17 Apr 2020 14:24:49 +1200 Subject: [PATCH 07/37] More renaming. This was causing the earlier build to fail. --- locust/argument_parser.py | 10 ---------- locust/test/test_log.py | 6 +++--- locust/test/test_main.py | 8 ++++---- locust/test/test_runners.py | 4 ++-- locust/test/test_sequential_taskset.py | 6 +++--- locust/test/test_stats.py | 4 ++-- locust/test/test_wait_time.py | 6 +++--- 7 files changed, 17 insertions(+), 27 deletions(-) diff --git a/locust/argument_parser.py b/locust/argument_parser.py index eb78687c58..3429357206 100644 --- a/locust/argument_parser.py +++ b/locust/argument_parser.py @@ -135,16 +135,6 @@ def setup_parser_arguments(parser): default=1, help="Number of concurrent Locust users. Only used together with --headless" ) - parser.add_argument( - '-u', '--users', - action='store_true', - help=configargparse.SUPPRESS - ) - parser.add_argument( - '-c', '--clients', - action='store_true', - help=configargparse.SUPPRESS - ) # User hatch rate parser.add_argument( '-r', '--hatch-rate', diff --git a/locust/test/test_log.py b/locust/test/test_log.py index a0a44d723f..161a197651 100644 --- a/locust/test/test_log.py +++ b/locust/test/test_log.py @@ -56,7 +56,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-c", "1", + "-u", "1", "-r", "1", "-t", "1", "--headless", @@ -97,7 +97,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-c", "1", + "-u", "1", "-r", "1", "-t", "1", "--headless", @@ -122,7 +122,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-c", "1", + "-u", "1", "-r", "1", "-t", "1", "--headless", diff --git a/locust/test/test_main.py b/locust/test/test_main.py index e7f094feed..334cf3afba 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -3,14 +3,14 @@ from locust import main from locust.argument_parser import parse_options from locust.main import create_environment -from locust.core import HttpLocust, Locust, TaskSet +from locust.core import HttpLocust, User, TaskSet from .testcases import LocustTestCase from .mock_locustfile import mock_locustfile class TestLoadLocustfile(LocustTestCase): def test_is_locust(self): - self.assertFalse(main.is_locust(Locust)) + self.assertFalse(main.is_locust(User)) self.assertFalse(main.is_locust(HttpLocust)) self.assertFalse(main.is_locust({})) self.assertFalse(main.is_locust([])) @@ -21,13 +21,13 @@ class MyTaskSet(TaskSet): class MyHttpLocust(HttpLocust): tasks = [MyTaskSet] - class MyLocust(Locust): + class MyLocust(User): tasks = [MyTaskSet] self.assertTrue(main.is_locust(MyHttpLocust)) self.assertTrue(main.is_locust(MyLocust)) - class ThriftLocust(Locust): + class ThriftLocust(User): abstract = True self.assertFalse(main.is_locust(ThriftLocust)) diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index 98831a9bc1..8d214d201b 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -180,7 +180,7 @@ def my_task(self): test_start_run = [0] - environment = Environment(locust_classes=[User]) + environment = Environment(locust_classes=[MyUser]) def on_test_start(*args, **kwargs): test_start_run[0] += 1 environment.events.test_start.add_listener(on_test_start) @@ -972,7 +972,7 @@ def my_task(self): with mock.patch("locust.rpc.rpc.Client", mocked_rpc()) as client: environment = Environment() - worker = self.get_runner(environment=environment, locust_classes=[User]) + worker = self.get_runner(environment=environment, locust_classes=[MyUser]) client.mocked_send(Message("hatch", { "hatch_rate": 5, diff --git a/locust/test/test_sequential_taskset.py b/locust/test/test_sequential_taskset.py index ee0cdeb740..2d9dd0a916 100644 --- a/locust/test/test_sequential_taskset.py +++ b/locust/test/test_sequential_taskset.py @@ -1,4 +1,4 @@ -from locust import Locust, task, constant +from locust import User, task, constant from locust.sequential_taskset import SequentialTaskSet from locust.exception import RescheduleTask from .testcases import LocustTestCase @@ -7,10 +7,10 @@ class TestTaskSet(LocustTestCase): def setUp(self): super(TestTaskSet, self).setUp() - class User(Locust): + class MyUser(User): host = "127.0.0.1" wait_time = constant(0) - self.locust = User(self.environment) + self.locust = MyUser(self.environment) def test_task_sequence_with_list(self): log = [] diff --git a/locust/test/test_stats.py b/locust/test/test_stats.py index e93c494a69..6b46e7ff27 100644 --- a/locust/test/test_stats.py +++ b/locust/test/test_stats.py @@ -7,7 +7,7 @@ import gevent import mock import locust -from locust import HttpLocust, TaskSet, task, Locust, constant +from locust import HttpLocust, TaskSet, task, User, constant from locust.env import Environment from locust.inspectlocust import get_task_ratio_dict from locust.rpc.protocol import Message @@ -382,7 +382,7 @@ def test_csv_stats_on_master_from_aggregated_stats(self): @mock.patch("locust.stats.CSV_STATS_INTERVAL_SEC", new=0.2) def test_user_count_in_csv_history_stats(self): start_time = int(time.time()) - class TestUser(Locust): + class TestUser(User): wait_time = constant(10) @task def t(self): diff --git a/locust/test/test_wait_time.py b/locust/test/test_wait_time.py index efbe378a78..84a6fc6b31 100644 --- a/locust/test/test_wait_time.py +++ b/locust/test/test_wait_time.py @@ -44,9 +44,9 @@ class MyUser(User): wait_time = constant(0) class TaskSet1(TaskSet): pass - self.assertEqual(0, User(self.environment).wait_time()) - self.assertEqual(0, TaskSet1(User(self.environment)).wait_time()) - taskset = TaskSet1(User(self.environment)) + self.assertEqual(0, MyUser(self.environment).wait_time()) + self.assertEqual(0, TaskSet1(MyUser(self.environment)).wait_time()) + taskset = TaskSet1(MyUser(self.environment)) start_time = time.time() taskset.wait() self.assertLess(time.time() - start_time, 0.002) From 558925702354d6e227e752d0dd226057da7babe6 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Fri, 17 Apr 2020 15:50:54 +1200 Subject: [PATCH 08/37] rever to -c --- locust/test/test_log.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locust/test/test_log.py b/locust/test/test_log.py index 161a197651..a0a44d723f 100644 --- a/locust/test/test_log.py +++ b/locust/test/test_log.py @@ -56,7 +56,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-u", "1", + "-c", "1", "-r", "1", "-t", "1", "--headless", @@ -97,7 +97,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-u", "1", + "-c", "1", "-r", "1", "-t", "1", "--headless", @@ -122,7 +122,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-u", "1", + "-c", "1", "-r", "1", "-t", "1", "--headless", From 25d253c22aedc65970f348e408a415289ecf3330 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Fri, 17 Apr 2020 15:57:41 +1200 Subject: [PATCH 09/37] use User class in test data --- locust/test/test_log.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/locust/test/test_log.py b/locust/test/test_log.py index a0a44d723f..78ed062aed 100644 --- a/locust/test/test_log.py +++ b/locust/test/test_log.py @@ -44,9 +44,9 @@ class TestLoggingOptions(LocustTestCase): def test_logging_output(self): with temporary_file(textwrap.dedent(""" import logging - from locust import Locust, task, constant + from locust import User, task, constant - class MyLocust(Locust): + class MyLocust(User): wait_time = constant(2) @task def my_task(self): @@ -56,7 +56,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-c", "1", + "-u", "1", "-r", "1", "-t", "1", "--headless", @@ -86,9 +86,9 @@ def my_task(self): def test_skip_logging(self): with temporary_file(textwrap.dedent(""" - from locust import Locust, task, constant + from locust import User, task, constant - class MyLocust(Locust): + class MyLocust(User): wait_time = constant(2) @task def my_task(self): @@ -97,7 +97,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-c", "1", + "-u", "1", "-r", "1", "-t", "1", "--headless", @@ -108,9 +108,9 @@ def my_task(self): def test_log_to_file(self): with temporary_file(textwrap.dedent(""" import logging - from locust import Locust, task, constant + from locust import User, task, constant - class MyLocust(Locust): + class MyLocust(User): wait_time = constant(2) @task def my_task(self): @@ -122,7 +122,7 @@ def my_task(self): output = subprocess.check_output([ "locust", "-f", file_path, - "-c", "1", + "-u", "1", "-r", "1", "-t", "1", "--headless", From 3c031291f395169b9583285cdfdd6b6dd434a8d1 Mon Sep 17 00:00:00 2001 From: Anuj Sharma Date: Fri, 17 Apr 2020 16:24:31 +1200 Subject: [PATCH 10/37] Rename runners --- locust/env.py | 12 ++++++------ locust/runners.py | 28 ++++++++++++++-------------- locust/test/test_locust_class.py | 8 ++++---- locust/test/test_runners.py | 24 ++++++++++++------------ locust/test/test_web.py | 4 ++-- locust/web.py | 6 +++--- 6 files changed, 41 insertions(+), 41 deletions(-) diff --git a/locust/env.py b/locust/env.py index c1c4a96bd4..e9a03ffe46 100644 --- a/locust/env.py +++ b/locust/env.py @@ -1,7 +1,7 @@ from .event import Events from .exception import RunnerAlreadyExistsError from .stats import RequestStats -from .runners import LocalLocustRunner, MasterLocustRunner, WorkerLocustRunner +from .runners import LocalRunner, MasterRunner, WorkerRunner from .web import WebUI @@ -76,20 +76,20 @@ def _create_runner(self, runner_class, *args, **kwargs): def create_local_runner(self): """ - Create a :class:`LocalLocustRunner ` instance for this Environment + Create a :class:`LocalRunner ` instance for this Environment """ - return self._create_runner(LocalLocustRunner) + return self._create_runner(LocalRunner) def create_master_runner(self, master_bind_host="*", master_bind_port=5557): """ - Create a :class:`MasterLocustRunner ` instance for this Environment + Create a :class:`MasterRunner ` instance for this Environment :param master_bind_host: Interface/host that the master should use for incoming worker connections. Defaults to "*" which means all interfaces. :param master_bind_port: Port that the master should listen for incoming worker connections on """ return self._create_runner( - MasterLocustRunner, + MasterRunner, master_bind_host=master_bind_host, master_bind_port=master_bind_port, ) @@ -105,7 +105,7 @@ def create_worker_runner(self, master_host, master_port): # and CPU cycles, since the response_times_cache is not needed for Worker nodes self.stats = RequestStats(use_response_times_cache=False) return self._create_runner( - WorkerLocustRunner, + WorkerRunner, master_host=master_host, master_port=master_port, ) diff --git a/locust/runners.py b/locust/runners.py index 725223ef25..f10f40b358 100644 --- a/locust/runners.py +++ b/locust/runners.py @@ -31,7 +31,7 @@ greenlet_exception_handler = greenlet_exception_logger(logger) -class LocustRunner(object): +class Runner(object): """ Orchestrates the load test by starting and stopping the locust users. @@ -302,7 +302,7 @@ def log_exception(self, node_id, msg, formatted_tb): self.exceptions[key] = row -class LocalLocustRunner(LocustRunner): +class LocalRunner(Runner): """ Runner for running single process load test """ @@ -310,7 +310,7 @@ def __init__(self, environment): """ :param environment: Environment instance """ - super(LocalLocustRunner, self).__init__(environment) + super(LocalRunner, self).__init__(environment) # register listener thats logs the exception for the local runner def on_locust_error(locust_instance, exception, tb): @@ -330,7 +330,7 @@ def start(self, locust_count, hatch_rate, wait=False): if self.hatching_greenlet: # kill existing hatching_greenlet before we start a new one self.hatching_greenlet.kill(block=True) - self.hatching_greenlet = self.greenlet.spawn(lambda: super(LocalLocustRunner, self).start(locust_count, hatch_rate, wait=wait)) + self.hatching_greenlet = self.greenlet.spawn(lambda: super(LocalRunner, self).start(locust_count, hatch_rate, wait=wait)) self.hatching_greenlet.link_exception(greenlet_exception_handler) def stop(self): @@ -340,7 +340,7 @@ def stop(self): self.environment.events.test_stop.fire(environment=self.environment) -class DistributedLocustRunner(LocustRunner): +class DistributedRunner(Runner): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) setup_distributed_stats_event_listeners(self.environment.events, self.stats) @@ -354,14 +354,14 @@ def __init__(self, id, state=STATE_INIT, heartbeat_liveness=HEARTBEAT_LIVENESS): self.cpu_usage = 0 self.cpu_warning_emitted = False -class MasterLocustRunner(DistributedLocustRunner): +class MasterRunner(DistributedRunner): """ Runner used to run distributed load tests across multiple processes and/or machines. - MasterLocustRunner doesn't spawn any locust user greenlets itself. Instead it expects - :class:`WorkerLocustRunners ` to connect to it, which it will then direct + MasterRunner doesn't spawn any locust user greenlets itself. Instead it expects + :class:`WorkerLocustRunners ` to connect to it, which it will then direct to start and stop locust user greenlets. Stats sent back from the - :class:`WorkerLocustRunners ` will aggregated. + :class:`WorkerLocustRunners ` will aggregated. """ def __init__(self, environment, master_bind_host, master_bind_port): """ @@ -422,7 +422,7 @@ def user_count(self): return sum([c.user_count for c in self.clients.values()]) def cpu_log_warning(self): - warning_emitted = LocustRunner.cpu_log_warning(self) + warning_emitted = Runner.cpu_log_warning(self) if self.worker_cpu_warning_emitted: logger.warning("CPU usage threshold was exceeded on workers during the test!") warning_emitted = True @@ -577,13 +577,13 @@ def client_listener(self): def worker_count(self): return len(self.clients.ready) + len(self.clients.hatching) + len(self.clients.running) -class WorkerLocustRunner(DistributedLocustRunner): +class WorkerRunner(DistributedRunner): """ Runner used to run distributed load tests across multiple processes and/or machines. - WorkerLocustRunner connects to a :class:`MasterLocustRunner` from which it'll receive - instructions to start and stop locust user greenlets. The WorkerLocustRunner will preiodically - take the stats generated by the running users and send back to the :class:`MasterLocustRunner`. + WorkerRunner connects to a :class:`MasterRunner` from which it'll receive + instructions to start and stop locust user greenlets. The WorkerRunner will preiodically + take the stats generated by the running users and send back to the :class:`MasterRunner`. """ def __init__(self, environment, master_host, master_port): diff --git a/locust/test/test_locust_class.py b/locust/test/test_locust_class.py index 8e78897fa4..acd663ac1f 100644 --- a/locust/test/test_locust_class.py +++ b/locust/test/test_locust_class.py @@ -87,12 +87,12 @@ def t2(self): self.assertEqual(3, len([t for t in l.tasks if t.__name__ == MyLocust.t2.__name__])) def test_tasks_on_abstract_locust(self): - class AbstractLocust(User): + class AbstractUser(User): abstract = True @task(2) def t1(self): pass - class MyLocust(AbstractLocust): + class MyLocust(AbstractUser): @task(3) def t2(self): pass @@ -102,7 +102,7 @@ def t2(self): def test_taskset_on_abstract_locust(self): v = [0] - class AbstractLocust(User): + class AbstractUser(User): abstract = True @task class task_set(TaskSet): @@ -110,7 +110,7 @@ class task_set(TaskSet): def t1(self): v[0] = 1 raise StopLocust() - class MyLocust(AbstractLocust): + class MyLocust(AbstractUser): pass l = MyLocust(self.environment) # check that the Locust can be run diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index 8d214d201b..ed4fd535df 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -13,7 +13,7 @@ from locust.exception import RPCError, StopLocust from locust.rpc import Message -from locust.runners import LocalLocustRunner, WorkerNode, WorkerLocustRunner, \ +from locust.runners import LocalRunner, WorkerNode, WorkerRunner, \ STATE_INIT, STATE_HATCHING, STATE_RUNNING, STATE_MISSING, STATE_STOPPED from locust.stats import RequestStats from locust.test.testcases import LocustTestCase @@ -111,7 +111,7 @@ def cpu_task(self): for i in range(1000000): _ = 3 / 2 environment = Environment(locust_classes=[CpuLocust]) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) self.assertFalse(runner.cpu_warning_emitted) runner.spawn_locusts(1, 1, wait=False) sleep(2.5) @@ -185,7 +185,7 @@ def on_test_start(*args, **kwargs): test_start_run[0] += 1 environment.events.test_start.add_listener(on_test_start) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) runner.start(locust_count=3, hatch_rate=3, wait=False) runner.hatching_greenlet.get(timeout=3) @@ -205,7 +205,7 @@ def on_test_stop(*args, **kwargs): test_stop_run[0] += 1 environment.events.test_stop.add_listener(on_test_stop) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) runner.start(locust_count=3, hatch_rate=3, wait=False) self.assertEqual(0, test_stop_run[0]) runner.stop() @@ -224,7 +224,7 @@ def on_test_stop(*args, **kwargs): test_stop_run[0] += 1 environment.events.test_stop.add_listener(on_test_stop) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) runner.start(locust_count=3, hatch_rate=3, wait=False) self.assertEqual(0, test_stop_run[0]) runner.quit() @@ -243,7 +243,7 @@ def on_test_stop(*args, **kwargs): test_stop_run[0] += 1 environment.events.test_stop.add_listener(on_test_stop) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) runner.start(locust_count=3, hatch_rate=3, wait=False) self.assertEqual(0, test_stop_run[0]) runner.stop() @@ -258,7 +258,7 @@ def my_task(self): pass environment = Environment(locust_classes=[MyUser]) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) runner.start(locust_count=10, hatch_rate=5, wait=False) sleep(0.6) runner.start(locust_count=5, hatch_rate=5, wait=False) @@ -282,7 +282,7 @@ def my_task(self): sleep(2) environment = Environment(locust_classes=[MyUser], reset_stats=True) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) runner.start(locust_count=6, hatch_rate=12, wait=False) sleep(0.25) self.assertGreaterEqual(runner.stats.get("/test", "GET").num_requests, 3) @@ -306,7 +306,7 @@ def my_task(self): sleep(2) environment = Environment(reset_stats=False, locust_classes=[MyUser]) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) runner.start(locust_count=6, hatch_rate=12, wait=False) sleep(0.25) self.assertGreaterEqual(runner.stats.get("/test", "GET").num_requests, 3) @@ -719,7 +719,7 @@ class MyTestLocust(User): wait_time = constant(0.1) environment = Environment(locust_classes=[MyTestLocust]) - runner = LocalLocustRunner(environment) + runner = LocalRunner(environment) timeout = gevent.Timeout(2.0) timeout.start() @@ -842,7 +842,7 @@ class MyLocust(User): # set config to catch exceptions in locust users self.environment.catch_exceptions = True self.environment.locust_classes = [MyLocust] - runner = LocalLocustRunner(self.environment) + runner = LocalRunner(self.environment) l = MyLocust(self.environment) # make sure HeyAnException isn't raised @@ -885,7 +885,7 @@ def get_runner(self, environment=None, locust_classes=[]): if environment is None: environment = self.environment environment.locust_classes = locust_classes - return WorkerLocustRunner(environment, master_host="localhost", master_port=5557) + return WorkerRunner(environment, master_host="localhost", master_port=5557) def test_worker_stop_timeout(self): class MyTestLocust(User): diff --git a/locust/test/test_web.py b/locust/test/test_web.py index bb2d7da108..d1e8838b7a 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -12,7 +12,7 @@ from locust.argument_parser import get_parser from locust.core import User, task from locust.env import Environment -from locust.runners import LocustRunner +from locust.runners import Runner from locust.web import WebUI from .testcases import LocustTestCase @@ -256,7 +256,7 @@ def setUp(self): parser = get_parser(default_config_files=[]) options = parser.parse_args(["--web-auth", "john:doe"]) - self.runner = LocustRunner(self.environment) + self.runner = Runner(self.environment) self.stats = self.runner.stats self.web_ui = self.environment.create_web_ui("127.0.0.1", 0, auth_credentials=options.web_auth) self.web_ui.app.view_functions["request_stats"].clear_cache() diff --git a/locust/web.py b/locust/web.py index f1aa2aeb26..1d36109ed5 100644 --- a/locust/web.py +++ b/locust/web.py @@ -16,7 +16,7 @@ from locust import __version__ as version from .exception import AuthCredentialsError -from .runners import MasterLocustRunner +from .runners import MasterRunner from .stats import failures_csv, requests_csv, sort_stats from .util.cache import memoize from .util.rounding import proper_round @@ -95,7 +95,7 @@ def index(): if not environment.runner: return make_response("Error: Locust Environment does not have any runner", 500) - is_distributed = isinstance(environment.runner, MasterLocustRunner) + is_distributed = isinstance(environment.runner, MasterRunner) if is_distributed: worker_count = environment.runner.worker_count else: @@ -220,7 +220,7 @@ def request_stats(): report["current_response_time_percentile_95"] = environment.runner.stats.total.get_current_response_time_percentile(0.95) report["current_response_time_percentile_50"] = environment.runner.stats.total.get_current_response_time_percentile(0.5) - is_distributed = isinstance(environment.runner, MasterLocustRunner) + is_distributed = isinstance(environment.runner, MasterRunner) if is_distributed: workers = [] for worker in environment.runner.clients.values(): From b9907962136630b58dfb4af34fde922062a9d6ed Mon Sep 17 00:00:00 2001 From: anuj_ Date: Mon, 20 Apr 2020 09:21:07 +1200 Subject: [PATCH 11/37] Use user instead of Locust --- locust/test/test_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locust/test/test_main.py b/locust/test/test_main.py index 2118876d5e..8beb5d2a67 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -92,7 +92,7 @@ def test_help_arg(self): def test_webserver(self): with temporary_file(content=textwrap.dedent(""" from locust import Locust, task, constant, events - class TestUser(Locust): + class TestUser(User): wait_time = constant(3) @task def my_task(): From 530db29ad7bd3ceda8f9c81f0b585984dd6a1a43 Mon Sep 17 00:00:00 2001 From: anuj_ Date: Mon, 20 Apr 2020 13:52:22 +1200 Subject: [PATCH 12/37] More renaming. Includes renaming in test and example files as well. --- examples/add_command_line_argument.py | 6 +- examples/basic.py | 6 +- examples/browse_docs_sequence_test.py | 4 +- examples/browse_docs_test.py | 4 +- examples/custom_wait_function.py | 10 +- .../custom_xmlrpc_client/xmlrpc_locustfile.py | 8 +- examples/dynamice_user_credentials.py | 4 +- examples/events.py | 4 +- examples/fast_http_locust.py | 8 +- examples/multiple_hosts.py | 10 +- examples/nested_inline_tasksets.py | 4 +- examples/semaphore_wait.py | 4 +- examples/use_as_lib.py | 4 +- locust/__init__.py | 2 +- locust/clients.py | 2 +- locust/contrib/fasthttp.py | 14 +- locust/core.py | 108 ++++++------- locust/env.py | 4 +- locust/event.py | 6 +- locust/exception.py | 6 +- locust/main.py | 6 +- locust/runners.py | 8 +- locust/sequential_taskset.py | 2 +- locust/stats.py | 2 +- locust/test/mock_locustfile.py | 6 +- locust/test/test_fasthttp.py | 114 +++++++------- locust/test/test_locust_class.py | 142 +++++++++--------- locust/test/test_log.py | 6 +- locust/test/test_main.py | 18 +-- locust/test/test_parser.py | 8 +- locust/test/test_runners.py | 104 ++++++------- locust/test/test_stats.py | 10 +- locust/test/test_taskratio.py | 14 +- locust/test/test_web.py | 28 ++-- locust/util/deprecation.py | 2 +- locust/wait_time.py | 6 +- 36 files changed, 347 insertions(+), 347 deletions(-) diff --git a/examples/add_command_line_argument.py b/examples/add_command_line_argument.py index f684cd03ab..e66b79c0d9 100644 --- a/examples/add_command_line_argument.py +++ b/examples/add_command_line_argument.py @@ -1,4 +1,4 @@ -from locust import HttpLocust, TaskSet, task, between +from locust import HttpUser, TaskSet, task, between from locust import events @@ -14,9 +14,9 @@ def _(environment, **kw): print("Custom argument supplied: %s" % environment.options.custom_argument) -class WebsiteUser(HttpLocust): +class WebsiteUser(HttpUser): """ - Locust user class that does requests to the locust web server running on localhost + User class that does requests to the locust web server running on localhost """ host = "http://127.0.0.1:8089" wait_time = between(2, 5) diff --git a/examples/basic.py b/examples/basic.py index b73d7b44eb..52270f7873 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -1,4 +1,4 @@ -from locust import HttpLocust, TaskSet, task, between +from locust import HttpUser, TaskSet, task, between def index(l): @@ -16,9 +16,9 @@ class UserTasks(TaskSet): def page404(self): self.client.get("/does_not_exist") -class WebsiteUser(HttpLocust): +class WebsiteUser(HttpUser): """ - Locust user class that does requests to the locust web server running on localhost + User class that does requests to the locust web server running on localhost """ host = "http://127.0.0.1:8089" wait_time = between(2, 5) diff --git a/examples/browse_docs_sequence_test.py b/examples/browse_docs_sequence_test.py index 5f36b94070..cc83349fdc 100644 --- a/examples/browse_docs_sequence_test.py +++ b/examples/browse_docs_sequence_test.py @@ -2,7 +2,7 @@ # browsing the Locust documentation on https://docs.locust.io/ import random -from locust import HttpLocust, SequentialTaskSet, task, between +from locust import HttpUser, SequentialTaskSet, task, between from pyquery import PyQuery @@ -36,7 +36,7 @@ def load_sub_page(self): r = self.client.get(url) -class AwesomeUser(HttpLocust): +class AwesomeUser(HttpUser): tasks = [BrowseDocumentationSequence] host = "https://docs.locust.io/en/latest/" diff --git a/examples/browse_docs_test.py b/examples/browse_docs_test.py index 1d93d2291a..62f0cd5805 100644 --- a/examples/browse_docs_test.py +++ b/examples/browse_docs_test.py @@ -2,7 +2,7 @@ # browsing the Locust documentation on https://docs.locust.io/ import random -from locust import HttpLocust, TaskSet, task, between +from locust import HttpUser, TaskSet, task, between from pyquery import PyQuery @@ -37,7 +37,7 @@ def load_sub_page(self): r = self.client.get(url) -class AwesomeUser(HttpLocust): +class AwesomeUser(HttpUser): tasks = [BrowseDocumentation] host = "https://docs.locust.io/en/latest/" diff --git a/examples/custom_wait_function.py b/examples/custom_wait_function.py index 2494c1ac4d..f360656b73 100644 --- a/examples/custom_wait_function.py +++ b/examples/custom_wait_function.py @@ -1,4 +1,4 @@ -from locust import HttpLocust, TaskSet, task +from locust import HttpUser, TaskSet, task import random def index(l): @@ -16,9 +16,9 @@ class UserTasks(TaskSet): def page404(self): self.client.get("/does_not_exist") -class WebsiteUser(HttpLocust): +class WebsiteUser(HttpUser): """ - Locust user class that does requests to the locust web server running on localhost + User class that does requests to the locust web server running on localhost """ host = "http://127.0.0.1:8089" # Most task inter-arrival times approximate to exponential distributions @@ -38,9 +38,9 @@ def strictExp(min_wait,max_wait,mu=1): break return result -class StrictWebsiteUser(HttpLocust): +class StrictWebsiteUser(HttpUser): """ - Locust user class that makes exponential requests but strictly between two bounds. + User class that makes exponential requests but strictly between two bounds. """ host = "http://127.0.0.1:8089" wait_time = lambda self: strictExp(3, 7) diff --git a/examples/custom_xmlrpc_client/xmlrpc_locustfile.py b/examples/custom_xmlrpc_client/xmlrpc_locustfile.py index 3acca957b8..1af2f5a049 100644 --- a/examples/custom_xmlrpc_client/xmlrpc_locustfile.py +++ b/examples/custom_xmlrpc_client/xmlrpc_locustfile.py @@ -31,19 +31,19 @@ def wrapper(*args, **kwargs): return wrapper -class XmlRpcLocust(User): +class XmlRpcUser(User): """ - This is the abstract Locust class which should be subclassed. It provides an XML-RPC client + This is the abstract User class which should be subclassed. It provides an XML-RPC client that can be used to make XML-RPC requests that will be tracked in Locust's statistics. """ abstract = True def __init__(self, *args, **kwargs): - super(XmlRpcLocust, self).__init__(*args, **kwargs) + super(XmlRpcUser, self).__init__(*args, **kwargs) self.client = XmlRpcClient(self.host) self.client._locust_environment = self.environment -class ApiUser(XmlRpcLocust): +class ApiUser(XmlRpcUser): host = "http://127.0.0.1:8877/" wait_time = between(0.1, 1) diff --git a/examples/dynamice_user_credentials.py b/examples/dynamice_user_credentials.py index aed2052d14..2456acf7c8 100644 --- a/examples/dynamice_user_credentials.py +++ b/examples/dynamice_user_credentials.py @@ -1,6 +1,6 @@ # locustfile.py -from locust import HttpLocust, TaskSet, task, between +from locust import HttpUser, TaskSet, task, between USER_CREDENTIALS = [ ("user1", "password"), @@ -19,6 +19,6 @@ def some_task(self): # user should be logged in here (unless the USER_CREDENTIALS ran out) self.client.get("/protected/resource") -class User(HttpLocust): +class User(HttpUser): tasks = [UserBehaviour] wait_time = between(5, 60) diff --git a/examples/events.py b/examples/events.py index da7c37251f..8d98c84804 100644 --- a/examples/events.py +++ b/examples/events.py @@ -5,7 +5,7 @@ track the sum of the content-length header in all successful HTTP responses """ -from locust import HttpLocust, TaskSet, task, web, between +from locust import HttpUser, TaskSet, task, web, between from locust import events @@ -18,7 +18,7 @@ def index(l): def stats(l): l.client.get("/stats/requests") -class WebsiteUser(HttpLocust): +class WebsiteUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = between(2, 5) tasks = [MyTaskSet] diff --git a/examples/fast_http_locust.py b/examples/fast_http_locust.py index 8b737edeba..e075030463 100644 --- a/examples/fast_http_locust.py +++ b/examples/fast_http_locust.py @@ -1,5 +1,5 @@ -from locust import HttpLocust, TaskSet, task, between -from locust.contrib.fasthttp import FastHttpLocust +from locust import HttpUser, TaskSet, task, between +from locust.contrib.fasthttp import FastHttpUser class UserTasks(TaskSet): @@ -12,9 +12,9 @@ def stats(self): self.client.get("/stats/requests") -class WebsiteUser(FastHttpLocust): +class WebsiteUser(FastHttpUser): """ - Locust user class that does requests to the locust web server running on localhost, + User class that does requests to the locust web server running on localhost, using the fast HTTP client """ host = "http://127.0.0.1:8089" diff --git a/examples/multiple_hosts.py b/examples/multiple_hosts.py index 6123983471..346587370d 100644 --- a/examples/multiple_hosts.py +++ b/examples/multiple_hosts.py @@ -1,13 +1,13 @@ import os -from locust import HttpLocust, TaskSet, task, between +from locust import HttpUser, TaskSet, task, between from locust.clients import HttpSession -class MultipleHostsLocust(HttpLocust): +class MultipleHostsUser(HttpUser): abstract = True def __init__(self, *args, **kwargs): - super(MultipleHostsLocust, self).__init__(*args, **kwargs) + super(MultipleHostsUser, self).__init__(*args, **kwargs) self.api_client = HttpSession(base_url=os.environ["API_HOST"]) @@ -21,9 +21,9 @@ def index(self): def index_other_host(self): self.locust.api_client.get("/stats/requests") -class WebsiteUser(MultipleHostsLocust): +class WebsiteUser(MultipleHostsUser): """ - Locust user class that does requests to the locust web server running on localhost + User class that does requests to the locust web server running on localhost """ host = "http://127.0.0.1:8089" wait_time = between(2, 5) diff --git a/examples/nested_inline_tasksets.py b/examples/nested_inline_tasksets.py index 2e08bf63a7..847da288d3 100644 --- a/examples/nested_inline_tasksets.py +++ b/examples/nested_inline_tasksets.py @@ -1,7 +1,7 @@ -from locust import HttpLocust, TaskSet, task, between +from locust import HttpUser, TaskSet, task, between -class WebsiteUser(HttpLocust): +class WebsiteUser(HttpUser): """ Example of the ability of inline nested TaskSet classes """ diff --git a/examples/semaphore_wait.py b/examples/semaphore_wait.py index 0ac7f97dcd..7ff2e9cd9a 100644 --- a/examples/semaphore_wait.py +++ b/examples/semaphore_wait.py @@ -1,4 +1,4 @@ -from locust import HttpLocust, TaskSet, task, events, between +from locust import HttpUser, TaskSet, task, events, between from gevent.lock import Semaphore @@ -20,7 +20,7 @@ def on_start(self): def index(self): self.client.get("/") -class WebsiteUser(HttpLocust): +class WebsiteUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = between(2, 5) tasks = [UserTasks] diff --git a/examples/use_as_lib.py b/examples/use_as_lib.py index 7ab5a5ea60..04600fa3e2 100644 --- a/examples/use_as_lib.py +++ b/examples/use_as_lib.py @@ -1,5 +1,5 @@ import gevent -from locust import HttpLocust, task, between +from locust import HttpUser, task, between from locust.env import Environment from locust.stats import stats_printer from locust.log import setup_logging @@ -7,7 +7,7 @@ setup_logging("INFO", None) -class User(HttpLocust): +class User(HttpUser): wait_time = between(1, 3) host = "https://docs.locust.io" diff --git a/locust/__init__.py b/locust/__init__.py index 6b9950e87b..0903736f28 100644 --- a/locust/__init__.py +++ b/locust/__init__.py @@ -1,4 +1,4 @@ -from .core import HttpLocust, User, TaskSet, task +from .core import HttpUser, User, TaskSet, task from .event import Events from .sequential_taskset import SequentialTaskSet from .wait_time import between, constant, constant_pacing diff --git a/locust/clients.py b/locust/clients.py index b6f569da14..84f23622a3 100644 --- a/locust/clients.py +++ b/locust/clients.py @@ -33,7 +33,7 @@ class HttpSession(requests.Session): the methods for making requests (get, post, delete, put, head, options, patch, request) can now take a *url* argument that's only the path part of the URL, in which case the host part of the URL will be prepended with the HttpSession.base_url which is normally inherited - from a Locust class' host property. + from a User class' host property. Each of the methods for making requests also takes two additional optional arguments which are Locust specific and doesn't exist in python-requests. These are: diff --git a/locust/contrib/fasthttp.py b/locust/contrib/fasthttp.py index 89b6a92e2f..0fff8f727a 100644 --- a/locust/contrib/fasthttp.py +++ b/locust/contrib/fasthttp.py @@ -47,14 +47,14 @@ def _construct_basic_auth_str(username, password): return 'Basic ' + b64encode(b':'.join((username, password))).strip().decode("ascii") -class FastHttpLocust(User): +class FastHttpUser(User): """ - FastHttpLocust uses a different HTTP client (geventhttpclient) compared to HttpLocust (python-requests). + FastHttpUser uses a different HTTP client (geventhttpclient) compared to HttpUser (python-requests). It's significantly faster, but not as capable. The behaviour of this user is defined by it's tasks. Tasks can be declared either directly on the class by using the :py:func:`@task decorator ` on the methods, or by setting - the :py:attr:`tasks attribute `. + the :py:attr:`tasks attribute `. This class creates a *client* attribute on instantiation which is an HTTP client with support for keeping a user session between requests. @@ -62,12 +62,12 @@ class by using the :py:func:`@task decorator ` on the methods, client = None """ - Instance of HttpSession that is created upon instantiation of Locust. + Instance of HttpSession that is created upon instantiation of User. The client support cookies, and therefore keeps the session between HTTP requests. """ - # Below are various UserAgent settings. Change these in your subclass to alter FastHttpLocust's behaviour. - # It needs to be done before FastHttpLocust is instantiated, changing them later will have no effect + # Below are various UserAgent settings. Change these in your subclass to alter FastHttpUser's behaviour. + # It needs to be done before FastHttpUser is instantiated, changing them later will have no effect network_timeout: float = 60.0 """Parameter passed to FastHttpSession""" @@ -90,7 +90,7 @@ class by using the :py:func:`@task decorator ` on the methods, def __init__(self, environment): super().__init__(environment) if self.host is None: - raise LocustError("You must specify the base host. Either in the host attribute in the Locust class, or on the command line using the --host option.") + raise LocustError("You must specify the base host. Either in the host attribute in the User class, or on the command line using the --host option.") if not re.match(r"^https?://[^/]+", self.host, re.I): raise LocustError("Invalid host (`%s`), must be a valid base URL. E.g. http://example.com" % self.host) diff --git a/locust/core.py b/locust/core.py index 96022db591..caaf64d88b 100644 --- a/locust/core.py +++ b/locust/core.py @@ -14,7 +14,7 @@ from .clients import HttpSession from .exception import (InterruptTaskSet, LocustError, RescheduleTask, - RescheduleTaskImmediately, StopLocust, MissingWaitTimeError) + RescheduleTaskImmediately, StopUser, MissingWaitTimeError) from .util import deprecation @@ -26,7 +26,7 @@ def task(weight=1): """ - Used as a convenience decorator to be able to declare tasks for a Locust or a TaskSet + Used as a convenience decorator to be able to declare tasks for a User or a TaskSet inline in the class. Example:: class ForumPage(TaskSet): @@ -61,16 +61,16 @@ def my_task() class NoClientWarningRaiser(object): """ The purpose of this class is to emit a sensible error message for old test scripts that - inherit from Locust, and expects there to be an HTTP client under the client attribute. + inherit from User, and expects there to be an HTTP client under the client attribute. """ def __getattr__(self, _): - raise LocustError("No client instantiated. Did you intend to inherit from HttpLocust?") + raise LocustError("No client instantiated. Did you intend to inherit from HttpUser?") def get_tasks_from_base_classes(bases, class_dict): """ - Function used by both TaskSetMeta and LocustMeta for collecting all declared tasks - on the TaskSet/Locust class and all its base classes + Function used by both TaskSetMeta and UserMeta for collecting all declared tasks + on the TaskSet/User class and all its base classes """ new_tasks = [] for base in bases: @@ -100,7 +100,7 @@ def get_tasks_from_base_classes(bases, class_dict): class TaskSetMeta(type): """ - Meta class for the main Locust class. It's used to allow Locust classes to specify task execution + Meta class for the main User class. It's used to allow User classes to specify task execution ratio using an {task:int} dict, or a [(task0,int), ..., (taskN,int)] list. """ @@ -111,12 +111,12 @@ def __new__(mcs, classname, bases, class_dict): class TaskSet(object, metaclass=TaskSetMeta): """ - Class defining a set of tasks that a Locust user will execute. + Class defining a set of tasks that a User will execute. When a TaskSet starts running, it will pick a task from the *tasks* attribute, execute it, and then sleep for the number of seconds returned by its *wait_time* function. If no wait_time method has been declared on the TaskSet, it'll call the - wait_time function on the Locust by default. It will then schedule another task + wait_time function on the User by default. It will then schedule another task for execution and so on. TaskSets can be nested, which means that a TaskSet's *tasks* attribute can contain @@ -130,7 +130,7 @@ class TaskSet(object, metaclass=TaskSetMeta): tasks = [] """ - Collection of python callables and/or TaskSet classes that the Locust user(s) will run. + Collection of python callables and/or TaskSet classes that the User(s) will run. If tasks is a list, the task to be performed will be picked randomly. @@ -146,33 +146,33 @@ class ForumPage(TaskSet): min_wait = None """ Deprecated: Use wait_time instead. - Minimum waiting time between the execution of locust tasks. Can be used to override - the min_wait defined in the root Locust class, which will be used if not set on the + Minimum waiting time between the execution of user tasks. Can be used to override + the min_wait defined in the root User class, which will be used if not set on the TaskSet. """ max_wait = None """ Deprecated: Use wait_time instead. - Maximum waiting time between the execution of locust tasks. Can be used to override - the max_wait defined in the root Locust class, which will be used if not set on the + Maximum waiting time between the execution of user tasks. Can be used to override + the max_wait defined in the root User class, which will be used if not set on the TaskSet. """ wait_function = None """ Deprecated: Use wait_time instead. - Function used to calculate waiting time between the execution of locust tasks in milliseconds. - Can be used to override the wait_function defined in the root Locust class, which will be used + Function used to calculate waiting time between the execution of user tasks in milliseconds. + Can be used to override the wait_function defined in the root User class, which will be used if not set on the TaskSet. """ locust = None - """Will refer to the root Locust class instance when the TaskSet has been instantiated""" + """Will refer to the root User class instance when the TaskSet has been instantiated""" parent = None """ - Will refer to the parent TaskSet, or Locust, class instance when the TaskSet has been + Will refer to the parent TaskSet, or User, class instance when the TaskSet has been instantiated. Useful for nested TaskSet classes. """ @@ -185,7 +185,7 @@ def __init__(self, parent): elif isinstance(parent, User): self.locust = parent else: - raise LocustError("TaskSet should be called with Locust instance or TaskSet instance as first argument") + raise LocustError("TaskSet should be called with User instance or TaskSet instance as first argument") self.parent = parent @@ -199,14 +199,14 @@ def __init__(self, parent): def on_start(self): """ - Called when a Locust user starts executing (enters) this TaskSet + Called when a User starts executing (enters) this TaskSet """ pass def on_stop(self): """ - Called when a Locust user stops executing this TaskSet. E.g. when TaskSet.interrupt() is called - or when the user is killed + Called when a User stops executing this TaskSet. E.g. when TaskSet.interrupt() is called + or when the User is killed """ pass @@ -242,7 +242,7 @@ def run(self, *args, **kwargs): raise RescheduleTaskImmediately(e.reschedule) from e else: raise RescheduleTask(e.reschedule) from e - except (StopLocust, GreenletExit): + except (StopUser, GreenletExit): self.on_stop() raise except Exception as e: @@ -271,9 +271,9 @@ def execute_task(self, task, *args, **kwargs): def schedule_task(self, task_callable, args=None, kwargs=None, first=False): """ - Add a task to the Locust's task execution queue. + Add a task to the User's task execution queue. - :param task_callable: Locust task to schedule. + :param task_callable: User task to schedule. :param args: Arguments that will be passed to the task callable. :param kwargs: Dict of keyword arguments that will be passed to the task callable. :param first: Optional keyword argument. If True, the task will be put first in the queue. @@ -311,7 +311,7 @@ class Tasks(TaskSet): def wait(self): """ - Make the running locust user sleep for a duration defined by the Locust.wait_time + Make the running user sleep for a duration defined by the Locust.wait_time function (or TaskSet.wait_time function if it's been defined). The user can also be killed gracefully while it's sleeping, so calling this @@ -330,17 +330,17 @@ def _sleep(self, seconds): def _check_stop_condition(self): if self.locust._state == LOCUST_STATE_STOPPING: - raise StopLocust() + raise StopUser() def interrupt(self, reschedule=True): """ Interrupt the TaskSet and hand over execution control back to the parent TaskSet. - If *reschedule* is True (default), the parent Locust will immediately re-schedule, + If *reschedule* is True (default), the parent User will immediately re-schedule, and execute, a new task. This method should not be called by the root TaskSet (the one that is immediately, - attached to the Locust class's *task_set* attribute), but rather in nested TaskSet + attached to the User class's *task_set* attribute), but rather in nested TaskSet classes further down the hierarchy. """ raise InterruptTaskSet(reschedule) @@ -348,16 +348,16 @@ def interrupt(self, reschedule=True): @property def client(self): """ - Reference to the :py:attr:`client ` attribute of the root - Locust instance. + Reference to the :py:attr:`client ` attribute of the root + User instance. """ return self.locust.client class DefaultTaskSet(TaskSet): """ - Default root TaskSet that executes tasks in Locust.tasks. - It executes tasks declared directly on the Locust with the Locust user instance as the task argument. + Default root TaskSet that executes tasks in User.tasks. + It executes tasks declared directly on the Locust with the user instance as the task argument. """ def get_next_task(self): return random.choice(self.locust.tasks) @@ -373,7 +373,7 @@ def execute_task(self, task, *args, **kwargs): class UserMeta(type): """ - Meta class for the main Locust class. It's used to allow Locust classes to specify task execution + Meta class for the main User class. It's used to allow User classes to specify task execution ratio using an {task:int} dict, or a [(task0,int), ..., (taskN,int)] list. """ def __new__(mcs, classname, bases, class_dict): @@ -397,11 +397,11 @@ class User(object, metaclass=UserMeta): The behaviour of this user is defined by its tasks. Tasks can be declared either directly on the class by using the :py:func:`@task decorator ` on methods, or by setting - the :py:attr:`tasks attribute `. + the :py:attr:`tasks attribute `. This class should usually be subclassed by a class that defines some kind of client. For example when load testing an HTTP system, you probably want to use the - :py:class:`HttpLocust ` class. + :py:class:`HttpUser ` class. """ host = None @@ -420,8 +420,8 @@ class by using the :py:func:`@task decorator ` on methods, or Example:: - from locust import Locust, between - class User(Locust): + from locust import User, between + class MyUser(User): wait_time = between(3, 25) """ @@ -466,13 +466,13 @@ def __init__(self, environment): def on_start(self): """ - Called when a Locust user starts running. + Called when a User starts running. """ pass def on_stop(self): """ - Called when a Locust user stops running (is killed) + Called when a User stops running (is killed) """ pass @@ -484,13 +484,13 @@ def run(self): self.on_start() self._taskset_instance.run() - except (GreenletExit, StopLocust) as e: + except (GreenletExit, StopUser) as e: # run the on_stop method, if it has one self.on_stop() def wait(self): """ - Make the running locust user sleep for a duration defined by the Locust.wait_time + Make the running user sleep for a duration defined by the User.wait_time function. The user can also be killed gracefully while it's sleeping, so calling this @@ -502,31 +502,31 @@ def wait(self): def start(self, gevent_group): """ - Start a greenlet that runs this locust instance. + Start a greenlet that runs this User instance. :param gevent_group: Group instance where the greenlet will be spawned. :type gevent_group: gevent.pool.Group :returns: The spawned greenlet. """ - def run_locust(user): + def run_user(user): """ - Main function for Locust user greenlet. It's important that this function takes the locust + Main function for User greenlet. It's important that this function takes the user instance as an argument, since we use greenlet_instance.args[0] to retrieve a reference to the - locust instance. + User instance. """ user.run() - self._greenlet = gevent_group.spawn(run_locust, self) + self._greenlet = gevent_group.spawn(run_user, self) return self._greenlet def stop(self, gevent_group, force=False): """ - Stop the locust user greenlet that exists in the gevent_group. - This method is not meant to be called from within the Locust's greenlet. + Stop the hyhyj1u1 user greenlet that exists in the gevent_group. + This method is not meant to be called from within the User's greenlet. :param gevent_group: Group instance where the greenlet will be spawned. :type gevent_group: gevent.pool.Group :param force: If False (the default) the stopping is done gracefully by setting the state to LOCUST_STATE_STOPPING - which will make the Locust instance stop once any currently running task is complete and on_stop + which will make the User instance stop once any currently running task is complete and on_stop methods are called. If force is True the greenlet will be killed immediately. :returns: True if the greenlet was killed immediately, otherwise False """ @@ -538,13 +538,13 @@ def stop(self, gevent_group, force=False): return False -class HttpLocust(User): +class HttpUser(User): """ Represents an HTTP "user" which is to be hatched and attack the system that is to be load tested. The behaviour of this user is defined by its tasks. Tasks can be declared either directly on the class by using the :py:func:`@task decorator ` on methods, or by setting - the :py:attr:`tasks attribute `. + the :py:attr:`tasks attribute `. This class creates a *client* attribute on instantiation which is an HTTP client with support for keeping a user session between requests. @@ -560,9 +560,9 @@ class by using the :py:func:`@task decorator ` on methods, or """ def __init__(self, *args, **kwargs): - super(HttpLocust, self).__init__(*args, **kwargs) + super(HttpUser, self).__init__(*args, **kwargs) if self.host is None: - raise LocustError("You must specify the base host. Either in the host attribute in the Locust class, or on the command line using the --host option.") + raise LocustError("You must specify the base host. Either in the host attribute in the User class, or on the command line using the --host option.") session = HttpSession( base_url=self.host, diff --git a/locust/env.py b/locust/env.py index 7259e66ad5..b34c4dabf0 100644 --- a/locust/env.py +++ b/locust/env.py @@ -19,7 +19,7 @@ class Environment: """Reference to RequestStats instance""" runner = None - """Reference to the :class:`LocustRunner ` instance""" + """Reference to the :class:`Runner ` instance""" web_ui = None """Reference to the WebUI instance""" @@ -96,7 +96,7 @@ def create_master_runner(self, master_bind_host="*", master_bind_port=5557): def create_worker_runner(self, master_host, master_port): """ - Create a :class:`WorkerLocustRunner ` instance for this Environment + Create a :class:`WorkerRunner ` instance for this Environment :param master_host: Host/IP of a running master node :param master_port: Port on master node to connect to diff --git a/locust/event.py b/locust/event.py index aca9b3536f..97346c3f68 100644 --- a/locust/event.py +++ b/locust/event.py @@ -63,11 +63,11 @@ class Events: locust_error = EventHook """ - Fired when an exception occurs inside the execution of a Locust class. + Fired when an exception occurs inside the execution of a User class. Event arguments: - :param locust_instance: Locust class instance where the exception occurred + :param locust_instance: User class instance where the exception occurred :param exception: Exception that was thrown :param tb: Traceback object (from sys.exc_info()[2]) """ @@ -137,7 +137,7 @@ class Events: test_start = EventHook """ Fired when a new load test is started. It's not fired again if the number of - Locust users change during a test. When running locust distributed the event is only fired + users change during a test. When running locust distributed the event is only fired on the master node and not on each worker node. """ diff --git a/locust/exception.py b/locust/exception.py index 79c3704f7f..3e619d081c 100644 --- a/locust/exception.py +++ b/locust/exception.py @@ -12,7 +12,7 @@ class MissingWaitTimeError(LocustError): class InterruptTaskSet(Exception): """ - Exception that will interrupt a Locust when thrown inside a task + Exception that will interrupt a User when thrown inside a task """ def __init__(self, reschedule=True): @@ -22,7 +22,7 @@ def __init__(self, reschedule=True): """ self.reschedule = reschedule -class StopLocust(Exception): +class StopUser(Exception): pass class RescheduleTask(Exception): @@ -35,7 +35,7 @@ class RescheduleTask(Exception): class RescheduleTaskImmediately(Exception): """ - When raised in a Locust task, another locust task will be rescheduled immediately + When raised in a User task, another User task will be rescheduled immediately """ class RPCError(Exception): diff --git a/locust/main.py b/locust/main.py index 6259162a04..cb9f489f78 100644 --- a/locust/main.py +++ b/locust/main.py @@ -13,7 +13,7 @@ from . import log from .argument_parser import parse_locustfile_option, parse_options -from .core import HttpLocust, User +from .core import HttpUser, User from .env import Environment from .inspectlocust import get_task_ratio_dict, print_task_ratio from .log import setup_logging, greenlet_exception_logger @@ -22,13 +22,13 @@ from .util.timespan import parse_timespan from .exception import AuthCredentialsError -_internals = [User, HttpLocust] +_internals = [User, HttpUser] version = locust.__version__ def is_locust(item): """ - Check if a variable is a runnable (non-abstract) Locust class + Check if a variable is a runnable (non-abstract) User class """ return bool( inspect.isclass(item) diff --git a/locust/runners.py b/locust/runners.py index f10f40b358..f7a60862e3 100644 --- a/locust/runners.py +++ b/locust/runners.py @@ -126,7 +126,7 @@ def weight_locusts(self, amount): residuals[locust] = amount * percent - round(amount * percent) if len(bucket) < amount: # We got too few locust classes in the bucket, so we need to create a few extra locusts, - # and we do this by iterating over each of the Locust classes - starting with the one + # and we do this by iterating over each of the User classes - starting with the one # where the residual from the rounding was the largest - and creating one of each until # we get the correct amount for locust in [l for l, r in sorted(residuals.items(), key=lambda x:x[1], reverse=True)][:amount-len(bucket)]: @@ -197,7 +197,7 @@ def kill_locust_instances(self, users): dying = Group() for user in users: if not user.stop(self.locusts, force=False): - # Locust.stop() returns False if the greenlet was not killed, so we'll need + # User.stop() returns False if the greenlet was not killed, so we'll need # to add it's greenlet to our dying Group so we can wait for it to finish it's task dying.add(user._greenlet) if not dying.join(timeout=self.environment.stop_timeout): @@ -359,9 +359,9 @@ class MasterRunner(DistributedRunner): Runner used to run distributed load tests across multiple processes and/or machines. MasterRunner doesn't spawn any locust user greenlets itself. Instead it expects - :class:`WorkerLocustRunners ` to connect to it, which it will then direct + :class:`WorkerRunners ` to connect to it, which it will then direct to start and stop locust user greenlets. Stats sent back from the - :class:`WorkerLocustRunners ` will aggregated. + :class:`WorkerRunners ` will aggregated. """ def __init__(self, environment, master_bind_host, master_bind_port): """ diff --git a/locust/sequential_taskset.py b/locust/sequential_taskset.py index b78957b60f..6bdca60ee7 100644 --- a/locust/sequential_taskset.py +++ b/locust/sequential_taskset.py @@ -35,7 +35,7 @@ def __new__(mcs, classname, bases, class_dict): class SequentialTaskSet(TaskSet, metaclass=SequentialTaskSetMeta): """ - Class defining a sequence of tasks that a Locust user will execute. + Class defining a sequence of tasks that a User will execute. Works like TaskSet, but task weight is ignored, and all tasks are executed in order. Tasks can either be specified by setting the *tasks* attribute to a list of tasks, or by declaring tasks diff --git a/locust/stats.py b/locust/stats.py index 8ba010ab62..9cc8febb6c 100644 --- a/locust/stats.py +++ b/locust/stats.py @@ -6,7 +6,7 @@ import gevent -from .exception import StopLocust +from .exception import StopUser import logging console_logger = logging.getLogger("locust.stats_logger") diff --git a/locust/test/mock_locustfile.py b/locust/test/mock_locustfile.py index fb4dc3f1e0..3c7becc95b 100644 --- a/locust/test/mock_locustfile.py +++ b/locust/test/mock_locustfile.py @@ -8,7 +8,7 @@ MOCK_LOUCSTFILE_CONTENT = ''' """This is a mock locust file for unit testing""" -from locust import HttpLocust, TaskSet, task, between +from locust import HttpUser, TaskSet, task, between def index(l): @@ -23,13 +23,13 @@ class UserTasks(TaskSet): tasks = [index, stats] -class LocustSubclass(HttpLocust): +class UserSubclass(HttpUser): host = "http://127.0.0.1:8089" wait_time = between(2, 5) tasks = [UserTasks] -class NotLocustSubclass(): +class NotUserSubclass(): host = "http://localhost:8000" ''' diff --git a/locust/test/test_fasthttp.py b/locust/test/test_fasthttp.py index 347ea91ace..6ec19f074c 100644 --- a/locust/test/test_fasthttp.py +++ b/locust/test/test_fasthttp.py @@ -2,7 +2,7 @@ import gevent from locust.core import task, TaskSet -from locust.contrib.fasthttp import FastHttpSession, FastHttpLocust +from locust.contrib.fasthttp import FastHttpSession, FastHttpUser from locust.exception import CatchResponseError, InterruptTaskSet, ResponseError from locust.main import is_locust from .testcases import WebserverTestCase @@ -174,139 +174,139 @@ def test_catch_response_default_fail(self): class TestRequestStatsWithWebserver(WebserverTestCase): def test_request_stats_content_length(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) locust.client.get("/ultra_fast") self.assertEqual(self.runner.stats.get("/ultra_fast", "GET").avg_content_length, len("This is an ultra fast response")) locust.client.get("/ultra_fast") self.assertEqual(self.runner.stats.get("/ultra_fast", "GET").avg_content_length, len("This is an ultra fast response")) def test_request_stats_no_content_length(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - l = MyLocust(self.environment) + l = MyUser(self.environment) path = "/no_content_length" r = l.client.get(path) self.assertEqual(self.runner.stats.get(path, "GET").avg_content_length, len("This response does not have content-length in the header")) def test_request_stats_no_content_length_streaming(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - l = MyLocust(self.environment) + l = MyUser(self.environment) path = "/no_content_length" r = l.client.get(path, stream=True) self.assertEqual(0, self.runner.stats.get(path, "GET").avg_content_length) def test_request_stats_named_endpoint(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) locust.client.get("/ultra_fast", name="my_custom_name") self.assertEqual(1, self.runner.stats.get("my_custom_name", "GET").num_requests) def test_request_stats_query_variables(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) locust.client.get("/ultra_fast?query=1") self.assertEqual(1, self.runner.stats.get("/ultra_fast?query=1", "GET").num_requests) def test_request_stats_put(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) locust.client.put("/put") self.assertEqual(1, self.runner.stats.get("/put", "PUT").num_requests) def test_request_connection_error(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://localhost:1" - locust = MyLocust(self.environment) + locust = MyUser(self.environment) response = locust.client.get("/", timeout=0.1) self.assertEqual(response.status_code, 0) self.assertEqual(1, self.runner.stats.get("/", "GET").num_failures) self.assertEqual(1, self.runner.stats.get("/", "GET").num_requests) -class TestFastHttpLocustClass(WebserverTestCase): +class TestFastHttpUserClass(WebserverTestCase): def test_is_abstract(self): - self.assertTrue(FastHttpLocust.abstract) - self.assertFalse(is_locust(FastHttpLocust)) + self.assertTrue(FastHttpUser.abstract) + self.assertFalse(is_locust(FastHttpUser)) def test_get_request(self): self.response = "" def t1(l): self.response = l.client.get("/ultra_fast") - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): tasks = [t1] host = "http://127.0.0.1:%i" % self.port - my_locust = MyLocust(self.environment) + my_locust = MyUser(self.environment) t1(my_locust) self.assertEqual(self.response.text, "This is an ultra fast response") def test_client_request_headers(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("hello", locust.client.get("/request_header_test", headers={"X-Header-Test":"hello"}).text) def test_client_get(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("GET", locust.client.get("/request_method").text) def test_client_get_absolute_url(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("GET", locust.client.get("http://127.0.0.1:%i/request_method" % self.port).text) def test_client_post(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("POST", locust.client.post("/request_method", {"arg":"hello world"}).text) self.assertEqual("hello world", locust.client.post("/post", {"arg":"hello world"}).text) def test_client_put(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("PUT", locust.client.put("/request_method", {"arg":"hello world"}).text) self.assertEqual("hello world", locust.client.put("/put", {"arg":"hello world"}).text) def test_client_delete(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("DELETE", locust.client.delete("/request_method").text) self.assertEqual(200, locust.client.delete("/request_method").status_code) def test_client_head(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual(200, locust.client.head("/request_method").status_code) def test_log_request_name_argument(self): self.response = "" - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): tasks = [] host = "http://127.0.0.1:%i" % self.port @@ -314,17 +314,17 @@ class MyLocust(FastHttpLocust): def t1(l): self.response = l.client.get("/ultra_fast", name="new name!") - my_locust = MyLocust(self.environment) + my_locust = MyUser(self.environment) my_locust.t1() self.assertEqual(1, self.runner.stats.get("new name!", "GET").num_requests) self.assertEqual(0, self.runner.stats.get("/ultra_fast", "GET").num_requests) def test_redirect_url_original_path_as_name(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - l = MyLocust(self.environment) + l = MyUser(self.environment) l.client.get("/redirect") self.assertEqual(1, len(self.runner.stats.entries)) @@ -332,13 +332,13 @@ class MyLocust(FastHttpLocust): self.assertEqual(0, self.runner.stats.get("/ultra_fast", "GET").num_requests) def test_network_timeout_setting(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): network_timeout = 0.5 host = "http://127.0.0.1:%i" % self.port - l = MyLocust(self.environment) + l = MyUser(self.environment) - timeout = gevent.Timeout(seconds=0.6, exception=AssertionError("Request took longer than 0.6 even though FastHttpLocust.network_timeout was set to 0.5")) + timeout = gevent.Timeout(seconds=0.6, exception=AssertionError("Request took longer than 0.6 even though FastHttpUser.network_timeout was set to 0.5")) timeout.start() r = l.client.get("/redirect?url=/redirect&delay=5.0") timeout.cancel() @@ -347,11 +347,11 @@ class MyLocust(FastHttpLocust): self.assertEqual(1, self.runner.stats.get("/redirect?url=/redirect&delay=5.0", "GET").num_failures) def test_max_redirect_setting(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): max_redirects = 1 # max_redirects and max_retries are funny names, because they are actually max attempts host = "http://127.0.0.1:%i" % self.port - l = MyLocust(self.environment) + l = MyUser(self.environment) l.client.get("/redirect") self.assertEqual(1, self.runner.stats.get("/redirect", "GET").num_failures) @@ -364,18 +364,18 @@ def test_slow_redirect(self): self.assertGreater(stats.avg_response_time, 500) def test_client_basic_auth(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - class MyAuthorizedLocust(FastHttpLocust): + class MyAuthorizedUser(FastHttpUser): host = "http://locust:menace@127.0.0.1:%i" % self.port - class MyUnauthorizedLocust(FastHttpLocust): + class MyUnauthorizedUser(FastHttpUser): host = "http://locust:wrong@127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) - unauthorized = MyUnauthorizedLocust(self.environment) - authorized = MyAuthorizedLocust(self.environment) + locust = MyUser(self.environment) + unauthorized = MyUnauthorizedUser(self.environment) + authorized = MyAuthorizedUser(self.environment) response = authorized.client.get("/basic_auth") self.assertEqual(200, response.status_code) self.assertEqual("Authorized", response.text) @@ -387,10 +387,10 @@ class TestFastHttpCatchResponse(WebserverTestCase): def setUp(self): super(TestFastHttpCatchResponse, self).setUp() - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port - self.locust = MyLocust(self.environment) + self.locust = MyUser(self.environment) self.num_failures = 0 self.num_success = 0 @@ -453,20 +453,20 @@ class MyTaskSet(TaskSet): def interrupted_task(self): with self.client.get("/ultra_fast", catch_response=True) as r: raise InterruptTaskSet() - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:%i" % self.port tasks = [MyTaskSet] - l = MyLocust(self.environment) + l = MyUser(self.environment) ts = MyTaskSet(l) self.assertRaises(InterruptTaskSet, lambda: ts.interrupted_task()) self.assertEqual(0, self.num_failures) self.assertEqual(0, self.num_success) def test_catch_response_connection_error_success(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:1" - l = MyLocust(self.environment) + l = MyUser(self.environment) with l.client.get("/", catch_response=True) as r: self.assertEqual(r.status_code, 0) self.assertEqual(None, r.content) @@ -475,9 +475,9 @@ class MyLocust(FastHttpLocust): self.assertEqual(0, self.num_failures) def test_catch_response_connection_error_fail(self): - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): host = "http://127.0.0.1:1" - l = MyLocust(self.environment) + l = MyUser(self.environment) with l.client.get("/", catch_response=True) as r: self.assertEqual(r.status_code, 0) self.assertEqual(None, r.content) diff --git a/locust/test/test_locust_class.py b/locust/test/test_locust_class.py index acd663ac1f..eb001d4a6a 100644 --- a/locust/test/test_locust_class.py +++ b/locust/test/test_locust_class.py @@ -3,10 +3,10 @@ from gevent.pool import Group from locust.exception import InterruptTaskSet, ResponseError -from locust import HttpLocust, User, TaskSet, task, between, constant +from locust import HttpUser, User, TaskSet, task, between, constant from locust.env import Environment from locust.exception import (CatchResponseError, LocustError, RescheduleTask, - RescheduleTaskImmediately, StopLocust) + RescheduleTaskImmediately, StopUser) from .testcases import LocustTestCase, WebserverTestCase @@ -75,16 +75,16 @@ def t4(self): self.assertEqual(t4_count, 13) def test_tasks_on_locust(self): - class MyLocust(User): + class MyUser(User): @task(2) def t1(self): pass @task(3) def t2(self): pass - l = MyLocust(self.environment) - self.assertEqual(2, len([t for t in l.tasks if t.__name__ == MyLocust.t1.__name__])) - self.assertEqual(3, len([t for t in l.tasks if t.__name__ == MyLocust.t2.__name__])) + l = MyUser(self.environment) + self.assertEqual(2, len([t for t in l.tasks if t.__name__ == MyUser.t1.__name__])) + self.assertEqual(3, len([t for t in l.tasks if t.__name__ == MyUser.t2.__name__])) def test_tasks_on_abstract_locust(self): class AbstractUser(User): @@ -92,13 +92,13 @@ class AbstractUser(User): @task(2) def t1(self): pass - class MyLocust(AbstractUser): + class MyUser(AbstractUser): @task(3) def t2(self): pass - l = MyLocust(self.environment) - self.assertEqual(2, len([t for t in l.tasks if t.__name__ == MyLocust.t1.__name__])) - self.assertEqual(3, len([t for t in l.tasks if t.__name__ == MyLocust.t2.__name__])) + l = MyUser(self.environment) + self.assertEqual(2, len([t for t in l.tasks if t.__name__ == MyUser.t1.__name__])) + self.assertEqual(3, len([t for t in l.tasks if t.__name__ == MyUser.t2.__name__])) def test_taskset_on_abstract_locust(self): v = [0] @@ -109,17 +109,17 @@ class task_set(TaskSet): @task def t1(self): v[0] = 1 - raise StopLocust() - class MyLocust(AbstractUser): + raise StopUser() + class MyUser(AbstractUser): pass - l = MyLocust(self.environment) - # check that the Locust can be run + l = MyUser(self.environment) + # check that the User can be run l.run() self.assertEqual(1, v[0]) def test_task_decorator_on_taskset(self): state = [0] - class MyLocust(User): + class MyUser(User): wait_time = constant(0) @task def t1(self): @@ -129,10 +129,10 @@ class MyTaskSet(TaskSet): @task def subtask(self): state[0] = 1 - raise StopLocust() + raise StopUser() - self.assertEqual([MyLocust.t1, MyLocust.MyTaskSet], MyLocust.tasks) - MyLocust(self.environment).run() + self.assertEqual([MyUser.t1, MyUser.MyTaskSet], MyUser.tasks) + MyUser(self.environment).run() self.assertEqual(1, state[0]) def test_on_start(self): @@ -387,19 +387,19 @@ def on_start(self): self.interrupt(reschedule=True) else: self.interrupt(reschedule=False) - - class MyLocust(User): + + class MyUser(User): host = "" tasks = [SubTaskSet] - l = MyLocust(Environment()) + l = MyUser(Environment()) task_set = SubTaskSet(l) self.assertRaises(RescheduleTaskImmediately, lambda: task_set.run(reschedule=True)) self.assertRaises(RescheduleTask, lambda: task_set.run(reschedule=False)) def test_parent_attribute(self): - from locust.exception import StopLocust + from locust.exception import StopUser parents = {} class SubTaskSet(TaskSet): @@ -412,15 +412,15 @@ def on_start(self): parents["subsub"] = self.parent @task def stop(self): - raise StopLocust() + raise StopUser() class RootTaskSet(TaskSet): tasks = [SubTaskSet] - class MyLocust(User): + class MyUser(User): host = "" tasks = [RootTaskSet] - l = MyLocust(Environment()) + l = MyUser(Environment()) l.run() self.assertTrue(isinstance(parents["sub"], RootTaskSet)) self.assertTrue(isinstance(parents["subsub"], SubTaskSet)) @@ -436,14 +436,14 @@ def t(self): log.append(0) self.wait() log.append(1) - raise StopLocust() + raise StopUser() l = TestUser(self.environment) l.run() self.assertEqual([0,1], log) def test_locust_on_start(self): - class MyLocust(User): + class MyUser(User): t1_executed = False t2_executed = False @@ -456,15 +456,15 @@ def t1(self): @task def t2(self): self.t2_executed = True - raise StopLocust() + raise StopUser() - l = MyLocust(self.environment) + l = MyUser(self.environment) l.run() self.assertTrue(l.t1_executed) self.assertTrue(l.t2_executed) def test_locust_on_stop(self): - class MyLocust(User): + class MyUser(User): on_stop_executed = False t2_executed = True @@ -474,9 +474,9 @@ def on_stop(self): @task def t2(self): self.t2_executed = True - raise StopLocust() + raise StopUser() - l = MyLocust(self.environment) + l = MyUser(self.environment) l.run() self.assertTrue(l.on_stop_executed) self.assertTrue(l.t2_executed) @@ -489,7 +489,7 @@ class TestUser(User): def t(self): self.test_state = 1 sleep(0.1) - raise StopLocust() + raise StopUser() group = Group() user = TestUser(self.environment) greenlet = user.start(group) @@ -518,7 +518,7 @@ def t(self): sleep(0) self.assertEqual(1, user.test_state) - # stop Locust instance gracefully + # stop User gracefully user.stop(group, force=False) sleep(0) # make sure instance is not killed right away @@ -546,7 +546,7 @@ def t(self): self.assertIn(greenlet, group) self.assertEqual(1, user.test_state) - # stop Locust instance gracefully + # stop User gracefully user.stop(group, force=True) sleep(0) # make sure instance is killed right away, and that the task did NOT get to finish @@ -559,79 +559,79 @@ def test_get_request(self): self.response = "" def t1(l): self.response = l.client.get("/ultra_fast") - class MyLocust(HttpLocust): + class MyUser(HttpUser): tasks = [t1] host = "http://127.0.0.1:%i" % self.port - my_locust = MyLocust(self.environment) + my_locust = MyUser(self.environment) t1(my_locust) self.assertEqual(self.response.text, "This is an ultra fast response") def test_client_request_headers(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("hello", locust.client.get("/request_header_test", headers={"X-Header-Test":"hello"}).text) def test_client_get(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("GET", locust.client.get("/request_method").text) def test_client_get_absolute_url(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("GET", locust.client.get("http://127.0.0.1:%i/request_method" % self.port).text) def test_client_post(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("POST", locust.client.post("/request_method", {"arg":"hello world"}).text) self.assertEqual("hello world", locust.client.post("/post", {"arg":"hello world"}).text) def test_client_put(self): - class MyLocust(HttpLocust): + class MyUserHttpUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUserHttpUser(self.environment) self.assertEqual("PUT", locust.client.put("/request_method", {"arg":"hello world"}).text) self.assertEqual("hello world", locust.client.put("/put", {"arg":"hello world"}).text) def test_client_delete(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual("DELETE", locust.client.delete("/request_method").text) self.assertEqual(200, locust.client.delete("/request_method").status_code) def test_client_head(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) + locust = MyUser(self.environment) self.assertEqual(200, locust.client.head("/request_method").status_code) def test_client_basic_auth(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - class MyAuthorizedLocust(HttpLocust): + class MyAuthorizedUser(HttpUser): host = "http://locust:menace@127.0.0.1:%i" % self.port - class MyUnauthorizedLocust(HttpLocust): + class MyUnauthorizedUser(HttpUser): host = "http://locust:wrong@127.0.0.1:%i" % self.port - locust = MyLocust(self.environment) - unauthorized = MyUnauthorizedLocust(self.environment) - authorized = MyAuthorizedLocust(self.environment) + locust = MyUser(self.environment) + unauthorized = MyUnauthorizedUser(self.environment) + authorized = MyAuthorizedUser(self.environment) response = authorized.client.get("/basic_auth") self.assertEqual(200, response.status_code) self.assertEqual("Authorized", response.text) @@ -639,7 +639,7 @@ class MyUnauthorizedLocust(HttpLocust): self.assertEqual(401, unauthorized.client.get("/basic_auth").status_code) def test_log_request_name_argument(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): tasks = [] host = "http://127.0.0.1:%i" % self.port @@ -647,7 +647,7 @@ class MyLocust(HttpLocust): def t1(l): l.client.get("/ultra_fast", name="new name!") - my_locust = MyLocust(self.environment) + my_locust = MyUser(self.environment) my_locust.t1() self.assertEqual(1, self.runner.stats.get("new name!", "GET").num_requests) @@ -660,20 +660,20 @@ def t1(self): self.client.get("/") self.interrupt() - class MyLocust(User): + class MyUser(User): host = "http://127.0.0.1:%i" % self.port tasks = [MyTaskSet] - my_locust = MyLocust(self.environment) + my_locust = MyUser(self.environment) self.assertRaises(LocustError, lambda: my_locust.client.get("/")) my_taskset = MyTaskSet(my_locust) self.assertRaises(LocustError, lambda: my_taskset.client.get("/")) def test_redirect_url_original_path_as_name(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - l = MyLocust(self.environment) + l = MyUser(self.environment) l.client.get("/redirect") self.assertEqual(1, len(self.runner.stats.entries)) @@ -685,10 +685,10 @@ class TestCatchResponse(WebserverTestCase): def setUp(self): super(TestCatchResponse, self).setUp() - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - self.locust = MyLocust(self.environment) + self.locust = MyUser(self.environment) self.num_failures = 0 self.num_success = 0 @@ -750,20 +750,20 @@ class MyTaskSet(TaskSet): def interrupted_task(self): with self.client.get("/ultra_fast", catch_response=True) as r: raise InterruptTaskSet() - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port tasks = [MyTaskSet] - l = MyLocust(self.environment) + l = MyUser(self.environment) ts = MyTaskSet(l) self.assertRaises(InterruptTaskSet, lambda: ts.interrupted_task()) self.assertEqual(0, self.num_failures) self.assertEqual(0, self.num_success) def test_catch_response_connection_error_success(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:1" - l = MyLocust(self.environment) + l = MyUser(self.environment) with l.client.get("/", catch_response=True) as r: self.assertEqual(r.status_code, 0) self.assertEqual(None, r.content) @@ -772,9 +772,9 @@ class MyLocust(HttpLocust): self.assertEqual(0, self.num_failures) def test_catch_response_connection_error_fail(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:1" - l = MyLocust(self.environment) + l = MyUser(self.environment) with l.client.get("/", catch_response=True) as r: self.assertEqual(r.status_code, 0) self.assertEqual(None, r.content) diff --git a/locust/test/test_log.py b/locust/test/test_log.py index 61e5dd5d16..e2d24cf6ce 100644 --- a/locust/test/test_log.py +++ b/locust/test/test_log.py @@ -40,7 +40,7 @@ def test_logging_output(self): custom_logger = logging.getLogger("custom_logger") - class MyLocust(User): + class MyUser(User): wait_time = constant(2) @task def my_task(self): @@ -88,7 +88,7 @@ def test_skip_logging(self): with temporary_file(textwrap.dedent(""" from locust import User, task, constant - class MyLocust(User): + class MyUser(User): wait_time = constant(2) @task def my_task(self): @@ -110,7 +110,7 @@ def test_log_to_file(self): import logging from locust import User, task, constant - class MyLocust(User): + class MyUser(User): wait_time = constant(2) @task def my_task(self): diff --git a/locust/test/test_main.py b/locust/test/test_main.py index 8beb5d2a67..c56fe1f32d 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -10,7 +10,7 @@ from locust import main from locust.argument_parser import parse_options from locust.main import create_environment -from locust.core import HttpLocust, User, TaskSet +from locust.core import HttpUser, User, TaskSet from .mock_locustfile import mock_locustfile from .testcases import LocustTestCase from .util import temporary_file @@ -19,20 +19,20 @@ class TestLoadLocustfile(LocustTestCase): def test_is_locust(self): self.assertFalse(main.is_locust(User)) - self.assertFalse(main.is_locust(HttpLocust)) + self.assertFalse(main.is_locust(HttpUser)) self.assertFalse(main.is_locust({})) self.assertFalse(main.is_locust([])) class MyTaskSet(TaskSet): pass - class MyHttpLocust(HttpLocust): + class MyHttpUser(HttpUser): tasks = [MyTaskSet] class MyLocust(User): tasks = [MyTaskSet] - self.assertTrue(main.is_locust(MyHttpLocust)) + self.assertTrue(main.is_locust(MyHttpUser)) self.assertTrue(main.is_locust(MyLocust)) class ThriftLocust(User): @@ -43,8 +43,8 @@ class ThriftLocust(User): def test_load_locust_file_from_absolute_path(self): with mock_locustfile() as mocked: docstring, locusts = main.load_locustfile(mocked.file_path) - self.assertIn('LocustSubclass', locusts) - self.assertNotIn('NotLocustSubclass', locusts) + self.assertIn('UserSubclass', locusts) + self.assertNotIn('NotUserSubclass', locusts) def test_load_locust_file_from_relative_path(self): with mock_locustfile() as mocked: @@ -58,8 +58,8 @@ def test_return_docstring_and_locusts(self): with mock_locustfile() as mocked: docstring, locusts = main.load_locustfile(mocked.file_path) self.assertEqual("This is a mock locust file for unit testing", docstring) - self.assertIn('LocustSubclass', locusts) - self.assertNotIn('NotLocustSubclass', locusts) + self.assertIn('UserSubclass', locusts) + self.assertNotIn('NotUserSubclass', locusts) def test_create_environment(self): options = parse_options(args=[ @@ -91,7 +91,7 @@ def test_help_arg(self): def test_webserver(self): with temporary_file(content=textwrap.dedent(""" - from locust import Locust, task, constant, events + from locust import User, task, constant, events class TestUser(User): wait_time = constant(3) @task diff --git a/locust/test/test_parser.py b/locust/test/test_parser.py index 81bb821207..a7309ff631 100644 --- a/locust/test/test_parser.py +++ b/locust/test/test_parser.py @@ -63,7 +63,7 @@ def test_parse_options(self): "-t", "5m", "--reset-stats", "--stop-timeout", "5", - "MyLocustClass", + "MyUserClass", ]) self.assertEqual("locustfile.py", options.locustfile) self.assertEqual(100, options.num_users) @@ -71,7 +71,7 @@ def test_parse_options(self): self.assertEqual("5m", options.run_time) self.assertTrue(options.reset_stats) self.assertEqual(5, options.stop_timeout) - self.assertEqual(["MyLocustClass"], options.locust_classes) + self.assertEqual(["MyUserClass>"], options.locust_classes) # check default arg self.assertEqual(8089, options.web_port) @@ -84,7 +84,7 @@ def test_parse_locustfile(self): "-t", "5m", "--reset-stats", "--stop-timeout", "5", - "MyLocustClass", + "MyUserClass", ]) self.assertEqual(mocked.file_path, locustfile) locustfile = parse_locustfile_option(args=[ @@ -103,7 +103,7 @@ def test_unknown_command_line_arg(self): "--reset-stats", "--stop-timeout", "5", "--unknown-flag", - "MyLocustClass", + "MyUserClass", ]) def test_custom_argument(self): diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index ed4fd535df..06ee3c664d 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -10,7 +10,7 @@ from locust.main import create_environment from locust.core import User, TaskSet, task from locust.env import Environment -from locust.exception import RPCError, StopLocust +from locust.exception import RPCError, StopUser from locust.rpc import Message from locust.runners import LocalRunner, WorkerNode, WorkerRunner, \ @@ -104,13 +104,13 @@ def test_cpu_warning(self): _monitor_interval = runners.CPU_MONITOR_INTERVAL runners.CPU_MONITOR_INTERVAL = 2.0 try: - class CpuLocust(User): + class CpuUser(User): wait_time = constant(0.001) @task def cpu_task(self): for i in range(1000000): _ = 3 / 2 - environment = Environment(locust_classes=[CpuLocust]) + environment = Environment(locust_classes=[CpuUser]) runner = LocalRunner(environment) self.assertFalse(runner.cpu_warning_emitted) runner.spawn_locusts(1, 1, wait=False) @@ -122,13 +122,13 @@ def cpu_task(self): def test_weight_locusts(self): maxDiff = 2048 - class BaseLocust(User): + class BaseUser(User): pass - class L1(BaseLocust): + class L1(BaseUser): weight = 101 - class L2(BaseLocust): + class L2(BaseUser): weight = 99 - class L3(BaseLocust): + class L3(BaseUser): weight = 100 runner = Environment(locust_classes=[L1, L2, L3]).create_local_runner() @@ -137,13 +137,13 @@ class L3(BaseLocust): self.assert_locust_class_distribution({L1:11, L2:10, L3:10}, runner.weight_locusts(31)) def test_weight_locusts_fewer_amount_than_locust_classes(self): - class BaseLocust(User): + class BaseUser(User): pass - class L1(BaseLocust): + class L1(BaseUser): weight = 101 - class L2(BaseLocust): + class L2(BaseUser): weight = 99 - class L3(BaseLocust): + class L3(BaseUser): weight = 100 runner = Environment(locust_classes=[L1, L2, L3]).create_local_runner() @@ -152,14 +152,14 @@ class L3(BaseLocust): def test_kill_locusts(self): triggered = [False] - class BaseLocust(User): + class BaseUser(User): wait_time = constant(1) @task class task_set(TaskSet): @task def trigger(self): triggered[0] = True - runner = Environment(locust_classes=[BaseLocust]).create_local_runner() + runner = Environment(locust_classes=[BaseUser]).create_local_runner() runner.spawn_locusts(2, hatch_rate=2, wait=False) self.assertEqual(2, len(runner.locusts)) g1 = list(runner.locusts)[0] @@ -324,7 +324,7 @@ def test_runner_reference_on_environment(self): class TestMasterWorkerRunners(LocustTestCase): def test_distributed_integration_run(self): """ - Full integration test that starts both a MasterLocustRunner and three WorkerLocustRunner instances + Full integration test that starts both a MasterRunner and three WorkerRunner instances and makes sure that their stats is sent to the Master. """ class TestUser(User): @@ -714,11 +714,11 @@ class MyTaskSet(TaskSet): def my_task(self): pass - class MyTestLocust(User): + class MyTestUser(User): tasks = [MyTaskSet] wait_time = constant(0.1) - environment = Environment(locust_classes=[MyTestLocust]) + environment = Environment(locust_classes=[MyTestUser]) runner = LocalRunner(environment) timeout = gevent.Timeout(2.0) @@ -797,15 +797,15 @@ def test_spawn_locusts_in_stepload_mode(self): self.assertEqual(10, num_clients, "Total number of locusts that would have been spawned for second step is not 10") def test_exception_in_task(self): - class MyLocust(User): + class MyUser(User): @task def will_error(self): raise HeyAnException(":(") - self.environment.locust_classes = [MyLocust] + self.environment.locust_classes = [MyUser] runner = self.environment.create_local_runner() - l = MyLocust(self.environment) + l = MyUser(self.environment) self.assertRaises(HeyAnException, l.run) self.assertRaises(HeyAnException, l.run) @@ -833,17 +833,17 @@ def will_error(self): @task(1) def will_stop(self): - raise StopLocust() + raise StopUser() - class MyLocust(User): + class MyUser(User): wait_time = constant(0.01) tasks = [MyTaskSet] # set config to catch exceptions in locust users self.environment.catch_exceptions = True - self.environment.locust_classes = [MyLocust] + self.environment.locust_classes = [MyUser] runner = LocalRunner(self.environment) - l = MyLocust(self.environment) + l = MyUser(self.environment) # make sure HeyAnException isn't raised l.run() @@ -872,14 +872,14 @@ def test_master_reset_connection(self): self.assertEqual(1, len(master.clients)) master.quit() -class TestWorkerLocustRunner(LocustTestCase): +class TestWorkerRunner(LocustTestCase): def setUp(self): - super(TestWorkerLocustRunner, self).setUp() + super(TestWorkerRunner, self).setUp() #self._report_to_master_event_handlers = [h for h in events.report_to_master._handlers] def tearDown(self): #events.report_to_master._handlers = self._report_to_master_event_handlers - super(TestWorkerLocustRunner, self).tearDown() + super(TestWorkerRunner, self).tearDown() def get_runner(self, environment=None, locust_classes=[]): if environment is None: @@ -888,14 +888,14 @@ def get_runner(self, environment=None, locust_classes=[]): return WorkerRunner(environment, master_host="localhost", master_port=5557) def test_worker_stop_timeout(self): - class MyTestLocust(User): + class MyTestUser(User): _test_state = 0 wait_time = constant(0) @task def the_task(self): - MyTestLocust._test_state = 1 + MyTestUser._test_state = 1 gevent.sleep(0.2) - MyTestLocust._test_state = 2 + MyTestUser._test_state = 2 with mock.patch("locust.rpc.rpc.Client", mocked_rpc()) as client: environment = Environment() @@ -903,7 +903,7 @@ def the_task(self): @environment.events.test_start.add_listener def on_test_start(**kw): test_start_run[0] = True - worker = self.get_runner(environment=environment, locust_classes=[MyTestLocust]) + worker = self.get_runner(environment=environment, locust_classes=[MyTestUser]) self.assertEqual(1, len(client.outbox)) self.assertEqual("client_ready", client.outbox[0].type) client.mocked_send(Message("hatch", { @@ -919,28 +919,28 @@ def on_test_start(**kw): self.assertEqual(1, len(worker.locusts)) # check that locust has started running gevent.sleep(0.01) - self.assertEqual(1, MyTestLocust._test_state) + self.assertEqual(1, MyTestUser._test_state) # send stop message client.mocked_send(Message("stop", None, "dummy_client_id")) worker.locusts.join() # check that locust user got to finish - self.assertEqual(2, MyTestLocust._test_state) + self.assertEqual(2, MyTestUser._test_state) # make sure the test_start was never fired on the worker self.assertFalse(test_start_run[0]) def test_worker_without_stop_timeout(self): - class MyTestLocust(User): + class MyTestUser(User): _test_state = 0 wait_time = constant(0) @task def the_task(self): - MyTestLocust._test_state = 1 + MyTestUser._test_state = 1 gevent.sleep(0.2) - MyTestLocust._test_state = 2 + MyTestUser._test_state = 2 with mock.patch("locust.rpc.rpc.Client", mocked_rpc()) as client: environment = Environment(stop_timeout=None) - worker = self.get_runner(environment=environment, locust_classes=[MyTestLocust]) + worker = self.get_runner(environment=environment, locust_classes=[MyTestUser]) self.assertEqual(1, len(client.outbox)) self.assertEqual("client_ready", client.outbox[0].type) client.mocked_send(Message("hatch", { @@ -956,12 +956,12 @@ def the_task(self): self.assertEqual(1, len(worker.locusts)) # check that locust has started running gevent.sleep(0.01) - self.assertEqual(1, MyTestLocust._test_state) + self.assertEqual(1, MyTestUser._test_state) # send stop message client.mocked_send(Message("stop", None, "dummy_client_id")) worker.locusts.join() # check that locust user did not get to finish - self.assertEqual(1, MyTestLocust._test_state) + self.assertEqual(1, MyTestUser._test_state) def test_change_user_count_during_hatching(self): class MyUser(User): @@ -1014,11 +1014,11 @@ def my_task(self): gevent.sleep(short_time) MyTaskSet.state = "third" # should only run when run time + stop_timeout is > short_time * 2 - class MyTestLocust(User): + class MyTestUser(User): tasks = [MyTaskSet] wait_time = constant(0) - environment = Environment(locust_classes=[MyTestLocust]) + environment = Environment(locust_classes=[MyTestUser]) runner = environment.create_local_runner() runner.start(1, 1, wait=False) gevent.sleep(short_time / 2) @@ -1026,7 +1026,7 @@ class MyTestLocust(User): self.assertEqual("first", MyTaskSet.state) # exit with timeout - environment = Environment(locust_classes=[MyTestLocust], stop_timeout=short_time/2) + environment = Environment(locust_classes=[MyTestUser], stop_timeout=short_time/2) runner = environment.create_local_runner() runner.start(1, 1, wait=False) gevent.sleep(short_time) @@ -1034,7 +1034,7 @@ class MyTestLocust(User): self.assertEqual("second", MyTaskSet.state) # allow task iteration to complete, with some margin - environment = Environment(locust_classes=[MyTestLocust], stop_timeout=short_time*3) + environment = Environment(locust_classes=[MyTestUser], stop_timeout=short_time*3) runner = environment.create_local_runner() runner.start(1, 1, wait=False) gevent.sleep(short_time) @@ -1062,11 +1062,11 @@ def on_start(self): def my_task(self): MyTaskSet.my_task_run = True - class MyTestLocust(User): + class MyTestUser(User): tasks = [MyTaskSet] wait_time = constant(0) - environment = create_environment([MyTestLocust], mocked_options()) + environment = create_environment([MyTestUser], mocked_options()) environment.stop_timeout = short_time runner = environment.create_local_runner() runner.start(1, 1) @@ -1083,11 +1083,11 @@ class MyTaskSet(TaskSet): def my_task(self): pass - class MyTestLocust(User): + class MyTestUser(User): tasks = [MyTaskSet] wait_time = between(1, 1) - environment = Environment(locust_classes=[MyTestLocust], stop_timeout=short_time) + environment = Environment(locust_classes=[MyTestUser], stop_timeout=short_time) runner = environment.create_local_runner() runner.start(1, 1) gevent.sleep(short_time) # sleep to make sure locust has had time to start waiting @@ -1112,11 +1112,11 @@ def a_task(self): class MyTaskSet(TaskSet): tasks = [MySubTaskSet] - class MyTestLocust(User): + class MyTestUser(User): tasks = [MyTaskSet] wait_time = constant(0) - environment = create_environment([MyTestLocust], mocked_options()) + environment = create_environment([MyTestUser], mocked_options()) environment.stop_timeout = short_time runner = environment.create_local_runner() runner.start(1, 1, wait=True) @@ -1140,11 +1140,11 @@ def a_task(self): state[0] = 1 self.interrupt(reschedule=False) - class MyTestLocust(User): + class MyTestUser(User): tasks = [MySubTaskSet] wait_time = constant(3) - environment = create_environment([MyTestLocust], mocked_options()) + environment = create_environment([MyTestUser], mocked_options()) environment.stop_timeout = 0.3 runner = environment.create_local_runner() runner.start(1, 1, wait=True) @@ -1171,11 +1171,11 @@ def my_task(self): gevent.sleep(short_time) MyTaskSet.state = "third" # should only run when run time + stop_timeout is > short_time * 2 - class MyTestLocust(User): + class MyTestUser(User): tasks = [MyTaskSet] wait_time = constant(0) - environment = create_environment([MyTestLocust], mocked_options()) + environment = create_environment([MyTestUser], mocked_options()) runner = environment.create_local_runner() runner.start(1, 1) gevent.sleep(short_time / 2) diff --git a/locust/test/test_stats.py b/locust/test/test_stats.py index 6b46e7ff27..77b834eacb 100644 --- a/locust/test/test_stats.py +++ b/locust/test/test_stats.py @@ -7,7 +7,7 @@ import gevent import mock import locust -from locust import HttpLocust, TaskSet, task, User, constant +from locust import HttpUser, TaskSet, task, User, constant from locust.env import Environment from locust.inspectlocust import get_task_ratio_dict from locust.rpc.protocol import Message @@ -564,9 +564,9 @@ def test_fail_ratio_with_half_failures(self): class TestRequestStatsWithWebserver(WebserverTestCase): def setUp(self): super().setUp() - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://127.0.0.1:%i" % self.port - self.locust = MyLocust(self.environment) + self.locust = MyUser(self.environment) def test_request_stats_content_length(self): self.locust.client.get("/ultra_fast") @@ -597,10 +597,10 @@ def test_request_stats_put(self): self.assertEqual(1, self.runner.stats.get("/put", "PUT").num_requests) def test_request_connection_error(self): - class MyLocust(HttpLocust): + class MyUser(HttpUser): host = "http://localhost:1" - locust = MyLocust(self.environment) + locust = MyUser(self.environment) response = locust.client.get("/", timeout=0.1) self.assertEqual(response.status_code, 0) self.assertEqual(1, self.runner.stats.get("/", "GET").num_failures) diff --git a/locust/test/test_taskratio.py b/locust/test/test_taskratio.py index 3822f7ec0e..4a917eb506 100644 --- a/locust/test/test_taskratio.py +++ b/locust/test/test_taskratio.py @@ -47,18 +47,18 @@ def task1(self): def task3(self): pass - class UnlikelyLocust(User): + class UnlikelyUser(User): weight = 1 tasks = [Tasks] - class MoreLikelyLocust(User): + class MoreLikelyUser(User): weight = 3 tasks = [Tasks] - ratio_dict = get_task_ratio_dict([UnlikelyLocust, MoreLikelyLocust], total=True) + ratio_dict = get_task_ratio_dict([UnlikelyUser, MoreLikelyUser], total=True) self.assertDictEqual({ - 'UnlikelyLocust': { + 'UnlikelyUser': { 'ratio': 0.25, 'tasks': { 'Tasks': { @@ -70,7 +70,7 @@ class MoreLikelyLocust(User): } }, }, - 'MoreLikelyLocust': { + 'MoreLikelyUser': { 'ratio': 0.75, 'tasks': { 'Tasks': { @@ -83,6 +83,6 @@ class MoreLikelyLocust(User): }, } }, ratio_dict) - unlikely = ratio_dict['UnlikelyLocust']['tasks']['Tasks']['tasks'] - likely = ratio_dict['MoreLikelyLocust']['tasks']['Tasks']['tasks'] + unlikely = ratio_dict['UnlikelyUser']['tasks']['Tasks']['tasks'] + likely = ratio_dict['MoreLikelyUser']['tasks']['Tasks']['tasks'] assert unlikely['task1']['ratio'] + unlikely['task3']['ratio'] + likely['task1']['ratio'] + likely['task3']['ratio'] == 1 diff --git a/locust/test/test_web.py b/locust/test/test_web.py index d1e8838b7a..347306060f 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -174,12 +174,12 @@ def test_exceptions_csv(self): self.assertEqual(2, int(rows[1][0]), "Exception count should be 2") def test_swarm_host_value_specified(self): - class MyLocust(User): + class MyUser(User): wait_time = constant(1) @task(1) def my_task(self): pass - self.environment.locust_classes = [MyLocust] + self.environment.locust_classes = [MyUser] response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, data={"locust_count": 5, "hatch_rate": 5, "host": "https://localhost"}, @@ -189,12 +189,12 @@ def my_task(self): self.assertEqual(self.environment.host, "https://localhost") def test_swarm_host_value_not_specified(self): - class MyLocust(User): + class MyUser(User): wait_time = constant(1) @task(1) def my_task(self): pass - self.environment.locust_classes = [MyLocust] + self.environment.locust_classes = [MyUser] response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, data={'locust_count': 5, 'hatch_rate': 5}, @@ -204,43 +204,43 @@ def my_task(self): self.assertEqual(self.environment.host, None) def test_host_value_from_locust_class(self): - class MyLocust(User): + class MyUser(User): host = "http://example.com" - self.environment.locust_classes = [MyLocust] + self.environment.locust_classes = [MyUser] response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertIn("http://example.com", response.content.decode("utf-8")) self.assertNotIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) def test_host_value_from_multiple_locust_classes(self): - class MyLocust(User): + class MyUser(User): host = "http://example.com" - class MyLocust2(User): + class MyUser2(User): host = "http://example.com" - self.environment.locust_classes = [MyLocust, MyLocust2] + self.environment.locust_classes = [MyUser, MyUser2] response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertIn("http://example.com", response.content.decode("utf-8")) self.assertNotIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) def test_host_value_from_multiple_locust_classes_different_hosts(self): - class MyLocust(User): + class MyUser(User): host = None - class MyLocust2(User): + class MyUser2(User): host = "http://example.com" - self.environment.locust_classes = [MyLocust, MyLocust2] + self.environment.locust_classes = [MyUser, MyUser2] response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertNotIn("http://example.com", response.content.decode("utf-8")) self.assertIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) def test_swarm_in_step_load_mode(self): - class MyLocust(User): + class MyUser(User): wait_time = constant(1) @task(1) def my_task(self): pass - self.environment.locust_classes = [MyLocust] + self.environment.locust_classes = [MyUser] self.environment.step_load = True response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, diff --git a/locust/util/deprecation.py b/locust/util/deprecation.py index 3e6b6ce98a..5ba63dc68b 100644 --- a/locust/util/deprecation.py +++ b/locust/util/deprecation.py @@ -10,5 +10,5 @@ def check_for_deprecated_task_set_attribute(class_dict): if "task_set" in class_dict: task_set = class_dict["task_set"] if issubclass(task_set, TaskSet) and not hasattr(task_set, "locust_task_weight"): - warnings.warn("Usage of Locust.task_set is deprecated since version 1.0. Set the tasks attribute instead " + warnings.warn("Usage of User.task_set is deprecated since version 1.0. Set the tasks attribute instead " "(tasks = [%s])" % task_set.__name__, DeprecationWarning) diff --git a/locust/wait_time.py b/locust/wait_time.py index 1399f37810..154fa6c6a4 100644 --- a/locust/wait_time.py +++ b/locust/wait_time.py @@ -8,7 +8,7 @@ def between(min_wait, max_wait): Example:: - class User(Locust): + class MyUser(User): # wait between 3.0 and 10.5 seconds after each task wait_time = between(3.0, 10.5) """ @@ -21,7 +21,7 @@ def constant(wait_time): Example:: - class User(Locust): + class MyUser(User): wait_time = constant(3) """ return lambda instance: wait_time @@ -36,7 +36,7 @@ def constant_pacing(wait_time): In the following example the task will always be executed once every second, no matter the task execution time:: - class User(Locust): + cclass MyUser(User): wait_time = constant_pacing(1) class task_set(TaskSet): @task From 5076958ae4a66cc4b622ee13fc63334e320af142 Mon Sep 17 00:00:00 2001 From: anuj_ Date: Mon, 20 Apr 2020 13:57:44 +1200 Subject: [PATCH 13/37] fixed typo --- locust/test/test_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locust/test/test_parser.py b/locust/test/test_parser.py index a7309ff631..d78c5981c2 100644 --- a/locust/test/test_parser.py +++ b/locust/test/test_parser.py @@ -71,7 +71,7 @@ def test_parse_options(self): self.assertEqual("5m", options.run_time) self.assertTrue(options.reset_stats) self.assertEqual(5, options.stop_timeout) - self.assertEqual(["MyUserClass>"], options.locust_classes) + self.assertEqual(["MyUserClass"], options.locust_classes) # check default arg self.assertEqual(8089, options.web_port) From de53ef8cf7941dd67f83405ea0012b9ee323a905 Mon Sep 17 00:00:00 2001 From: anuj_ Date: Mon, 20 Apr 2020 14:54:28 +1200 Subject: [PATCH 14/37] documentation updated --- docs/api.rst | 18 ++-- docs/increase-performance.rst | 24 +++--- docs/quickstart.rst | 10 +-- docs/running-locust-without-web-ui.rst | 4 +- docs/testing-other-systems.rst | 12 +-- docs/third-party-tools.rst | 4 +- docs/use-as-lib.rst | 2 +- docs/writing-a-locustfile.rst | 115 ++++++++++++------------- 8 files changed, 94 insertions(+), 95 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index 3f92fe5b03..ef88f80f05 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -3,16 +3,16 @@ API ### -Locust class +User class ============ -.. autoclass:: locust.core.Locust +.. autoclass:: locust.core.User :members: wait_time, tasks, weight, abstract, on_start, on_stop, wait -HttpLocust class +HttpUser class ================ -.. autoclass:: locust.core.HttpLocust +.. autoclass:: locust.core.HttpUser :members: wait_time, tasks, client, abstract @@ -107,17 +107,17 @@ The event hooks are instances of the **locust.events.EventHook** class: to prevent your code from breaking if new arguments are added in a future version. -Locust Runner classes +Runner classes ===================== -.. autoclass:: locust.runners.LocustRunner +.. autoclass:: locust.runners.Runner :members: start, stop, quit, user_count -.. autoclass:: locust.runners.LocalLocustRunner +.. autoclass:: locust.runners.LocalRunner -.. autoclass:: locust.runners.MasterLocustRunner +.. autoclass:: locust.runners.MasterRunner -.. autoclass:: locust.runners.WorkerLocustRunner +.. autoclass:: locust.runners.WorkerRunner Web UI class diff --git a/docs/increase-performance.rst b/docs/increase-performance.rst index 9a47391c05..8a936e7c71 100644 --- a/docs/increase-performance.rst +++ b/docs/increase-performance.rst @@ -7,27 +7,27 @@ Increase Locust's performance with a faster HTTP client Locust's default HTTP client uses `python-requests `_. The reason for this is that requests is a very well-maintained python package, that provides a really nice API, that many python developers are familiar with. Therefore, -in many cases, we recommend that you use the default :py:class:`HttpLocust ` +in many cases, we recommend that you use the default :py:class:`HttpUser ` which uses requests. However, if you're planning to run really large scale tests, Locust comes with an alternative HTTP client, -:py:class:`FastHttpLocust ` which +:py:class:`FastHttpUser ` which uses `geventhttpclient `_ instead of requests. This client is significantly faster, and we've seen 5x-6x performance increases for making HTTP-requests. This does not necessarily mean that the number of users one can simulate per CPU core will automatically increase 5x-6x, since it also depends on what else the load testing script does. However, if your locust scripts are spending most of their -CPU time in making HTTP-requests, you are likely to see signifant performance gains. +CPU time in making HTTP-requests, you are likely to see significant performance gains. -How to use FastHttpLocust +How to use FastHttpUser =========================== -Subclass FastHttpLocust instead of HttpLocust:: +Subclass FastHttpUser instead of HttpUser:: from locust import task, between - from locust.contrib.fasthttp import FastHttpLocust + from locust.contrib.fasthttp import FastHttpUser - class MyLocust(FastHttpLocust): + class MyUser(FastHttpUser): wait_time = between(1, 60) @task @@ -37,19 +37,19 @@ Subclass FastHttpLocust instead of HttpLocust:: .. note:: - FastHttpLocust uses a whole other HTTP client implementation, with a different API, compared to - the default HttpLocust that uses python-requests. Therefore FastHttpLocust might not work as a - drop-in replacement for HttpLocust, depending on how the HttpClient is used. + FastHttpUser uses a whole other HTTP client implementation, with a different API, compared to + the default HttpUser that uses python-requests. Therefore FastHttpUser might not work as a + drop-in replacement for HttpUser, depending on how the HttpClient is used. API === -FastHttpLocust class +FastHttpUser class -------------------- -.. autoclass:: locust.contrib.fasthttp.FastHttpLocust +.. autoclass:: locust.contrib.fasthttp.FastHttpUser :members: network_timeout, connection_timeout, max_redirects, max_retries, insecure diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 086f6ad678..c4a905e451 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -21,9 +21,9 @@ Below is a quick little example of a simple **locustfile.py**: .. code-block:: python import random - from locust import HttpLocust, task, between + from locust import HttpUser, task, between - class WebsiteUser(HttpLocust): + class WebsiteUser(HttpUser): wait_time = between(5, 9) @task(2) @@ -37,7 +37,7 @@ Below is a quick little example of a simple **locustfile.py**: self.client.get("/post?id=%i" % post_id, name="/post?id=[post-id]") def on_start(self): - """ on_start is called when a Locust start before any task is scheduled """ + """ on_start is called when a User starts before any task is scheduled """ self.login() def login(self): @@ -49,10 +49,10 @@ Let's break it down: .. code-block:: python - class WebsiteUser(HttpLocust): + class WebsiteUser(HttpUser): Here we define a class for the users that we will be simulating. It inherits from -:py:class:`HttpLocust ` which gives each user a ``client`` attribute, +:py:class:`HttpUser ` which gives each user a ``client`` attribute, which is an instance of :py:class:`HttpSession `, that can be used to make HTTP requests to the target system that we want to load test. When a test starts, locust will create an instance of this class for every user that it simulates, and each of these diff --git a/docs/running-locust-without-web-ui.rst b/docs/running-locust-without-web-ui.rst index 084c602991..159c457f8f 100644 --- a/docs/running-locust-without-web-ui.rst +++ b/docs/running-locust-without-web-ui.rst @@ -5,13 +5,13 @@ Running Locust without the web UI ================================= You can run locust without the web UI - for example if you want to run it in some automated flow, -like a CI server - by using the ``--headless`` flag together with ``-c`` and ``-r``: +like a CI server - by using the ``--headless`` flag together with ``-u`` and ``-r``: .. code-block:: console $ locust -f locust_files/my_locust_file.py --headless -c 1000 -r 100 -``-c`` specifies the number of Locust users to spawn, and ``-r`` specifies the hatch rate +``-u`` specifies the number of Users to spawn, and ``-r`` specifies the hatch rate (number of users to spawn per second). diff --git a/docs/testing-other-systems.rst b/docs/testing-other-systems.rst index ea6d0eac0e..021cb9b87c 100644 --- a/docs/testing-other-systems.rst +++ b/docs/testing-other-systems.rst @@ -7,19 +7,19 @@ any request/response based system, by writing a custom client that triggers :py:attr:`request_success ` and :py:attr:`request_failure ` events. -Sample XML-RPC Locust client +Sample XML-RPC User client ============================ -Here is an example of a Locust class, **XmlRpcLocust**, which provides an XML-RPC client, -**XmlRpcClient**, and tracks all requests made: +Here is an example of a Locust class, **XmlRpcUser**, which provides an XML-RPC client, +**XmlRpcUser**, and tracks all requests made: .. literalinclude:: ../examples/custom_xmlrpc_client/xmlrpc_locustfile.py If you've written Locust tests before, you'll recognize the class called ``ApiUser`` which is a normal -Locust class that has a couple of tasks declared. However, the ``ApiUser`` inherits from -``XmlRpcLocust`` that you can see right above ``ApiUser``. The ``XmlRpcLocust`` is marked as abstract +User class that has a couple of tasks declared. However, the ``ApiUser`` inherits from +``XmlRpcUser`` that you can see right above ``ApiUser``. The ``XmlRpcUser`` is marked as abstract using ``abstract = True`` which means that Locust till not try to create simulated users from that class -(only of classes that extends it). ``XmlRpcLocust`` provides an instance of XmlRpcClient under the +(only of classes that extends it). ``XmlRpcUser`` provides an instance of XmlRpcClient under the ``client`` attribute. The ``XmlRpcClient`` is a wrapper around the standard diff --git a/docs/third-party-tools.rst b/docs/third-party-tools.rst index aecdcf5f07..2ba4e73c6f 100644 --- a/docs/third-party-tools.rst +++ b/docs/third-party-tools.rst @@ -18,8 +18,8 @@ Using other languages ===================== A Locust master and a Locust worker communicate by exchanging `msgpack `_ messages, which is -supported by many languages. So, you can write your Locust tasks in any languages you like. For convenience, some -libraries do the job as a worker runner. They run your Locust tasks, and report to master regularly. +supported by many languages. So, you can write your User tasks in any languages you like. For convenience, some +libraries do the job as a worker runner. They run your User tasks, and report to master regularly. Golang diff --git a/docs/use-as-lib.rst b/docs/use-as-lib.rst index c028b75ac4..8bfe9c4199 100644 --- a/docs/use-as-lib.rst +++ b/docs/use-as-lib.rst @@ -16,7 +16,7 @@ The :py:class:`Environment ` instance's :py:meth:`create_local_runner `, :py:meth:`create_master_runner ` or :py:meth:`create_worker_runner can then be used to start a -:py:class:`LocustRunner ` instance, which can be used to start a load test: +:py:class:`Runner ` instance, which can be used to start a load test: .. code-block:: python diff --git a/docs/writing-a-locustfile.rst b/docs/writing-a-locustfile.rst index 3cc3a4baab..6eb2a19f0e 100644 --- a/docs/writing-a-locustfile.rst +++ b/docs/writing-a-locustfile.rst @@ -16,7 +16,7 @@ The *wait_time* attribute ------------------------- In addition to the *task_set* attribute, one should also declare a -:py:attr:`wait_time ` method. It's used to determine +:py:attr:`wait_time ` method. It's used to determine for how long a simulated user will wait between executing tasks. Locust comes with a few built in functions that return a few common wait_time methods. @@ -29,22 +29,22 @@ With the following locustfile, each user would wait between 5 and 15 seconds bet .. code-block:: python - from locust import Locust, TaskSet, task, between + from locust import User, TaskSet, task, between class MyTaskSet(TaskSet): @task def my_task(self): print("executing my_task") - class User(Locust): + class MyUser(User): task_set = MyTaskSet wait_time = between(5, 15) The wait_time method should return a number of seconds (or fraction of a second) and can also be declared on a TaskSet class, in which case it will only be used for that TaskSet. -It's also possible to declare your own wait_time method directly on a Locust or TaskSet class. The -following locust class would start sleeping for one second and then one, two, three, etc. +It's also possible to declare your own wait_time method directly on a User or TaskSet class. The +following User class would start sleeping for one second and then one, two, three, etc. .. code-block:: python @@ -67,18 +67,18 @@ to use from the same file like so: .. code-block:: console - $ locust -f locust_file.py WebUserLocust MobileUserLocust + $ locust -f locust_file.py WebUser MobileUser If you wish to make one of these locusts execute more often you can set a weight attribute on those classes. Say for example, web users are three times more likely than mobile users: .. code-block:: python - class WebUserLocust(Locust): + class WebUser(User): weight = 3 ... - class MobileUserLocust(Locust): + class MobileUser(User): weight = 1 ... @@ -96,14 +96,14 @@ is specified on the command line or in the web request. The *tasks* attribute --------------------- -A Locust class can have tasks declared as methods under it using the :py:func:`@task ` decorator, but one can also -specify tasks using the *tasks* attribute which is descibed in more details :ref:`below `. +A User class can have tasks declared as methods under it using the :py:func:`@task ` decorator, but one can also +specify tasks using the *tasks* attribute which is described in more details :ref:`below `. Tasks ===== -When a load test is started, an instance of a Locust class will be created for each simulated user +When a load test is started, an instance of a User class will be created for each simulated user and they will start running within their own green thread. When these users run they pick tasks that they execute, sleeps for awhile, and then picks a new task and so on. @@ -113,30 +113,30 @@ stuff like "loading the start page", "searching for some product", "making a bid Declaring tasks --------------- -The typical way of declaring tasks for a Locust class (or a TaskSet) it to use the +The typical way of declaring tasks for a User class (or a TaskSet) it to use the :py:meth:`task ` decorator. Here is an example: .. code-block:: python - from locust import Locust, task, constant + from locust import User, task, constant - class MyLocust(Locust): + class MyUser(User): wait_time = constant(1) @task def my_task(self): - print("Locust instance (%r) executing my_task" % self) + print("User instance (%r) executing my_task" % self) **@task** takes an optional weight argument that can be used to specify the task's execution ratio. In the following example *task2* will have twice the chance of being picked as *task1*: .. code-block:: python - from locust import Locust, task, between + from locust import User, task, between - class MyLocust(Locust): + class MyUser(User): wait_time = between(5, 15) @task(3) @@ -154,24 +154,24 @@ tasks attribute --------------- Using the @task decorator to declare tasks is a convenience, and usually the best way to do -it. However, it's also possible to define the tasks of a Locust or TaskSet by setting the -:py:attr:`tasks ` attribute (using the @task decorator will actually +it. However, it's also possible to define the tasks of a User or TaskSet by setting the +:py:attr:`tasks ` attribute (using the @task decorator will actually just populate the *tasks* attribute). The *tasks* attribute is either a list of Task, or a ** dict, where Task is either a python callable or a TaskSet class (more on that below). If the task is a normal python function they -receive a single argument which is the Locust instance that is executing the task. +receive a single argument which is the User instance that is executing the task. -Here is an example of a locust task declared as a normal python function: +Here is an example of a User task declared as a normal python function: .. code-block:: python - from locust import Locust, constant + from locust import User, constant def my_task(l): pass - class MyLocust(Locust): + class MyUser(User): tasks = [my_task] wait_time = constant(1) @@ -200,12 +200,12 @@ TaskSet class Since real websites are usually built up in an hierarchical way, with multiple sub-sections, locust has the TaskSet class. A locust task can not only be a Python callable, but also a TaskSet class. A TaskSet is a collection of locust tasks that will be executed much like the -tasks declared directly on a Locust class, with the user sleeping in between task executions. +tasks declared directly on a User class, with the user sleeping in between task executions. Here's a short example of a locustfile that has a TaskSet: .. code-block:: python - from locust import Locust, TaskSet, between + from locust import User, TaskSet, between class ForumSection(TaskSet): @task(10) @@ -220,7 +220,7 @@ Here's a short example of a locustfile that has a TaskSet: def stop(self): self.interrupt() - class LoggedInUser(Locust): + class LoggedInUser(User): wait_time = between(5, 120) tasks = {ForumSection:2} @@ -228,11 +228,11 @@ Here's a short example of a locustfile that has a TaskSet: def index_page(self): pass -A TaskSet can also be inlined directly under a Locust/TaskSet class using the @task decorator: +A TaskSet can also be inlined directly under a User/TaskSet class using the @task decorator: .. code-block:: python - class MyUser(Locust): + class MyUser(User): @task(1) class MyTaskSet(TaskSet): ... @@ -254,10 +254,10 @@ For example we could define TaskSets with the following structure:: - Filter movies - About page -When a running Locust thread picks a TaskSet class for execution an instance of this class will +When a running User thread picks a TaskSet class for execution an instance of this class will be created and execution will then go into this TaskSet. What happens then is that one of the TaskSet's tasks will be picked and executed, and then the thread will sleep for a duration specified -by the Locust's wait_time function (unless a ``wait_time`` function has been declared directly on +by the User's wait_time function (unless a ``wait_time`` function has been declared directly on the TaskSet class, in which case it'll use that function instead), then pick a new task from the TaskSet's tasks, wait again, and so on. @@ -267,7 +267,7 @@ Interrupting a TaskSet ---------------------- One important thing to know about TaskSets is that they will never stop executing their tasks, and -hand over execution back to their parent Locust/TaskSet, by themselves. This has to be done by the +hand over execution back to their parent User/TaskSet, by themselves. This has to be done by the developer by calling the :py:meth:`TaskSet.interrupt() ` method. .. autofunction:: locust.core.TaskSet.interrupt @@ -278,7 +278,7 @@ simulated user would never stop running tasks from the Forum taskset once it has .. code-block:: python - class RegisteredUser(Locust): + class RegisteredUser(User): @task class Forum(TaskSet): @task(5) @@ -297,23 +297,23 @@ Using the interrupt function, we can — together with task weighting — define is that a simulated user leaves the forum. -Differences between tasks in TaskSet and Locust classes +Differences between tasks in TaskSet and User classes ------------------------------------------------------- -One difference for tasks residing under a TaskSet, compared to tasks residing directly under a Locust, +One difference for tasks residing under a TaskSet, compared to tasks residing directly under a User, is that the argument that they are passed when executed (``self`` for tasks declared as methods with the :py:func:`@task ` decorator) is a reference to the TaskSet instance, instead of -the Locust user instance. The Locust instance can be accessed from within a TaskSet instance through the +the User instance. The User instance can be accessed from within a TaskSet instance through the :py:attr:`TaskSet.locust `. TaskSets also contains a convenience :py:attr:`client ` attribute that refers to the client attribute on the -Locust instance. +User instance. -Referencing the Locust instance, or the parent TaskSet instance +Referencing the User instance, or the parent TaskSet instance --------------------------------------------------------------- A TaskSet instance will have the attribute :py:attr:`locust ` point to -its Locust instance, and the attribute :py:attr:`parent ` point to its +its User instance, and the attribute :py:attr:`parent ` point to its parent TaskSet instance. @@ -362,16 +362,15 @@ and then it will start over at ``first_task`` again. on_start and on_stop methods ============================ -Locust and TaskSet classes can declare an :py:meth:`on_start ` method and/or -:py:meth:`on_stop ` method. A Locust user will call it's -:py:meth:`on_start ` method when it starts running, and it's -:py:meth:`on_stop ` method when it stops running. For a TaskSet, the +User and TaskSet classes can declare an :py:meth:`on_start ` method and/or +:py:meth:`on_stop ` method. A User will call it's +:py:meth:`on_start ` method when it starts running, and it's +:py:meth:`on_stop ` method when it stops running. For a TaskSet, the :py:meth:`on_start ` method is called when a simulated user starts executing that TaskSet, and :py:meth:`on_stop ` is called when the simulated user stops -executing that TaskSet (when :py:meth:`interrupt() ` is called, or the locust +executing that TaskSet (when :py:meth:`interrupt() ` is called, or the user is killed). - test_start and test_stop events =============================== @@ -397,25 +396,25 @@ When running Locust distributed the ``test_start`` and ``test_stop`` events will Making HTTP requests ===================== -So far, we've only covered the task scheduling part of a Locust user. In order to actually load test -a system we need to make HTTP requests. To help us do this, the :py:class:`HttpLocust ` +So far, we've only covered the task scheduling part of a User. In order to actually load test +a system we need to make HTTP requests. To help us do this, the :py:class:`HttpLocust ` class exists. When using this class, each instance gets a -:py:attr:`client ` attribute which will be an instance of +:py:attr:`client ` attribute which will be an instance of :py:attr:`HttpSession ` which can be used to make HTTP requests. -.. autoclass:: locust.core.HttpLocust +.. autoclass:: locust.core.HttpUser :members: client :noindex: -When inheriting from the HttpLocust class, we can use its client attribute to make HTTP requests +When inheriting from the HttpUser class, we can use its client attribute to make HTTP requests against the server. Here is an example of a locust file that can be used to load test a site with two URLs; **/** and **/about/**: .. code-block:: python - from locust import HttpLocust, task, between + from locust import HttpUser, task, between - class MyLocust(HttpLocust): + class MyUser(HttpUser): wait_time = between(5, 15) @task(2) @@ -426,27 +425,27 @@ with two URLs; **/** and **/about/**: def about(self): self.client.get("/about/") -Using the above Locust class, each simulated user will wait between 5 and 15 seconds +Using the above User class, each simulated user will wait between 5 and 15 seconds between the requests, and **/** will be requested twice as much as **/about/**. Using the HTTP client ---------------------- -Each instance of HttpLocust has an instance of :py:class:`HttpSession ` +Each instance of HttpUser has an instance of :py:class:`HttpSession ` in the *client* attribute. The HttpSession class is actually a subclass of -:py:class:`requests.Session` and can be used to make HTTP requests, that will be reported to Locust's +:py:class:`requests.Session` and can be used to make HTTP requests, that will be reported to User's statistics, using the :py:meth:`get `, :py:meth:`post `, :py:meth:`put `, :py:meth:`delete `, :py:meth:`head `, :py:meth:`patch ` and :py:meth:`options ` methods. The HttpSession instance will preserve cookies between requests so that it can be used to log in -to websites and keep a session between requests. The client attribute can also be referenced from the Locust +to websites and keep a session between requests. The client attribute can also be referenced from the User instance's TaskSet instances so that it's easy to retrieve the client and make HTTP requests from within your tasks. Here's a simple example that makes a GET request to the */about* path (in this case we assume *self* -is an instance of a :py:class:`TaskSet ` or :py:class:`HttpLocust ` +is an instance of a :py:class:`TaskSet ` or :py:class:`HttpUser ` class: .. code-block:: python @@ -465,7 +464,7 @@ Safe mode --------- The HTTP client is configured to run in safe_mode. What this does is that any request that fails due to a connection error, timeout, or similar will not raise an exception, but rather return an empty dummy -Response object. The request will be reported as a failure in Locust's statistics. The returned dummy +Response object. The request will be reported as a failure in User's statistics. The returned dummy Response's *content* attribute will be set to None, and its *status_code* will be 0. @@ -506,7 +505,7 @@ Grouping requests to URLs with dynamic parameters ------------------------------------------------- It's very common for websites to have pages whose URLs contain some kind of dynamic parameter(s). -Often it makes sense to group these URLs together in Locust's statistics. This can be done +Often it makes sense to group these URLs together in User's statistics. This can be done by passing a *name* argument to the :py:class:`HttpSession's ` different request methods. From 07ff3482eef12065e5270c58c394813ab6e365e1 Mon Sep 17 00:00:00 2001 From: anuj_ Date: Tue, 21 Apr 2020 15:57:58 +1200 Subject: [PATCH 15/37] Rename the locust_classes to user_classes. Updated relevant documentation. --- docs/running-locust-distributed.rst | 6 ++-- docs/use-as-lib.rst | 2 +- examples/use_as_lib.py | 2 +- locust/argument_parser.py | 10 +++--- locust/env.py | 6 ++-- locust/main.py | 28 ++++++++-------- locust/runners.py | 10 +++--- locust/test/test_main.py | 4 +-- locust/test/test_parser.py | 2 +- locust/test/test_runners.py | 52 ++++++++++++++--------------- locust/test/test_stats.py | 2 +- locust/test/test_web.py | 16 ++++----- locust/web.py | 4 +-- 13 files changed, 72 insertions(+), 72 deletions(-) diff --git a/docs/running-locust-distributed.rst b/docs/running-locust-distributed.rst index 7caac89e2a..171cd68764 100644 --- a/docs/running-locust-distributed.rst +++ b/docs/running-locust-distributed.rst @@ -22,11 +22,11 @@ processor core** on the worker machines. .. note:: It's recommended that you start a number of simulated users that are greater than - ``number of locust classes * number of workers`` when running Locust distributed. + ``number of user classes * number of workers`` when running Locust distributed. Otherwise - due to the current implementation - - you might end up with a distribution of the Locust classes that doesn't correspond to the - Locust classes' ``weight`` attribute. And if the hatch rate is lower than the number of worker + you might end up with a distribution of the User classes that doesn't correspond to the + User classes' ``weight`` attribute. And if the hatch rate is lower than the number of worker nodes, the hatching would occur in "bursts" where all worker node would hatch a single user and then sleep for multiple seconds, hatch another user, sleep and repeat. diff --git a/docs/use-as-lib.rst b/docs/use-as-lib.rst index 8bfe9c4199..a4b47b7ac4 100644 --- a/docs/use-as-lib.rst +++ b/docs/use-as-lib.rst @@ -10,7 +10,7 @@ To run Locust as a library you need to create an :py:class:`Environment ` instance's :py:meth:`create_local_runner `, diff --git a/examples/use_as_lib.py b/examples/use_as_lib.py index 04600fa3e2..fc1e34101d 100644 --- a/examples/use_as_lib.py +++ b/examples/use_as_lib.py @@ -20,7 +20,7 @@ def task_404(self): self.client.get("/non-existing-path") # setup Environment and Runner -env = Environment(locust_classes=[User]) +env = Environment(user_classes=[User]) env.create_local_runner() # start a WebUI instance diff --git a/locust/argument_parser.py b/locust/argument_parser.py index 3429357206..99219bc5c6 100644 --- a/locust/argument_parser.py +++ b/locust/argument_parser.py @@ -362,12 +362,12 @@ def setup_parser_arguments(parser): help="Number of seconds to wait for a simulated user to complete any executing task before exiting. Default is to terminate immediately. This parameter only needs to be specified for the master process when running Locust distributed." ) - locust_classes_group = parser.add_argument_group("Locust user classes") - locust_classes_group.add_argument( - 'locust_classes', + user_classes_group = parser.add_argument_group("User classes") + user_classes_group.add_argument( + 'user_classes', nargs='*', - metavar='LocustClass', - help="Optionally specify which Locust classes that should be used (available Locust classes can be listed with -l or --list)", + metavar='UserClass', + help="Optionally specify which User classes that should be used (available User classes can be listed with -l or --list)", ) def get_parser(default_config_files=DEFAULT_CONFIG_FILES): diff --git a/locust/env.py b/locust/env.py index b34c4dabf0..61e779382a 100644 --- a/locust/env.py +++ b/locust/env.py @@ -12,7 +12,7 @@ class Environment: See :ref:`events` for available events. """ - locust_classes = [] + user_classes = [] """Locust User classes that the runner will run""" stats = None @@ -47,7 +47,7 @@ class Environment: def __init__( self, *, - locust_classes=[], + user_classes=[], events=None, host=None, reset_stats=False, @@ -60,7 +60,7 @@ def __init__( else: self.events = Events() - self.locust_classes = locust_classes + self.user_classes = user_classes self.stats = RequestStats() self.host = host self.reset_stats = reset_stats diff --git a/locust/main.py b/locust/main.py index cb9f489f78..64f0a08128 100644 --- a/locust/main.py +++ b/locust/main.py @@ -88,12 +88,12 @@ def __import_locustfile__(filename, path): return imported.__doc__, locusts -def create_environment(locust_classes, options, events=None): +def create_environment(user_classes, options, events=None): """ Create an Environment instance from options """ return Environment( - locust_classes=locust_classes, + user_classes=user_classes, events=events, host=options.host, reset_stats=options.reset_stats, @@ -138,35 +138,35 @@ def main(): logger.error("No Locust class found!") sys.exit(1) - # make sure specified Locust exists - if options.locust_classes: - missing = set(options.locust_classes) - set(locusts.keys()) + # make sure specified User exists + if options.user_classes: + missing = set(options.user_classes) - set(locusts.keys()) if missing: - logger.error("Unknown Locust(s): %s\n" % (", ".join(missing))) + logger.error("Unknown User(s): %s\n" % (", ".join(missing))) sys.exit(1) else: - names = set(options.locust_classes) & set(locusts.keys()) - locust_classes = [locusts[n] for n in names] + names = set(options.user_classes) & set(locusts.keys()) + user_classes = [locusts[n] for n in names] else: # list() call is needed to consume the dict_view object in Python 3 - locust_classes = list(locusts.values()) + user_classes = list(locusts.values()) # create locust Environment - environment = create_environment(locust_classes, options, events=locust.events) + environment = create_environment(user_classes, options, events=locust.events) if options.show_task_ratio: print("\n Task ratio per locust class") print( "-" * 80) - print_task_ratio(locust_classes) + print_task_ratio(user_classes) print("\n Total task ratio") print("-" * 80) - print_task_ratio(locust_classes, total=True) + print_task_ratio(user_classes, total=True) sys.exit(0) if options.show_task_ratio_json: from json import dumps task_data = { - "per_class": get_task_ratio_dict(locust_classes), - "total": get_task_ratio_dict(locust_classes, total=True) + "per_class": get_task_ratio_dict(user_classes), + "total": get_task_ratio_dict(user_classes, total=True) } print(dumps(task_data)) sys.exit(0) diff --git a/locust/runners.py b/locust/runners.py index f7a60862e3..6576e05f8a 100644 --- a/locust/runners.py +++ b/locust/runners.py @@ -80,8 +80,8 @@ def __del__(self): self.greenlet.kill(block=False) @property - def locust_classes(self): - return self.environment.locust_classes + def user_classes(self): + return self.environment.user_classes @property def stats(self): @@ -111,9 +111,9 @@ def weight_locusts(self, amount): returns a list "bucket" with the weighted locusts """ bucket = [] - weight_sum = sum([locust.weight for locust in self.locust_classes]) + weight_sum = sum([locust.weight for locust in self.user_classes]) residuals = {} - for locust in self.locust_classes: + for locust in self.user_classes: if self.environment.host is not None: locust.host = self.environment.host @@ -146,7 +146,7 @@ def spawn_locusts(self, spawn_count, hatch_rate, wait=False): existing_count = len(self.locusts) logger.info("Hatching and swarming %i users at the rate %g users/s (%i users already running)..." % (spawn_count, hatch_rate, existing_count)) - occurrence_count = dict([(l.__name__, 0) for l in self.locust_classes]) + occurrence_count = dict([(l.__name__, 0) for l in self.user_classes]) def hatch(): sleep_time = 1.0 / hatch_rate diff --git a/locust/test/test_main.py b/locust/test/test_main.py index c56fe1f32d..63ab714158 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -29,11 +29,11 @@ class MyTaskSet(TaskSet): class MyHttpUser(HttpUser): tasks = [MyTaskSet] - class MyLocust(User): + class MyUser(User): tasks = [MyTaskSet] self.assertTrue(main.is_locust(MyHttpUser)) - self.assertTrue(main.is_locust(MyLocust)) + self.assertTrue(main.is_locust(MyUser)) class ThriftLocust(User): abstract = True diff --git a/locust/test/test_parser.py b/locust/test/test_parser.py index d78c5981c2..3a5d0beaad 100644 --- a/locust/test/test_parser.py +++ b/locust/test/test_parser.py @@ -71,7 +71,7 @@ def test_parse_options(self): self.assertEqual("5m", options.run_time) self.assertTrue(options.reset_stats) self.assertEqual(5, options.stop_timeout) - self.assertEqual(["MyUserClass"], options.locust_classes) + self.assertEqual(["MyUserClass"], options.user_classes) # check default arg self.assertEqual(8089, options.web_port) diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index 06ee3c664d..2e20186135 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -110,7 +110,7 @@ class CpuUser(User): def cpu_task(self): for i in range(1000000): _ = 3 / 2 - environment = Environment(locust_classes=[CpuUser]) + environment = Environment(user_classes=[CpuUser]) runner = LocalRunner(environment) self.assertFalse(runner.cpu_warning_emitted) runner.spawn_locusts(1, 1, wait=False) @@ -131,12 +131,12 @@ class L2(BaseUser): class L3(BaseUser): weight = 100 - runner = Environment(locust_classes=[L1, L2, L3]).create_local_runner() + runner = Environment(user_classes=[L1, L2, L3]).create_local_runner() self.assert_locust_class_distribution({L1:10, L2:9, L3:10}, runner.weight_locusts(29)) self.assert_locust_class_distribution({L1:10, L2:10, L3:10}, runner.weight_locusts(30)) self.assert_locust_class_distribution({L1:11, L2:10, L3:10}, runner.weight_locusts(31)) - def test_weight_locusts_fewer_amount_than_locust_classes(self): + def test_weight_locusts_fewer_amount_than_user_classes(self): class BaseUser(User): pass class L1(BaseUser): @@ -146,7 +146,7 @@ class L2(BaseUser): class L3(BaseUser): weight = 100 - runner = Environment(locust_classes=[L1, L2, L3]).create_local_runner() + runner = Environment(user_classes=[L1, L2, L3]).create_local_runner() self.assertEqual(1, len(runner.weight_locusts(1))) self.assert_locust_class_distribution({L1:1}, runner.weight_locusts(1)) @@ -159,7 +159,7 @@ class task_set(TaskSet): @task def trigger(self): triggered[0] = True - runner = Environment(locust_classes=[BaseUser]).create_local_runner() + runner = Environment(user_classes=[BaseUser]).create_local_runner() runner.spawn_locusts(2, hatch_rate=2, wait=False) self.assertEqual(2, len(runner.locusts)) g1 = list(runner.locusts)[0] @@ -180,7 +180,7 @@ def my_task(self): test_start_run = [0] - environment = Environment(locust_classes=[MyUser]) + environment = Environment(user_classes=[MyUser]) def on_test_start(*args, **kwargs): test_start_run[0] += 1 environment.events.test_start.add_listener(on_test_start) @@ -200,7 +200,7 @@ def my_task(self): pass test_stop_run = [0] - environment = Environment(locust_classes=[User]) + environment = Environment(user_classes=[User]) def on_test_stop(*args, **kwargs): test_stop_run[0] += 1 environment.events.test_stop.add_listener(on_test_stop) @@ -219,7 +219,7 @@ def my_task(self): pass test_stop_run = [0] - environment = Environment(locust_classes=[User]) + environment = Environment(user_classes=[User]) def on_test_stop(*args, **kwargs): test_stop_run[0] += 1 environment.events.test_stop.add_listener(on_test_stop) @@ -238,7 +238,7 @@ def my_task(self): pass test_stop_run = [0] - environment = Environment(locust_classes=[MyUser]) + environment = Environment(user_classes=[MyUser]) def on_test_stop(*args, **kwargs): test_stop_run[0] += 1 environment.events.test_stop.add_listener(on_test_stop) @@ -257,7 +257,7 @@ class MyUser(User): def my_task(self): pass - environment = Environment(locust_classes=[MyUser]) + environment = Environment(user_classes=[MyUser]) runner = LocalRunner(environment) runner.start(locust_count=10, hatch_rate=5, wait=False) sleep(0.6) @@ -281,7 +281,7 @@ def my_task(self): ) sleep(2) - environment = Environment(locust_classes=[MyUser], reset_stats=True) + environment = Environment(user_classes=[MyUser], reset_stats=True) runner = LocalRunner(environment) runner.start(locust_count=6, hatch_rate=12, wait=False) sleep(0.25) @@ -305,7 +305,7 @@ def my_task(self): ) sleep(2) - environment = Environment(reset_stats=False, locust_classes=[MyUser]) + environment = Environment(reset_stats=False, user_classes=[MyUser]) runner = LocalRunner(environment) runner.start(locust_count=6, hatch_rate=12, wait=False) sleep(0.25) @@ -339,13 +339,13 @@ def incr_stats(l): ) with mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3): # start a Master runner - master_env = Environment(locust_classes=[TestUser]) + master_env = Environment(user_classes=[TestUser]) master = master_env.create_master_runner("*", 0) sleep(0) # start 3 Worker runners workers = [] for i in range(3): - worker_env = Environment(locust_classes=[TestUser]) + worker_env = Environment(user_classes=[TestUser]) worker = worker_env.create_worker_runner("127.0.0.1", master.server.port) workers.append(worker) @@ -718,7 +718,7 @@ class MyTestUser(User): tasks = [MyTaskSet] wait_time = constant(0.1) - environment = Environment(locust_classes=[MyTestUser]) + environment = Environment(user_classes=[MyTestUser]) runner = LocalRunner(environment) timeout = gevent.Timeout(2.0) @@ -802,7 +802,7 @@ class MyUser(User): def will_error(self): raise HeyAnException(":(") - self.environment.locust_classes = [MyUser] + self.environment.user_classes = [MyUser] runner = self.environment.create_local_runner() l = MyUser(self.environment) @@ -841,7 +841,7 @@ class MyUser(User): # set config to catch exceptions in locust users self.environment.catch_exceptions = True - self.environment.locust_classes = [MyUser] + self.environment.user_classes = [MyUser] runner = LocalRunner(self.environment) l = MyUser(self.environment) @@ -881,10 +881,10 @@ def tearDown(self): #events.report_to_master._handlers = self._report_to_master_event_handlers super(TestWorkerRunner, self).tearDown() - def get_runner(self, environment=None, locust_classes=[]): + def get_runner(self, environment=None, user_classes=[]): if environment is None: environment = self.environment - environment.locust_classes = locust_classes + environment.user_classes = user_classes return WorkerRunner(environment, master_host="localhost", master_port=5557) def test_worker_stop_timeout(self): @@ -903,7 +903,7 @@ def the_task(self): @environment.events.test_start.add_listener def on_test_start(**kw): test_start_run[0] = True - worker = self.get_runner(environment=environment, locust_classes=[MyTestUser]) + worker = self.get_runner(environment=environment, user_classes=[MyTestUser]) self.assertEqual(1, len(client.outbox)) self.assertEqual("client_ready", client.outbox[0].type) client.mocked_send(Message("hatch", { @@ -940,7 +940,7 @@ def the_task(self): with mock.patch("locust.rpc.rpc.Client", mocked_rpc()) as client: environment = Environment(stop_timeout=None) - worker = self.get_runner(environment=environment, locust_classes=[MyTestUser]) + worker = self.get_runner(environment=environment, user_classes=[MyTestUser]) self.assertEqual(1, len(client.outbox)) self.assertEqual("client_ready", client.outbox[0].type) client.mocked_send(Message("hatch", { @@ -972,7 +972,7 @@ def my_task(self): with mock.patch("locust.rpc.rpc.Client", mocked_rpc()) as client: environment = Environment() - worker = self.get_runner(environment=environment, locust_classes=[MyUser]) + worker = self.get_runner(environment=environment, user_classes=[MyUser]) client.mocked_send(Message("hatch", { "hatch_rate": 5, @@ -1018,7 +1018,7 @@ class MyTestUser(User): tasks = [MyTaskSet] wait_time = constant(0) - environment = Environment(locust_classes=[MyTestUser]) + environment = Environment(user_classes=[MyTestUser]) runner = environment.create_local_runner() runner.start(1, 1, wait=False) gevent.sleep(short_time / 2) @@ -1026,7 +1026,7 @@ class MyTestUser(User): self.assertEqual("first", MyTaskSet.state) # exit with timeout - environment = Environment(locust_classes=[MyTestUser], stop_timeout=short_time/2) + environment = Environment(user_classes=[MyTestUser], stop_timeout=short_time / 2) runner = environment.create_local_runner() runner.start(1, 1, wait=False) gevent.sleep(short_time) @@ -1034,7 +1034,7 @@ class MyTestUser(User): self.assertEqual("second", MyTaskSet.state) # allow task iteration to complete, with some margin - environment = Environment(locust_classes=[MyTestUser], stop_timeout=short_time*3) + environment = Environment(user_classes=[MyTestUser], stop_timeout=short_time * 3) runner = environment.create_local_runner() runner.start(1, 1, wait=False) gevent.sleep(short_time) @@ -1087,7 +1087,7 @@ class MyTestUser(User): tasks = [MyTaskSet] wait_time = between(1, 1) - environment = Environment(locust_classes=[MyTestUser], stop_timeout=short_time) + environment = Environment(user_classes=[MyTestUser], stop_timeout=short_time) runner = environment.create_local_runner() runner.start(1, 1) gevent.sleep(short_time) # sleep to make sure locust has had time to start waiting diff --git a/locust/test/test_stats.py b/locust/test/test_stats.py index 77b834eacb..dc0b6a1181 100644 --- a/locust/test/test_stats.py +++ b/locust/test/test_stats.py @@ -387,7 +387,7 @@ class TestUser(User): @task def t(self): self.environment.runner.stats.log_request("GET", "/", 10, 10) - environment = Environment(locust_classes=[TestUser]) + environment = Environment(user_classes=[TestUser]) runner = environment.create_local_runner() runner.start(3, 5) # spawn a user every 0.2 second gevent.sleep(0.1) diff --git a/locust/test/test_web.py b/locust/test/test_web.py index 347306060f..59f56057c6 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -179,7 +179,7 @@ class MyUser(User): @task(1) def my_task(self): pass - self.environment.locust_classes = [MyUser] + self.environment.user_classes = [MyUser] response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, data={"locust_count": 5, "hatch_rate": 5, "host": "https://localhost"}, @@ -194,7 +194,7 @@ class MyUser(User): @task(1) def my_task(self): pass - self.environment.locust_classes = [MyUser] + self.environment.user_classes = [MyUser] response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, data={'locust_count': 5, 'hatch_rate': 5}, @@ -206,29 +206,29 @@ def my_task(self): def test_host_value_from_locust_class(self): class MyUser(User): host = "http://example.com" - self.environment.locust_classes = [MyUser] + self.environment.user_classes = [MyUser] response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertIn("http://example.com", response.content.decode("utf-8")) self.assertNotIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) - def test_host_value_from_multiple_locust_classes(self): + def test_host_value_from_multiple_user_classes(self): class MyUser(User): host = "http://example.com" class MyUser2(User): host = "http://example.com" - self.environment.locust_classes = [MyUser, MyUser2] + self.environment.user_classes = [MyUser, MyUser2] response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertIn("http://example.com", response.content.decode("utf-8")) self.assertNotIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) - def test_host_value_from_multiple_locust_classes_different_hosts(self): + def test_host_value_from_multiple_user_classes_different_hosts(self): class MyUser(User): host = None class MyUser2(User): host = "http://example.com" - self.environment.locust_classes = [MyUser, MyUser2] + self.environment.user_classes = [MyUser, MyUser2] response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertNotIn("http://example.com", response.content.decode("utf-8")) @@ -240,7 +240,7 @@ class MyUser(User): @task(1) def my_task(self): pass - self.environment.locust_classes = [MyUser] + self.environment.user_classes = [MyUser] self.environment.step_load = True response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, diff --git a/locust/web.py b/locust/web.py index f5923a2296..253698d49d 100644 --- a/locust/web.py +++ b/locust/web.py @@ -106,8 +106,8 @@ def index(): override_host_warning = False if environment.host: host = environment.host - elif environment.runner.locust_classes: - all_hosts = set([l.host for l in environment.runner.locust_classes]) + elif environment.runner.user_classes: + all_hosts = set([l.host for l in environment.runner.user_classes]) if len(all_hosts) == 1: host = list(all_hosts)[0] else: From 365d2e593b97e6ed147c17f5cb47ff012defbba7 Mon Sep 17 00:00:00 2001 From: anuj_ Date: Tue, 21 Apr 2020 17:26:45 +1200 Subject: [PATCH 16/37] More renaming. There is an implicit contextual change i.e. locusts are now referred to as users therefore changed some of the verbs of various methods. Especially `kill_locusts`, which is now changed to `stop_users` as `kill_users` wouldn't read very well. --- locust/core.py | 2 +- locust/env.py | 2 +- locust/event.py | 2 +- locust/main.py | 18 ++-- locust/runners.py | 194 ++++++++++++++++++------------------ locust/test/test_runners.py | 52 +++++----- locust/web.py | 4 +- 7 files changed, 137 insertions(+), 137 deletions(-) diff --git a/locust/core.py b/locust/core.py index caaf64d88b..3d8e6eae7f 100644 --- a/locust/core.py +++ b/locust/core.py @@ -246,7 +246,7 @@ def run(self, *args, **kwargs): self.on_stop() raise except Exception as e: - self.locust.environment.events.locust_error.fire(locust_instance=self, exception=e, tb=sys.exc_info()[2]) + self.locust.environment.events.user_error.fire(locust_instance=self, exception=e, tb=sys.exc_info()[2]) if self.locust.environment.catch_exceptions: logger.error("%s\n%s", e, traceback.format_exc()) self.wait() diff --git a/locust/env.py b/locust/env.py index 61e779382a..a9013c2102 100644 --- a/locust/env.py +++ b/locust/env.py @@ -13,7 +13,7 @@ class Environment: """ user_classes = [] - """Locust User classes that the runner will run""" + """User classes that the runner will run""" stats = None """Reference to RequestStats instance""" diff --git a/locust/event.py b/locust/event.py index 97346c3f68..bc4767f4ef 100644 --- a/locust/event.py +++ b/locust/event.py @@ -61,7 +61,7 @@ class Events: :param exception: Exception instance that was thrown """ - locust_error = EventHook + user_error = EventHook """ Fired when an exception occurs inside the execution of a User class. diff --git a/locust/main.py b/locust/main.py index 64f0a08128..396840322f 100644 --- a/locust/main.py +++ b/locust/main.py @@ -108,7 +108,7 @@ def main(): locustfile = parse_locustfile_option() # import the locustfile - docstring, locusts = load_locustfile(locustfile) + docstring, users = load_locustfile(locustfile) # parse all command line options options = parse_options() @@ -129,27 +129,27 @@ def main(): greenlet_exception_handler = greenlet_exception_logger(logger) if options.list_commands: - print("Available Locusts:") - for name in locusts: + print("Available Users:") + for name in users: print(" " + name) sys.exit(0) - if not locusts: - logger.error("No Locust class found!") + if not users: + logger.error("No User class found!") sys.exit(1) # make sure specified User exists if options.user_classes: - missing = set(options.user_classes) - set(locusts.keys()) + missing = set(options.user_classes) - set(users.keys()) if missing: logger.error("Unknown User(s): %s\n" % (", ".join(missing))) sys.exit(1) else: - names = set(options.user_classes) & set(locusts.keys()) - user_classes = [locusts[n] for n in names] + names = set(options.user_classes) & set(users.keys()) + user_classes = [users[n] for n in names] else: # list() call is needed to consume the dict_view object in Python 3 - user_classes = list(locusts.values()) + user_classes = list(users.values()) # create locust Environment environment = create_environment(user_classes, options, events=locust.events) diff --git a/locust/runners.py b/locust/runners.py index 6576e05f8a..f7fa0a1af0 100644 --- a/locust/runners.py +++ b/locust/runners.py @@ -33,7 +33,7 @@ class Runner(object): """ - Orchestrates the load test by starting and stopping the locust users. + Orchestrates the load test by starting and stopping the users. Use one of the :meth:`create_local_runner `, :meth:`create_master_runner ` or @@ -43,7 +43,7 @@ class Runner(object): """ def __init__(self, environment): self.environment = environment - self.locusts = Group() + self.users = Group() self.greenlet = Group() self.state = STATE_INIT self.hatching_greenlet = None @@ -94,9 +94,9 @@ def errors(self): @property def user_count(self): """ - :returns: Number of currently running locust users + :returns: Number of currently running users """ - return len(self.locusts) + return len(self.users) def cpu_log_warning(self): """Called at the end of the test to repeat the warning & return the status""" @@ -105,46 +105,46 @@ def cpu_log_warning(self): return True return False - def weight_locusts(self, amount): + def weight_users(self, amount): """ - Distributes the amount of locusts for each WebLocust-class according to it's weight - returns a list "bucket" with the weighted locusts + Distributes the amount of users for each WebLocust-class according to it's weight + returns a list "bucket" with the weighted users """ bucket = [] - weight_sum = sum([locust.weight for locust in self.user_classes]) + weight_sum = sum([user.weight for user in self.user_classes]) residuals = {} - for locust in self.user_classes: + for user in self.user_classes: if self.environment.host is not None: - locust.host = self.environment.host + user.host = self.environment.host - # create locusts depending on weight - percent = locust.weight / float(weight_sum) - num_locusts = int(round(amount * percent)) - bucket.extend([locust for x in range(num_locusts)]) + # create users depending on weight + percent = user.weight / float(weight_sum) + num_users = int(round(amount * percent)) + bucket.extend([user for x in range(num_users)]) # used to keep track of the amount of rounding was done if we need # to add/remove some instances from bucket - residuals[locust] = amount * percent - round(amount * percent) + residuals[user] = amount * percent - round(amount * percent) if len(bucket) < amount: - # We got too few locust classes in the bucket, so we need to create a few extra locusts, + # We got too few User classes in the bucket, so we need to create a few extra users, # and we do this by iterating over each of the User classes - starting with the one # where the residual from the rounding was the largest - and creating one of each until # we get the correct amount - for locust in [l for l, r in sorted(residuals.items(), key=lambda x:x[1], reverse=True)][:amount-len(bucket)]: - bucket.append(locust) + for user in [l for l, r in sorted(residuals.items(), key=lambda x:x[1], reverse=True)][:amount-len(bucket)]: + bucket.append(user) elif len(bucket) > amount: - # We've got too many locusts due to rounding errors so we need to remove some - for locust in [l for l, r in sorted(residuals.items(), key=lambda x:x[1])][:len(bucket)-amount]: - bucket.remove(locust) + # We've got too many users due to rounding errors so we need to remove some + for user in [l for l, r in sorted(residuals.items(), key=lambda x:x[1])][:len(bucket)-amount]: + bucket.remove(user) return bucket - def spawn_locusts(self, spawn_count, hatch_rate, wait=False): - bucket = self.weight_locusts(spawn_count) + def spawn_users(self, spawn_count, hatch_rate, wait=False): + bucket = self.weight_users(spawn_count) spawn_count = len(bucket) if self.state == STATE_INIT or self.state == STATE_STOPPED: self.state = STATE_HATCHING - existing_count = len(self.locusts) + existing_count = len(self.users) logger.info("Hatching and swarming %i users at the rate %g users/s (%i users already running)..." % (spawn_count, hatch_rate, existing_count)) occurrence_count = dict([(l.__name__, 0) for l in self.user_classes]) @@ -152,60 +152,60 @@ def hatch(): sleep_time = 1.0 / hatch_rate while True: if not bucket: - logger.info("All locusts hatched: %s (%i already running)" % ( + logger.info("All users hatched: %s (%i already running)" % ( ", ".join(["%s: %d" % (name, count) for name, count in occurrence_count.items()]), existing_count, )) - self.environment.events.hatch_complete.fire(user_count=len(self.locusts)) + self.environment.events.hatch_complete.fire(user_count=len(self.users)) return - locust_class = bucket.pop(random.randint(0, len(bucket)-1)) - occurrence_count[locust_class.__name__] += 1 - new_locust = locust_class(self.environment) - new_locust.start(self.locusts) - if len(self.locusts) % 10 == 0: - logger.debug("%i locusts hatched" % len(self.locusts)) + user_class = bucket.pop(random.randint(0, len(bucket)-1)) + occurrence_count[user_class.__name__] += 1 + new_user = user_class(self.environment) + new_user.start(self.users) + if len(self.users) % 10 == 0: + logger.debug("%i users hatched" % len(self.users)) if bucket: gevent.sleep(sleep_time) hatch() if wait: - self.locusts.join() - logger.info("All locusts dead\n") + self.users.join() + logger.info("All users stopped\n") - def kill_locusts(self, kill_count): + def stop_users(self, user_count): """ - Kill a kill_count of weighted locusts from the Group() object in self.locusts + Stop a stop_count of weighted users from the Group() object in self.users """ - bucket = self.weight_locusts(kill_count) - kill_count = len(bucket) - logger.info("Killing %i locusts" % kill_count) - to_kill = [] - for g in self.locusts: + bucket = self.weight_users(user_count) + user_count = len(bucket) + logger.info("Stopping %i users" % user_count) + to_stop = [] + for g in self.users: for l in bucket: user = g.args[0] if l == type(user): - to_kill.append(user) + to_stop.append(user) bucket.remove(l) break - self.kill_locust_instances(to_kill) + self.stop_user_instances(to_stop) self.environment.events.hatch_complete.fire(user_count=self.user_count) - def kill_locust_instances(self, users): + def stop_user_instances(self, users): if self.environment.stop_timeout: - dying = Group() + stopping = Group() for user in users: - if not user.stop(self.locusts, force=False): - # User.stop() returns False if the greenlet was not killed, so we'll need - # to add it's greenlet to our dying Group so we can wait for it to finish it's task - dying.add(user._greenlet) - if not dying.join(timeout=self.environment.stop_timeout): - logger.info("Not all locusts finished their tasks & terminated in %s seconds. Killing them..." % self.environment.stop_timeout) - dying.kill(block=True) + if not user.stop(self.users, force=False): + # User.stop() returns False if the greenlet was not stopped, so we'll need + # to add it's greenlet to our stopping Group so we can wait for it to finish it's task + stopping.add(user._greenlet) + if not stopping.join(timeout=self.environment.stop_timeout): + logger.info("Not all users finished their tasks & terminated in %s seconds. Stopping them..." % self.environment.stop_timeout) + stopping.kill(block=True) else: for user in users: - user.stop(self.locusts, force=True) + user.stop(self.users, force=True) def monitor_cpu(self): process = psutil.Process() @@ -216,12 +216,12 @@ def monitor_cpu(self): self.cpu_warning_emitted = True gevent.sleep(CPU_MONITOR_INTERVAL) - def start(self, locust_count, hatch_rate, wait=False): + def start(self, user_count, hatch_rate, wait=False): """ Start running a load test - :param locust_count: Number of locust users to start - :param hatch_rate: Number of locust users to spawn per second + :param user_count: Number of users to start + :param hatch_rate: Number of users to spawn per second :param wait: If True calls to this method will block until all users are spawned. If False (the default), a greenlet that spawns the users will be started and the call to this method will return immediately. @@ -231,37 +231,37 @@ def start(self, locust_count, hatch_rate, wait=False): self.exceptions = {} self.cpu_warning_emitted = False self.worker_cpu_warning_emitted = False - self.target_user_count = locust_count + self.target_user_count = user_count - # Dynamically changing the locust count + # Dynamically changing the user count if self.state != STATE_INIT and self.state != STATE_STOPPED: self.state = STATE_HATCHING - if self.user_count > locust_count: - # Kill some locusts - kill_count = self.user_count - locust_count - self.kill_locusts(kill_count) - elif self.user_count < locust_count: - # Spawn some locusts - spawn_count = locust_count - self.user_count - self.spawn_locusts(spawn_count=spawn_count, hatch_rate=hatch_rate) + if self.user_count > user_count: + # Stop some users + stop_count = self.user_count - user_count + self.stop_users(stop_count) + elif self.user_count < user_count: + # Spawn some users + spawn_count = user_count - self.user_count + self.spawn_users(spawn_count=spawn_count, hatch_rate=hatch_rate) else: self.environment.events.hatch_complete.fire(user_count=self.user_count) else: self.hatch_rate = hatch_rate - self.spawn_locusts(locust_count, hatch_rate=hatch_rate, wait=wait) + self.spawn_users(user_count, hatch_rate=hatch_rate, wait=wait) - def start_stepload(self, locust_count, hatch_rate, step_locust_count, step_duration): - if locust_count < step_locust_count: - logger.error("Invalid parameters: total locust count of %d is smaller than step locust count of %d" % (locust_count, step_locust_count)) + def start_stepload(self, user_count, hatch_rate, step_user_count, step_duration): + if user_count < step_user_count: + logger.error("Invalid parameters: total user count of %d is smaller than step user count of %d" % (user_count, step_user_count)) return - self.total_clients = locust_count + self.total_clients = user_count if self.stepload_greenlet: logger.info("There is an ongoing swarming in Step Load mode, will stop it now.") self.stepload_greenlet.kill() - logger.info("Start a new swarming in Step Load mode: total locust count of %d, hatch rate of %d, step locust count of %d, step duration of %d " % (locust_count, hatch_rate, step_locust_count, step_duration)) + logger.info("Start a new swarming in Step Load mode: total user count of %d, hatch rate of %d, step user count of %d, step duration of %d " % (user_count, hatch_rate, step_user_count, step_duration)) self.state = STATE_INIT - self.stepload_greenlet = self.greenlet.spawn(self.stepload_worker, hatch_rate, step_locust_count, step_duration) + self.stepload_greenlet = self.greenlet.spawn(self.stepload_worker, hatch_rate, step_user_count, step_duration) self.stepload_greenlet.link_exception(greenlet_exception_handler) def stepload_worker(self, hatch_rate, step_clients_growth, step_duration): @@ -272,18 +272,18 @@ def stepload_worker(self, hatch_rate, step_clients_growth, step_duration): logger.info('Step Load is finished.') break self.start(current_num_clients, hatch_rate) - logger.info('Step loading: start hatch job of %d locust.' % (current_num_clients)) + logger.info('Step loading: start hatch job of %d user.' % (current_num_clients)) gevent.sleep(step_duration) def stop(self): """ - Stop a running load test by killing all running locusts + Stop a running load test by stopping all running users """ self.state = STATE_CLEANUP - # if we are currently hatching locusts we need to kill the hatching greenlet first + # if we are currently hatching users we need to kill the hatching greenlet first if self.hatching_greenlet and not self.hatching_greenlet.ready(): self.hatching_greenlet.kill(block=True) - self.kill_locust_instances([g.args[0] for g in self.locusts]) + self.stop_user_instances([g.args[0] for g in self.users]) self.state = STATE_STOPPED self.cpu_log_warning() @@ -313,13 +313,13 @@ def __init__(self, environment): super(LocalRunner, self).__init__(environment) # register listener thats logs the exception for the local runner - def on_locust_error(locust_instance, exception, tb): + def on_user_error(user_instance, exception, tb): formatted_tb = "".join(traceback.format_tb(tb)) self.log_exception("local", str(exception), formatted_tb) - self.environment.events.locust_error.add_listener(on_locust_error) + self.environment.events.user_error.add_listener(on_user_error) - def start(self, locust_count, hatch_rate, wait=False): - self.target_user_count = locust_count + def start(self, user_count, hatch_rate, wait=False): + self.target_user_count = user_count if hatch_rate > 100: logger.warning("Your selected hatch rate is very high (>100), and this is known to sometimes cause issues. Do you really need to ramp up that fast?") @@ -330,7 +330,7 @@ def start(self, locust_count, hatch_rate, wait=False): if self.hatching_greenlet: # kill existing hatching_greenlet before we start a new one self.hatching_greenlet.kill(block=True) - self.hatching_greenlet = self.greenlet.spawn(lambda: super(LocalRunner, self).start(locust_count, hatch_rate, wait=wait)) + self.hatching_greenlet = self.greenlet.spawn(lambda: super(LocalRunner, self).start(user_count, hatch_rate, wait=wait)) self.hatching_greenlet.link_exception(greenlet_exception_handler) def stop(self): @@ -358,9 +358,9 @@ class MasterRunner(DistributedRunner): """ Runner used to run distributed load tests across multiple processes and/or machines. - MasterRunner doesn't spawn any locust user greenlets itself. Instead it expects + MasterRunner doesn't spawn any user greenlets itself. Instead it expects :class:`WorkerRunners ` to connect to it, which it will then direct - to start and stop locust user greenlets. Stats sent back from the + to start and stop user greenlets. Stats sent back from the :class:`WorkerRunners ` will aggregated. """ def __init__(self, environment, master_bind_host, master_bind_port): @@ -403,7 +403,7 @@ def missing(self): self.greenlet.spawn(self.heartbeat_worker).link_exception(greenlet_exception_handler) self.greenlet.spawn(self.client_listener).link_exception(greenlet_exception_handler) - # listener that gathers info on how many locust users the worker has spawned + # listener that gathers info on how many users the worker has spawned def on_worker_report(client_id, data): if client_id not in self.clients: logger.info("Discarded report from unrecognized worker %s", client_id) @@ -428,8 +428,8 @@ def cpu_log_warning(self): warning_emitted = True return warning_emitted - def start(self, locust_count, hatch_rate): - self.target_user_count = locust_count + def start(self, user_count, hatch_rate): + self.target_user_count = user_count num_workers = len(self.clients.ready) + len(self.clients.running) + len(self.clients.hatching) if not num_workers: logger.warning("You are running in distributed mode but have no worker servers connected. " @@ -437,11 +437,11 @@ def start(self, locust_count, hatch_rate): return self.hatch_rate = hatch_rate - worker_num_clients = locust_count // (num_workers or 1) + worker_num_clients = user_count // (num_workers or 1) worker_hatch_rate = float(hatch_rate) / (num_workers or 1) - remaining = locust_count % num_workers + remaining = user_count % num_workers - logger.info("Sending hatch jobs of %d locusts and %.2f hatch rate to %d ready clients" % (worker_num_clients, worker_hatch_rate, num_workers)) + logger.info("Sending hatch jobs of %d users and %.2f hatch rate to %d ready clients" % (worker_num_clients, worker_hatch_rate, num_workers)) if worker_hatch_rate > 100: logger.warning("Your selected hatch rate is very high (>100/worker), and this is known to sometimes cause issues. Do you really need to ramp up that fast?") @@ -582,7 +582,7 @@ class WorkerRunner(DistributedRunner): Runner used to run distributed load tests across multiple processes and/or machines. WorkerRunner connects to a :class:`MasterRunner` from which it'll receive - instructions to start and stop locust user greenlets. The WorkerRunner will preiodically + instructions to start and stop user greenlets. The WorkerRunner will preiodically take the stats generated by the running users and send back to the :class:`MasterRunner`. """ @@ -603,13 +603,13 @@ def __init__(self, environment, master_host, master_port): self.worker_state = STATE_INIT self.greenlet.spawn(self.stats_reporter).link_exception(greenlet_exception_handler) - # register listener for when all locust users have hatched, and report it to the master node + # register listener for when all users have hatched, and report it to the master node def on_hatch_complete(user_count): self.client.send(Message("hatch_complete", {"count":user_count}, self.client_id)) self.worker_state = STATE_RUNNING self.environment.events.hatch_complete.add_listener(on_hatch_complete) - # register listener that adds the current number of spawned locusts to the report that is sent to the master node + # register listener that adds the current number of spawned users to the report that is sent to the master node def on_report_to_master(client_id, data): data["user_count"] = self.user_count self.environment.events.report_to_master.add_listener(on_report_to_master) @@ -619,11 +619,11 @@ def on_quitting(): self.client.send(Message("quit", None, self.client_id)) self.environment.events.quitting.add_listener(on_quitting) - # register listener thats sends locust exceptions to master - def on_locust_error(locust_instance, exception, tb): + # register listener thats sends user exceptions to master + def on_user_error(user_instance, exception, tb): formatted_tb = "".join(traceback.format_tb(tb)) self.client.send(Message("exception", {"msg" : str(exception), "traceback" : formatted_tb}, self.client_id)) - self.environment.events.locust_error.add_listener(on_locust_error) + self.environment.events.user_error.add_listener(on_user_error) def heartbeat(self): while True: @@ -660,7 +660,7 @@ def worker(self): if self.hatching_greenlet: # kill existing hatching greenlet before we launch new one self.hatching_greenlet.kill(block=True) - self.hatching_greenlet = self.greenlet.spawn(lambda: self.start(locust_count=job["num_clients"], hatch_rate=job["hatch_rate"])) + self.hatching_greenlet = self.greenlet.spawn(lambda: self.start(user_count=job["num_clients"], hatch_rate=job["hatch_rate"])) self.hatching_greenlet.link_exception(greenlet_exception_handler) elif msg.type == "stop": self.stop() diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index 2e20186135..db23989944 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -113,7 +113,7 @@ def cpu_task(self): environment = Environment(user_classes=[CpuUser]) runner = LocalRunner(environment) self.assertFalse(runner.cpu_warning_emitted) - runner.spawn_locusts(1, 1, wait=False) + runner.spawn_users(1, 1, wait=False) sleep(2.5) runner.quit() self.assertTrue(runner.cpu_warning_emitted) @@ -132,9 +132,9 @@ class L3(BaseUser): weight = 100 runner = Environment(user_classes=[L1, L2, L3]).create_local_runner() - self.assert_locust_class_distribution({L1:10, L2:9, L3:10}, runner.weight_locusts(29)) - self.assert_locust_class_distribution({L1:10, L2:10, L3:10}, runner.weight_locusts(30)) - self.assert_locust_class_distribution({L1:11, L2:10, L3:10}, runner.weight_locusts(31)) + self.assert_locust_class_distribution({L1:10, L2:9, L3:10}, runner.weight_users(29)) + self.assert_locust_class_distribution({L1:10, L2:10, L3:10}, runner.weight_users(30)) + self.assert_locust_class_distribution({L1:11, L2:10, L3:10}, runner.weight_users(31)) def test_weight_locusts_fewer_amount_than_user_classes(self): class BaseUser(User): @@ -147,8 +147,8 @@ class L3(BaseUser): weight = 100 runner = Environment(user_classes=[L1, L2, L3]).create_local_runner() - self.assertEqual(1, len(runner.weight_locusts(1))) - self.assert_locust_class_distribution({L1:1}, runner.weight_locusts(1)) + self.assertEqual(1, len(runner.weight_users(1))) + self.assert_locust_class_distribution({L1:1}, runner.weight_users(1)) def test_kill_locusts(self): triggered = [False] @@ -160,11 +160,11 @@ class task_set(TaskSet): def trigger(self): triggered[0] = True runner = Environment(user_classes=[BaseUser]).create_local_runner() - runner.spawn_locusts(2, hatch_rate=2, wait=False) + runner.spawn_users(2, hatch_rate=2, wait=False) self.assertEqual(2, len(runner.locusts)) g1 = list(runner.locusts)[0] g2 = list(runner.locusts)[1] - runner.kill_locusts(2) + runner.stop_users(2) self.assertEqual(0, len(runner.locusts)) self.assertTrue(g1.dead) self.assertTrue(g2.dead) @@ -186,7 +186,7 @@ def on_test_start(*args, **kwargs): environment.events.test_start.add_listener(on_test_start) runner = LocalRunner(environment) - runner.start(locust_count=3, hatch_rate=3, wait=False) + runner.start(user_count=3, hatch_rate=3, wait=False) runner.hatching_greenlet.get(timeout=3) self.assertEqual(1, test_start_run[0]) @@ -206,7 +206,7 @@ def on_test_stop(*args, **kwargs): environment.events.test_stop.add_listener(on_test_stop) runner = LocalRunner(environment) - runner.start(locust_count=3, hatch_rate=3, wait=False) + runner.start(user_count=3, hatch_rate=3, wait=False) self.assertEqual(0, test_stop_run[0]) runner.stop() self.assertEqual(1, test_stop_run[0]) @@ -225,7 +225,7 @@ def on_test_stop(*args, **kwargs): environment.events.test_stop.add_listener(on_test_stop) runner = LocalRunner(environment) - runner.start(locust_count=3, hatch_rate=3, wait=False) + runner.start(user_count=3, hatch_rate=3, wait=False) self.assertEqual(0, test_stop_run[0]) runner.quit() self.assertEqual(1, test_stop_run[0]) @@ -244,7 +244,7 @@ def on_test_stop(*args, **kwargs): environment.events.test_stop.add_listener(on_test_stop) runner = LocalRunner(environment) - runner.start(locust_count=3, hatch_rate=3, wait=False) + runner.start(user_count=3, hatch_rate=3, wait=False) self.assertEqual(0, test_stop_run[0]) runner.stop() runner.quit() @@ -259,11 +259,11 @@ def my_task(self): environment = Environment(user_classes=[MyUser]) runner = LocalRunner(environment) - runner.start(locust_count=10, hatch_rate=5, wait=False) + runner.start(user_count=10, hatch_rate=5, wait=False) sleep(0.6) - runner.start(locust_count=5, hatch_rate=5, wait=False) + runner.start(user_count=5, hatch_rate=5, wait=False) runner.hatching_greenlet.join() - self.assertEqual(5, len(runner.locusts)) + self.assertEqual(5, len(runner.users)) runner.quit() def test_reset_stats(self): @@ -283,7 +283,7 @@ def my_task(self): environment = Environment(user_classes=[MyUser], reset_stats=True) runner = LocalRunner(environment) - runner.start(locust_count=6, hatch_rate=12, wait=False) + runner.start(user_count=6, hatch_rate=12, wait=False) sleep(0.25) self.assertGreaterEqual(runner.stats.get("/test", "GET").num_requests, 3) sleep(0.3) @@ -307,7 +307,7 @@ def my_task(self): environment = Environment(reset_stats=False, user_classes=[MyUser]) runner = LocalRunner(environment) - runner.start(locust_count=6, hatch_rate=12, wait=False) + runner.start(user_count=6, hatch_rate=12, wait=False) sleep(0.25) self.assertGreaterEqual(runner.stats.get("/test", "GET").num_requests, 3) sleep(0.3) @@ -626,7 +626,7 @@ def test_sends_hatch_data_to_ready_running_hatching_workers(self): master.clients[1].state = STATE_INIT master.clients[2].state = STATE_HATCHING master.clients[3].state = STATE_RUNNING - master.start(locust_count=5,hatch_rate=5) + master.start(user_count=5, hatch_rate=5) self.assertEqual(3, len(server.outbox)) @@ -916,13 +916,13 @@ def on_test_start(**kw): # wait for worker to hatch locusts self.assertIn("hatching", [m.type for m in client.outbox]) worker.hatching_greenlet.join() - self.assertEqual(1, len(worker.locusts)) + self.assertEqual(1, len(worker.users)) # check that locust has started running gevent.sleep(0.01) self.assertEqual(1, MyTestUser._test_state) # send stop message client.mocked_send(Message("stop", None, "dummy_client_id")) - worker.locusts.join() + worker.users.join() # check that locust user got to finish self.assertEqual(2, MyTestUser._test_state) # make sure the test_start was never fired on the worker @@ -953,13 +953,13 @@ def the_task(self): # wait for worker to hatch locusts self.assertIn("hatching", [m.type for m in client.outbox]) worker.hatching_greenlet.join() - self.assertEqual(1, len(worker.locusts)) + self.assertEqual(1, len(worker.users)) # check that locust has started running gevent.sleep(0.01) self.assertEqual(1, MyTestUser._test_state) # send stop message client.mocked_send(Message("stop", None, "dummy_client_id")) - worker.locusts.join() + worker.users.join() # check that locust user did not get to finish self.assertEqual(1, MyTestUser._test_state) @@ -990,7 +990,7 @@ def my_task(self): }, "dummy_client_id")) sleep(0) worker.hatching_greenlet.join() - self.assertEqual(9, len(worker.locusts)) + self.assertEqual(9, len(worker.users)) worker.quit() class TestMessageSerializing(unittest.TestCase): @@ -1179,7 +1179,7 @@ class MyTestUser(User): runner = environment.create_local_runner() runner.start(1, 1) gevent.sleep(short_time / 2) - runner.kill_locusts(1) + runner.stop_users(1) self.assertEqual("first", MyTaskSet.state) runner.quit() environment.runner = None @@ -1188,7 +1188,7 @@ class MyTestUser(User): runner = environment.create_local_runner() runner.start(1, 1) gevent.sleep(short_time) - runner.kill_locusts(1) + runner.stop_users(1) self.assertEqual("second", MyTaskSet.state) runner.quit() environment.runner = None @@ -1200,7 +1200,7 @@ class MyTestUser(User): timeout = gevent.Timeout(short_time * 2) timeout.start() try: - runner.kill_locusts(1) + runner.stop_users(1) runner.locusts.join() except gevent.Timeout: self.fail("Got Timeout exception. Some locusts must have kept runnining after iteration finish") diff --git a/locust/web.py b/locust/web.py index 253698d49d..7928e66c21 100644 --- a/locust/web.py +++ b/locust/web.py @@ -111,8 +111,8 @@ def index(): if len(all_hosts) == 1: host = list(all_hosts)[0] else: - # since we have mulitple Locust classes with different host attributes, we'll - # inform that specifying host will override the host for all Locust classes + # since we have mulitple User classes with different host attributes, we'll + # inform that specifying host will override the host for all User classes override_host_warning = True host = None else: From a8239a398e7b4a9e3b5d190c53b868dca1c1297e Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Tue, 21 Apr 2020 10:47:00 +0200 Subject: [PATCH 17/37] Rename Runner.users to Runner.user_greenlets. Fix a broken test. --- locust/runners.py | 24 ++++++++++++------------ locust/test/test_runners.py | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/locust/runners.py b/locust/runners.py index f7fa0a1af0..46f33727eb 100644 --- a/locust/runners.py +++ b/locust/runners.py @@ -43,7 +43,7 @@ class Runner(object): """ def __init__(self, environment): self.environment = environment - self.users = Group() + self.user_greenlets = Group() self.greenlet = Group() self.state = STATE_INIT self.hatching_greenlet = None @@ -96,7 +96,7 @@ def user_count(self): """ :returns: Number of currently running users """ - return len(self.users) + return len(self.user_greenlets) def cpu_log_warning(self): """Called at the end of the test to repeat the warning & return the status""" @@ -144,7 +144,7 @@ def spawn_users(self, spawn_count, hatch_rate, wait=False): if self.state == STATE_INIT or self.state == STATE_STOPPED: self.state = STATE_HATCHING - existing_count = len(self.users) + existing_count = len(self.user_greenlets) logger.info("Hatching and swarming %i users at the rate %g users/s (%i users already running)..." % (spawn_count, hatch_rate, existing_count)) occurrence_count = dict([(l.__name__, 0) for l in self.user_classes]) @@ -156,21 +156,21 @@ def hatch(): ", ".join(["%s: %d" % (name, count) for name, count in occurrence_count.items()]), existing_count, )) - self.environment.events.hatch_complete.fire(user_count=len(self.users)) + self.environment.events.hatch_complete.fire(user_count=len(self.user_greenlets)) return user_class = bucket.pop(random.randint(0, len(bucket)-1)) occurrence_count[user_class.__name__] += 1 new_user = user_class(self.environment) - new_user.start(self.users) - if len(self.users) % 10 == 0: - logger.debug("%i users hatched" % len(self.users)) + new_user.start(self.user_greenlets) + if len(self.user_greenlets) % 10 == 0: + logger.debug("%i users hatched" % len(self.user_greenlets)) if bucket: gevent.sleep(sleep_time) hatch() if wait: - self.users.join() + self.user_greenlets.join() logger.info("All users stopped\n") def stop_users(self, user_count): @@ -181,7 +181,7 @@ def stop_users(self, user_count): user_count = len(bucket) logger.info("Stopping %i users" % user_count) to_stop = [] - for g in self.users: + for g in self.user_greenlets: for l in bucket: user = g.args[0] if l == type(user): @@ -196,7 +196,7 @@ def stop_user_instances(self, users): if self.environment.stop_timeout: stopping = Group() for user in users: - if not user.stop(self.users, force=False): + if not user.stop(self.user_greenlets, force=False): # User.stop() returns False if the greenlet was not stopped, so we'll need # to add it's greenlet to our stopping Group so we can wait for it to finish it's task stopping.add(user._greenlet) @@ -205,7 +205,7 @@ def stop_user_instances(self, users): stopping.kill(block=True) else: for user in users: - user.stop(self.users, force=True) + user.stop(self.user_greenlets, force=True) def monitor_cpu(self): process = psutil.Process() @@ -283,7 +283,7 @@ def stop(self): # if we are currently hatching users we need to kill the hatching greenlet first if self.hatching_greenlet and not self.hatching_greenlet.ready(): self.hatching_greenlet.kill(block=True) - self.stop_user_instances([g.args[0] for g in self.users]) + self.stop_user_instances([g.args[0] for g in self.user_greenlets]) self.state = STATE_STOPPED self.cpu_log_warning() diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index db23989944..cf47695322 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -161,11 +161,11 @@ def trigger(self): triggered[0] = True runner = Environment(user_classes=[BaseUser]).create_local_runner() runner.spawn_users(2, hatch_rate=2, wait=False) - self.assertEqual(2, len(runner.locusts)) - g1 = list(runner.locusts)[0] - g2 = list(runner.locusts)[1] + self.assertEqual(2, len(runner.user_greenlets)) + g1 = list(runner.user_greenlets)[0] + g2 = list(runner.user_greenlets)[1] runner.stop_users(2) - self.assertEqual(0, len(runner.locusts)) + self.assertEqual(0, len(runner.user_greenlets)) self.assertTrue(g1.dead) self.assertTrue(g2.dead) self.assertTrue(triggered[0]) @@ -263,7 +263,7 @@ def my_task(self): sleep(0.6) runner.start(user_count=5, hatch_rate=5, wait=False) runner.hatching_greenlet.join() - self.assertEqual(5, len(runner.users)) + self.assertEqual(5, len(runner.user_greenlets)) runner.quit() def test_reset_stats(self): @@ -916,13 +916,13 @@ def on_test_start(**kw): # wait for worker to hatch locusts self.assertIn("hatching", [m.type for m in client.outbox]) worker.hatching_greenlet.join() - self.assertEqual(1, len(worker.users)) + self.assertEqual(1, len(worker.user_greenlets)) # check that locust has started running gevent.sleep(0.01) self.assertEqual(1, MyTestUser._test_state) # send stop message client.mocked_send(Message("stop", None, "dummy_client_id")) - worker.users.join() + worker.user_greenlets.join() # check that locust user got to finish self.assertEqual(2, MyTestUser._test_state) # make sure the test_start was never fired on the worker @@ -953,13 +953,13 @@ def the_task(self): # wait for worker to hatch locusts self.assertIn("hatching", [m.type for m in client.outbox]) worker.hatching_greenlet.join() - self.assertEqual(1, len(worker.users)) + self.assertEqual(1, len(worker.user_greenlets)) # check that locust has started running gevent.sleep(0.01) self.assertEqual(1, MyTestUser._test_state) # send stop message client.mocked_send(Message("stop", None, "dummy_client_id")) - worker.users.join() + worker.user_greenlets.join() # check that locust user did not get to finish self.assertEqual(1, MyTestUser._test_state) @@ -990,7 +990,7 @@ def my_task(self): }, "dummy_client_id")) sleep(0) worker.hatching_greenlet.join() - self.assertEqual(9, len(worker.users)) + self.assertEqual(9, len(worker.user_greenlets)) worker.quit() class TestMessageSerializing(unittest.TestCase): From 5d23b6d61d7a73a5c10b112454dcee021b7d82c5 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Tue, 21 Apr 2020 10:52:40 +0200 Subject: [PATCH 18/37] Fix broken tests --- locust/core.py | 2 +- locust/test/test_runners.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/locust/core.py b/locust/core.py index 3d8e6eae7f..3efb2f65cd 100644 --- a/locust/core.py +++ b/locust/core.py @@ -246,7 +246,7 @@ def run(self, *args, **kwargs): self.on_stop() raise except Exception as e: - self.locust.environment.events.user_error.fire(locust_instance=self, exception=e, tb=sys.exc_info()[2]) + self.locust.environment.events.user_error.fire(user_instance=self, exception=e, tb=sys.exc_info()[2]) if self.locust.environment.catch_exceptions: logger.error("%s\n%s", e, traceback.format_exc()) self.wait() diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index cf47695322..2bc31ad773 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -1201,7 +1201,7 @@ class MyTestUser(User): timeout.start() try: runner.stop_users(1) - runner.locusts.join() + runner.user_greenlets.join() except gevent.Timeout: self.fail("Got Timeout exception. Some locusts must have kept runnining after iteration finish") finally: From 6a2e914fb331cc96ac282be750948323a9493831 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Tue, 21 Apr 2020 16:41:51 +0200 Subject: [PATCH 19/37] Change LocustClass to UserClass in CLI help message --- locust/argument_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locust/argument_parser.py b/locust/argument_parser.py index 99219bc5c6..506e2ab4c9 100644 --- a/locust/argument_parser.py +++ b/locust/argument_parser.py @@ -66,7 +66,7 @@ def get_empty_argument_parser(add_help=True, default_config_files=DEFAULT_CONFIG formatter_class=argparse.RawDescriptionHelpFormatter, usage=argparse.SUPPRESS, description=textwrap.dedent(""" - Usage: locust [OPTIONS] [LocustClass ...] + Usage: locust [OPTIONS] [UserClass ...] """), #epilog="", From f53d397de0910713ece33dfb5e3049a4eac0ec04 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Tue, 21 Apr 2020 16:44:00 +0200 Subject: [PATCH 20/37] Fix docstring --- locust/event.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locust/event.py b/locust/event.py index bc4767f4ef..78ca0465d4 100644 --- a/locust/event.py +++ b/locust/event.py @@ -67,7 +67,7 @@ class Events: Event arguments: - :param locust_instance: User class instance where the exception occurred + :param user_instance: User class instance where the exception occurred :param exception: Exception that was thrown :param tb: Traceback object (from sys.exc_info()[2]) """ From 0dc6f0524f5d14243917d79810c96675e3107834 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Tue, 21 Apr 2020 16:47:26 +0200 Subject: [PATCH 21/37] Replace renamed `-c` flag with `-u` in the docs examples --- docs/running-locust-in-step-load-mode.rst | 2 +- docs/running-locust-without-web-ui.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/running-locust-in-step-load-mode.rst b/docs/running-locust-in-step-load-mode.rst index 30510de340..b20ed28dec 100644 --- a/docs/running-locust-in-step-load-mode.rst +++ b/docs/running-locust-in-step-load-mode.rst @@ -39,7 +39,7 @@ If you want to run Locust in step load mode without the web UI, you can do that .. code-block:: console - $ locust -f --headless -c 1000 -r 100 --run-time 1h30m --step-load --step-clients 300 --step-time 20m + $ locust -f --headless -u 1000 -r 100 --run-time 1h30m --step-load --step-clients 300 --step-time 20m Locust will swarm the clients by step and shutdown once the time is up. diff --git a/docs/running-locust-without-web-ui.rst b/docs/running-locust-without-web-ui.rst index 159c457f8f..25d461a0aa 100644 --- a/docs/running-locust-without-web-ui.rst +++ b/docs/running-locust-without-web-ui.rst @@ -9,7 +9,7 @@ like a CI server - by using the ``--headless`` flag together with ``-u`` and ``- .. code-block:: console - $ locust -f locust_files/my_locust_file.py --headless -c 1000 -r 100 + $ locust -f locust_files/my_locust_file.py --headless -u 1000 -r 100 ``-u`` specifies the number of Users to spawn, and ``-r`` specifies the hatch rate (number of users to spawn per second). @@ -22,7 +22,7 @@ If you want to specify the run time for a test, you can do that with ``--run-tim .. code-block:: console - $ locust -f --headless -c 1000 -r 100 --run-time 1h30m + $ locust -f --headless -u 1000 -r 100 --run-time 1h30m Locust will shutdown once the time is up. @@ -33,7 +33,7 @@ By default, locust will stop your tasks immediately. If you want to allow your t .. code-block:: console - $ locust -f --headless -c 1000 -r 100 --run-time 1h30m --stop-timeout 99 + $ locust -f --headless -u 1000 -r 100 --run-time 1h30m --stop-timeout 99 .. _running-locust-distributed-without-web-ui: From 405dd867b69533dd76443f7372d33b0f8c604e83 Mon Sep 17 00:00:00 2001 From: anuj_ Date: Wed, 22 Apr 2020 15:09:45 +1200 Subject: [PATCH 22/37] fix broken test --- locust/test/test_fasthttp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locust/test/test_fasthttp.py b/locust/test/test_fasthttp.py index c58c9fe45a..7f83c72aa5 100644 --- a/locust/test/test_fasthttp.py +++ b/locust/test/test_fasthttp.py @@ -356,7 +356,7 @@ class MyUser(FastHttpUser): self.assertEqual(1, self.runner.stats.get("/redirect", "GET").num_failures) def test_allow_redirects_override(self): - class MyLocust(FastHttpLocust): + class MyLocust(FastHttpUser): host = "http://127.0.0.1:%i" % self.port l = MyLocust(self.environment) resp = l.client.get("/redirect", allow_redirects=False) From e450dc270c4063bd85286176a613344dc077cf26 Mon Sep 17 00:00:00 2001 From: anuj_ Date: Wed, 22 Apr 2020 16:15:50 +1200 Subject: [PATCH 23/37] More renaming after merging from master --- locust/argument_parser.py | 7 ++----- locust/main.py | 8 ++++---- locust/runners.py | 22 ++++++++++---------- locust/templates/index.html | 8 ++++---- locust/test/test_runners.py | 40 ++++++++++++++++++------------------- locust/test/test_web.py | 4 ++-- locust/web.py | 4 ++-- 7 files changed, 45 insertions(+), 48 deletions(-) diff --git a/locust/argument_parser.py b/locust/argument_parser.py index 2f1a4da589..5d58353a01 100644 --- a/locust/argument_parser.py +++ b/locust/argument_parser.py @@ -132,14 +132,12 @@ def setup_parser_arguments(parser): '-u', '--users', type=int, dest='num_users', - default=1, help="Number of concurrent Locust users. Only used together with --headless" ) # User hatch rate parser.add_argument( '-r', '--hatch-rate', type=float, - default=1, help="The rate per second in which users are spawned. Only used together with --headless" ) # Time limit of the test run @@ -171,7 +169,7 @@ def setup_parser_arguments(parser): web_ui_group.add_argument( '--headless', action='store_true', - help="Disable the web interface, and instead start the load test immediately. Requires -c and -t to be specified." + help="Disable the web interface, and instead start the load test immediately. Requires -u and -t to be specified." ) web_ui_group.add_argument( '--web-auth', @@ -304,13 +302,12 @@ def setup_parser_arguments(parser): step_load_group.add_argument( '--step-load', action='store_true', - help="Enable Step Load mode to monitor how performance metrics varies when user load increases. Requires --step-clients and --step-time to be specified." + help="Enable Step Load mode to monitor how performance metrics varies when user load increases. Requires --step-users and --step-time to be specified." ) # Number of users to increase by Step step_load_group.add_argument( '--step-users', type=int, - default=1, help="User count to increase by step in Step Load mode. Only used together with --step-load" ) step_load_group.add_argument( diff --git a/locust/main.py b/locust/main.py index a4fd64328c..4c9603e88d 100644 --- a/locust/main.py +++ b/locust/main.py @@ -254,12 +254,12 @@ def timelimit_stop(): time.sleep(1) if not options.worker: # apply headless mode defaults - if options.num_clients is None: - options.num_clients = 1 + if options.num_users is None: + options.num_users = 1 if options.hatch_rate is None: options.hatch_rate = 1 - if options.step_clients is None: - options.step_clients = 1 + if options.step_users is None: + options.step_users = 1 # start the test if options.step_time: diff --git a/locust/runners.py b/locust/runners.py index 46f33727eb..79d1e0e39b 100644 --- a/locust/runners.py +++ b/locust/runners.py @@ -254,7 +254,7 @@ def start_stepload(self, user_count, hatch_rate, step_user_count, step_duration) if user_count < step_user_count: logger.error("Invalid parameters: total user count of %d is smaller than step user count of %d" % (user_count, step_user_count)) return - self.total_clients = user_count + self.total_users = user_count if self.stepload_greenlet: logger.info("There is an ongoing swarming in Step Load mode, will stop it now.") @@ -264,15 +264,15 @@ def start_stepload(self, user_count, hatch_rate, step_user_count, step_duration) self.stepload_greenlet = self.greenlet.spawn(self.stepload_worker, hatch_rate, step_user_count, step_duration) self.stepload_greenlet.link_exception(greenlet_exception_handler) - def stepload_worker(self, hatch_rate, step_clients_growth, step_duration): - current_num_clients = 0 + def stepload_worker(self, hatch_rate, step_users_growth, step_duration): + current_num_users = 0 while self.state == STATE_INIT or self.state == STATE_HATCHING or self.state == STATE_RUNNING: - current_num_clients += step_clients_growth - if current_num_clients > int(self.total_clients): + current_num_users += step_users_growth + if current_num_users > int(self.total_users): logger.info('Step Load is finished.') break - self.start(current_num_clients, hatch_rate) - logger.info('Step loading: start hatch job of %d user.' % (current_num_clients)) + self.start(current_num_users, hatch_rate) + logger.info('Step loading: start hatch job of %d user.' % (current_num_users)) gevent.sleep(step_duration) def stop(self): @@ -454,13 +454,13 @@ def start(self, user_count, hatch_rate): for client in (self.clients.ready + self.clients.running + self.clients.hatching): data = { "hatch_rate": worker_hatch_rate, - "num_clients": worker_num_clients, + "num_users": worker_num_clients, "host": self.environment.host, "stop_timeout": self.environment.stop_timeout, } if remaining > 0: - data["num_clients"] += 1 + data["num_users"] += 1 remaining -= 1 self.server.send_to_client(Message("hatch", data, client.id)) @@ -654,13 +654,13 @@ def worker(self): self.client.send(Message("hatching", None, self.client_id)) job = msg.data self.hatch_rate = job["hatch_rate"] - self.target_user_count = job["num_clients"] + self.target_user_count = job["num_users"] self.environment.host = job["host"] self.environment.stop_timeout = job["stop_timeout"] if self.hatching_greenlet: # kill existing hatching greenlet before we launch new one self.hatching_greenlet.kill(block=True) - self.hatching_greenlet = self.greenlet.spawn(lambda: self.start(user_count=job["num_clients"], hatch_rate=job["hatch_rate"])) + self.hatching_greenlet = self.greenlet.spawn(lambda: self.start(user_count=job["num_users"], hatch_rate=job["hatch_rate"])) self.hatching_greenlet.link_exception(greenlet_exception_handler) elif msg.type == "stop": self.stop() diff --git a/locust/templates/index.html b/locust/templates/index.html index 14405a401f..a136fca07a 100644 --- a/locust/templates/index.html +++ b/locust/templates/index.html @@ -59,7 +59,7 @@

Start new Locust swarm

-
+

{% endif %}
diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index 8eee75b24d..a73bfba75f 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -83,18 +83,18 @@ class HeyAnException(Exception): class TestLocustRunner(LocustTestCase): def assert_locust_class_distribution(self, expected_distribution, classes): - # Construct a {LocustClass => count} dict from a list of locust classes + # Construct a {UserClass => count} dict from a list of user classes distribution = {} - for locust_class in classes: - if not locust_class in distribution: - distribution[locust_class] = 0 - distribution[locust_class] += 1 + for user_class in classes: + if not user_class in distribution: + distribution[user_class] = 0 + distribution[user_class] += 1 expected_str = str({k.__name__:v for k,v in expected_distribution.items()}) actual_str = str({k.__name__:v for k,v in distribution.items()}) self.assertEqual( expected_distribution, distribution, - "Expected a locust class distribution of %s but found %s" % ( + "Expected a User class distribution of %s but found %s" % ( expected_str, actual_str, ), diff --git a/locust/test/test_web.py b/locust/test/test_web.py index 0d4d043acb..ee2664ce59 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -238,7 +238,7 @@ class MyUser(User): response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertIn("http://example.com", response.content.decode("utf-8")) - self.assertNotIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) + self.assertNotIn("setting this will override the host on all User classes", response.content.decode("utf-8")) def test_host_value_from_multiple_user_classes(self): class MyUser(User): @@ -249,7 +249,7 @@ class MyUser2(User): response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertIn("http://example.com", response.content.decode("utf-8")) - self.assertNotIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) + self.assertNotIn("setting this will override the host on all User classes", response.content.decode("utf-8")) def test_host_value_from_multiple_user_classes_different_hosts(self): class MyUser(User): @@ -260,7 +260,7 @@ class MyUser2(User): response = requests.get("http://127.0.0.1:%i/" % self.web_port) self.assertEqual(200, response.status_code) self.assertNotIn("http://example.com", response.content.decode("utf-8")) - self.assertIn("setting this will override the host on all Locust classes", response.content.decode("utf-8")) + self.assertIn("setting this will override the host on all User classes", response.content.decode("utf-8")) def test_swarm_in_step_load_mode(self): class MyUser(User): From 36673979db810cc7eff75bd0602e34e28bc0a0b8 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Wed, 22 Apr 2020 17:19:47 +0200 Subject: [PATCH 27/37] Rename locust attribute on TaskSet to user --- docs/api.rst | 4 ++-- examples/multiple_hosts.py | 4 ++-- locust/core.py | 36 ++++++++++++++++---------------- locust/test/test_locust_class.py | 12 +++++------ locust/test/test_runners.py | 4 ++-- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index ef88f80f05..d1b0484814 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -20,7 +20,7 @@ TaskSet class ============= .. autoclass:: locust.core.TaskSet - :members: locust, parent, wait_time, client, tasks, interrupt, schedule_task, on_start, on_stop, wait + :members: user, parent, wait_time, client, tasks, interrupt, schedule_task, on_start, on_stop, wait task decorator ============== @@ -31,7 +31,7 @@ SequentialTaskSet class ======================= .. autoclass:: locust.sequential_taskset.SequentialTaskSet - :members: locust, parent, wait_time, client, tasks, interrupt, schedule_task, on_start, on_stop + :members: user, parent, wait_time, client, tasks, interrupt, schedule_task, on_start, on_stop .. _wait_time_functions: diff --git a/examples/multiple_hosts.py b/examples/multiple_hosts.py index 346587370d..826a485fd6 100644 --- a/examples/multiple_hosts.py +++ b/examples/multiple_hosts.py @@ -15,11 +15,11 @@ class UserTasks(TaskSet): # but it might be convenient to use the @task decorator @task def index(self): - self.locust.client.get("/") + self.user.client.get("/") @task def index_other_host(self): - self.locust.api_client.get("/stats/requests") + self.user.api_client.get("/stats/requests") class WebsiteUser(MultipleHostsUser): """ diff --git a/locust/core.py b/locust/core.py index 3efb2f65cd..56800bf10c 100644 --- a/locust/core.py +++ b/locust/core.py @@ -167,7 +167,7 @@ class ForumPage(TaskSet): if not set on the TaskSet. """ - locust = None + user = None """Will refer to the root User class instance when the TaskSet has been instantiated""" parent = None @@ -181,9 +181,9 @@ def __init__(self, parent): self._time_start = time() if isinstance(parent, TaskSet): - self.locust = parent.locust + self.user = parent.user elif isinstance(parent, User): - self.locust = parent + self.user = parent else: raise LocustError("TaskSet should be called with User instance or TaskSet instance as first argument") @@ -191,11 +191,11 @@ def __init__(self, parent): # if this class doesn't have a min_wait, max_wait or wait_function defined, copy it from Locust if not self.min_wait: - self.min_wait = self.locust.min_wait + self.min_wait = self.user.min_wait if not self.max_wait: - self.max_wait = self.locust.max_wait + self.max_wait = self.user.max_wait if not self.wait_function: - self.wait_function = self.locust.wait_function + self.wait_function = self.user.wait_function def on_start(self): """ @@ -246,8 +246,8 @@ def run(self, *args, **kwargs): self.on_stop() raise except Exception as e: - self.locust.environment.events.user_error.fire(user_instance=self, exception=e, tb=sys.exc_info()[2]) - if self.locust.environment.catch_exceptions: + self.user.environment.events.user_error.fire(user_instance=self, exception=e, tb=sys.exc_info()[2]) + if self.user.environment.catch_exceptions: logger.error("%s\n%s", e, traceback.format_exc()) self.wait() else: @@ -299,13 +299,13 @@ def wait_time(self): class Tasks(TaskSet): wait_time = between(3, 25) """ - if self.locust.wait_time: - return self.locust.wait_time() + if self.user.wait_time: + return self.user.wait_time() elif self.min_wait is not None and self.max_wait is not None: return random.randint(self.min_wait, self.max_wait) / 1000.0 else: raise MissingWaitTimeError("You must define a wait_time method on either the %s or %s class" % ( - type(self.locust).__name__, + type(self.user).__name__, type(self).__name__, )) @@ -320,16 +320,16 @@ def wait(self): gevent.sleep() instead. """ self._check_stop_condition() - self.locust._state = LOCUST_STATE_WAITING + self.user._state = LOCUST_STATE_WAITING self._sleep(self.wait_time()) self._check_stop_condition() - self.locust._state = LOCUST_STATE_RUNNING + self.user._state = LOCUST_STATE_RUNNING def _sleep(self, seconds): gevent.sleep(seconds) def _check_stop_condition(self): - if self.locust._state == LOCUST_STATE_STOPPING: + if self.user._state == LOCUST_STATE_STOPPING: raise StopUser() def interrupt(self, reschedule=True): @@ -351,7 +351,7 @@ def client(self): Reference to the :py:attr:`client ` attribute of the root User instance. """ - return self.locust.client + return self.user.client class DefaultTaskSet(TaskSet): @@ -360,15 +360,15 @@ class DefaultTaskSet(TaskSet): It executes tasks declared directly on the Locust with the user instance as the task argument. """ def get_next_task(self): - return random.choice(self.locust.tasks) + return random.choice(self.user.tasks) def execute_task(self, task, *args, **kwargs): if hasattr(task, "tasks") and issubclass(task, TaskSet): # task is (nested) TaskSet class - task(self.locust).run(*args, **kwargs) + task(self.user).run(*args, **kwargs) else: # task is a function - task(self.locust, *args, **kwargs) + task(self.user, *args, **kwargs) class UserMeta(type): diff --git a/locust/test/test_locust_class.py b/locust/test/test_locust_class.py index eb001d4a6a..8579bfcba9 100644 --- a/locust/test/test_locust_class.py +++ b/locust/test/test_locust_class.py @@ -195,11 +195,11 @@ def t2(self): def test_on_stop_when_locust_stops(self): class MyTasks(TaskSet): def on_stop(self): - self.locust.on_stop_executed = True + self.user.on_stop_executed = True @task def t2(self): - self.locust.t2_executed = True + self.user.t2_executed = True class MyUser(User): t2_executed = False @@ -330,7 +330,7 @@ class MySubTaskSet(TaskSet): constant(1) @task() def a_task(self): - self.locust.sub_locust_task_executed = True + self.user.sub_locust_task_executed = True self.interrupt() class MyTaskSet(TaskSet): @@ -349,7 +349,7 @@ class MySubTaskSet(TaskSet): wait_time = constant(0.001) @task() def a_task(self): - self.locust.sub_locust_task_executed = True + self.user.sub_locust_task_executed = True self.interrupt() self.sub_locust_task_executed = False @@ -363,8 +363,8 @@ class MySubTaskSet(TaskSet): wait_time = constant(0.001) @task() def a_task(self): - self.locust.sub_taskset_args = self.args - self.locust.sub_taskset_kwargs = self.kwargs + self.user.sub_taskset_args = self.args + self.user.sub_taskset_kwargs = self.kwargs self.interrupt() class MyTaskSet(TaskSet): sub_locust_args = None diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index a73bfba75f..a055439d24 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -273,7 +273,7 @@ class MyUser(User): class task_set(TaskSet): @task def my_task(self): - self.locust.environment.events.request_success.fire( + self.user.environment.events.request_success.fire( request_type="GET", name="/test", response_time=666, @@ -297,7 +297,7 @@ class MyUser(User): class task_set(TaskSet): @task def my_task(self): - self.locust.environment.events.request_success.fire( + self.user.environment.events.request_success.fire( request_type="GET", name="/test", response_time=666, From 47c104b4b2f78ade906b01120df58dc6cd2032b4 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Wed, 22 Apr 2020 17:28:38 +0200 Subject: [PATCH 28/37] Rename locust -> user in docstrings --- locust/contrib/fasthttp.py | 2 +- locust/core.py | 4 ++-- locust/event.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/locust/contrib/fasthttp.py b/locust/contrib/fasthttp.py index 8ba3b10ff0..afe4f8de61 100644 --- a/locust/contrib/fasthttp.py +++ b/locust/contrib/fasthttp.py @@ -85,7 +85,7 @@ class by using the :py:func:`@task decorator ` on the methods, """Parameter passed to FastHttpSession. Default True, meaning no SSL verification.""" abstract = True - """Dont register this as a locust that can be run by itself""" + """Dont register this as a User class that can be run by itself""" def __init__(self, environment): super().__init__(environment) diff --git a/locust/core.py b/locust/core.py index 56800bf10c..b71ccce747 100644 --- a/locust/core.py +++ b/locust/core.py @@ -450,10 +450,10 @@ class ForumPage(TaskSet): """ weight = 10 - """Probability of locust being chosen. The higher the weight, the greater the chance of it being chosen.""" + """Probability of user class being chosen. The higher the weight, the greater the chance of it being chosen.""" abstract = True - """If abstract is True, the class is meant to be subclassed, and users will not choose this locust during a test""" + """If abstract is True, the class is meant to be subclassed, and locust will not spawn users of this class during a test.""" client = NoClientWarningRaiser() _state = None diff --git a/locust/event.py b/locust/event.py index 78ca0465d4..d05c4dfd1e 100644 --- a/locust/event.py +++ b/locust/event.py @@ -101,7 +101,7 @@ class Events: hatch_complete = EventHook """ - Fired when all locust users has been spawned. + Fired when all simulated users has been spawned. Event arguments: From ad42d4eaba3c3f5e5c1a791d8fcc3bb8b8264bb6 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Wed, 22 Apr 2020 17:32:28 +0200 Subject: [PATCH 29/37] Rename is_locust function to is_user_class --- locust/main.py | 20 ++++++++++---------- locust/test/test_fasthttp.py | 4 ++-- locust/test/test_main.py | 34 +++++++++++++++++----------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/locust/main.py b/locust/main.py index 7204b20f27..dcf7be8dfc 100644 --- a/locust/main.py +++ b/locust/main.py @@ -26,7 +26,7 @@ version = locust.__version__ -def is_locust(item): +def is_user_class(item): """ Check if a variable is a runnable (non-abstract) User class """ @@ -84,8 +84,8 @@ def __import_locustfile__(filename, path): sys.path.insert(index + 1, directory) del sys.path[0] # Return our two-tuple - locusts = {name:value for name, value in vars(imported).items() if is_locust(value)} - return imported.__doc__, locusts + user_classes = {name:value for name, value in vars(imported).items() if is_user_class(value)} + return imported.__doc__, user_classes def create_environment(user_classes, options, events=None): @@ -109,7 +109,7 @@ def main(): locustfile = parse_locustfile_option() # import the locustfile - docstring, users = load_locustfile(locustfile) + docstring, user_classes = load_locustfile(locustfile) # parse all command line options options = parse_options() @@ -131,26 +131,26 @@ def main(): if options.list_commands: print("Available Users:") - for name in users: + for name in user_classes: print(" " + name) sys.exit(0) - if not users: + if not user_classes: logger.error("No User class found!") sys.exit(1) # make sure specified User exists if options.user_classes: - missing = set(options.user_classes) - set(users.keys()) + missing = set(options.user_classes) - set(user_classes.keys()) if missing: logger.error("Unknown User(s): %s\n" % (", ".join(missing))) sys.exit(1) else: - names = set(options.user_classes) & set(users.keys()) - user_classes = [users[n] for n in names] + names = set(options.user_classes) & set(user_classes.keys()) + user_classes = [user_classes[n] for n in names] else: # list() call is needed to consume the dict_view object in Python 3 - user_classes = list(users.values()) + user_classes = list(user_classes.values()) # create locust Environment environment = create_environment(user_classes, options, events=locust.events) diff --git a/locust/test/test_fasthttp.py b/locust/test/test_fasthttp.py index 7f83c72aa5..e187da8f66 100644 --- a/locust/test/test_fasthttp.py +++ b/locust/test/test_fasthttp.py @@ -4,7 +4,7 @@ from locust.core import task, TaskSet from locust.contrib.fasthttp import FastHttpSession, FastHttpUser from locust.exception import CatchResponseError, InterruptTaskSet, ResponseError -from locust.main import is_locust +from locust.main import is_user_class from .testcases import WebserverTestCase @@ -237,7 +237,7 @@ class MyUser(FastHttpUser): class TestFastHttpUserClass(WebserverTestCase): def test_is_abstract(self): self.assertTrue(FastHttpUser.abstract) - self.assertFalse(is_locust(FastHttpUser)) + self.assertFalse(is_user_class(FastHttpUser)) def test_get_request(self): self.response = "" diff --git a/locust/test/test_main.py b/locust/test/test_main.py index 8bb887149e..80baac510f 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -19,11 +19,11 @@ class TestLoadLocustfile(LocustTestCase): - def test_is_locust(self): - self.assertFalse(main.is_locust(User)) - self.assertFalse(main.is_locust(HttpUser)) - self.assertFalse(main.is_locust({})) - self.assertFalse(main.is_locust([])) + def test_is_user_class(self): + self.assertFalse(main.is_user_class(User)) + self.assertFalse(main.is_user_class(HttpUser)) + self.assertFalse(main.is_user_class({})) + self.assertFalse(main.is_user_class([])) class MyTaskSet(TaskSet): pass @@ -34,34 +34,34 @@ class MyHttpUser(HttpUser): class MyUser(User): tasks = [MyTaskSet] - self.assertTrue(main.is_locust(MyHttpUser)) - self.assertTrue(main.is_locust(MyUser)) + self.assertTrue(main.is_user_class(MyHttpUser)) + self.assertTrue(main.is_user_class(MyUser)) class ThriftLocust(User): abstract = True - self.assertFalse(main.is_locust(ThriftLocust)) + self.assertFalse(main.is_user_class(ThriftLocust)) def test_load_locust_file_from_absolute_path(self): with mock_locustfile() as mocked: - docstring, locusts = main.load_locustfile(mocked.file_path) - self.assertIn('UserSubclass', locusts) - self.assertNotIn('NotUserSubclass', locusts) + docstring, user_classes = main.load_locustfile(mocked.file_path) + self.assertIn('UserSubclass', user_classes) + self.assertNotIn('NotUserSubclass', user_classes) def test_load_locust_file_from_relative_path(self): with mock_locustfile() as mocked: - docstring, locusts = main.load_locustfile(os.path.join('./locust/test/', mocked.filename)) + docstring, user_classes = main.load_locustfile(os.path.join('./locust/test/', mocked.filename)) def test_load_locust_file_with_a_dot_in_filename(self): with mock_locustfile(filename_prefix="mocked.locust.file") as mocked: - docstring, locusts = main.load_locustfile(mocked.file_path) + docstring, user_classes = main.load_locustfile(mocked.file_path) - def test_return_docstring_and_locusts(self): + def test_return_docstring_and_user_classes(self): with mock_locustfile() as mocked: - docstring, locusts = main.load_locustfile(mocked.file_path) + docstring, user_classes = main.load_locustfile(mocked.file_path) self.assertEqual("This is a mock locust file for unit testing", docstring) - self.assertIn('UserSubclass', locusts) - self.assertNotIn('NotUserSubclass', locusts) + self.assertIn('UserSubclass', user_classes) + self.assertNotIn('NotUserSubclass', user_classes) def test_create_environment(self): options = parse_options(args=[ From 17edbb68fa344f37315e757c61e144d11beded9d Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Wed, 22 Apr 2020 17:38:39 +0200 Subject: [PATCH 30/37] More "locust" -> "user" renaming --- examples/semaphore_wait.py | 8 ++++---- locust/test/test_web.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/semaphore_wait.py b/examples/semaphore_wait.py index 7ff2e9cd9a..5b061be132 100644 --- a/examples/semaphore_wait.py +++ b/examples/semaphore_wait.py @@ -2,18 +2,18 @@ from gevent.lock import Semaphore -all_locusts_spawned = Semaphore() -all_locusts_spawned.acquire() +all_users_spawned = Semaphore() +all_users_spawned.acquire() @events.init.add_listener def _(environment, **kw): @environment.events.hatch_complete.add_listener def on_hatch_complete(**kw): - all_locusts_spawned.release() + all_users_spawned.release() class UserTasks(TaskSet): def on_start(self): - all_locusts_spawned.wait() + all_users_spawned.wait() self.wait() @task diff --git a/locust/test/test_web.py b/locust/test/test_web.py index ee2664ce59..49f77a69a4 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -231,7 +231,7 @@ def my_task(self): self.assertEqual(None, response.json()["host"]) self.assertEqual(self.environment.host, None) - def test_host_value_from_locust_class(self): + def test_host_value_from_user_class(self): class MyUser(User): host = "http://example.com" self.environment.user_classes = [MyUser] From 29c18cf84f13432992f0b7f9f468e6eb9a4dbc65 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Wed, 22 Apr 2020 17:50:47 +0200 Subject: [PATCH 31/37] Rename "locust" to -> "user" in WebUI HTML template --- locust/static/locust.js | 8 ++++---- locust/templates/index.html | 16 ++++++++-------- locust/test/test_web.py | 10 +++++----- locust/web.py | 8 ++++---- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/locust/static/locust.js b/locust/static/locust.js index 8aecc0eaf2..c57b0d1a3c 100644 --- a/locust/static/locust.js +++ b/locust/static/locust.js @@ -1,6 +1,6 @@ $(window).ready(function() { - if($("#locust_count").length > 0) { - $("#locust_count").focus().select(); + if($("#user_count").length > 0) { + $("#user_count").focus().select(); } }); @@ -26,13 +26,13 @@ $("#box_stop a.reset-button").click(function(event) { $("#new_test").click(function(event) { event.preventDefault(); $("#start").show(); - $("#locust_count").focus().select(); + $("#user_count").focus().select(); }); $(".edit_test").click(function(event) { event.preventDefault(); $("#edit").show(); - $("#new_locust_count").focus().select(); + $("#new_user_count").focus().select(); }); $(".close_link").click(function(event) { diff --git a/locust/templates/index.html b/locust/templates/index.html index a2b5d56eb9..00954956e4 100644 --- a/locust/templates/index.html +++ b/locust/templates/index.html @@ -58,8 +58,8 @@

Start new Locust swarm

- -
+ +


{% if is_step_load %} - -
+ +

{% endif %} @@ -88,13 +88,13 @@

Start new Locust swarm

Change the locust count

- -
+ +

{% if is_step_load %} - -
+ +

{% endif %} diff --git a/locust/test/test_web.py b/locust/test/test_web.py index 49f77a69a4..d05ba97ce5 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -56,9 +56,9 @@ def test_index(self): def test_index_with_hatch_options(self): html_to_option = { - 'locust_count':['-u','100'], + 'user_count':['-u','100'], 'hatch_rate':['-r','10.0'], - 'step_locust_count':['--step-users','20'], + 'step_user_count':['--step-users','20'], 'step_duration':['--step-time','15'], } self.environment.step_load = True @@ -210,7 +210,7 @@ def my_task(self): self.environment.user_classes = [MyUser] response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, - data={"locust_count": 5, "hatch_rate": 5, "host": "https://localhost"}, + data={"user_count": 5, "hatch_rate": 5, "host": "https://localhost"}, ) self.assertEqual(200, response.status_code) self.assertEqual("https://localhost", response.json()["host"]) @@ -225,7 +225,7 @@ def my_task(self): self.environment.user_classes = [MyUser] response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, - data={'locust_count': 5, 'hatch_rate': 5}, + data={'user_count': 5, 'hatch_rate': 5}, ) self.assertEqual(200, response.status_code) self.assertEqual(None, response.json()["host"]) @@ -272,7 +272,7 @@ def my_task(self): self.environment.step_load = True response = requests.post( "http://127.0.0.1:%i/swarm" % self.web_port, - data={"locust_count":5, "hatch_rate":2, "step_locust_count":2, "step_duration": "2m"} + data={"user_count":5, "hatch_rate":2, "step_user_count":2, "step_duration": "2m"} ) self.assertEqual(200, response.status_code) self.assertIn("Step Load Mode", response.text) diff --git a/locust/web.py b/locust/web.py index 2c8e95dfec..4e4c4e7399 100644 --- a/locust/web.py +++ b/locust/web.py @@ -137,18 +137,18 @@ def index(): @self.auth_required_if_enabled def swarm(): assert request.method == "POST" - locust_count = int(request.form["locust_count"]) + user_count = int(request.form["user_count"]) hatch_rate = float(request.form["hatch_rate"]) if (request.form.get("host")): environment.host = str(request.form["host"]) if environment.step_load: - step_locust_count = int(request.form["step_locust_count"]) + step_user_count = int(request.form["step_user_count"]) step_duration = parse_timespan(str(request.form["step_duration"])) - environment.runner.start_stepload(locust_count, hatch_rate, step_locust_count, step_duration) + environment.runner.start_stepload(user_count, hatch_rate, step_user_count, step_duration) return jsonify({'success': True, 'message': 'Swarming started in Step Load Mode', 'host': environment.host}) - environment.runner.start(locust_count, hatch_rate) + environment.runner.start(user_count, hatch_rate) return jsonify({'success': True, 'message': 'Swarming started', 'host': environment.host}) @app.route('/stop') From 796d86e8b52826a64930e12501ca71c2cceaa5d4 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Wed, 22 Apr 2020 17:51:06 +0200 Subject: [PATCH 32/37] Increase sleep time to make test less flaky --- locust/test/test_main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locust/test/test_main.py b/locust/test/test_main.py index 80baac510f..34ef2bbe17 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -146,7 +146,7 @@ def test_web_options(self): "--web-host", interface, "--web-port", str(port) ], stdout=PIPE, stderr=PIPE) - gevent.sleep(0.5) + gevent.sleep(1) self.assertEqual(200, requests.get("http://%s:%i/" % (interface, port), timeout=1).status_code) proc.terminate() @@ -157,6 +157,6 @@ def test_web_options(self): "--web-host", "*", "--web-port", str(port), ], stdout=PIPE, stderr=PIPE) - gevent.sleep(0.5) + gevent.sleep(1) self.assertEqual(200, requests.get("http://127.0.0.1:%i/" % port, timeout=1).status_code) proc.terminate() From 8db7c2d1e10402f1a006e344c53839eaa4df747d Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Thu, 23 Apr 2020 12:24:35 +0200 Subject: [PATCH 33/37] More "locust" -> "user" renaming --- README.md | 8 ++++---- docs/what-is-locust.rst | 9 ++++----- docs/writing-a-locustfile.rst | 2 +- locust/inspectlocust.py | 4 ++-- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 5ac666ee64..0c00a846f8 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ Locust is an easy-to-use, distributed, user load testing tool. It is intended for load-testing web sites (or other systems) and figuring out how many concurrent users a system can handle. -The idea is that during a test, a swarm of locusts will attack your website. The behavior of each locust (or test user if you will) is -defined by you and the swarming process is monitored from a web UI in real-time. This will help you battle test and identify bottlenecks -in your code before letting real users in. +The idea is that during a test, a swarm of simulated users will attack your website. The behavior of each user is defined by you +using Python code, and the swarming process is monitored from a web UI in real-time. This will help you battle test and identify +bottlenecks in your code before letting real users in. Locust is completely event-based, and therefore it's possible to support thousands of concurrent users on a single machine. In contrast to many other event-based apps it doesn't use callbacks. Instead it uses light-weight processes, through gevent. @@ -42,7 +42,7 @@ of callbacks, your code looks and behaves like normal, blocking Python code. Locust has a neat HTML+JS that shows all relevant test details in real-time. And since the UI is web-based, it's cross-platform and easily extendable. * **Can test any system**
- Even though Locust is web-oriented, it can be used to test almost any system. Just write a client for what ever you wish to test and swarm it with locusts! It's super easy! + Even though Locust is web-oriented, it can be used to test almost any system. Just write a client for what ever you wish to test and swarm it with users! It's super easy! * **Hackable**
Locust is very small and very hackable and we intend to keep it that way. All heavy-lifting of evented I/O and coroutines are delegated to gevent. The brittleness of alternative testing tools was the reason we created Locust. diff --git a/docs/what-is-locust.rst b/docs/what-is-locust.rst index 387e0eb9e3..b8c1691140 100644 --- a/docs/what-is-locust.rst +++ b/docs/what-is-locust.rst @@ -5,11 +5,10 @@ What is Locust? Locust is an easy-to-use, distributed, user load testing tool. It is intended for load-testing web sites (or other systems) and figuring out how many concurrent users a system can handle. -The idea is that during a test, a swarm of `locusts `_ -will attack your website. The behavior of each -locust (or test user if you will) is defined by you and the swarming process is monitored from a -web UI in real-time. This will help you battle test and identify bottlenecks in your code before -letting real users in. +The idea is that during a test, a swarm of `locust `_ users +will attack your website. The behavior of each user is defined by you using Python code, and the +swarming process is monitored from a web UI in real-time. This will help you battle test and identify +bottlenecks in your code before letting real users in. Locust is completely event-based, and therefore it's possible to support thousands of concurrent users on a single machine. In contrast to many other event-based apps it doesn't use callbacks. diff --git a/docs/writing-a-locustfile.rst b/docs/writing-a-locustfile.rst index 568bf69662..65268e59f9 100644 --- a/docs/writing-a-locustfile.rst +++ b/docs/writing-a-locustfile.rst @@ -69,7 +69,7 @@ user classes to use from the same locustfile by passing them as command line arg $ locust -f locust_file.py WebUser MobileUser -If you wish to make one of these locusts execute more often you can set a weight attribute on those +If you wish to simulate more users of a certain type you can set a weight attribute on those classes. Say for example, web users are three times more likely than mobile users: .. code-block:: python diff --git a/locust/inspectlocust.py b/locust/inspectlocust.py index 8a9fa1e46f..7e8b4b8a5a 100644 --- a/locust/inspectlocust.py +++ b/locust/inspectlocust.py @@ -3,8 +3,8 @@ from .core import User, TaskSet -def print_task_ratio(locusts, total=False, level=0, parent_ratio=1.0): - d = get_task_ratio_dict(locusts, total=total, parent_ratio=parent_ratio) +def print_task_ratio(user_classes, total=False, level=0, parent_ratio=1.0): + d = get_task_ratio_dict(user_classes, total=total, parent_ratio=parent_ratio) _print_task_ratio(d) def _print_task_ratio(x, level=0): From 08228a484d73d9222ed53b656c27db977f61df28 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Thu, 23 Apr 2020 12:58:49 +0200 Subject: [PATCH 34/37] Update python references in documentation ("locust" -> "user" renaming) --- docs/extending-locust.rst | 2 +- docs/use-as-lib.rst | 4 ++-- docs/writing-a-locustfile.rst | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/extending-locust.rst b/docs/extending-locust.rst index 352835e627..6315bea66c 100644 --- a/docs/extending-locust.rst +++ b/docs/extending-locust.rst @@ -7,7 +7,7 @@ Locust comes with a number of events hooks that can be used to extend Locust in Event hooks live on the Environment instance under the :py:attr:`events ` attribute. However, since the Environment instance hasn't been created when locustfiles are imported, the events object can also be accessed at the module level of the locustfile through the -:py:attr:`locust.events` variable. +:py:obj:`locust.events` variable. Here's an example on how to set up an event listener:: diff --git a/docs/use-as-lib.rst b/docs/use-as-lib.rst index a4b47b7ac4..2760879982 100644 --- a/docs/use-as-lib.rst +++ b/docs/use-as-lib.rst @@ -15,8 +15,8 @@ To run Locust as a library you need to create an :py:class:`Environment ` instance's :py:meth:`create_local_runner `, :py:meth:`create_master_runner ` or -:py:meth:`create_worker_runner can then be used to start a -:py:class:`Runner ` instance, which can be used to start a load test: +:py:meth:`create_worker_runner ` can then be used to start a +:py:class:`Runner ` instance, which can be used to start a load test: .. code-block:: python diff --git a/docs/writing-a-locustfile.rst b/docs/writing-a-locustfile.rst index 65268e59f9..cc7a87fb15 100644 --- a/docs/writing-a-locustfile.rst +++ b/docs/writing-a-locustfile.rst @@ -304,7 +304,7 @@ One difference for tasks residing under a TaskSet, compared to tasks residing di is that the argument that they are passed when executed (``self`` for tasks declared as methods with the :py:func:`@task ` decorator) is a reference to the TaskSet instance, instead of the User instance. The User instance can be accessed from within a TaskSet instance through the -:py:attr:`TaskSet.locust `. TaskSets also contains a convenience +:py:attr:`TaskSet.user `. TaskSets also contains a convenience :py:attr:`client ` attribute that refers to the client attribute on the User instance. @@ -312,7 +312,7 @@ User instance. Referencing the User instance, or the parent TaskSet instance --------------------------------------------------------------- -A TaskSet instance will have the attribute :py:attr:`locust ` point to +A TaskSet instance will have the attribute :py:attr:`locust ` point to its User instance, and the attribute :py:attr:`parent ` point to its parent TaskSet instance. @@ -400,7 +400,7 @@ So far, we've only covered the task scheduling part of a User. In order to actua a system we need to make HTTP requests. To help us do this, the :py:class:`HttpLocust ` class exists. When using this class, each instance gets a :py:attr:`client ` attribute which will be an instance of -:py:attr:`HttpSession ` which can be used to make HTTP requests. +:py:attr:`HttpSession ` which can be used to make HTTP requests. .. autoclass:: locust.core.HttpUser :members: client @@ -445,7 +445,7 @@ instance's TaskSet instances so that it's easy to retrieve the client and make H tasks. Here's a simple example that makes a GET request to the */about* path (in this case we assume *self* -is an instance of a :py:class:`TaskSet ` or :py:class:`HttpUser ` +is an instance of a :py:class:`TaskSet ` or :py:class:`HttpUser ` class: .. code-block:: python From 339eae328f0ba10c3181207119db2a4b3e00e877 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Thu, 23 Apr 2020 13:58:03 +0200 Subject: [PATCH 35/37] Use new tasks API in example that had been missed --- docs/writing-a-locustfile.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/writing-a-locustfile.rst b/docs/writing-a-locustfile.rst index cc7a87fb15..eaf6167dcc 100644 --- a/docs/writing-a-locustfile.rst +++ b/docs/writing-a-locustfile.rst @@ -37,7 +37,7 @@ With the following locustfile, each user would wait between 5 and 15 seconds bet print("executing my_task") class MyUser(User): - task_set = MyTaskSet + tasks = [MyTaskSet] wait_time = between(5, 15) The wait_time method should return a number of seconds (or fraction of a second) and can also From 4f4b83bfdacdc6fe729fa2486e2c0db3e998e3ef Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Thu, 23 Apr 2020 14:06:20 +0200 Subject: [PATCH 36/37] Rename local variable worker_num_clients to worker_num_users --- locust/runners.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locust/runners.py b/locust/runners.py index 79d1e0e39b..c1eaa50384 100644 --- a/locust/runners.py +++ b/locust/runners.py @@ -437,11 +437,11 @@ def start(self, user_count, hatch_rate): return self.hatch_rate = hatch_rate - worker_num_clients = user_count // (num_workers or 1) + worker_num_users = user_count // (num_workers or 1) worker_hatch_rate = float(hatch_rate) / (num_workers or 1) remaining = user_count % num_workers - logger.info("Sending hatch jobs of %d users and %.2f hatch rate to %d ready clients" % (worker_num_clients, worker_hatch_rate, num_workers)) + logger.info("Sending hatch jobs of %d users and %.2f hatch rate to %d ready clients" % (worker_num_users, worker_hatch_rate, num_workers)) if worker_hatch_rate > 100: logger.warning("Your selected hatch rate is very high (>100/worker), and this is known to sometimes cause issues. Do you really need to ramp up that fast?") @@ -454,7 +454,7 @@ def start(self, user_count, hatch_rate): for client in (self.clients.ready + self.clients.running + self.clients.hatching): data = { "hatch_rate": worker_hatch_rate, - "num_users": worker_num_clients, + "num_users": worker_num_users, "host": self.environment.host, "stop_timeout": self.environment.stop_timeout, } From 5aca141c9414734d97436117286aca86d8d3051c Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Thu, 23 Apr 2020 14:33:55 +0200 Subject: [PATCH 37/37] Add entry about "Locust" -> "User" renaming, to Changelog --- docs/changelog.rst | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 585a43143d..2fae2ec13a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -7,8 +7,18 @@ For full details of the Locust changelog, please see https://github.com/locustio 1.0 (In development) ==================== -Breaking changes ----------------- +This version contains some breaking changes. + +Locust class renamed to User +---------------------------- + +We've renamed the ``Locust`` and ``HttpLocust`` classes to ``User`` and ``HttpUser``. The ``locust`` attribute on +:py:class:`TaskSet ` instances has been renamed to :py:attr:`user `. + + + +Other breaking changes +---------------------- * The option for running Locust without the Web UI has been renamed from ``--no-web`` to ``--headless``. * Removed ``Locust.setup``, ``Locust.teardown``, ``TaskSet.setup`` and ``TaskSet.teardown`` hooks. If you want to