locusts support weight feature

This commit is contained in:
debugtalk
2018-10-29 22:16:41 +08:00
parent aed7013b1d
commit 2d5ff04b46
10 changed files with 133 additions and 50 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
__title__ = 'HttpRunner' __title__ = 'HttpRunner'
__description__ = 'One-stop solution for HTTP(S) testing.' __description__ = 'One-stop solution for HTTP(S) testing.'
__url__ = 'https://github.com/HttpRunner/HttpRunner' __url__ = 'https://github.com/HttpRunner/HttpRunner'
__version__ = '1.5.14' __version__ = '1.5.15'
__author__ = 'debugtalk' __author__ = 'debugtalk'
__author_email__ = 'mail@debugtalk.com' __author_email__ = 'mail@debugtalk.com'
__license__ = 'MIT' __license__ = 'MIT'
+1 -1
View File
@@ -6,4 +6,4 @@ try:
except ImportError: except ImportError:
pass pass
from httprunner.api import HttpRunner, LocustRunner from httprunner.api import HttpRunner
-19
View File
@@ -255,22 +255,3 @@ class HttpRunner(object):
html_report_name, html_report_name,
html_report_template html_report_template
) )
class LocustRunner(object):
def __init__(self, locust_client):
self.runner = HttpRunner(http_client_session=locust_client)
def run(self, path):
try:
self.runner.run(path)
except exceptions.MyBaseError as ex:
# TODO: refactor
from locust.events import request_failure
request_failure.fire(
request_type=test.testcase_dict.get("request", {}).get("method"),
name=test.testcase_dict.get("request", {}).get("url"),
response_time=0,
exception=ex
)
+7 -2
View File
@@ -14,8 +14,13 @@ class Context(object):
""" init Context with testcase variables and functions. """ init Context with testcase variables and functions.
""" """
# testcase level context # testcase level context
## TESTCASE_SHARED_VARIABLES_MAPPING and TESTCASE_SHARED_FUNCTIONS_MAPPING will not change. ## TESTCASE_SHARED_VARIABLES_MAPPING and TESTCASE_SHARED_FUNCTIONS_MAPPING are unchangeable.
self.TESTCASE_SHARED_VARIABLES_MAPPING = variables or OrderedDict() if isinstance(variables, list):
self.TESTCASE_SHARED_VARIABLES_MAPPING = utils.convert_mappinglist_to_orderdict(variables)
else:
# dict
self.TESTCASE_SHARED_VARIABLES_MAPPING = variables or OrderedDict()
self.TESTCASE_SHARED_FUNCTIONS_MAPPING = functions or OrderedDict() self.TESTCASE_SHARED_FUNCTIONS_MAPPING = functions or OrderedDict()
# testcase level request, will not change # testcase level request, will not change
+47
View File
@@ -987,3 +987,50 @@ def load_tests(path, dot_env_path=None):
testcases_list = [] testcases_list = []
return testcases_list return testcases_list
def load_locust_tests(path, dot_env_path=None):
""" load locust testcases
Args:
path (str): testcase/testsuite file path.
dot_env_path (str): specified .env file path
Returns:
dict: locust testcases with weight
{
"config": {...},
"tests": [
# weight 3
[teststep11],
[teststep11],
[teststep11],
# weight 2
[teststep21, teststep22],
[teststep21, teststep22]
]
}
"""
raw_testcase = load_file(path)
project_mapping = load_project_tests(path, dot_env_path)
config = {
"refs": project_mapping
}
tests = []
for item in raw_testcase:
key, test_block = item.popitem()
if key == "config":
config.update(test_block)
elif key == "test":
teststeps = _load_teststeps(test_block, project_mapping)
weight = test_block.pop("weight", 1)
for _ in range(weight):
tests.append(teststeps)
return {
"config": config,
"tests": tests
}
-3
View File
@@ -40,13 +40,10 @@ def gen_locustfile(testcase_file_path):
"templates", "templates",
"locustfile_template" "locustfile_template"
) )
testcases = loader.load_tests(testcase_file_path)
host = testcases[0].get("config", {}).get("request", {}).get("base_url", "")
with io.open(template_path, encoding='utf-8') as template: with io.open(template_path, encoding='utf-8') as template:
with io.open(locustfile_path, 'w', encoding='utf-8') as locustfile: with io.open(locustfile_path, 'w', encoding='utf-8') as locustfile:
template_content = template.read() template_content = template.read()
template_content = template_content.replace("$HOST", host)
template_content = template_content.replace("$TESTCASE_FILE", testcase_file_path) template_content = template_content.replace("$TESTCASE_FILE", testcase_file_path)
locustfile.write(template_content) locustfile.write(template_content)
+33 -11
View File
@@ -1,24 +1,46 @@
#coding: utf-8 import logging
import random
import zmq import zmq
from httprunner.exceptions import MyBaseError, MyBaseFailure
from httprunner.loader import load_locust_tests
from httprunner.runner import Runner
from locust import HttpLocust, TaskSet, task from locust import HttpLocust, TaskSet, task
from httprunner import LocustRunner from locust.events import request_failure
from httprunner.loader import load_tests
logging.getLogger().setLevel(logging.CRITICAL)
logging.getLogger('locust.main').setLevel(logging.INFO)
logging.getLogger('locust.runners').setLevel(logging.INFO)
class WebPageTasks(TaskSet): class WebPageTasks(TaskSet):
def on_start(self): def on_start(self):
self.test_runner = LocustRunner(self.client) self.test_runner = Runner(self.locust.config, self.client)
self.testcases = loader.load_tests(self.locust.file_path) self.testcases = load_locust_tests(self.locust.file_path)
@task @task(weight=1)
def test_specified_scenario(self): def test_any(self):
self.test_runner.run(self.testcases) teststeps = random.choice(self.locust.tests)
for teststep in teststeps:
try:
self.test_runner.run_test(teststep)
except (MyBaseError, MyBaseFailure) as ex:
request_failure.fire(
request_type=teststep.get("request", {}).get("method"),
name=teststep.get("name"),
response_time=0,
exception=ex
)
class WebPageUser(HttpLocust): class WebPageUser(HttpLocust):
host = "$HOST"
task_set = WebPageTasks task_set = WebPageTasks
min_wait = 1000 min_wait = 10
max_wait = 5000 max_wait = 30
file_path = "$TESTCASE_FILE" file_path = "$TESTCASE_FILE"
locust_tests = load_locust_tests(file_path)
config = locust_tests["config"]
tests = locust_tests["tests"]
host = config.get('request', {}).get('base_url', '')
+34
View File
@@ -0,0 +1,34 @@
- config:
name: basic test with httpbin
request:
base_url: https://httpbin.org/
- test:
name: index
weight: 5
request:
url: /
method: GET
validate:
- eq: ["status_code", 200]
- contains: [content, "HTTP Request & Response Service"]
- test:
name: headers
weight: 3
request:
url: /headers
method: GET
validate:
- eq: ["status_code", 200]
- eq: [content.headers.Host, "httpbin.org"]
- test:
name: user-agent
weight: 2
request:
url: /user-agent
method: GET
validate:
- eq: ["status_code", 200]
- startswith: [content.user-agent, "python-requests"]
+1 -13
View File
@@ -2,7 +2,7 @@ import os
import shutil import shutil
import time import time
from httprunner import HttpRunner, LocustRunner, api, loader, parser from httprunner import HttpRunner, api, loader, parser
from locust import HttpLocust from locust import HttpLocust
from tests.api_server import HTTPBIN_SERVER from tests.api_server import HTTPBIN_SERVER
from tests.base import ApiServerUnittest from tests.base import ApiServerUnittest
@@ -375,15 +375,3 @@ class TestHttpRunner(ApiServerUnittest):
os.getcwd(), 'tests/httpbin/basic.yml') os.getcwd(), 'tests/httpbin/basic.yml')
runner = HttpRunner().run(testcase_file_path) runner = HttpRunner().run(testcase_file_path)
self.assertTrue(runner.summary["success"]) self.assertTrue(runner.summary["success"])
class TestLocustRunner(ApiServerUnittest):
def setUp(self):
WebPageUser = type('WebPageUser', (HttpLocust,), {})
self.locust_client = WebPageUser.client
def test_LocustRunner(self):
testcase_file = os.path.join(os.getcwd(), 'tests', 'httpbin', 'basic.yml')
locust_runner = LocustRunner(self.locust_client)
locust_runner.run(testcase_file)
+9
View File
@@ -553,3 +553,12 @@ class TestSuiteLoader(unittest.TestCase):
self.assertIn("get_token", project_mapping["def-api"]) self.assertIn("get_token", project_mapping["def-api"])
self.assertIn("setup_and_reset", project_mapping["def-testcase"]) self.assertIn("setup_and_reset", project_mapping["def-testcase"])
self.assertEqual(project_mapping["env"]["PROJECT_KEY"], "ABCDEFGH") self.assertEqual(project_mapping["env"]["PROJECT_KEY"], "ABCDEFGH")
def test_load_locust_tests(self):
path = os.path.join(
os.getcwd(), 'tests/data/demo_locust.yml')
locust_tests = loader.load_locust_tests(path)
self.assertEqual(locust_tests["config"]["refs"]["env"]["UserName"], "debugtalk")
self.assertEqual(len(locust_tests["tests"]), 10)
self.assertEqual(locust_tests["tests"][0][0]["name"], "index")
self.assertEqual(locust_tests["tests"][9][0]["name"], "user-agent")