之前的文章写了pytest-bdd做接口自动化测试,最近有个想法,用接口测试框架的接口信息,生产jmeter测试脚本,这样有了接口测试用例后,可以自动生成性能测试脚本。进行性能测试。
使用jmeter编辑了一个正常的测试脚本,来分析一下jmeter脚本内容。
通过上图发现,jmeter脚本就是xml格式的文件,这样我们可以根据生成的脚本,用python直接生成相应格式的脚本,看一下jmeter是否可以打开。
首先,我们先初始化xml文件的最外层标签。
import xml.etree.ElementTree as ET
class JmeterCore:
def __init__(self):
self.jmeter_test_plan = ET.Element('jmeterTestPlan')
self.jmeter_test_plan.set('version', '1.2')
self.jmeter_test_plan.set('properties', '5.0')
self.jmeter_test_plan.set('jmeter', '5.6.3')
self.hash_tree = ET.SubElement(self.jmeter_test_plan, 'hashTree')
然后,我们生成jmeter的测试计划模块。函数传参的parent为上面的生成的最外层xml标签。
class JmeterCore(base.General):
def add_test_plan(self, parent, name):
test_plan = ET.SubElement(parent, 'TestPlan')
test_plan.set('guiclass', 'TestPlanGui')
test_plan.set('testclass', 'TestPlan')
test_plan.set('testname', name)
elemet_prop = ET.SubElement(test_plan, 'elementProp')
elemet_prop.set('name', 'TestPlan.user_defined_variables')
elemet_prop.set('elementType', 'Arguments')
elemet_prop.set('guiclass', 'ArgumentsPanel')
elemet_prop.set('testclass', 'Arguments')
elemet_prop.set('testname', '用户定义的变量')
collection_prop = ET.SubElement(elemet_prop, 'collectionProp')
collection_prop.set('name', 'Arguments.arguments')
bool_prop1 = ET.SubElement(test_plan, 'boolProp')
bool_prop1.set('name', 'TestPlan.functional_mode')
bool_prop1.text = 'false'
bool_prop2 = ET.SubElement(test_plan, 'boolProp')
bool_prop2.set('name', 'TestPlan.serialize_threadgroups')
bool_prop2.text = 'false'
增加线程组,线程组的父级标签为最外层xml标签。
def add_thread_group(self, parent, name, **kwargs):
hash_tree = ET.SubElement(parent, 'hashTree')
thread_group = ET.SubElement(hash_tree, 'ThreadGroup')
thread_group.set('guiclass', 'ThreadGroupGui')
thread_group.set('testclass', 'ThreadGroup')
thread_group.set('testname', name)
prop_map = {
'comments': self.add_str_prop,
'num_threads': self.add_int_prop,
'ramp_time': self.add_int_prop,
'same_user_on_next_iteration': self.add_bool_prop,
'on_sample_error': self.add_str_prop,
'duration': self.add_long_prop,
'delay': self.add_long_prop,
'delayedStart': self.add_bool_prop,
'scheduler': self.add_bool_prop
}
keys_map = {
'comments': 'TestPlan.comments',
'num_threads': 'ThreadGroup.num_threads',
'ramp_time': 'ThreadGroup.ramp_time',
'same_user_on_next_iteration': 'ThreadGroup.same_user_on_next_iteration',
'on_sample_error': 'ThreadGroup.on_sample_error',
'duration': 'ThreadGroup.duration',
'delay': 'ThreadGroup.delay',
'delayedStart': 'ThreadGroup.delayedStart',
'scheduler': 'ThreadGroup.scheduler'
}
for key, value in kwargs.items():
if key == 'loops':
self.add_loop_controller(self, thread_group, value)
elif key in prop_map:
if value is not None or value != '':
prop_map[key](self,thread_group, keys_map[key], value)
return hash_tree
在线程组增加http取样器。http取样器的父级标签为线程组。
def add_http_sampler(self, parent, name, **kwargs):
hash_tree = ET.SubElement(parent, 'hashTree')
http_sampler = ET.SubElement(hash_tree, 'HTTPSamplerProxy')
http_sampler.set('guiclass', 'HttpTestSampleGui')
http_sampler.set('testclass', 'HTTPSamplerProxy')
http_sampler.set('testname', name)
prop_map = {
'comments': self.add_str_prop,
'domain': self.add_str_prop,
'port': self.add_str_prop,
'protocol': self.add_str_prop,
'contentEncoding': self.add_str_prop,
'path': self.add_str_prop,
'follow_redirects': self.add_bool_prop,
'method': self.add_str_prop,
'use_keepalive': self.add_bool_prop,
'auto_redirects': self.add_bool_prop,
'DO_MULTIPART_POST': self.add_bool_prop,
'BROWSER_COMPATIBLE_MULTIPART': self.add_bool_prop,
'postBodyRaw': self.add_bool_prop
}
keys_map = {
'comments': 'TestPlan.comments',
'domain': 'HTTPSampler.domain',
'port': 'HTTPSampler.port',
'protocol': 'HTTPSampler.protocol',
'contentEncoding': 'HTTPSampler.contentEncoding',
'path': 'HTTPSampler.path',
'follow_redirects': 'HTTPSampler.follow_redirects',
'method': 'HTTPSampler.method',
'use_keepalive': 'HTTPSampler.use_keepalive',
'auto_redirects': 'HTTPSampler.auto_redirects',
'DO_MULTIPART_POST': 'HTTPSampler.DO_MULTIPART_POST',
'BROWSER_COMPATIBLE_MULTIPART': 'HTTPSampler.BROWSER_COMPATIBLE_MULTIPART',
'postBodyRaw': 'HTTPSampler.postBodyRaw'
}
for key, value in kwargs.items():
if key == 'arguments':
self.add_arguments(self, http_sampler, value)
elif key in prop_map:
if value is not None or value != '':
prop_map[key](self,http_sampler, keys_map[key], value)