locust 2.26.1.dev72__py3-none-any.whl → 2.27.1.dev7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- locust/_version.py +2 -2
- locust/argument_parser.py +1 -1
- locust/env.py +0 -2
- locust/html.py +37 -83
- locust/main.py +10 -14
- locust/stats.py +3 -10
- locust/test/test_fasthttp.py +6 -4
- locust/test/test_main.py +6 -15
- locust/test/test_web.py +53 -199
- locust/web.py +18 -56
- {locust-2.26.1.dev72.dist-info → locust-2.27.1.dev7.dist-info}/METADATA +1 -1
- {locust-2.26.1.dev72.dist-info → locust-2.27.1.dev7.dist-info}/RECORD +16 -41
- locust/static/chart.js +0 -133
- locust/static/css/application.css +0 -491
- locust/static/css/application.css.map +0 -1
- locust/static/css/tables.css +0 -74
- locust/static/css/tables.css.map +0 -1
- locust/static/echarts.common.min.js +0 -22
- locust/static/img/favicon.ico +0 -0
- locust/static/img/logo.png +0 -0
- locust/static/img/ui-screenshot-charts.png +0 -0
- locust/static/img/ui-screenshot-start-test.png +0 -0
- locust/static/img/ui-screenshot-stats.png +0 -0
- locust/static/img/ui-screenshot-workers.png +0 -0
- locust/static/jquery-1.11.3.min.js +0 -5
- locust/static/jquery.jqote2.min.js +0 -14
- locust/static/jquery.tools.min.js +0 -17
- locust/static/locust.js +0 -324
- locust/static/sass/_base.sass +0 -27
- locust/static/sass/_mixins.sass +0 -3
- locust/static/sass/application.sass +0 -320
- locust/static/sass/tables.sass +0 -61
- locust/static/tasks.js +0 -48
- locust/static/vintage.js +0 -35
- locust/templates/index.html +0 -370
- locust/templates/report.html +0 -265
- locust/templates/stats_data.html +0 -10
- {locust-2.26.1.dev72.dist-info → locust-2.27.1.dev7.dist-info}/LICENSE +0 -0
- {locust-2.26.1.dev72.dist-info → locust-2.27.1.dev7.dist-info}/WHEEL +0 -0
- {locust-2.26.1.dev72.dist-info → locust-2.27.1.dev7.dist-info}/entry_points.txt +0 -0
- {locust-2.26.1.dev72.dist-info → locust-2.27.1.dev7.dist-info}/top_level.txt +0 -0
locust/test/test_web.py
CHANGED
@@ -79,13 +79,19 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
79
79
|
web_ui.stop()
|
80
80
|
|
81
81
|
def test_index(self):
|
82
|
-
self.assertEqual(
|
82
|
+
self.assertEqual(self.web_ui, self.environment.web_ui)
|
83
83
|
|
84
|
-
def test_index_with_spawn_options(self):
|
85
84
|
html_to_option = {
|
86
|
-
"
|
85
|
+
"num_users": ["-u", "100"],
|
87
86
|
"spawn_rate": ["-r", "10.0"],
|
88
87
|
}
|
88
|
+
|
89
|
+
response = requests.get("http://127.0.0.1:%i/" % self.web_port)
|
90
|
+
d = pq(response.content.decode("utf-8"))
|
91
|
+
|
92
|
+
self.assertEqual(200, response.status_code)
|
93
|
+
self.assertTrue(d("#root"))
|
94
|
+
|
89
95
|
for html_name_to_test in html_to_option.keys():
|
90
96
|
# Test that setting each spawn option individually populates the corresponding field in the html, and none of the others
|
91
97
|
self.environment.parsed_options = parse_options(html_to_option[html_name_to_test])
|
@@ -95,15 +101,23 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
95
101
|
|
96
102
|
d = pq(response.content.decode("utf-8"))
|
97
103
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
104
|
+
self.assertIn(f'"{html_name_to_test}": {html_to_option[html_name_to_test][1]}', str(d("script")))
|
105
|
+
|
106
|
+
def test_index_with_spawn_options(self):
|
107
|
+
html_to_option = {
|
108
|
+
"num_users": ["-u", "100"],
|
109
|
+
"spawn_rate": ["-r", "10.0"],
|
110
|
+
}
|
111
|
+
|
112
|
+
for html_name_to_test in html_to_option.keys():
|
113
|
+
self.environment.parsed_options = parse_options(html_to_option[html_name_to_test])
|
114
|
+
|
115
|
+
response = requests.get("http://127.0.0.1:%i/" % self.web_port)
|
116
|
+
self.assertEqual(200, response.status_code)
|
117
|
+
|
118
|
+
d = pq(response.content.decode("utf-8"))
|
119
|
+
|
120
|
+
self.assertIn(f'"{html_name_to_test}": {html_to_option[html_name_to_test][1]}', str(d))
|
107
121
|
|
108
122
|
def test_stats_no_data(self):
|
109
123
|
self.assertEqual(200, requests.get("http://127.0.0.1:%i/stats/requests" % self.web_port).status_code)
|
@@ -771,30 +785,6 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
771
785
|
self.assertEqual(200, response.status_code)
|
772
786
|
self.assertEqual(my_dict["val"], 42)
|
773
787
|
|
774
|
-
def test_custom_argument_dropdown(self):
|
775
|
-
class MyUser(User):
|
776
|
-
host = "http://example.com"
|
777
|
-
|
778
|
-
@locust.events.init_command_line_parser.add_listener
|
779
|
-
def _(parser, **kw):
|
780
|
-
parser.add_argument("--my-argument", default="a", choices=["a", "b"], help="Pick one")
|
781
|
-
|
782
|
-
parsed_options = parse_options(args=["--my-argument", "b"])
|
783
|
-
self.environment.user_classes = [MyUser]
|
784
|
-
self.environment.parsed_options = parsed_options
|
785
|
-
self.environment.web_ui.parsed_options = parsed_options
|
786
|
-
|
787
|
-
response = requests.get("http://127.0.0.1:%i/" % self.web_port)
|
788
|
-
self.assertEqual(200, response.status_code)
|
789
|
-
|
790
|
-
# regex to match the intended select tag with id from the custom argument
|
791
|
-
dropdown_pattern = re.compile(r"<select[^>]*id=\"my_argument\"[^>]*>", flags=re.I)
|
792
|
-
self.assertRegex(response.text, dropdown_pattern)
|
793
|
-
|
794
|
-
# regex to match the input that generates if it fails to find the choices
|
795
|
-
textfield_pattern = re.compile(r"<input[^>]*id=\"my_argument\"[^>]*>", flags=re.I)
|
796
|
-
self.assertNotRegex(response.text, textfield_pattern)
|
797
|
-
|
798
788
|
def test_swarm_host_value_not_specified(self):
|
799
789
|
class MyUser(User):
|
800
790
|
wait_time = constant(1)
|
@@ -922,40 +912,42 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
922
912
|
response = requests.get("http://127.0.0.1:%i/" % self.web_port)
|
923
913
|
self.assertEqual(200, response.status_code)
|
924
914
|
self.assertNotIn("http://example.com", response.content.decode("utf-8"))
|
925
|
-
self.assertIn("setting this will override the host on all User classes", response.content.decode("utf-8"))
|
926
915
|
|
927
916
|
def test_report_page(self):
|
928
917
|
self.stats.log_request("GET", "/test", 120, 5612)
|
929
918
|
r = requests.get("http://127.0.0.1:%i/stats/report" % self.web_port)
|
919
|
+
|
920
|
+
d = pq(r.content.decode("utf-8"))
|
921
|
+
|
930
922
|
self.assertEqual(200, r.status_code)
|
931
|
-
self.assertIn("
|
932
|
-
self.assertIn("
|
933
|
-
self.assertIn("
|
934
|
-
self.assertIn(
|
935
|
-
'<a href="?download=1">Download the Report</a>',
|
936
|
-
r.text,
|
937
|
-
"Download report link not found in HTML content",
|
938
|
-
)
|
923
|
+
self.assertIn('"host": "None"', str(d))
|
924
|
+
self.assertIn('"num_requests": 1', str(d))
|
925
|
+
self.assertIn('"is_report": true', str(d))
|
926
|
+
self.assertIn('"show_download_link": true', str(d))
|
939
927
|
|
940
928
|
def test_report_page_empty_stats(self):
|
941
929
|
r = requests.get("http://127.0.0.1:%i/stats/report" % self.web_port)
|
942
930
|
self.assertEqual(200, r.status_code)
|
943
|
-
self.assertIn("<title>Test Report for None</title>", r.text)
|
944
|
-
self.assertIn("charts-container", r.text)
|
945
931
|
|
946
932
|
def test_report_download(self):
|
947
933
|
self.stats.log_request("GET", "/test", 120, 5612)
|
948
934
|
r = requests.get("http://127.0.0.1:%i/stats/report?download=1" % self.web_port)
|
935
|
+
|
936
|
+
d = pq(r.content.decode("utf-8"))
|
937
|
+
|
949
938
|
self.assertEqual(200, r.status_code)
|
950
939
|
self.assertIn("attachment", r.headers.get("Content-Disposition", ""))
|
951
|
-
self.
|
940
|
+
self.assertIn('"show_download_link": false', str(d))
|
952
941
|
|
953
942
|
def test_report_host(self):
|
954
943
|
self.environment.host = "http://test.com"
|
955
944
|
self.stats.log_request("GET", "/test", 120, 5612)
|
956
945
|
r = requests.get("http://127.0.0.1:%i/stats/report" % self.web_port)
|
946
|
+
|
947
|
+
d = pq(r.content.decode("utf-8"))
|
948
|
+
|
957
949
|
self.assertEqual(200, r.status_code)
|
958
|
-
self.assertIn("http://test.com",
|
950
|
+
self.assertIn('"host": "http://test.com"', str(d))
|
959
951
|
|
960
952
|
def test_report_host2(self):
|
961
953
|
class MyUser(User):
|
@@ -969,8 +961,11 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
969
961
|
self.environment.user_classes = [MyUser]
|
970
962
|
self.stats.log_request("GET", "/test", 120, 5612)
|
971
963
|
r = requests.get("http://127.0.0.1:%i/stats/report" % self.web_port)
|
964
|
+
|
965
|
+
d = pq(r.content.decode("utf-8"))
|
966
|
+
|
972
967
|
self.assertEqual(200, r.status_code)
|
973
|
-
self.assertIn("http://test2.com",
|
968
|
+
self.assertIn('"host": "http://test2.com"', str(d))
|
974
969
|
|
975
970
|
def test_report_exceptions(self):
|
976
971
|
try:
|
@@ -981,8 +976,10 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
981
976
|
self.runner.log_exception("local", str(e), "".join(traceback.format_tb(tb)))
|
982
977
|
self.stats.log_request("GET", "/test", 120, 5612)
|
983
978
|
r = requests.get("http://127.0.0.1:%i/stats/report" % self.web_port)
|
984
|
-
|
985
|
-
|
979
|
+
|
980
|
+
d = pq(r.content.decode("utf-8"))
|
981
|
+
|
982
|
+
self.assertIn('exceptions_statistics": [{"count": 2', str(d))
|
986
983
|
|
987
984
|
# Prior to 088a98bf8ff4035a0de3becc8cd4e887d618af53, the "nodes" field for each exception in
|
988
985
|
# "self.runner.exceptions" was accidentally mutated in "get_html_report" to a string.
|
@@ -992,54 +989,6 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
992
989
|
isinstance(next(iter(self.runner.exceptions.values()))["nodes"], set), "exception object has been mutated"
|
993
990
|
)
|
994
991
|
|
995
|
-
def test_custom_shape_deactivate_num_users_and_spawn_rate(self):
|
996
|
-
class TestShape(LoadTestShape):
|
997
|
-
def tick(self):
|
998
|
-
return None
|
999
|
-
|
1000
|
-
self.environment.shape_class = TestShape
|
1001
|
-
|
1002
|
-
response = requests.get("http://127.0.0.1:%i/" % self.web_port)
|
1003
|
-
self.assertEqual(200, response.status_code)
|
1004
|
-
|
1005
|
-
# regex to match the intended select tag with id from the custom argument
|
1006
|
-
re_disabled_user_count = re.compile(
|
1007
|
-
r"<input[^>]*id=\"(new_)?user_count\"[^>]*disabled=\"disabled\"[^>]*>", flags=re.I
|
1008
|
-
)
|
1009
|
-
self.assertRegex(response.text, re_disabled_user_count)
|
1010
|
-
|
1011
|
-
re_disabled_spawn_rate = re.compile(
|
1012
|
-
r"<input[^>]*id=\"(new_)?spawn_rate\"[^>]*disabled=\"disabled\"[^>]*>", flags=re.I
|
1013
|
-
)
|
1014
|
-
self.assertRegex(response.text, re_disabled_spawn_rate)
|
1015
|
-
|
1016
|
-
def test_custom_shape_with_use_common_options_keep_num_users_and_spawn_rate(self):
|
1017
|
-
class TestShape(LoadTestShape):
|
1018
|
-
use_common_options = True
|
1019
|
-
|
1020
|
-
def tick(self):
|
1021
|
-
return None
|
1022
|
-
|
1023
|
-
self.environment.shape_class = TestShape
|
1024
|
-
|
1025
|
-
response = requests.get("http://127.0.0.1:%i/" % self.web_port)
|
1026
|
-
self.assertEqual(200, response.status_code)
|
1027
|
-
|
1028
|
-
# regex to match the intended select tag with id from the custom argument
|
1029
|
-
re_user_count = re.compile(r"<input[^>]*id=\"(new_)?user_count\"[^>]*>", flags=re.I)
|
1030
|
-
re_disabled_user_count = re.compile(
|
1031
|
-
r"<input[^>]*id=\"(new_)?user_count\"[^>]*disabled=\"disabled\"[^>]*>", flags=re.I
|
1032
|
-
)
|
1033
|
-
self.assertRegex(response.text, re_user_count)
|
1034
|
-
self.assertNotRegex(response.text, re_disabled_user_count)
|
1035
|
-
|
1036
|
-
re_spawn_rate = re.compile(r"<input[^>]*id=\"(new_)?spawn_rate\"[^>]*>", flags=re.I)
|
1037
|
-
re_disabled_spawn_rate = re.compile(
|
1038
|
-
r"<input[^>]*id=\"(new_)?spawn_rate\"[^>]*disabled=\"disabled\"[^>]*>", flags=re.I
|
1039
|
-
)
|
1040
|
-
self.assertRegex(response.text, re_spawn_rate)
|
1041
|
-
self.assertNotRegex(response.text, re_disabled_spawn_rate)
|
1042
|
-
|
1043
992
|
def test_html_stats_report(self):
|
1044
993
|
self.environment.locustfile = "locust.py"
|
1045
994
|
self.environment.host = "http://localhost"
|
@@ -1049,8 +998,9 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
1049
998
|
|
1050
999
|
d = pq(response.content.decode("utf-8"))
|
1051
1000
|
|
1052
|
-
self.
|
1053
|
-
self.assertIn("
|
1001
|
+
self.assertTrue(d("#root"))
|
1002
|
+
self.assertIn('"locustfile": "locust.py"', str(d))
|
1003
|
+
self.assertIn('"host": "http://localhost"', str(d))
|
1054
1004
|
|
1055
1005
|
def test_logs(self):
|
1056
1006
|
log_handler = LogReader()
|
@@ -1128,7 +1078,7 @@ class TestWebUIAuth(LocustTestCase):
|
|
1128
1078
|
parser = get_parser(default_config_files=[])
|
1129
1079
|
self.environment.parsed_options = parser.parse_args(["--web-login"])
|
1130
1080
|
|
1131
|
-
self.web_ui = self.environment.create_web_ui("127.0.0.1", 0,
|
1081
|
+
self.web_ui = self.environment.create_web_ui("127.0.0.1", 0, web_login=True)
|
1132
1082
|
|
1133
1083
|
self.web_ui.app.secret_key = "secret!"
|
1134
1084
|
gevent.sleep(0.01)
|
@@ -1280,99 +1230,3 @@ class TestWebUIFullHistory(LocustTestCase, _HeaderCheckMixin):
|
|
1280
1230
|
self.assertEqual("/test2", rows[2][3])
|
1281
1231
|
self.assertEqual("", rows[3][2])
|
1282
1232
|
self.assertEqual("Aggregated", rows[3][3])
|
1283
|
-
|
1284
|
-
|
1285
|
-
class TestModernWebUI(LocustTestCase, _HeaderCheckMixin):
|
1286
|
-
def setUp(self):
|
1287
|
-
super().setUp()
|
1288
|
-
|
1289
|
-
get_parser(default_config_files=[])
|
1290
|
-
self.stats = self.environment.stats
|
1291
|
-
|
1292
|
-
self.web_ui = self.environment.create_web_ui("127.0.0.1", 0, modern_ui=True)
|
1293
|
-
self.web_ui.app.view_functions["request_stats"].clear_cache()
|
1294
|
-
gevent.sleep(0.01)
|
1295
|
-
self.web_port = self.web_ui.server.server_port
|
1296
|
-
|
1297
|
-
def tearDown(self):
|
1298
|
-
super().tearDown()
|
1299
|
-
self.web_ui.stop()
|
1300
|
-
self.runner.quit()
|
1301
|
-
|
1302
|
-
def test_index_with_modern_ui(self):
|
1303
|
-
self.assertEqual(self.web_ui, self.environment.web_ui)
|
1304
|
-
|
1305
|
-
html_to_option = {
|
1306
|
-
"num_users": ["-u", "100"],
|
1307
|
-
"spawn_rate": ["-r", "10.0"],
|
1308
|
-
}
|
1309
|
-
|
1310
|
-
response = requests.get("http://127.0.0.1:%i/" % self.web_port)
|
1311
|
-
d = pq(response.content.decode("utf-8"))
|
1312
|
-
|
1313
|
-
self.assertEqual(200, response.status_code)
|
1314
|
-
self.assertTrue(d("#root"))
|
1315
|
-
|
1316
|
-
for html_name_to_test in html_to_option.keys():
|
1317
|
-
# Test that setting each spawn option individually populates the corresponding field in the html, and none of the others
|
1318
|
-
self.environment.parsed_options = parse_options(html_to_option[html_name_to_test])
|
1319
|
-
|
1320
|
-
response = requests.get("http://127.0.0.1:%i/" % self.web_port)
|
1321
|
-
self.assertEqual(200, response.status_code)
|
1322
|
-
|
1323
|
-
d = pq(response.content.decode("utf-8"))
|
1324
|
-
|
1325
|
-
self.assertIn(f'"{html_name_to_test}": {html_to_option[html_name_to_test][1]}', str(d("script")))
|
1326
|
-
|
1327
|
-
def test_web_ui_no_runner(self):
|
1328
|
-
env = Environment()
|
1329
|
-
web_ui = WebUI(env, "127.0.0.1", 0)
|
1330
|
-
gevent.sleep(0.01)
|
1331
|
-
try:
|
1332
|
-
response = requests.get("http://127.0.0.1:%i/" % web_ui.server.server_port)
|
1333
|
-
self.assertEqual(500, response.status_code)
|
1334
|
-
self.assertEqual("Error: Locust Environment does not have any runner", response.text)
|
1335
|
-
finally:
|
1336
|
-
web_ui.stop()
|
1337
|
-
|
1338
|
-
def test_html_stats_report(self):
|
1339
|
-
self.environment.locustfile = "locust.py"
|
1340
|
-
self.environment.host = "http://localhost"
|
1341
|
-
|
1342
|
-
response = requests.get("http://127.0.0.1:%i/stats/report" % self.web_port)
|
1343
|
-
self.assertEqual(200, response.status_code)
|
1344
|
-
|
1345
|
-
d = pq(response.content.decode("utf-8"))
|
1346
|
-
|
1347
|
-
self.assertTrue(d("#root"))
|
1348
|
-
self.assertIn('"locustfile": "locust.py"', str(d))
|
1349
|
-
self.assertIn('"host": "http://localhost"', str(d))
|
1350
|
-
|
1351
|
-
def test_update_user(self):
|
1352
|
-
class MyUser1(User):
|
1353
|
-
@task
|
1354
|
-
def my_task(self):
|
1355
|
-
pass
|
1356
|
-
|
1357
|
-
@task
|
1358
|
-
def my_task_2(self):
|
1359
|
-
pass
|
1360
|
-
|
1361
|
-
class MyUser2(User):
|
1362
|
-
@task
|
1363
|
-
def my_task(self):
|
1364
|
-
pass
|
1365
|
-
|
1366
|
-
self.environment.user_classes = [MyUser1, MyUser2]
|
1367
|
-
self.environment.available_user_classes = {"User1": MyUser1, "User2": MyUser2}
|
1368
|
-
self.environment.available_user_tasks = {"User1": MyUser1.tasks, "User2": MyUser2.tasks}
|
1369
|
-
|
1370
|
-
requests.post(
|
1371
|
-
"http://127.0.0.1:%i/user" % self.web_port,
|
1372
|
-
json={"user_class_name": "User1", "host": "http://localhost", "tasks": ["my_task_2"]},
|
1373
|
-
)
|
1374
|
-
|
1375
|
-
self.assertEqual(
|
1376
|
-
self.environment.available_user_classes["User1"].json(),
|
1377
|
-
{"host": "http://localhost", "tasks": ["my_task_2"], "fixed_count": 0, "weight": 1},
|
1378
|
-
)
|
locust/web.py
CHANGED
@@ -32,7 +32,7 @@ from gevent import pywsgi
|
|
32
32
|
from . import __version__ as version
|
33
33
|
from . import argument_parser
|
34
34
|
from . import stats as stats_module
|
35
|
-
from .html import get_html_report
|
35
|
+
from .html import BUILD_PATH, ROOT_PATH, STATIC_PATH, get_html_report
|
36
36
|
from .log import greenlet_exception_logger
|
37
37
|
from .runners import STATE_MISSING, STATE_RUNNING, MasterRunner
|
38
38
|
from .stats import StatsCSV, StatsCSVFileWriter, StatsErrorDict, sort_stats
|
@@ -95,7 +95,6 @@ class WebUI:
|
|
95
95
|
stats_csv_writer: StatsCSV | None = None,
|
96
96
|
delayed_start=False,
|
97
97
|
userclass_picker_is_active=False,
|
98
|
-
modern_ui=False,
|
99
98
|
):
|
100
99
|
"""
|
101
100
|
Create WebUI instance and start running the web server in a separate greenlet (self.greenlet)
|
@@ -118,20 +117,21 @@ class WebUI:
|
|
118
117
|
self.tls_cert = tls_cert
|
119
118
|
self.tls_key = tls_key
|
120
119
|
self.userclass_picker_is_active = userclass_picker_is_active
|
121
|
-
self.modern_ui = modern_ui
|
122
120
|
self.web_login = web_login
|
123
121
|
app = Flask(__name__)
|
124
122
|
CORS(app)
|
125
123
|
self.app = app
|
126
124
|
app.jinja_env.add_extension("jinja2.ext.do")
|
127
125
|
app.debug = True
|
128
|
-
root_path =
|
129
|
-
|
130
|
-
self.webui_build_path = os.path.join(root_path, "webui", "dist")
|
126
|
+
app.root_path = ROOT_PATH
|
127
|
+
self.webui_build_path = BUILD_PATH
|
131
128
|
self.greenlet: gevent.Greenlet | None = None
|
132
129
|
self._swarm_greenlet: gevent.Greenlet | None = None
|
133
130
|
self.template_args = {}
|
134
131
|
self.auth_args = {}
|
132
|
+
self.app.template_folder = BUILD_PATH
|
133
|
+
self.app.static_folder = STATIC_PATH
|
134
|
+
self.app.static_url_path = "/assets/"
|
135
135
|
|
136
136
|
if self.web_login:
|
137
137
|
self.login_manager = LoginManager()
|
@@ -160,11 +160,7 @@ class WebUI:
|
|
160
160
|
return make_response("Error: Locust Environment does not have any runner", 500)
|
161
161
|
self.update_template_args()
|
162
162
|
|
163
|
-
|
164
|
-
self.set_static_modern_ui()
|
165
|
-
|
166
|
-
return render_template("index.html", template_args=self.template_args)
|
167
|
-
return render_template("index.html", **self.template_args)
|
163
|
+
return render_template("index.html", template_args=self.template_args)
|
168
164
|
|
169
165
|
@app.route("/swarm", methods=["POST"])
|
170
166
|
@self.auth_required_if_enabled
|
@@ -302,7 +298,6 @@ class WebUI:
|
|
302
298
|
res = get_html_report(
|
303
299
|
self.environment,
|
304
300
|
show_download_link=not request.args.get("download"),
|
305
|
-
use_modern_ui=self.modern_ui,
|
306
301
|
theme=theme,
|
307
302
|
)
|
308
303
|
if request.args.get("download"):
|
@@ -416,25 +411,12 @@ class WebUI:
|
|
416
411
|
report["total_fail_per_sec"] = total_stats["current_fail_per_sec"]
|
417
412
|
report["total_avg_response_time"] = total_stats["avg_response_time"]
|
418
413
|
report["fail_ratio"] = environment.runner.stats.total.fail_ratio
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
f"response_time_percentile_{percentile}": environment.runner.stats.total.get_current_response_time_percentile(
|
423
|
-
percentile
|
424
|
-
)
|
425
|
-
for percentile in stats_module.MODERN_UI_PERCENTILES_TO_CHART
|
426
|
-
}
|
427
|
-
else:
|
428
|
-
report["current_response_time_percentile_1"] = (
|
429
|
-
environment.runner.stats.total.get_current_response_time_percentile(
|
430
|
-
stats_module.PERCENTILES_TO_CHART[0]
|
431
|
-
)
|
432
|
-
)
|
433
|
-
report["current_response_time_percentile_2"] = (
|
434
|
-
environment.runner.stats.total.get_current_response_time_percentile(
|
435
|
-
stats_module.PERCENTILES_TO_CHART[1]
|
436
|
-
)
|
414
|
+
report["current_response_time_percentiles"] = {
|
415
|
+
f"response_time_percentile_{percentile}": environment.runner.stats.total.get_current_response_time_percentile(
|
416
|
+
percentile
|
437
417
|
)
|
418
|
+
for percentile in stats_module.PERCENTILES_TO_CHART
|
419
|
+
}
|
438
420
|
|
439
421
|
if isinstance(environment.runner, MasterRunner):
|
440
422
|
workers = []
|
@@ -520,15 +502,10 @@ class WebUI:
|
|
520
502
|
if not self.web_login:
|
521
503
|
return redirect(url_for("index"))
|
522
504
|
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
"auth.html",
|
528
|
-
auth_args=self.auth_args,
|
529
|
-
)
|
530
|
-
else:
|
531
|
-
return "Web Auth is only available on the modern web ui."
|
505
|
+
return render_template(
|
506
|
+
"auth.html",
|
507
|
+
auth_args=self.auth_args,
|
508
|
+
)
|
532
509
|
|
533
510
|
@app.route("/user", methods=["POST"])
|
534
511
|
def update_user():
|
@@ -581,11 +558,6 @@ class WebUI:
|
|
581
558
|
|
582
559
|
return wrapper
|
583
560
|
|
584
|
-
def set_static_modern_ui(self):
|
585
|
-
self.app.template_folder = self.webui_build_path
|
586
|
-
self.app.static_folder = os.path.join(self.webui_build_path, "assets")
|
587
|
-
self.app.static_url_path = "/assets/"
|
588
|
-
|
589
561
|
def update_template_args(self):
|
590
562
|
override_host_warning = False
|
591
563
|
if self.environment.host:
|
@@ -634,17 +606,6 @@ class WebUI:
|
|
634
606
|
else None
|
635
607
|
)
|
636
608
|
|
637
|
-
if self.modern_ui:
|
638
|
-
percentiles = {
|
639
|
-
"percentiles_to_chart": stats_module.MODERN_UI_PERCENTILES_TO_CHART,
|
640
|
-
"percentiles_to_statistics": stats_module.PERCENTILES_TO_STATISTICS,
|
641
|
-
}
|
642
|
-
else:
|
643
|
-
percentiles = {
|
644
|
-
"percentile1": stats_module.PERCENTILES_TO_CHART[0],
|
645
|
-
"percentile2": stats_module.PERCENTILES_TO_CHART[1],
|
646
|
-
}
|
647
|
-
|
648
609
|
self.template_args = {
|
649
610
|
"locustfile": self.environment.locustfile,
|
650
611
|
"state": self.environment.runner.state,
|
@@ -670,7 +631,8 @@ class WebUI:
|
|
670
631
|
"available_shape_classes": available_shape_classes,
|
671
632
|
"available_user_tasks": available_user_tasks,
|
672
633
|
"users": users,
|
673
|
-
|
634
|
+
"percentiles_to_chart": stats_module.PERCENTILES_TO_CHART,
|
635
|
+
"percentiles_to_statistics": stats_module.PERCENTILES_TO_STATISTICS,
|
674
636
|
}
|
675
637
|
|
676
638
|
def _update_shape_class(self, shape_class_name):
|
@@ -1,52 +1,27 @@
|
|
1
1
|
locust/__init__.py,sha256=g6oA-Ba_hs3gLWVf5MKJ1mvfltI8MFnDWG8qslqm8yg,1402
|
2
2
|
locust/__main__.py,sha256=vBQ82334kX06ImDbFlPFgiBRiLIinwNk3z8Khs6hd74,31
|
3
|
-
locust/_version.py,sha256=
|
4
|
-
locust/argument_parser.py,sha256=
|
3
|
+
locust/_version.py,sha256=KfITNoysCewEedAEshROjJKa4Y8wd2JXKEHzxzR7Rpg,426
|
4
|
+
locust/argument_parser.py,sha256=amD8faLijyrBtkDZaLuQdKXrN2U0DcvF_EWCTpnftNA,28714
|
5
5
|
locust/clients.py,sha256=YKuAyMAbxs8_-w7XJw0hc67KFBNNLxibsw6FwiS01Q8,14781
|
6
6
|
locust/debug.py,sha256=We6Z9W0btkKSc7PxWmrZx-xMynvOOsKhG6jmDgQin0g,5134
|
7
7
|
locust/dispatch.py,sha256=vYh0QEDFgJ3hY0HgSk-EiNO7IP9ffzXF_Et8wB9JvsI,16995
|
8
|
-
locust/env.py,sha256=
|
8
|
+
locust/env.py,sha256=SLtUQCYaiv_oq_Nz1xaB0OD8RkTdESt2b71vz_qohpo,12452
|
9
9
|
locust/event.py,sha256=xgNKbcejxy1TNUfIdgV75KgD2_BOwQmvjrJ4hWuydRw,7740
|
10
10
|
locust/exception.py,sha256=jGgJ32ubuf4pWdlaVOkbh2Y0LlG0_DHi-lv3ib8ppOE,1791
|
11
|
-
locust/html.py,sha256=
|
11
|
+
locust/html.py,sha256=Qz3Php454f5QwIdJyP2ckJ2L9aNkdZQCVahFELfMBIc,3983
|
12
12
|
locust/input_events.py,sha256=ZIyePyAMuA_YFYWg18g_pE4kwuQV3RbEB250MzXRwjY,3314
|
13
13
|
locust/log.py,sha256=2IVp9YL4ZPfWdj3sBFuOHfgneg3g7m7tUGR-sy2s3E8,3155
|
14
|
-
locust/main.py,sha256=
|
14
|
+
locust/main.py,sha256=FM8mkO3HGXJCaUbXZNXn1Yy37fuUaiS3VuLEk7pbbwQ,27831
|
15
15
|
locust/py.typed,sha256=gkWLl8yD4mIZnNYYAIRM8g9VarLvWmTAFeUfEbxJLBw,65
|
16
16
|
locust/runners.py,sha256=Go8b8fpOAfFy6JuNcot7KyguHuExA6eoPHVmcgx3RoI,67813
|
17
17
|
locust/shape.py,sha256=t-lwBS8LOjWcKXNL7j2U3zroIXJ1b0fazUwpRYQOKXw,1973
|
18
|
-
locust/stats.py,sha256=
|
19
|
-
locust/web.py,sha256=
|
18
|
+
locust/stats.py,sha256=dulIckrNr3t01LSOFvpr7LdBHj1YXHlEoK7q3b79z0A,45581
|
19
|
+
locust/web.py,sha256=_7uelOUgnBJA80ZKjcIQ67zSxz0uEH5hoQDcZ8mP6XU,26720
|
20
20
|
locust/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
21
|
locust/contrib/fasthttp.py,sha256=vByPepw35DF84qZ2xK89yHgjOA_8btV0wig_rSR6p4g,26757
|
22
22
|
locust/rpc/__init__.py,sha256=nVGoHWFQxZjnhCDWjbgXIbmFbN9sizAjkhvSs9_642c,58
|
23
23
|
locust/rpc/protocol.py,sha256=n-rb3GZQcAlldYDj4E4GuFGylYj_26GSS5U29meft5Y,1282
|
24
24
|
locust/rpc/zmqrpc.py,sha256=7DLIXzkQr7992zmZwAqNgcqzm7LOQAOQtz0tUGv5-Gg,2637
|
25
|
-
locust/static/chart.js,sha256=Aue4SxJZhv9I3k0Nr2uXTrdrLxsrX7x_a0d4u3a1e_Q,4796
|
26
|
-
locust/static/echarts.common.min.js,sha256=2h6zIZeHk-eGAiC-qYvxv7uW5S1HcyM72K5FbcVhky4,620458
|
27
|
-
locust/static/jquery-1.11.3.min.js,sha256=7LkWEzqTdpEfELxcZZlS6wAx5Ff13zZ83lYO2_ujj7g,95957
|
28
|
-
locust/static/jquery.jqote2.min.js,sha256=kkYnMvNSQ0_h-YsHCRzBF3v4yEfRdcEacMusrnW4BK0,3381
|
29
|
-
locust/static/jquery.tools.min.js,sha256=elDu82RR_6K-TWXb2qTSxAz96-upLyHBrnypvQSIu3c,2981
|
30
|
-
locust/static/locust.js,sha256=3Z-7JNT9t46dYFXUxRd-wDrfj1VrWbeuMmQu16GVqy0,10264
|
31
|
-
locust/static/tasks.js,sha256=Gi999xLri5s_x_Xr_o_Xo-zsXsgaDSyWNcctmZySnZs,1370
|
32
|
-
locust/static/vintage.js,sha256=aNBHBqGMT-oTINb5wVaeRykd3tFI-FWV8C46qAHcx40,1137
|
33
|
-
locust/static/css/application.css,sha256=XoDwPgPsnLiF-RlCFR4Pipuz2diy1oimXW0pPs6xq4s,9550
|
34
|
-
locust/static/css/application.css.map,sha256=mwJQ10Tc5HzQ71JFPn1BtoULU7pBi91wX5DDoDvBtM0,2089
|
35
|
-
locust/static/css/tables.css,sha256=KZDZbn_DEM0pkuUWPTu0ogEwCUU4bWXWfIeShXNCIW0,1403
|
36
|
-
locust/static/css/tables.css.map,sha256=7FqJQhCK0Q_EgNGUc-1BEqfs0Z7N8Jk_Aw0GKd4OtNY,411
|
37
|
-
locust/static/img/favicon.ico,sha256=IUl-rYqfpHdV38e-s0bkmFIeLS-n3Ug0DQxk-h202hI,8348
|
38
|
-
locust/static/img/logo.png,sha256=iEdgwYwXapNPY1BeAn2qSCAk4rsEeYecYbN7GjNpr9A,24553
|
39
|
-
locust/static/img/ui-screenshot-charts.png,sha256=eK5hVgKM9uSZJd87BhimZMCspH03R1fuIfYeac2g0kQ,79701
|
40
|
-
locust/static/img/ui-screenshot-start-test.png,sha256=sQJB4V9FQ3VXiWZVVweh7lkK-0NuBeEMUNoqbIJ_pv8,64670
|
41
|
-
locust/static/img/ui-screenshot-stats.png,sha256=l6COjiS31ceox6kqdFs_7YKs1QgvwSQB0-VlwunD6Qk,95837
|
42
|
-
locust/static/img/ui-screenshot-workers.png,sha256=5MapSjLOBcieRMxeJAmAqszhwu72sE4PIHD9UzLVFFg,151806
|
43
|
-
locust/static/sass/_base.sass,sha256=UaC1ViXp-Sz_5S6ggjctxurevfaGx8RdFdG6VEZK-lc,458
|
44
|
-
locust/static/sass/_mixins.sass,sha256=Sy5r_1WTWM0k646SYm0XF1WNN2HJxtQ4QO7rVVkIfoI,69
|
45
|
-
locust/static/sass/application.sass,sha256=v_S916UmdCOno4A0cGfDpVmFFxZxSQ4XOU_0MqjvotU,8512
|
46
|
-
locust/static/sass/tables.sass,sha256=mG3RXKJRU2NTI6jz__1RUEwjAGdJzgzYpuRCP8jLT1I,1361
|
47
|
-
locust/templates/index.html,sha256=7Qe69jYG7Vv9G0xWNtbALcqgl_m79GeHSYJxmlaQoBA,21651
|
48
|
-
locust/templates/report.html,sha256=Q1NmZWZL61-tLzJaR8kKG2tkjMjI6ry-OXEFvgM4PHM,10667
|
49
|
-
locust/templates/stats_data.html,sha256=MoBvJE41VtG3eriHkP4qWgQs3QNTsFTvS03aCenh0j0,1264
|
50
25
|
locust/test/__init__.py,sha256=CaVC4yA4DnCO8EY3LbedPHFg86a9Lqlpe92JuiX3THw,396
|
51
26
|
locust/test/fake_module1_for_env_test.py,sha256=dzGYWCr1SSkd8Yyo68paUNrCNW7YY_QgjRb7sM37gG0,164
|
52
27
|
locust/test/fake_module2_for_env_test.py,sha256=dzGYWCr1SSkd8Yyo68paUNrCNW7YY_QgjRb7sM37gG0,164
|
@@ -55,13 +30,13 @@ locust/test/mock_logging.py,sha256=qapKrKhTdlVc8foJB2Hxjn7SB6soaLeAj3VF4A6kZtw,8
|
|
55
30
|
locust/test/test_debugging.py,sha256=omQ0w5_Xh1xuTBzkd3VavEIircwtlmoOEHcMInY67vU,1053
|
56
31
|
locust/test/test_dispatch.py,sha256=RjoncanN4FFt-aiTl4G8XRoc81n6fwfO8CacbjzpvP8,168856
|
57
32
|
locust/test/test_env.py,sha256=l0fLl9nubdgzxwFNajmBkJvQc5cO5rOTE4p12lbCbs0,8919
|
58
|
-
locust/test/test_fasthttp.py,sha256=
|
33
|
+
locust/test/test_fasthttp.py,sha256=cuWsS9t875Mrik0xTXlsfHde90F6_cgKWKJ3_Dr0ldw,30723
|
59
34
|
locust/test/test_http.py,sha256=VQCVY0inLC0RS-V3E9WHL3vBLGokZjQt0zKSrTNlQmM,12536
|
60
35
|
locust/test/test_interruptable_task.py,sha256=LZKSV-aJNnwfvAxguz6SckBEuGEnfGimoIgVfJ2wQTA,1377
|
61
36
|
locust/test/test_load_locustfile.py,sha256=v-muHoM-CYu8t7DXm4AQtFP2q8RYfnTTUBqj7uVqhig,8494
|
62
37
|
locust/test/test_locust_class.py,sha256=oGhhOX848jHRQnIfFlhLlW-kHGYLyYsfDX8hM07Ro7g,25506
|
63
38
|
locust/test/test_log.py,sha256=YPY6vgTAy1KaNU2qoVvQrTH5x_mzRrljEHrkSBy3yxs,7553
|
64
|
-
locust/test/test_main.py,sha256=
|
39
|
+
locust/test/test_main.py,sha256=R2akeBreg6aXC2Dhs-HxvFq_0EE64hzEaIZmAVALW4w,84866
|
65
40
|
locust/test/test_old_wait_api.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
66
41
|
locust/test/test_parser.py,sha256=-2VO5Dopg-VoWvIgXrmr7GN40cqrnjUoctBHmVlyewg,17826
|
67
42
|
locust/test/test_runners.py,sha256=xfBdRPOH1CiNk4Rwqmbx6S1e2BDuWdtqDw9omDJ50Ec,159395
|
@@ -72,7 +47,7 @@ locust/test/test_taskratio.py,sha256=SQ-sBqeFm2GhkfCD_57-fPzQrk1ilSw3DRb0_nwyxAI
|
|
72
47
|
locust/test/test_users.py,sha256=lp6yAKGK9_MIs9F7s1Vc3561P4oRavhpeVo2y9w3SUU,2135
|
73
48
|
locust/test/test_util.py,sha256=DmFTgNSWWx8zrsx9_ZGO6MsySmBV1H_GzNIVzzyapCM,1229
|
74
49
|
locust/test/test_wait_time.py,sha256=3evSEp6amMWFrzmSYs71MCeIsu7Rtarldb_HnwgSrU0,2353
|
75
|
-
locust/test/test_web.py,sha256=
|
50
|
+
locust/test/test_web.py,sha256=8v1RFeF7GDXDv616uzI3adSxoYSxctoZinmwupX5-K8,45767
|
76
51
|
locust/test/test_zmqrpc.py,sha256=kONaZ11hwnneLwaVn7lIDVV7KHpEP2nkxuKhfb9ba3o,2173
|
77
52
|
locust/test/testcases.py,sha256=ZaPYNxSSChAs0nts_13mCGY7WFW8AjXQZdPOvwAK0TY,6961
|
78
53
|
locust/test/util.py,sha256=98HXLClkycNTxLiuy1d3W_tM6dBU9bA-p5ZXMfncaWE,2754
|
@@ -95,9 +70,9 @@ locust/webui/dist/report.html,sha256=sOdZZVgZbqgu86BBCSQf3uQUYXgmgSnXF32JpnyAII8
|
|
95
70
|
locust/webui/dist/assets/favicon.ico,sha256=IUl-rYqfpHdV38e-s0bkmFIeLS-n3Ug0DQxk-h202hI,8348
|
96
71
|
locust/webui/dist/assets/index-941b6e82.js,sha256=G3n5R81Svt0HzbWaV3AV20jLWGLr4X50UZ-Adu2KcxU,1645614
|
97
72
|
locust/webui/dist/assets/logo.png,sha256=EIVPqr6wE_yqguHaqFHIsH0ZACLSrvNWyYO7PbyIj4w,19299
|
98
|
-
locust-2.
|
99
|
-
locust-2.
|
100
|
-
locust-2.
|
101
|
-
locust-2.
|
102
|
-
locust-2.
|
103
|
-
locust-2.
|
73
|
+
locust-2.27.1.dev7.dist-info/LICENSE,sha256=78XGpIn3fHVBfaxlPNUfjVufSN7QsdhpJMRJHv2AFpo,1095
|
74
|
+
locust-2.27.1.dev7.dist-info/METADATA,sha256=RnJ-aygcQwLlpQsZUwU2Qq24xSXls2irhORfqQ6Tjtc,7266
|
75
|
+
locust-2.27.1.dev7.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
76
|
+
locust-2.27.1.dev7.dist-info/entry_points.txt,sha256=RAdt8Ku-56m7bFjmdj-MBhbF6h4NX7tVODR9QNnOg0E,44
|
77
|
+
locust-2.27.1.dev7.dist-info/top_level.txt,sha256=XSsjgPA8Ggf9TqKVbkwSqZFuPlZ085X13M9orDycE20,7
|
78
|
+
locust-2.27.1.dev7.dist-info/RECORD,,
|