change: remove locust temporarily

This commit is contained in:
debugtalk
2020-05-15 22:48:59 +08:00
parent d05c235029
commit 0e5ca838fb
11 changed files with 13 additions and 435 deletions

View File

@@ -2,29 +2,12 @@ import argparse
import os
import sys
if len(sys.argv) >= 2 and sys.argv[1] == "locusts":
# monkey patch ssl at beginning to avoid RecursionError when running locust.
try:
from gevent import monkey
monkey.patch_ssl()
from locust.main import main as _
except ImportError:
msg = """
Locust is not installed, install first and try again.
install with pip:
$ pip install locustio
"""
print(msg)
sys.exit(1)
import pytest
from httprunner import __description__, __version__, exceptions
from httprunner.ext.har2case import init_har2case_parser, main_har2case
from httprunner.ext.scaffold import init_parser_scaffold, main_scaffold
from httprunner.ext.locusts import init_parser_locusts, main_locusts
from httprunner.ext.make import init_make_parser, main_make, convert_testcase_path
from httprunner.ext.scaffold import init_parser_scaffold, main_scaffold
def init_parser_run(subparsers):
@@ -69,7 +52,6 @@ def main():
sub_parser_run = init_parser_run(subparsers)
sub_parser_scaffold = init_parser_scaffold(subparsers)
sub_parser_har2case = init_har2case_parser(subparsers)
sub_parser_locusts = init_parser_locusts(subparsers)
sub_parser_make = init_make_parser(subparsers)
if len(sys.argv) == 1:
@@ -90,9 +72,6 @@ def main():
elif sys.argv[1] == "har2case":
# httprunner har2case
sub_parser_har2case.print_help()
elif sys.argv[1] == "locusts":
# httprunner locusts
sub_parser_locusts.print_help()
elif sys.argv[1] == "run":
# httprunner run
pytest.main(["-h"])
@@ -100,7 +79,9 @@ def main():
# httprunner make
sub_parser_make.print_help()
sys.exit(0)
elif len(sys.argv) == 3 and sys.argv[1] == "run" and sys.argv[2] in ["-h", "--help"]:
elif (
len(sys.argv) == 3 and sys.argv[1] == "run" and sys.argv[2] in ["-h", "--help"]
):
# httprunner run -h
pytest.main(["-h"])
sys.exit(0)
@@ -121,8 +102,6 @@ def main():
main_scaffold(args)
elif sys.argv[1] == "har2case":
main_har2case(args)
elif sys.argv[1] == "locusts":
main_locusts(args, extra_args)
elif sys.argv[1] == "make":
main_make(args.testcase_path)

View File

@@ -1,104 +0,0 @@
# locusts
## Installation
```shell script
$ pip install locustio
```
## Usage
```shell script
$ locusts -f xxx.yml
```
```shell script
$ locusts -f xxx.yml --processes
```
```shell script
$ python3 -m httprunner.ext.locusts -h
Usage: locust [options] [LocustClass [LocustClass2 ... ]]
Options:
-h, --help show this help message and exit
-H HOST, --host=HOST Host to load test in the following format:
http://10.21.32.33
--web-host=WEB_HOST Host to bind the web interface to. Defaults to '' (all
interfaces)
-P PORT, --port=PORT, --web-port=PORT
Port on which to run web host
-f LOCUSTFILE, --locustfile=LOCUSTFILE
Python module file to import, e.g. '../other.py'.
Default: locustfile
--csv=CSVFILEBASE, --csv-base-name=CSVFILEBASE
Store current request stats to files in CSV format.
--master Set locust to run in distributed mode with this
process as master
--slave Set locust to run in distributed mode with this
process as slave
--master-host=MASTER_HOST
Host or IP address of locust master for distributed
load testing. Only used when running with --slave.
Defaults to 127.0.0.1.
--master-port=MASTER_PORT
The port to connect to that is used by the locust
master for distributed load testing. Only used when
running with --slave. Defaults to 5557. Note that
slaves will also connect to the master node on this
port + 1.
--master-bind-host=MASTER_BIND_HOST
Interfaces (hostname, ip) that locust master should
bind to. Only used when running with --master.
Defaults to * (all available interfaces).
--master-bind-port=MASTER_BIND_PORT
Port that locust master should bind to. Only used when
running with --master. Defaults to 5557. Note that
Locust will also use this port + 1, so by default the
master node will bind to 5557 and 5558.
--heartbeat-liveness=HEARTBEAT_LIVENESS
set number of seconds before failed heartbeat from
slave
--heartbeat-interval=HEARTBEAT_INTERVAL
set number of seconds delay between slave heartbeats
to master
--expect-slaves=EXPECT_SLAVES
How many slaves master should expect to connect before
starting the test (only when --no-web used).
--no-web Disable the web interface, and instead start running
the test immediately. Requires -c and -r to be
specified.
-c NUM_CLIENTS, --clients=NUM_CLIENTS
Number of concurrent Locust users. Only used together
with --no-web
-r HATCH_RATE, --hatch-rate=HATCH_RATE
The rate per second in which clients are spawned. Only
used together with --no-web
-t RUN_TIME, --run-time=RUN_TIME
Stop after the specified amount of time, e.g. (300s,
20m, 3h, 1h30m, etc.). Only used together with --no-
web
-L LOGLEVEL, --loglevel=LOGLEVEL
Choose between DEBUG/INFO/WARNING/ERROR/CRITICAL.
Default is INFO.
--logfile=LOGFILE Path to log file. If not set, log will go to
stdout/stderr
--print-stats Print stats in the console
--only-summary Only print the summary stats
--no-reset-stats [DEPRECATED] Do not reset statistics once hatching has
been completed. This is now the default behavior. See
--reset-stats to disable
--reset-stats Reset statistics once hatching has been completed.
Should be set on both master and slaves when running
in distributed mode
-l, --list Show list of possible locust classes and exit
--show-task-ratio print table of the locust classes' task execution
ratio
--show-task-ratio-json
print json data of the locust classes' task execution
ratio
-V, --version show program's version number and exit
--exit-code-on-error=EXIT_CODE_ON_ERROR
sets the exit code to post on error
```

View File

@@ -1,94 +0,0 @@
import multiprocessing
import sys
from loguru import logger
from httprunner import __version__
from httprunner.ext.locusts.core import (
start_locust_main,
parse_locustfile,
quick_run_locusts,
start_master,
start_slaves,
)
CPU_COUNT = multiprocessing.cpu_count()
def init_parser_locusts(subparsers):
sub_parser_locusts = subparsers.add_parser(
"locusts", help="Run load test with locust."
)
sub_parser_locusts.add_argument(
"--locust-help", action="store_true", default=False, help="Show locust help."
)
sub_parser_locusts.add_argument(
"test_file", nargs="?", help="Specify YAML/JSON testcase file."
)
sub_parser_locusts.add_argument(
"--master", action="store_true", default=False, help="Start locust master."
)
sub_parser_locusts.add_argument(
"--slaves", type=int, help="Specify locust slave number."
)
sub_parser_locusts.add_argument(
"--quickstart",
action="store_true",
default=False,
help=f"Start locust master with {CPU_COUNT} slaves.",
)
return sub_parser_locusts
def main_locusts(args, extra_args):
""" Performance test with locust: parse command line options and run commands.
"""
logger.info(f"HttpRunner version: {__version__}")
sys.argv = ["locust", *extra_args]
if args.locust_help:
sys.argv = ["locust", "-h"]
start_locust_main()
def get_arg_index(*target_args):
for arg in target_args:
if arg not in sys.argv:
continue
return sys.argv.index(arg) + 1
return None
# set logging level
loglevel_index = get_arg_index("-L", "--loglevel")
if loglevel_index and loglevel_index < len(sys.argv):
loglevel = sys.argv[loglevel_index]
loglevel = loglevel.upper()
else:
# default
loglevel = "INFO"
logger.remove()
logger.add(sys.stdout, level=loglevel)
if not args.test_file:
logger.error("Testcase file is not specified, exit.")
sys.exit(1)
# convert httprunner yaml/json case to locustfile.py
locustfile_path = parse_locustfile(args.test_file)
sys.argv.extend(["-f", locustfile_path])
manager = multiprocessing.Manager()
try:
if args.quickstart:
quick_run_locusts(CPU_COUNT)
elif args.master:
start_master(sys.argv)
elif args.slaves:
start_slaves(args.slaves)
else:
quick_run_locusts(CPU_COUNT)
except KeyboardInterrupt:
manager.shutdown()

View File

@@ -1,100 +0,0 @@
import io
import multiprocessing
import os
import sys
from loguru import logger
def parse_locustfile(file_path):
""" parse testcase file and return locustfile path.
if file_path is a Python file, assume it is a locustfile
if file_path is a YAML/JSON file, convert it to locustfile
"""
if not os.path.isfile(file_path):
logger.error("file path invalid, exit.")
sys.exit(1)
file_suffix = os.path.splitext(file_path)[1]
if file_suffix == ".py":
locustfile_path = file_path
elif file_suffix in [".yaml", ".yml", ".json"]:
locustfile_path = gen_locustfile(file_path)
else:
# '' or other suffix
logger.error("file type should be YAML/JSON/Python, exit.")
sys.exit(1)
return locustfile_path
def gen_locustfile(testcase_file_path):
""" generate locustfile from template.
"""
locustfile_path = "locustfile.py"
template_path = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "locustfile_template.py"
)
with io.open(template_path, encoding="utf-8") as template:
with io.open(locustfile_path, "w", encoding="utf-8") as locustfile:
template_content = template.read()
template_content = template_content.replace(
"$TESTCASE_FILE", testcase_file_path
)
locustfile.write(template_content)
return locustfile_path
def start_locust_main():
logger.info(f"run command: {sys.argv}")
from locust.main import main
main()
def start_master(sys_argv):
sys_argv.append("--master")
sys.argv = sys_argv
start_locust_main()
def start_slave(sys_argv):
if "--slave" not in sys_argv:
sys_argv.extend(["--slave"])
sys.argv = sys_argv
start_locust_main()
def init_slave_processes(slave_num):
""" init specified number of locust slave processes."""
processes = []
for _ in range(slave_num):
p_slave = multiprocessing.Process(target=start_slave, args=(sys.argv,))
p_slave.daemon = True
p_slave.start()
processes.append(p_slave)
return processes
def start_slaves(slave_num):
logger.info(f"Start {slave_num} locust slaves ...")
processes = init_slave_processes(slave_num)
[process.join() for process in processes]
def quick_run_locusts(slave_num):
""" quick start locust master and multiple slaves.
Args:
slave_num: locust slaves number
"""
logger.info(f"Start locust master with {slave_num} slaves ...")
processes = init_slave_processes(slave_num)
processes.append(multiprocessing.Process(target=start_master, args=(sys.argv,)))
[process.join() for process in processes]

View File

@@ -1,20 +0,0 @@
config:
name: create users with uid
variables:
device_sn: ${gen_random_string(15)}
base_url: "http://127.0.0.1:5000"
testcases:
-
name: create user 1000 and check result.
testcase: testcases/create_user.yml
weight: 2
variables:
uid: 1000
-
name: create user 1001 and check result.
testcase: testcases/create_user.yml
weight: 3
variables:
uid: 1001

View File

@@ -1,43 +0,0 @@
import logging
import random
from locust import HttpLocust, TaskSet, task
from locust.events import request_failure
from httprunner.exceptions import MyBaseError, MyBaseFailure
from httprunner.ext.locusts.utils import prepare_locust_tests
from httprunner.runner import Runner
logging.getLogger().setLevel(logging.CRITICAL)
logging.getLogger("locust.main").setLevel(logging.INFO)
logging.getLogger("locust.runners").setLevel(logging.INFO)
class WebPageTasks(TaskSet):
def on_start(self):
config = {}
self.test_runner = Runner(config, self.client)
@task
def test_any(self):
test_dict = random.choice(self.locust.tests)
try:
self.test_runner.run_test(test_dict)
except (AssertionError, MyBaseError, MyBaseFailure) as ex:
request_failure.fire(
request_type=self.test_runner.exception_request_type,
name=self.test_runner.exception_name,
response_time=0,
exception=ex,
)
class WebPageUser(HttpLocust):
host = ""
task_set = WebPageTasks
min_wait = 10
max_wait = 30
# file_path is generated on locusts startup
file_path = "$TESTCASE_FILE"
tests = prepare_locust_tests(file_path)

View File

@@ -1,29 +0,0 @@
from httprunner import loader, parser
def prepare_locust_tests(path):
""" prepare locust testcases
Args:
path (str): testcase file path.
Returns:
list: locust tests data
[
testcase1_dict,
testcase2_dict
]
"""
tests_mapping = loader.load_cases(path)
testcases = parser.parse_tests(tests_mapping)
locust_tests = []
for testcase in testcases:
testcase_weight = testcase.get("config", {}).pop("weight", 1)
for _ in range(testcase_weight):
locust_tests.append(testcase)
return locust_tests

View File

@@ -1,17 +0,0 @@
import os
import unittest
from httprunner.ext.locusts.utils import prepare_locust_tests
class TestLocust(unittest.TestCase):
def test_prepare_locust_tests(self):
path = os.path.join(os.path.dirname(__file__), "data", "demo_locusts.yml")
locust_tests = prepare_locust_tests(path)
self.assertEqual(len(locust_tests), 2 + 3)
name_list = [
"create user 1000 and check result.",
"create user 1001 and check result.",
]
self.assertIn(locust_tests[0]["config"]["name"], name_list)
self.assertIn(locust_tests[4]["config"]["name"], name_list)

View File

@@ -12,7 +12,7 @@ class TestLoader(unittest.TestCase):
)
def test_make_testcase_folder(self):
path = "examples/postman_echo/request_methods/"
path = ["examples/postman_echo/request_methods/"]
testcase_python_list = main_make(path)
self.assertIn(
"examples/postman_echo/request_methods/request_with_functions_test.py",

View File

@@ -115,10 +115,16 @@ class ResponseObject(object):
"""
self.resp_obj = resp_obj
try:
body = resp_obj.json()
except ValueError:
body = resp_obj.content
self.resp_obj_meta = {
"status_code": resp_obj.status_code,
"headers": resp_obj.headers,
"body": resp_obj.json(),
"body": body,
}
self.validation_results: Dict = {}

View File

@@ -169,7 +169,7 @@ class HttpRunner(object):
if self.config.path:
self.project_meta = load_project_meta(self.config.path)
else:
elif not self.project_meta:
self.project_meta = ProjectMeta()
self.start_at = time.time()