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、计算机基础

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/100458.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM——垃圾回收器G1+垃圾回收调优

4.4 G1(一个垃圾回收器) 定义: 取代了CMS垃圾回收器。和CMS一样时并发的。 适用场景: 物理上分区,逻辑上分代。 相关JVM参数: -XX:UseG1GC-XX:G1HeapRegionSizesize-XX:MaxGCPauseMillistime 1) G1 垃圾回收阶段 三个回收阶段&#xff0…

Pydev·离线git包

Pydev离线git包 1.下载离线git包:eclipse.egit.repository-4.4.0.201606070830-r.zip 2.将解压后目录:eclipse.egit.repository-4.4.0.201606070830-r\plugins下的jar文件放到 ide\eclipse\plugins目录下 3.重启pydevIDE 百度搜索站长工具:h…

不负众望~历时4年修炼,这本册子终于成书了(文末赠书)

名字:阿玥的小东东 学习:Python、C/C 主页链接:阿玥的小东东的博客_CSDN博客-python&&c高级知识,过年必备,C/C知识讲解领域博主 目录 精进Spring Boot首选读物 “小册”变“大书”,彻底弄懂Spring Boot 全方位配套资源…

PHP“牵手”淘宝商品评论数据采集方法,淘宝API接口申请指南

淘宝天猫商品评论数据接口 API 是开放平台提供的一种 API 接口,它可以帮助开发者获取商品的详细信息,包括商品的标题、描述、图片等信息。在电商平台的开发中,详情接口API是非常常用的 API,因此本文将详细介绍详情接口 API 的使用…

Linux journalctl命令详解(journalctl指令)(systemd服务默认日志管理工具)

文章目录 Linux Journalctl命令详解1. Journalctl简介2. Journalctl基础使用3. 过滤日志条目4. 时间戳和日志轮转5. 高级应用6. journalctl --help指令文档英文中文 注意事项journal日志不会将程序输出的空行显示,日志会被压缩得满满当当。journal日志不会自动持久化…

【C++入门到精通】C++入门 —— priority_queue(STL)优先队列

阅读导航 前言一、priority_queue简介1. 概念2. 特点 二、priority_queue使用1. 基本操作2. 底层结构 三、priority_queue模拟实现⭕ C代码⭕priority_queue中的仿函数 总结温馨提示 前言 ⭕文章绑定了VS平台下std::priority_queue的源码,大家可以下载了解一下&…

boost::array和boost::multi_array

boost::array Boost.Array是一个模板&#xff0c;需要两个模板参数&#xff0c;分别是数据的类型和数组的大小。 boost::array<int, 1024> temp_array;由于是模板参数&#xff0c;所以数组的大小必须是一个可以在编译阶段就可以推理得到的值。定义以后&#xff0c;就可…

数据结构——线性数据结构(数组,链表,栈,队列)

文章目录 1. 数组2. 链表2.1. 链表简介2.2. 链表分类2.2.1. 单链表2.2.2. 循环链表2.2.3. 双向链表2.2.4. 双向循环链表 2.3. 应用场景2.4. 数组 vs 链表 3. 栈3.1. 栈简介3.2. 栈的常见应用常见应用场景3.2.1. 实现浏览器的回退和前进功能3.2.2. 检查符号是否成对出现3.2.3. 反…

QT VS编译环境无法打开包括文件type_traits

这问题&#xff0c;别人给的处理方法都是&#xff1a; 添加环境变量执行vsvars32.bat/vcvarsall.bat/vsdevcmd.bat重新安装QT项目&#xff1a;执行qmake。。。。 个人不推荐配置环境编译&#xff0c;除非你非常熟&#xff0c;因为配置环境变量需要你知道有哪些路径需要添加&a…

手机自动无人直播,实景无人直播真的有用吗?

继数字人直播之后&#xff0c;手机自动直播开始火热了起来&#xff0c;因为其门槛低&#xff0c;成本低&#xff0c;一部手机一个账号就可以实现直播&#xff0c;一时深受广大商家的好评。那么&#xff0c;手机自动无人直播究竟是如何实现自动直播的呢&#xff1f; 在传统的直…

视频集中存储/云存储/磁盘阵列EasyCVR平台接入RTSP设备出现离线情况的排查

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

SAP LTMC基础教程之物料主数据详细操作示例

SAP LTMC基础教程之物料主数据详细操作示例 SAP S/4HANA 1610版本的推出已经不再建议使用LSMW了&#xff0c;使用中会受到很多限制&#xff08;比如特性、类的导入&#xff09;&#xff0c;而是推出了新工具LTMC。记录并分享LTMC的操作。 有几个注意点能够搞明白基本都能成功…

数据结构——B-树、B+树、B*树

一、B-树 1. B-树概念 B树是一种适合外查找的、平衡的多叉树。一棵m阶&#xff08;m>2&#xff09;的B树&#xff0c;是一棵平衡的M路平衡搜索树&#xff0c;它可以是空树或满足以下性质&#xff1a; &#xff08;1&#xff09;根节点至少有两个孩子。 &#xff08;2&#…

Qt关于hex转double,或者QByteArray转double

正常的00 ae 02 33这种类型的hex数据类型可以直接通过以下代码进行转换 double QDataConversion::hexToDouble(QByteArray p_buf) {double retValue 0;if(p_buf.size()>4){QString str1 byteArrayToHexStr(p_buf.mid(0,1));QString str2 byteArrayToHexStr(p_buf.mid(1,…

香蕉派社区推出带10G SFP+ 端口的Banana Pi BPI-R4 Wifi7开源路由器

香蕉派BPI-R4 根据著名Banana Pi品牌背后的公司Sinovoip提供的初步信息&#xff0c;他们即将推出的Banana Pi BPI-R4路由器板目前正在开发中。与之前的 Banana Pi R3 板相比&#xff0c;这在规格上将有显着提升。这就是我们目前所知道的。 您可以选择 R4 板的两种不同配置。具…

MySQL数据库的操作

目录 创建数据库字符集和校验规则查看系统默认字符集以及校验规则校验规则对数据库的影响 操纵数据库查看已经创建的数据库显示某个数据库的创建语句修改数据库删除数据库 数据库备份和还原备份还原 查看连接情况 创建数据库 语法: create database [if not exists] 数据库名字…

二、SQL,如何实现表的创建和查询

1、新建表格&#xff08;在当前数据库中新建一个表格&#xff09;&#xff1a; &#xff08;1&#xff09;基础语法&#xff1a; create table [表名]( [字段:列标签] [该列数据类型] comment [字段注释], [字段:列标签] [该列数据类型] comment [字段注释], ……&#xff0c…

java可变字符串

一、常用方法 以StringBuilder为例 1、append(String str) 添加 StringBuilder str new StringBuilder("hello"); System.out.println(str);//在源字符串后添加world StringBuilder add str.append("world"); System.out.println(add);//结果helloworl…

大数据时代,个人信息数据库保护的挑战及其对策

挑战&#xff1a; 数据泄露&#xff1a;大数据时代&#xff0c;个人信息数据库面临被黑客攻击、内部员工滥用权限等风险&#xff0c;导致个人信息泄露的风险增加。 隐私保护&#xff1a;随着大数据的快速发展&#xff0c;个人信息的采集和分析变得更加广泛和深入。但是&#xf…

kaggle注册不显示验证码

edge浏览器 1.点击浏览器右上角三个点 2.点击扩展 3.点击管理扩展 4.点击获取Microsoft Edge扩展&#xff0c;在左上角输入Head Editor 5.输入https://www.azurezeng.com/static/HE-GoogleRedirect.json 6.下载后&#xff0c;点保存 成功&#xff01;