这种好 BUG,爆出来干啥?
hhhhh
加 celery 接管 task 的执行,celery 是支持多任务并发的,rabbimt / redis 作为中间队列,并发方式单机的话我建议你选择 gevent 。
可以不用,但是如果你的项目频繁变动,你需要经常维护的时候,我建议还是对整个测试框架的设计重构一下。比如 Web UI 里面的 POM 模式,比如 httprunner 在 2.x 重构后的分层机制,这些都是为了方便后期的维护迭代,以及对复用部分的高度封装。
对的,所以要看具体项目的埋点方案,或者在 SDK 里面加入 console.log ,一般来说这样做比较方便调试。
这个要看你们项目里面埋点上报的 SDK 是怎么写的,比如神策,只要收集到上报的事件就会在 console 里面打印出来,不然开发自测的时候怎么知道自己写的埋点有被正确触发呢?当然不同的埋点方案有不同的设计,这里以 console 打印埋点信息为例。
更多原理层内容见 Buried-Point-Pro 项目的前身:https://testerhome.com/topics/21136
不是让你写前端,而是测前端 hhhhh 项目跑起来以后发的请求都会经过代理返回你 mock 的数据,从而看是否符合业务需求。
这个是你们项目前端开发项目比后端快,你要先测前端的时候,没有接口自然要先 mock 数据,不过你要按照后端约定好的数据格式来 mock 数据,然后把你们前端项目的 proxy 改一下就可以了。
重构并优化了一下代码,新增了不少 demo 体验演示和 debug 信息,也支持过滤无用上报事件和重复事件上报的检测 ~
有,用 puppeteer
技术肯定是要的,但是可能不是纯技术,而是结合到了实际的业务场景里面,问你有没有技术方案可以落地实施从而解决业务测试痛点。
简单点的,对网页性能打开速度和稳定性的,这是之前我做的:https://testerhome.com/topics/20613
深入一点的,一般都是在你们的项目代码里面加入探针,做一个前端实时的监控系统,给你的推荐:https://github.com/wangweianger/zanePerfor
QQ 群 552643038
嗯,puppeteer 就是 nodejs 版的 selenium,但是包装了 chromeDevTools 的很多功能在里面。
$X_CSRF_Token 与 $ X-CSRF-Token 跟这个下划线和横杠有关系
这个跟 goreplay 差不多吗?
接口没有必要用 POM 的设计模式来封装,接口像 Httprunner 这些都非常成熟好用,可以用脚手架去管理,也在社区的开源项目里面,可以去了解一下。
opendiffy/diffy 和 twitter/diffy 有什么不一样的地方?
方案一可借鉴轮子:
https://github.com/wuyuewuzhenmin/Jmeter-ptc
方案二可借鉴轮子:
https://github.com/myzhan/boomer
你都从 yaml 文件里面拿到了所有的请求和参数这一些,接下来不就像写接口测试脚本一样吗,把对应的参数放到 python 的脚本里面对应的位置,然后用 requests 去执行。所谓的 testsuite testcase teststep ,无非就是执行过程中的先后顺序,然后再去遍历执行每个过程中又嵌套的 testsuite testcase teststep。
""" Running testcases. """
Examples:
>>> tests_mapping = {
"project_mapping": {
"functions": {}
},
"testcases": [
{
"config": {
"name": "XXXX",
"base_url": "http://127.0.0.1",
"verify": False
},
"teststeps": [
{
"name": "test description",
"variables": [], # optional
"request": {
"url": "http://127.0.0.1:5000/api/users/1000",
"method": "GET"
}
}
]
}
]
}
>>> testcases = parser.parse_tests(tests_mapping)
>>> parsed_testcase = testcases[0]
>>> test_runner = runner.Runner(parsed_testcase["config"])
>>> test_runner.run_test(parsed_testcase["teststeps"][0])
首先,校验 yaml 文件的格式,返回 yaml 的数据。
def load_yaml_file(yaml_file):
""" load yaml file and check file content format
"""
with io.open(yaml_file, 'r', encoding='utf-8') as stream:
yaml_content = yaml.load(stream)
_check_format(yaml_file, yaml_content)
return yaml_content
接下来,根据你的测试指令后的文件的后缀名,读取对应格式的文件。
def load_file(file_path):
if not os.path.isfile(file_path):
raise exceptions.FileNotFound("{} does not exist.".format(file_path))
file_suffix = os.path.splitext(file_path)[1].lower()
if file_suffix == '.json':
return load_json_file(file_path)
elif file_suffix in ['.yaml', '.yml']:
return load_yaml_file(file_path)
elif file_suffix == ".csv":
return load_csv_file(file_path)
else:
# '' or other suffix
err_msg = u"Unsupported file format: {}".format(file_path)
logger.log_warning(err_msg)
return []
然后,下面这个我觉得就很明显了。
def load_teststep(raw_testinfo):
...
def load_testcase(raw_testcase):
...
def load_testcase_v2(raw_testcase):
""" load testcase in format version 2. """
...
def load_testsuite(raw_testsuite):
...
剩下一些类似 __extend_with_api_ref() __extend_with_testcase_ref() 等等的函数,无非就是读取你的测试步骤中调用的扩展 api 或者 testcase,locate_debugtalk_py() 函数作用就更明显了。一系列相关的东西都加载完,最后开始 load_test 进行最后的汇总组合。
def load_tests(path, dot_env_path=None):
""" load testcases from file path, extend and merge with api/testcase definitions.
Args:
path (str): testcase/testsuite file/foler path.
path could be in 2 types:
- absolute/relative file path
- absolute/relative folder path
dot_env_path (str): specified .env file path
Returns:
dict: tests mapping, include project_mapping and testcases.
each testcase is corresponding to a file.
{
"project_mapping": {
"PWD": "XXXXX",
"functions": {},
"env": {}
},
"testcases": [
{ # testcase data structure
"config": {
"name": "desc1",
"path": "testcase1_path",
"variables": [], # optional
},
"teststeps": [
# test data structure
{
'name': 'test desc1',
'variables': [], # optional
'extract': [], # optional
'validate': [],
'request': {}
},
test_dict_2 # another test dict
]
},
testcase_2_dict # another testcase dict
],
"testsuites": [
{ # testsuite data structure
"config": {},
"testcases": {
"testcase1": {},
"testcase2": {},
}
},
testsuite_2_dict
]
}
"""
if not os.path.exists(path):
err_msg = "path not exist: {}".format(path)
logger.log_error(err_msg)
raise exceptions.FileNotFound(err_msg)
if not os.path.isabs(path):
path = os.path.join(os.getcwd(), path)
load_project_tests(path, dot_env_path)
tests_mapping = {
"project_mapping": project_mapping
}
def __load_file_content(path):
loaded_content = None
try:
loaded_content = load_test_file(path)
except exceptions.FileFormatError:
logger.log_warning("Invalid test file format: {}".format(path))
if not loaded_content:
pass
elif loaded_content["type"] == "testsuite":
tests_mapping.setdefault("testsuites", []).append(loaded_content)
elif loaded_content["type"] == "testcase":
tests_mapping.setdefault("testcases", []).append(loaded_content)
elif loaded_content["type"] == "api":
tests_mapping.setdefault("apis", []).append(loaded_content)
if os.path.isdir(path):
files_list = load_folder_files(path)
for path in files_list:
__load_file_content(path)
elif os.path.isfile(path):
__load_file_content(path)
return tests_mapping
总之,多看看源码就好辣 hhh
源码:https://github.com/httprunner/httprunner
回答问题的相关代码文件: ./httprunner/loader.py
ppts v1.4.0: 当输出格式为 json 时,支持通过 webhook 发送测试数据给群机器人