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的安装与基本使用 首先,我们需要使…...
Spring Schedular 定时任务
大家好 , 我是苏麟 , 今天带来定时任务的实现 . Spring网站 : 入门 |计划任务 (spring.io) 什么是定时任务 通过时间表达式来进行调度和执行的一类任务被称为定时任务 定时任务实现 1.Spring Schedule (Spring boot 默认整合了) 2.Quartz(独立于Spring 存在的定时任务框架…...
营业额统计
营业额统计 # 题目描述 Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger 拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日&…...
使用lodash的throttle函数会触发两次
当使用lodash的throttle函数时会触发两次,分别在最开始和最后。 严格来说不算是bug,因为官方文档写的很清楚。throttle函数其实有三个参数: _.throttle(func, [wait0], [options]) func: 要节流的函数 wait: 等待时间 options: 选项 op…...
如何使用CSS实现一个瀑布流布局?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现瀑布流布局⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚…...
dfs之有重复字符串的排列组合
https://leetcode.cn/problems/permutation-ii-lcci/description/ ■ 题目描述 考古问题,假设以前的石碑被打碎成了很多块,每块上面都有一个或若干个字符,请你写个程序来把之前石碑上文字可能的组合全部写出来,按升序进行排列。…...
Java之抽象类
Java之抽象类 抽象类概念抽象类如何使用抽象类的特性 作者简介: zoro-1,目前大一,正在学习Java,数据结构等 作者主页:zoro-1的主页 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖Ὁ…...
“无Internet连接但是可以上网” 解决全流程
先说我的最后解决方法: 修改注册表下\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet下 的 EnableActiveProbing 项:将 1 改成 0 为什么要解决“无Internet连接但是可以上网”这个问题? 因为虽然可以上百…...
VS2022 CMake报错解决小结
目录 一、问题背景 二、问题分析 三、问题解决 一、问题背景 VS2022中能够跨平台的工程类型就是CMake项目,一套代码能跨windows/Linux/Mac多种操作系统。而实际使用时,发现相关资料比较少,需要摸索一下。 碰到的问题简述: 1、C…...
java之webservice_aegis.xml学习
开门见山,直奔主题,让我们先来看一个接口: public interface UserInfo {public Collection findRoleInfosByUserID(String userUniqueID);public User findUserInfosByUserID(String userUniqueID);public String test();} 观察此接口,首先我们看findRoleInfosByUserID方法…...
总结 TCP 协议的相关特性
TCP协议段格式: 如图, 端口号: 是其中一个重要的部分,知道端口号才能确认数据交给哪个应用程序(端口号属于传输层的概念). 4位首部长度:4bit表示的范围是0->15,在此处,单位是"4字节",因此,将这里的数值 * 4,才是真正的报头长度,即TCP 报头最大长度,60…...
在手机怎样使用wordpress/深圳网络营销公司
前言:电商中:我们想查看某个用户所有的订单,或者想查看某个用户在某个时间段内所有的订单,此时我们需要对订单表数据进行筛选,按照用户、时间进行过滤,得到我们期望的结果。 此时我们需要使用条件查询来对…...
哈尔滨建设网站公司/网站不收录怎么解决
1.datagridview中UserDeletingRow事件,当删除行时,UserDeletingRow事件不会触发,但选择行时,并且按delete键时,将会触发UserDeletingRow事件。 2.如果自定义复合控件时,当设置了Dock和Anchor属性时…...
手机做网站对比路由器做网站/微信crm系统
网络提示错误720的解决方法之一参考文章: (1)网络提示错误720的解决方法之一 (2)https://www.cnblogs.com/lemon1991/p/5046868.html 备忘一下。...
网站建设与管理个人职业生涯规划书/苏州seo网站公司
代码如下: package array.guigu.demo; /*** 快速排序* 通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,* 则分别对这两部分继续进行排序,直到整个序列有序。*/ public class MyQuickSo…...
网站关键词排名优化方法/百度关键词首页排名服务
蒙特卡洛方法(Monte Carlo method,也有翻译成“蒙特卡罗方法”)是以概率和统计的理论、方法为基础的一种数值计算方法,将所求解的问题同一定的概率模型相联系,用计算机实现统计模拟或抽样,以获得问题的近似…...
宁津建设局网站/廊坊首页霸屏优化
回答:首先机械设计专业少不了有三维图纸设计实践,这是对电脑性能、尤其是显卡性能要求最高的部分,因此电脑的配置应该以满足三维设计的要求为准。相比之下,其他大部分专业对电脑反而都没有显卡性能的要求,因为显卡主要…...