Python+request+unittest实现接口测试框架集成实例
这篇文章主要介绍了Python+request+unittest实现接口测试框架集成实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
1、为什么要写代码实现接口自动化
大家知道很多接口测试工具可以实现对接口的测试,如postman、jmeter、fiddler等等,而且使用方便,那么为什么还要写代码实现接口自动化呢?工具虽然方便,但也不足之处:
测试数据不可控制
接口测试本质是对数据的测试,调用接口,输入一些数据,随后,接口返回一些数据。验证接口返回数据的正确性。在用工具运行测试用例之前不得不手动向数据库中插入测试数据。这样我们的接口测试是不是就没有那么“自动化了”。
无法测试加密接口
这是接口测试工具的一大硬伤,如我们前面开发的接口用工具测试完全没有问题,但遇到需要对接口参 数进行加密/解密的接口,例如 md5、base64、AES 等常见加密方式。本书第十一章会对加密接口进行介绍。 又或者接口的参数需要使用时间戳,也是工具很难模拟的。
扩展能力不足
当我们在享受工具所带来的便利的同时,往往也会受制于工具所带来的局限。例如,我想将测试结果生 成 HMTL 格式测试报告,我想将测试报告发送到指定邮箱。我想对接口测试做定时任务。我想对接口测试做持续集成。这些需求都是工具难以实现的。
2、接口自动化测试设计
接口测试调用过程可以用下图概括,增加了测试数据库
一般的 接口工具 测试过程:
1、接口工具调用被测系统的接口(传参 username="zhangsan")。
2、系统接口根据传参(username="zhangsan")向 正式数据库 中查询数据。
3、将查询结果组装成一定格式的数据,并返回给被调用者。
4、人工或通过工具的断言功能检查接口测试的正确性。
接口自动化测试项目,为了使接口测试对数据变得可控,测试过程如下:
1、接口测试项目先向 测试数据库 中插入测试数据(zhangsan 的个人信息)。
2、调用被测系统接口(传参 username="zhangsan")。
3、系统接口根据传参(username="zhangsan")向测试数据库中进行查询并得到 zhangsan 个人信息。
4、将查询结果组装成一定格式的数据,并返回给被调用者。
5、通过单元测试框架断言接口返回的数据(zhangsan 的个人信息),并生成测试报告。
为了使正式数据库的数据不被污染,建议使用独立的 测试数据库 。
3、requests库
Requests 使用的是 urllib3,因此继承了它的所有特性。Requests 支持 HTTP 连接保持和连接池 ,支持 使用cookie保持会话 ,支持 文件上传 ,支持 自动确定响应内容的编码。 对request库的更详细的介绍可以看我之前接口测试基础的文章:
4、接口测试代码示例
下面以之前用 python+django 开发的用户签到系统为背景,展示接口测试的代码。
为什么开发接口?开发的接口主要给谁来用?
前端和后端分离是近年来 Web 应用开发的一个发展趋势。这种模式将带来以下优势:
1、后端可以不用必须精通前端技术(HTML/JavaScript/CSS),只专注于数据的处理,对外提供 API 接口。
2、前端的专业性越来越高,通过 API 接口获取数据,从而专注于页面的设计。
3、前后端分离增加接口的应用范围,开发的接口可以应用到 Web 页面上,也可以应用到移动 APP 上。
在这种开发模式下,接口测试工作就会变得尤为重要了。
开发实现的接口代码示例:
# 添加发布会接口实现
def add_event(request):eid = request.POST.get('eid','') # 发布会idname = request.POST.get('name','') # 发布会标题limit = request.POST.get('limit','') # 限制人数status = request.POST.get('status','') # 状态address = request.POST.get('address','') # 地址start_time = request.POST.get('start_time','') # 发布会时间if eid =='' or name == '' or limit == '' or address == '' or start_time == '':return JsonResponse({'status':10021,'message':'parameter error'})result = Event.objects.filter(id=eid)if result:return JsonResponse({'status':10022,'message':'event id already exists'})result = Event.objects.filter(name=name)if result:return JsonResponse({'status':10023,'message':'event name already exists'})if status == '':status = 1try:Event.objects.create(id=eid,name=name,limit=limit,address=address,status=int(status),start_time=start_time)except ValidationError:error = 'start_time format error. It must be in YYYY-MM-DD HH:MM:SS format.'return JsonResponse({'status':10024,'message':error})return JsonResponse({'status':200,'message':'add event success'})
通过POST请求接收发布会参数:发布会id、标题、人数、状态、地址和时间等参数。
首先,判断eid、name、limit、address、start_time等字段均不能为空,否则JsonResponse()返回相应的状态码和提示。JsonResponse()是一个非常有用的方法,它可以直接将字典转化成Json格式返回到客户端。
接下来,判断发布会id是否存在,以及发布会名称(name)是否存在;如果存在将返回相应的状态码和 提示信息。
再接下来,判断发布会状态是否为空,如果为空,将状态设置为1(True)。
最后,将数据插入到 Event 表,在插入的过程中如果日期格式错误,将抛出 ValidationError 异常,接收 该异常并返回相应的状态和提示,否则,插入成功,返回状态码200和“add event success”的提示。
# 发布会查询接口实现
def get_event_list(request):eid = request.GET.get("eid", "") # 发布会idname = request.GET.get("name", "") # 发布会名称if eid == '' and name == '':return JsonResponse({'status':10021,'message':'parameter error'})if eid != '':event = {}try:result = Event.objects.get(id=eid)except ObjectDoesNotExist:return JsonResponse({'status':10022, 'message':'query result is empty'})else:event['eid'] = result.idevent['name'] = result.nameevent['limit'] = result.limitevent['status'] = result.statusevent['address'] = result.addressevent['start_time'] = result.start_timereturn JsonResponse({'status':200, 'message':'success', 'data':event})if name != '':datas = []results = Event.objects.filter(name__contains=name)if results:for r in results:event = {}event['eid'] = r.idevent['name'] = r.nameevent['limit'] = r.limitevent['status'] = r.statusevent['address'] = r.addressevent['start_time'] = r.start_timedatas.append(event)return JsonResponse({'status':200, 'message':'success', 'data':datas})else:return JsonResponse({'status':10022, 'message':'query result is empty'})
通过GET请求接收发布会id和name 参数。两个参数都是可选的。首先,判断当两个参数同时为空,接口返回状态码10021,参数错误。
如果发布会id不为空,优先通过id查询,因为id的唯一性,所以,查询结果只会有一条,将查询结果 以 key:value 对的方式存放到定义的event字典中,并将数据字典作为整个返回字典中data对应的值返回。
name查询为模糊查询,查询数据可能会有多条,返回的数据稍显复杂;首先将查询的每一条数据放到一 个字典event中,再把每一个字典再放到数组datas中,最后再将整个数组做为返回字典中data对应的值返回。
接口测试代码示例
#查询发布会接口测试代码
import requestsurl = "http://127.0.0.1:8000/api/get_event_list/"
r = requests.get(url, params={'eid':'1'})
result = r.json()
print(result)
assert result['status'] == 200
assert result['message'] == "success"
assert result['data']['name'] == "xx 产品发布会"
assert result['data']['address'] == "北京林匹克公园水立方"
assert result['data']['start_time'] == "2016-10-15T18:00:00"
因为“发布会查询接口”是GET类型,所以,通过requests库的get()方法调用,第一个参数为调用接口的URL地址,params设置接口的参数,参数以字典形式组织。
json()方法可以将接口返回的json格式的数据转化为字典。
接下来就是通过 assert 语句对接字典中的数据进行断言。分别断言status、message 和data的相关数据等。
使用unittest单元测试框架开发接口测试用例
#发布会查询接口测试代码
import unittest
import requestsclass GetEventListTest(unittest.TestCase):def setUp(self):self.base_url = "http://127.0.0.1:8000/api/get_event_list/"def test_get_event_list_eid_null(self):''' eid 参数为空 '''r = requests.get(self.base_url, params={'eid':''})result = r.json()self.assertEqual(result['status'], 10021)self.assertEqual(result['message'], 'parameter error')def test_get_event_list_eid_error(self):''' eid=901 查询结果为空 '''r = requests.get(self.base_url, params={'eid':901})result = r.json()self.assertEqual(result['status'], 10022)self.assertEqual(result['message'], 'query result is empty')def test_get_event_list_eid_success(self):''' 根据 eid 查询结果成功 '''r = requests.get(self.base_url, params={'eid':1})result = r.json()self.assertEqual(result['status'], 200)self.assertEqual(result['message'], 'success')self.assertEqual(result['data']['name'],u'mx6发布会')self.assertEqual(result['data']['address'],u'北京国家会议中心')def test_get_event_list_nam_result_null(self):''' 关键字‘abc'查询 '''r = requests.get(self.base_url, params={'name':'abc'})result = r.json()self.assertEqual(result['status'], 10022)self.assertEqual(result['message'], 'query result is empty')def test_get_event_list_name_find(self):''' 关键字‘发布会'模糊查询 '''r = requests.get(self.base_url, params={'name':'发布会'})result = r.json()self.assertEqual(result['status'], 200)self.assertEqual(result['message'], 'success')self.assertEqual(result['data'][0]['name'],u'mx6发布会')self.assertEqual(result['data'][0]['address'],u'北京国家会议中心')
49if __name__ == '__main__':unittest.main()
unittest单元测试框架可以帮助 组织和运行接口测试用例。
5、接口自动化测试框架实现
关于接口自动化测试,unittest 已经帮我们做了大部分工作,接下来只需要 集成数据库操作 ,以及 HTMLTestRunner测试报告生成 扩展即可。
框架结构如下图:
pyrequests 框架:
db_fixture/: 初始化接口测试数据。
interface/: 用于编写接口自动化测试用例。
report/: 生成接口自动化测试报告。
db_config.ini : 数据库配置文件。
HTMLTestRunner.py unittest 单元测试框架扩展,生成 HTML 格式的测试报告。
run_tests.py : 执行所有接口测试用例。
4.1、数据库配置
首先,需要修改被测系统将数据库指向测试数据库。以 MySQL数据库为例,针对 django 项目而言,修改.../guest/settings.py 文件。可以在系统测试环境单独创建一个测试库。 这样做的目的是让接口测试的数据不会清空或污染到功能测试库的数据。 其他框架开发的项目与django项目类似,这个工作一般由开发同学完成,我们测试同学更多关注的是测试框架的代码。
4.2、框架代码实现
4.2.1、首先,创 建数据库配置文件.../db_config.ini
4.2.2、接下来, 简单封装数据库操作,数据库表数据的插入和清除 ,.../db_fixture/ mysql_db.py
import pymysql.cursors
import os
import configparser as cparser# ======== Reading db_config.ini setting ===========
base_dir = str(os.path.dirname(os.path.dirname(__file__)))
base_dir = base_dir.replace('\\', '/')
file_path = base_dir + "/db_config.ini"cf = cparser.ConfigParser()cf.read(file_path)
host = cf.get("mysqlconf", "host")
port = cf.get("mysqlconf", "port")
db = cf.get("mysqlconf", "db_name")
user = cf.get("mysqlconf", "user")
password = cf.get("mysqlconf", "password")# ======== MySql base operating ===================
class DB:def __init__(self):try:# Connect to the databaseself.connection = pymysql.connect(host=host,port=int(port),user=user,password=password,db=db,charset='utf8mb4',cursorclass=pymysql.cursors.DictCursor)except pymysql.err.OperationalError as e:print("Mysql Error %d: %s" % (e.args[0], e.args[1]))# clear table datadef clear(self, table_name):# real_sql = "truncate table " + table_name + ";"real_sql = "delete from " + table_name + ";"with self.connection.cursor() as cursor:cursor.execute("SET FOREIGN_KEY_CHECKS=0;")cursor.execute(real_sql)self.connection.commit()# insert sql statementdef insert(self, table_name, table_data):for key in table_data:table_data[key] = "'"+str(table_data[key])+"'"key = ','.join(table_data.keys())value = ','.join(table_data.values())real_sql = "INSERT INTO " + table_name + " (" + key + ") VALUES (" + value + ")"#print(real_sql)with self.connection.cursor() as cursor:cursor.execute(real_sql)self.connection.commit()# close databasedef close(self):self.connection.close()# init datadef init_data(self, datas):for table, data in datas.items():self.clear(table)for d in data:self.insert(table, d)self.close()if __name__ == '__main__':db = DB()table_name = "sign_event"data = {'id':1,'name':'红米','`limit`':2000,'status':1,'address':'北京会展中心','start_time':'2016-08-20 00:25:42'}table_name2 = "sign_guest"data2 = {'realname':'alen','phone':12312341234,'email':'alen@mail.com','sign':0,'event_id':1}db.clear(table_name)db.insert(table_name, data)db.close()
首先,读取 db_config.ini 配置文件。 创建 DB 类,__init__()方法初始化,通过 pymysql.connect()连接数据库。
因为这里只用到数据库表的清除和插入,所以只创建 clear()和 insert()两个方法。其中,insert()方法对数 据的插入做了简单的格式转化,可将字典转化成 SQL 插入语句,这样格式转化了方便了数据库表数据的创建。
最后,通过 close()方法用于关闭数据库连接。
4.2.3、接下来接下来 创建测试数据 ,.../db_fixture/ test_data.py
import sys
sys.path.append('../db_fixture')
try:from mysql_db import DB
except ImportError:from .mysql_db import DB# create data
datas = {'sign_event':[{'id':1,'name':'红米Pro发布会','`limit`':2000,'status':1,'address':'北京会展中心','start_time':'2017-08-20 14:00:00'},{'id':2,'name':'可参加人数为0','`limit`':0,'status':1,'address':'北京会展中心','start_time':'2017-08-20 14:00:00'},{'id':3,'name':'当前状态为0关闭','`limit`':2000,'status':0,'address':'北京会展中心','start_time':'2017-08-20 14:00:00'},{'id':4,'name':'发布会已结束','`limit`':2000,'status':1,'address':'北京会展中心','start_time':'2001-08-20 14:00:00'},{'id':5,'name':'小米5发布会','`limit`':2000,'status':1,'address':'北京国家会议中心','start_time':'2017-08-20 14:00:00'},],'sign_guest':[{'id':1,'realname':'alen','phone':13511001100,'email':'alen@mail.com','sign':0,'event_id':1},{'id':2,'realname':'has sign','phone':13511001101,'email':'sign@mail.com','sign':1,'event_id':1},{'id':3,'realname':'tom','phone':13511001102,'email':'tom@mail.com','sign':0,'event_id':5},],
}# Inster table datas
def init_data():DB().init_data(datas)if __name__ == '__main__':init_data()
init_data()函数用于读取 datas 字典中的数据,调用 DB 类中的 clear()方法清除数据库,然后,调用 insert() 方法插入表数据。
4.2.4、编写 接口测试用例 。创建添加发布会接口测试文件.../interface/ add_event_test.py
import unittest
import requests
import os, sys
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, parentdir)
from db_fixture import test_dataclass AddEventTest(unittest.TestCase):''' 添加发布会 '''def setUp(self):self.base_url = "http://127.0.0.1:8000/api/add_event/"def tearDown(self):print(self.result)def test_add_event_all_null(self):''' 所有参数为空 '''payload = {'eid':'','':'','limit':'','address':"",'start_time':''}r = requests.post(self.base_url, data=payload)self.result = r.json()self.assertEqual(self.result['status'], 10021)self.assertEqual(self.result['message'], 'parameter error')def test_add_event_eid_exist(self):''' id已经存在 '''payload = {'eid':1,'name':'一加4发布会','limit':2000,'address':"深圳宝体",'start_time':'2017'}r = requests.post(self.base_url, data=payload)self.result = r.json()self.assertEqual(self.result['status'], 10022)self.assertEqual(self.result['message'], 'event id already exists')def test_add_event_name_exist(self):''' 名称已经存在 '''payload = {'eid':11,'name':'红米Pro发布会','limit':2000,'address':"深圳宝体",'start_time':'2017'}r = requests.post(self.base_url,data=payload)self.result = r.json()self.assertEqual(self.result['status'], 10023)self.assertEqual(self.result['message'], 'event name already exists')def test_add_event_data_type_error(self):''' 日期格式错误 '''payload = {'eid':11,'name':'一加4手机发布会','limit':2000,'address':"深圳宝体",'start_time':'2017'}r = requests.post(self.base_url,data=payload)self.result = r.json()self.assertEqual(self.result['status'], 10024)self.assertIn('start_time format error.', self.result['message'])def test_add_event_success(self):''' 添加成功 '''payload = {'eid':11,'name':'一加4手机发布会','limit':2000,'address':"深圳宝体",'start_time':'2017-05-10 12:00:00'}r = requests.post(self.base_url,data=payload)self.result = r.json()self.assertEqual(self.result['status'], 200)self.assertEqual(self.result['message'], 'add event success')if __name__ == '__main__':test_data.init_data() # 初始化接口测试数据unittest.main()
在测试接口之前,调用test_data.py文件中的init_data()方法初始化数据库中的测试数据。
创建AddEventTest测试类继承 unittest.TestCase 类,通过创建测试用例,调用相关接口,并验证接口返回 的数据。
4.2.5、创建 run_tests.py 文件
当开发的接口达到一定数量后,就需要考虑 分文件分目录 的来 划分 接口测试用例,如何批量的执行不同文件目录下的用例呢?unittest单元测试框架提供的 discover() 方法可以帮助我们做到这一点。并使用 HTMLTestRunner 扩展生成 HTML 格式的测试报告。
import time, sys
sys.path.append('./interface')
sys.path.append('./db_fixture')
from HTMLTestRunner import HTMLTestRunner
import unittest
from db_fixture import test_data# 指定测试用例为当前文件夹下的 interface 目录
test_dir = './interface'
discover = unittest.defaultTestLoader.discover(test_dir, pattern='*_test.py')if __name__ == "__main__":test_data.init_data() # 初始化接口测试数据now = time.strftime("%Y-%m-%d %H_%M_%S")filename = './report/' + now + '_result.html'fp = open(filename, 'wb')runner = HTMLTestRunner(stream=fp,title='Guest Manage System Interface Test Report',description='Implementation Example with: ')runner.run(discover)fp.close()
首先,通过调用test_data.py文件中的init_data()函数来初始化接口测试数据。
使用unittest框架所提供的discover()方法,查找 interface/ 目录下,所有匹配_test.py 的测试文件(星 号匹配任意字符)。
HTMLTestRunner 为unittest单元测试框架的扩展,利用它所提供的HTMLTestRunner()类来替换unittest单元测试框架的TextTestRunner()类,从而生成HTML格式的测试报告。
遗憾的是HTMLTestRunner并不支持Python3.x,大家可以在网上找到适用于Python3.x的HTMLTestRunner.py文件,使用在自己的接口自动化工程中。
通过 time 的 strftime()方法获取当前时间,并且转化成一定的时间格式。作为测试报告的名称。这样做目的是是为了避免因为生成的报告的名称重名而造成报告的覆盖。最终,将测试报告存放于report/目录下面。如下图,一张完整的接口自动化测试报告。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持“软件测试pytest”。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
软件测试面试小程序
被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!
涵盖以下这些面试题板块:
1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux
6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!
相关文章:

Python+request+unittest实现接口测试框架集成实例
这篇文章主要介绍了Pythonrequestunittest实现接口测试框架集成实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 1、为什么要写代码实现接口自动化 大家知道很多接口测试工具可以实现对接口的测试…...

django/flask+python+vue汽车租赁管理系统_1ma2x
开发语言:Python 框架:django/flask Python版本:python3.7.7 数据库:mysql 数据库工具:Navicat 开发软件:PyCharm . 课题主要分为三大模块:即管理员模块、用户模块和普通管理员模块࿰…...

胜者打仗,就像高山上决开积水,势不可挡
胜者打仗,就像高山上决开积水,势不可挡 【安志强趣讲《孙子兵法》16讲】 【原文】 是故胜兵先胜而后求战,败兵先战而后求胜。善用兵者,修道而保法,故能为胜败之政。 【注释】 修道:指从各方面修治“先立于不…...

stm32的命令规则
stm32型号的说明:以STM32F103RBT6这个型号的芯片为例,该型号的组成为7个部分,其命名规则如下:...

1. HBase中文学习手册之揭开Hbase的神秘面纱
揭开Hbase的神秘面纱 1.1 欢迎使用 Apache Hbase1.1.1 什么是 Hbase?1.1.2 Hbase的前世今生1.1.3 HBase的技术选型?1.1.3.1 不适合使用 HBase的场景1.1.3.2 适合使用 HBase的场景 1.1.4 HBase的特点1.1.4.1 HBase的优点1.1.4.2 HBase的缺点 1.1.5 HBase设计架构 1.…...

[线程/C++]线程同(异)步和原子变量
文章目录 1.线程的使用1.1 函数构造1.2 公共成员函数1.2.1 get_id()1.2.2 join()2.2.3 detach()2.2.5 joinable()2.2.6 operator 1.3 静态函数1.4 call_once 2. this_thread 命名空间2.1 get_id()2.2 sleep_for()2.3 sleep_until()2.4 yield() 3. 线程同步之互斥锁3.1 std:mute…...

全球网络加速器GA和内容分发网络CDN,哪个更适合您的组织使用?
对互联网用户来说,提供最佳的用户体验至关重要:网页加载时间过长、视频播放断断续续以及服务忽然中断等问题都足以在瞬间失去客户。因此可以帮助提高您的网站或APP提高加载性能的解决方案就至关重要:全球网络加速器和CDN就是其中的两种解决方…...

蓝凌OA custom.jsp 任意文件读取
曾子曰:“慎终追远,民德归厚矣。” 漏洞复现 访问漏洞url: 出现漏洞的文件为 custom.jsp,构造payload: /sys/ui/extend/varkind/custom.jsp var{"body":{"file":"file:///etc/passwd&q…...

(二)结构型模式:7、享元模式(Flyweight Pattern)(C++实例)
目录 1、享元模式(Flyweight Pattern)含义 2、享元模式的UML图学习 3、享元模式的应用场景 4、享元模式的优缺点 5、C实现享元模式的简单实例 1、享元模式(Flyweight Pattern)含义 享元模式(Flyweight)…...
laravel 多次查询请求,下次请求清除上次请求的where 条件
在Laravel中,可以使用where方法来添加查询条件,但是每次添加where条件时,都会在查询构造器中持久化这些条件,直到你手动重置它们。所以,如果你想在下一次查询中清除上次查询的where条件,有以下几种选择&…...
C++根据如下使用类MyDate的程序,写出类MyDate的定义,MyDate中有三个数据成员:年year,月month,日day完成以下要求
题目: 根据如下使用类MyDate的程序,写出类MyDate的定义,MyDate中有三个数据成员: 年year,月month,日day int year,month,day; void main() { MyDate d1, d2; d1.set(2015, 12, 31); d2.set(d1); d1.…...

微盟集团中报增长稳健 重点发力智慧零售AI赛道
零售数字化进程已从渠道构建走向了用户的深度运营。粗放式用户运营体系无法适应“基于用户增长所需配套的精细化运营能力”,所以需要有个体、群体、个性化、自动化运营——即在对的时候、以对的方式、把对的内容推给用户。 出品|产业家 2023年已经过半,经济复苏成为…...
设计模式(7)模板方法模式
一、定义: 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。 //模板方法抽象类 public abstract class AbstractClass {//模板方法publ…...
2308C++协程流程9
参考 #include <协程> #include "简异中.cpp" //用来中文定义的.元<类 T>构 P;元<类 T>构 任务{用 承诺型P<T>;任务()默认;动 符号 协待()常 无异{构 等待器{极 直接协()常 无异{中 p.是准备好();}协柄 挂起协(协柄<>o)常 无异{p.连续…...

基于学习交流社区的自动化测试实现
一 项目介绍 项目名称 项目名称: 学习交流社区 项目介绍 项目介绍: 学习交流社区是一个基于Spring的前后端分离的在线论坛系统。使用了MySQL数据库来存储相关信息,项目完成后使用Xshell将其部署到云服务器上。 前端页面: 前端共由…...
2023-08-21力扣每日一题
链接: 2337. 移动片段得到字符串 题意: L可以和左边的_交换,R可以和右边的_交换,求判断A是否能通过交换(不限次数)变成B 解: 观察可知,如果存在RL,一定不能交换出LR,…...

对象存储服务-MinIO基本集成
是什么 MinIO 是一个高性能的分布式对象存储服务,适合存储非结构化数据,如图片,音频,视频,日志等。对象文件最大可以达到5TB。 安装启动 mkdir -p /usr/local/minio cd /usr/local/minio# 下载安装包 wget https:/…...
Yarn介绍及快速安装 - Debian/Ubuntu Linux
1.Yarn介绍 Yarn 是一个用于管理 JavaScript 包的快速、可靠和安全的包管理器。它是由 Facebook、Google、Exponent 和 Tilde 团队共同开发的,旨在提供比 npm 更快速、可靠的包管理体验。 以下是 Yarn 的一些主要特点和优势: 快速安装:Yarn…...
【新日语(2)】第10課 中国の生活に慣れるかどうか少し心配です
第10課 中国の生活に慣れるかどうか少し心配です 注释: ~かどうか:“是否”。 练习A 一、例句 田中さんは鈴木さんに、30分ぐらい遅れると言いました。 田中先生告诉铃木先生,他会迟到大约30分钟。 注释: &…...
Python 网页解析初级篇:BeautifulSoup库的入门使用
在Python的网络爬虫中,网页解析是一项重要的技术。而在众多的网页解析库中,BeautifulSoup库凭借其简单易用而广受欢迎。在本篇文章中,我们将学习BeautifulSoup库的基本用法。 一、BeautifulSoup的安装与基本使用 首先,我们需要使…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...