当前位置: 首页 > news >正文

接口自动化测试_L1

目录:

  1. 接口自动化测试框架介绍
    1. 接口测试场景
    2. 自动化测试场景
    3. 接口测试在分层测试中的位置
    4. 接口自动化测试与 Web/App 自动化测试对比
    5. 接口自动化测试与 Web/App 自动化测试对比
    6. 接口测试工具类型
    7. 为什么推荐 Requests
    8. Requests 优势
    9. Requests 环境准备
  2. 接口请求方法
  3. 接口请求参数
  4. 接口请求头
  5. 接口请求体-json
  6. 接口响应断言
  7. json响应体断言
  8. 宠物商店接口自动化测试实战

1.接口自动化测试框架介绍

接口测试场景

自动化测试场景 

接口测试在分层测试中的位置 

接口自动化测试与 Web/App 自动化测试对比 

接口自动化测试与 Web/App 自动化测试对比 

看起来接口自动化测试什么都比 Web/App 自动化测试要好,为什么还要做 Web/App 自动化测试?

  • 接口关注数据无法触达用户体验。
接口测试工具类型
测试类型工具价值
接口抓包Charles、Postman接口抓包工具,可以抓取 App 的数据包
接口测试Postman接口调试工具,接口手工测试工具,学习成本低,直接安装即可使用
接口自动化测试Requests、RestAssured用于接口自动化测试的 Java、Python 第三方库,需要与对应编程语言结合使用
性能测试JMeter性能测试工具
为什么推荐 Requests
  • 是由 Python 实现的 API 测试框架。
  • 支持发起 POST, GET, PUT, DELETE 等请求。
  • 可以用来验证和校对响应信息。
Requests 优势 
  • 功能全面:HTTP/HTTPS 支持全面。
  • 使用简单:简单易用,不用关心底层细节。
  • 定制性高:结合测试框架完成二次封装,比如 HttpRunner。
Requests 环境准备 
  • 安装命令:pip install requests

2.接口请求方法

常见 HTTP 请求方法构造
方法说明
requests.request()构造一个请求,支撑以下各方法的基础方法。
requests.get()构造 HTTP 协议中的 GET 请求。
requests.post()构造 HTTP 协议中的 POST 请求。
requests.put()构造 HTTP 协议中的 PUT 请求。
requests.delete()构造 HTTP 协议中的 DELETE 请求。
底层设计

HTTP 协议知识回顾 
  • URL 结构
  • HTTP 请求
  • HTTP 响应
构造 GET 请求
  • requests.get(url, params=None, **kwargs)
    • url: 接口 url。
    • params:拼接在 url 中的请求参数。
    • **kwargs:更多底层支持的参数。
import requestsdef test_get():# 定义接口的 url 和拼接在 url 中的请求参数url = "https://httpbin.ceshiren.com/get"# 发出 GET 请求,r 接收接口响应r = requests.get(url, verify=False)# 打印接口响应print(r.json())
构造 POST 请求 
  • requests.post(url, data=None, json=None, **kwargs)
    • url: 接口 url。
    • data:表单格式请求体。
    • json:JSON 格式请求体。
    • **kwargs:更多底层支持的参数。
def test_post():# 定义接口的 urlurl = "https://httpbin.ceshiren.com/post"# 发出 POST 请求,r 接收接口响应response = requests.post(url, verify=False)# 打印接口响应print(response.text)
构造 PUT 请求
  • requests.put(url, data=None, **kwargs)
    • url: 接口 url。
    • data:表单格式请求体。
    • **kwargs:更多底层支持的参数。
def test_put():# 定义接口的 urlurl = "https://httpbin.ceshiren.com/put"# 发出 POST 请求,r 接收接口响应r = requests.put(url, verify=False)# 打印接口响应print(r)
 构造 DELETE 请求
  • requests.delete(url, **kwargs)
    • url: 接口 url。
    • **kwargs:更多底层支持的参数。
def test_delete():# 定义接口的 url 和表单格式请求体url = "https://httpbin.ceshiren.com/delete"# 发出 POST 请求,r 接收接口响应r = requests.delete(url, verify=False)# 打印接口响应print(r)
构造请求方法
  • requests.request(method, url, **kwargs)
    • method: 请求方法。
      • GETOPTIONSHEADPOSTPUTPATCHDELETE
    • url: 接口 url。
    • **kwargs:更多底层支持的参数。
  1. GET:GET是最常见的方法,通常用于请求服务器发送某些资源。浏览器大部分时间都在使用GET方法,比如当你在网址栏输入一个URL,或者点击一个链接时。GET请求会将请求参数附加在URL后面,以'?'符号分隔。这些参数会被浏览器发送到服务器,但是浏览器不会保存这些参数,也就是说,GET请求不应该是用来发送敏感数据的,因为这些数据可能会被第三方获取。
  2. OPTIONS:OPTIONS方法用于获取目标资源支持的通信选项。它可以用来检查服务器的性能,或者查看可以使用哪些HTTP方法来请求一个特定的URL。
  3. HEAD:HEAD方法和GET方法类似,但是服务器在响应中只返回HTTP头部,而不返回实际的数据。这可以用来检查链接的有效性,或者获取有关资源的元数据,例如Last-Modified头,ETag头等。
  4. POST:POST方法用于向服务器发送数据。它通常用于提交表单,上传文件等。POST请求会将请求主体发送到服务器,这个主体可以包含表单数据,文件内容等。服务器可以根据这些数据执行一些动作,例如创建新的资源。
  5. PUT:PUT方法用于更新服务器上的资源。它与POST方法的主要区别是,PUT请求通常知道它正在更新的资源的完整URL,而POST请求通常不知道。因此,PUT请求通常用于更新已经存在的资源,而POST请求用于创建新的资源。
  6. PATCH:PATCH方法是PUT方法的简化版本。与PUT相比,PATCH请求通常只包含资源的部分更新信息,而不是完整的信息。因此,PATCH方法通常用于对资源的部分进行修改。
  7. DELETE:DELETE方法是HTTP方法中最简单的一个。它用于从服务器删除资源。当你点击一个删除链接或者执行相应的JavaScript代码时,你的浏览器就会向服务器发送一个DELETE请求。
def request(method, url, **kwargs):"""Constructs and sends a :class:`Request <Request>`.:param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.:param url: URL for the new :class:`Request` object.:param params: (optional) Dictionary, list of tuples or bytes to sendin the query string for the :class:`Request`.:param data: (optional) Dictionary, list of tuples, bytes, or file-likeobject to send in the body of the :class:`Request`.:param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.:param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.:param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.:param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a stringdefining the content type of the given file and ``custom_headers`` a dict-like object containing additional headersto add for the file.:param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.:param timeout: (optional) How many seconds to wait for the server to send databefore giving up, as a float, or a :ref:`(connect timeout, readtimeout) <timeouts>` tuple.:type timeout: float or tuple:param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.:type allow_redirects: bool:param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.:param verify: (optional) Either a boolean, in which case it controls whether we verifythe server's TLS certificate, or a string, in which case it must be a pathto a CA bundle to use. Defaults to ``True``.:param stream: (optional) if ``False``, the response content will be immediately downloaded.:param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.:return: :class:`Response <Response>` object:rtype: requests.Response
底层参数说明
参数应用场景
method请求方法
url请求 URL
params请求中携带 URL 参数
data请求中携带请求体(默认为表单请求)
json请求中携带 json 格式的请求体
headers请求中携带头信息
cookies请求中携带 cookies
files请求中携带文件格式的请求体
auth请求中携带认证信息
timeout设置请求超时时间
allow_redirects请求是否允许重定向
proxies设置请求代理
verify请求是否要认证
cert请求中携带 ssl 证书

 

3.接口请求参数

请求参数简介
  • 接口请求中携带的,会在路径之后使用?代表客户端向服务端传递的参数。
  • 使用 key=value 形式拼接在 URL 中。
  • 如果有多个,则使用&分隔
  • 案例: https://ceshiren.com/search?expanded=true&q=requests
 携带请求参数的方式
  • 常用两种方式:
    • 直接在 URL 中拼接:?username=LiMing&id=666
    • 通过 params 参数传递:requests.get(url, params)
 携带请求参数的 GET 请求
def test_get_by_params():url = "https://httpbin.ceshiren.com/get"params = {"get_key": "get_value"}r = requests.get(url, params=params, verify=False)print(r.json())def test_get_by_url():url = "https://httpbin.ceshiren.com/get?get_key=get_value"r = requests.get(url, verify=False)print(r.json())
携带请求参数的 POST 请求 
def test_post_by_params():url = "https://httpbin.ceshiren.com/post"params = {"post_key": "post_value"}r = requests.post(url, params=params,verify=False)print(r.json())

4.接口请求头

请求头信息的使用场景
  • 身份认证
  • 指定数据类型

请求头信息 
  • HTTP 请求头是在 HTTP 请求消息中包含的元数据信息,用于描述请求或响应的一些属性和特征。
  • 实际工作过程中具体要关注的头信息字段需要和研发沟通。
  • 常见的头信息(右侧表格):
内容含义
Authorization表示客户端请求的身份验证信息
Cookie表示客户端的状态信息,通常用于身份验证和会话管理
Content-Type表示请求消息体的 MIME 类型
User-Agent发送请求的客户端软件信息
构造头信息
  • 使用 headers 参数传入。
  • 通常使用字典格式。
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)

 代码示例:

import requestsdef test_header():url = "https://httpbin.ceshiren.com/get"headers = {"name": "LiMing", "User-Agent": "apple", "Content-type": "application/json"}r = requests.get(url, verify=False, headers=headers)print(r.json())

5.接口请求体-json

接口请求体简介 
  • 进行HTTP请求时,发送给服务器的数据。
  • 数据格式类型可以是JSON、XML、文本、图像等格式。
  • 请求体的格式和内容取决于服务器端API的设计和开发人员的要求。

常用接口请求体
类型介绍Content-type
JSON(JavaScript Object Notation)轻量级的数据交换格式,最常见的一种类型。application/json
表单数据(Form Data)以键值对的形式提交数据,例如通过 HTML 表单提交数据。application/x-www-form-urlencoded
XML(eXtensible Markup Language)常用的标记语言,通常用于传递配置文件等数据。application/xml
text/xml
文件(File)可以通过请求体上传文件数据,例如上传图片、视频等文件。上传文件的 MIME 类型,例如 image/jpeg
multipart/form-data
纯文本(Text)纯文本数据,例如发送邮件、发送短信等场景text/plain
其他格式二进制数据、protobuf 等格式
JSON 简介
  • 是 JavaScript Object Notation 的缩写。
  • 是一种轻量级的数据交换格式。
  • 是理想的接口数据交换语言。
  • Content-Type 为 application/json。

JSON 格式请求体示例 
  1. 进入登录页面。
  2. 打开开发者工具。
  3. 输入用户名密码,点击登录。
  4. https://litemall.hogwarts.ceshiren.com/#/login

 构造 JSON 格式请求体
  • 定义为字典格式。
  • 使用 json 参数传入。
import requestsdef test_request_body():url = "https://httpbin.ceshiren.com/post"request_body = {"name": "LiMing", "teacher": 'Jenny'}r = requests.post(url, verify=False, json=request_body)print(r.json())

6.接口响应断言

 接口断言使用场景
  • 问题:
    1. 如何确保请求可以发送成功。
    2. 如何保证符合业务需求。
  • 解决方案:
    • 通过获取响应信息,验证接口请求是否成功,是否符合业务需求。
Requests 中的响应结果对象 
import requestsdef test_assert():url = "https://httpbin.ceshiren.com/get"r = requests.get(url, verify=False)print(r)
响应结果类型 
属性含义
r响应 Response 对象(可以使用任意的变量名)
r.status_codeHTTP 响应状态码
r.headers返回一个字典,包含响应头的所有信息。
r.text返回响应的内容,是一个字符串。
r.url编码之后的请求的 url
r.content返回响应的内容,是一个字节流。
r.raw响应的原始内容
r.json()如果响应的内容是 JSON 格式,可以使用该方法将其解析成 Python 对象。

代码示例:

import requestsdef test_assert():url = "https://httpbin.ceshiren.com/get"r = requests.get(url, verify=False)print("------------------------------------------")print(r.status_code)print("------------------------------------------")print(r.headers)print("------------------------------------------")print(r.text)print("------------------------------------------")print(r.url)print("------------------------------------------")print(r.content)print("------------------------------------------")print(r.raw)print("------------------------------------------")print(r.json())
响应状态码断言 
  • 基础断言:
    • r.status_code

 代码示例:

def test_assert_base():url = "https://httpbin.ceshiren.com/get"r = requests.get(url, verify=False)assert r.status_code == 200

7.json响应体断言

什么是 JSON 响应体?
  • JSON格式的响应体指的是HTTP响应中的消息体(message body),它是以JSON格式编码的数据。
{"name": "John","age": 30,"city": "New York"
}
断言 JSON 格式响应体使用场景 
  • 验证API接口的返回结果是否符合预期。
    • 业务场景上是否符合预期。
    • 格式是否符合文档规范。 
断言 JSON 格式响应体 
  • r.json():返回 python 字典。
import requestsdef test_res_json():r = requests.get("https://httpbin.ceshiren.com/get")assert r.status_code == 200assert r.json()["url"] == "https://httpbin.ceshiren.com/get"

代码示例:

import requestsdef test_resonse_body_json():url = "https://httpbin.ceshiren.com/get"r = requests.get(url, verify=False)print(r.json())print(r.json()["headers"])print(r.json()["headers"]["Host"])assert r.status_code == 200assert r.json()["url"] == "https://httpbin.ceshiren.com/get"def test_resonse_body_json_fail():url = "https://www.baidu.com"r = requests.get(url)# 如果响应体是非 json 的场景,那么就不要使用 r.json() 的方式,否则则会# raise RequestsJSONDecodeError# print(r.json())# 可以使用r.textprint(r.text)assert r.status_code == 200
若碰到复杂断言应该如何处理? 
  • 多层嵌套的数据提取与断言: JSONPath
  • 整体结构响应断言: JSONSchema
  • 自行编写解析算法

 

8.宠物商店接口自动化测试实战

被测产品
  • PetStore 宠物商城:
    • 一个在线的小型的商城。
    • 主要提供了增删查改等操作接口。
    • 结合 Swagger 实现了接口的管理。

 

需求说明
  • 完成宠物商城宠物查询功能接口自动化测试。
    • 编写自动化测试脚本。
    • 完成断言。

 

相关知识点
形式章节描述
知识点接口请求方法http 接口请求方法构造
知识点接口请求参数http 接口请求参数构造
知识点接口请求体-jsonhttp 接口请求体为 json 格式
知识点接口响应断言http 接口响应状态码断言

实战思路

宠物商店需求分析
  • 被测产品:宠物商店系统 - 查询宠物信息
  • 宠物商店接口文档:https://petstore.swagger.io/
接口测试用例设计
  • 宠物查询单接口用例

 

编写接口自动化测试脚本思路
  1. 查询宠物信息。

 

编写自动化测试脚本 

test_petstore.py

import requestsfrom interface_automation_testing.接口自动化测试_L1.宠物商店接口自动化测试实战.utils.log_util import loggerclass TestPetstorePetsearch:def setup_class(self):# 定义接口请求 URLself.base_url = "https://petstore.swagger.io/v2/pet"self.search_url = self.base_url + "/findByStatus"# "【冒烟】传入available状态可以正确获取该状态下的宠物信息"def test_search_pet1(self):# 查询接口请求参数params = {"status": "available"}# 发出查询请求r = requests.get(self.search_url, params=params, verify=False)logger.info('【冒烟】传入available状态可以正确获取该状态下的宠物信息')# 状态断言assert r.status_code == 200# 业务断言assert r.json() != []assert "id" in r.json()[0]

项目结构:

 

脚本优化 - 添加日志
  • 新建日志配置。
  • 在用例中使用配置好的日志实例。
import logging
import osfrom logging.handlers import RotatingFileHandler# 绑定绑定句柄到logger对象
logger = logging.getLogger(__name__)# 获取当前工具文件所在的路径
root_path = os.path.dirname(os.path.abspath(__file__))# 拼接当前要输出日志的路径
root_len = len(root_path)
strs = root_path[0:root_len-6]
log_dir_path = os.sep.join([strs,f'datas\logs'])if not os.path.isdir(log_dir_path):os.mkdir(log_dir_path)# 创建日志记录器,指明日志保存路径,每个日志的大小,保存日志的上限
file_log_handler = RotatingFileHandler(os.sep.join([log_dir_path, 'log.log']),maxBytes=1024 * 1024, backupCount=10,encoding="utf-8")# 设置日志的格式
date_string = '%Y-%m-%d %H:%M:%S'
formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] [%(filename)s]/[line: %(lineno)d]/[%(funcName)s] %(message)s ',date_string)# 日志输出到控制台的句柄
stream_handler = logging.StreamHandler()# 将日志记录器指定日志的格式
file_log_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)# 为全局的日志工具对象添加日志记录器
# 绑定绑定句柄到logger对象
logger.addHandler(stream_handler)
logger.addHandler(file_log_handler)# 设置日志输出级别
logger.setLevel(level=logging.INFO)def prit_path():print(root_path)print(log_dir_path)prit_path()
脚本优化 - 参数化
  • 使用 pytest parametrize 装饰器实现宠物状态的参数化。

test_petstore_parameterization.py

import pytest
import requestsfrom interface_automation_testing.接口自动化测试_L1.宠物商店接口自动化测试实战.utils.log_util import loggerclass TestPetstorePetsearch:def setup_class(self):# 定义接口请求 URLself.base_url = "https://petstore.swagger.io/v2/pet"self.search_url = self.base_url + "/findByStatus"# "【冒烟】传入available状态可以正确获取该状态下的宠物信息"# "【冒烟】传入pending状态可以正确获取该状态下的宠物信息"# "【冒烟】传入sold状态可以正确获取该状态下的宠物信息"@pytest.mark.parametrize("status",['available', 'pending', 'sold'],ids=["available_pets", "pending_pets", "sold_pets"])def test_search_pet1(self, status):# 查询接口请求参数params = {"status": status}# 发出查询请求r = requests.get(self.search_url, params=params, verify=False)logger.info(f'【冒烟】传入{status}状态可以正确获取该状态下的宠物信息')# 状态断言assert r.status_code == 200# 业务断言assert r.json() != []assert "id" in r.json()[0]# "【异常】传入非指定状态字符串﹐响应为空"# "【异常】传入非指定状态数字,响应为空"# "【异常】传入空字符串,响应为空""@pytest.mark.parametrize("status",['petstatus', '123456', ''],ids=["petstatus_pets", "123456_pets", "null_pets"])def test_search_pet2(self, status):# 查询接口请求参数params = {"status": status}# 发出查询请求r = requests.get(self.search_url, params=params, verify=False)logger.info(f'【异常】传入{status}字符串﹐响应为空')# 状态断言assert r.status_code == 200# 业务断言assert r.json() == []# 【异常】不传入status,响应为空"def test_search_pet3(self):# 查询接口请求参数# 发出查询请求r = requests.get(self.search_url, verify=False)logger.info(f'【异常】不传入status,响应为空')# 状态断言assert r.status_code == 200# 业务断言assert r.json() == []# "【异常】传入非status 的参数,响应为空"def test_search_pet4(self):# 查询接口请求参数params = {"key": "available"}# 发出查询请求r = requests.get(self.search_url, params=params, verify=False)logger.info(f'【异常】传入非status 的参数,响应为空')# 状态断言assert r.status_code == 200# 业务断言assert r.json() == []
 生成测试报告
  • 安装 allure 相关依赖。
# 生成报告信息
pytest --alluredir=./report
# 生成报告在线服务,查看报告
allure serve ./report/
pytest -vs .\test_petstore_parameterization.py --alluredir=./datas/report --clean-alluredir

 运行结果:

 

allure serve .\report\

 运行结果:

 

 总结
  • 通过 Swagger 文档获取接口信息。
  • 使用 Requests 发出携带请求参数的 GET 请求。
  • 断言响应符合是否符合预期。
  • 添加 Log 日志。
  • 使用参数化方式实现一条用例可执行多个测试数据。
  • 生成 Allure 测试报告。

项目地址: template: 用来存放开发模版 - Gitee.com

相关文章:

接口自动化测试_L1

目录&#xff1a; 接口自动化测试框架介绍 接口测试场景自动化测试场景接口测试在分层测试中的位置接口自动化测试与 Web/App 自动化测试对比接口自动化测试与 Web/App 自动化测试对比接口测试工具类型为什么推荐 RequestsRequests 优势Requests 环境准备接口请求方法接口请求…...

Windows提权

1. MySQL提权 1.1 UDF提权 udf ‘user defined function’&#xff0c;即’用户自定义函数’。是通过添加新函数&#xff0c;对MYSQL的功能进行扩充 1、如何获得udf文件 2、将文件放到哪才能让mysql承认这个函数 3、函数功能 4、为什么这东西能提权(自定义函数指令是直接…...

香港服务器的优势?

香港服务器作为近年来国内站长建站使用最为频繁的服务器之一&#xff0c;香港服务器是不需要备案的&#xff0c;而且相对于众多国内服务器 来说&#xff0c;的确是有诸多优势&#xff0c;下面就来具体说下选择香港服务器的优势&#xff1a; 1、访问速度快 搭建网站&#xff0c;…...

关于开展2023年度光明科学城出站博士后生活资助申报工作的通知

各相关单位&#xff1a; 根据《光明区关于实施光明科学城“人才高地计划”的若干措施》&#xff08;深光发〔2022〕1号&#xff09;和《光明科学城青年科技人才培育专项行动方案》&#xff08;深光人才〔2022〕2号&#xff09;有关规定&#xff0c;现就2023年度光明科学城出站博…...

“.NET视频总结:认识框架的结构和组件,掌握开发工具的奥妙“

目录 第一单元&#xff1a;二十一世纪程序执行 背景: 总结&#xff1a; 第二单元:对象导向与类别设计 背景: 总结&#xff1a; 第三单元&#xff1a;使用类别与基底类别库 背景: 总结: 第四单元:Windows开发程序 背景: 总结: 第五单元:防护式程序设计 背景: 总结…...

STM32 CubeMX PWM三种模式(互补,死区互补,普通)(HAL库)

STM32 CubeMX PWM两种模式&#xff08;HAL库&#xff09; STM32 CubeMX STM32 CubeMX PWM两种模式&#xff08;HAL库&#xff09;一、互补对称输出STM32 CubeMX设置代码部分 二、带死区互补模式STM32 CubeMX设置代码 三、普通模式STM32 CubeMX设置代码部分 总结 一、互补对称输…...

Linux系统导入导出docker容器的sql数据

Linux系统导入导出docker容器的sql数据 一 要从Docker容器中将数据库导出到本地 确保您已经安装了Docker&#xff0c;并且已经运行了包含数据库的Docker容器。 检查容器中运行的数据库服务的名称或容器ID。您可以使用命令 docker ps 来列出正在运行的容器和相关信息。 使用…...

SpringBoot之使用Redis和注解实现接口幂等性

文章目录 1 接口幂等性1.1 概念1.2 实现思路1.3 代码实现1.3.1 pom1.3.2 JedisUtil1.3.3 自定义注解ApiIdempotent1.3.4 ApiIdempotentInterceptor拦截器1.3.5 TokenServiceImpl1.3.6 TestApplication 1.4 测试验证1.4.1 获取token的控制器TokenController1.4.2 TestController…...

《3D 数学基础》几何检测-相交性检测

目录 1. 2D直线相交 2. 3D射线相交点 3. 射线和平面的交点 4. 3个平面的交点 5. 射线和圆或者球交点 6. 两个圆或者球是否相交 7. 球和平面的相交性检测 8. 射线和AABB的相交性&#xff08;13.17&#xff09; 9. 射线和三角形的相交性&#xff08;13.16&#xff09; …...

文字与视频结合效果

效果展示 CSS 知识点 mix-blend-mode 属性的运用 实现整体页面布局 <section class"sec"><video autoplay muted loop><source src"./video.mp4" type"video/mp4" /></video><h2>Run</h2><!-- 用于切…...

大数据Doris(九):配置BE步骤

文章目录 配置BE步骤 一、配置be节点...

BuyVM 纽约 VPS 测评

description: 发布于 2023-07-05 BuyVM 纽约 VPS 测评 产品链接&#xff1a;https://my.frantech.ca/cart.php?gid38 G口不限流量&#xff0c;抗一般投诉&#xff0c;不抗版权投诉。 CPU很快&#xff0c;硬盘不错。 无大陆优化&#xff0c;但大陆连通性很不错&#xff0c;…...

H3C交换机的40G堆叠线 ,可以插在普通光口做堆叠吗?

环境&#xff1a; S6520X-24ST-SI交换机 H3C LSWM1QSTK2万兆40G堆叠线QSFP 问题描述&#xff1a; H3C交换机的40G堆叠线 &#xff0c;可以插在普通光口做堆叠吗&#xff1f; 解答&#xff1a; 1.H3C交换机的40G堆叠线通常是用于连接堆叠模块或堆叠端口的。这些堆叠线通常使…...

【Java 进阶篇】JavaScript三元运算符详解

JavaScript是一门广泛用于前端和后端开发的编程语言&#xff0c;具备强大的表达式和运算符。本篇博客将重点介绍JavaScript中的三元运算符&#xff0c;解释其语法、用法和示例。如果您是JavaScript初学者&#xff0c;或者希望更深入了解这门语言的运算符&#xff0c;那么这篇博…...

MySQL数据库技术笔记(4)

关系型数据库需要使用设计范式&#xff1a; 第一范式&#xff1a;遵从原子性&#xff0c;属性不可再分&#xff0c;数据库表的每一列都是不可分割的基本数据项&#xff0c;同一列中不能有多个值。 例如&#xff1a;需要创建一张地址表&#xff0c;存储地址信息。将地址信息划…...

批量图片转文字识别OCR身份证件信息提取软件

现在的OCR软件很多&#xff0c;有在线的也有本地的&#xff0c;单识别文字功能还行&#xff0c;不过能批量识别的好像不多&#xff0c;网上搜了几个都不怎么好用。尤其是识别身份证件之类的软件&#xff0c;并且还能提取出识别到的信息&#xff0c;比如姓名 名族地址等等更少。…...

Mac/Wins Matlab如何查看APPs源码

查看Apps方法一样&#xff0c;点击HOME-preferences-MATLAB-Apps查看你的Apps安装路径。 你的Apps文件就安装在该目录下&#xff0c;直接进入这个目录就可以看到你自己写的APPs文件&#xff0c;...

Web应用-Thinkphp框架-开发指南

Thinkphp框架 二级导航分类&#xff0c;模板继承&#xff0c;内置标签Public 修改MVC模块化 ——访问机制传参加载模版模版引入 分离Runtime 缓存文件管理员添加数据验证及验证场景 控制器 validate 在sql执行&#xff08;敏感操作&#xff09;之前验证数据模板 分页数据表连接…...

LeetCode【300】最长递增子序列

题目&#xff1a; 思路&#xff1a; 通常来说&#xff0c;子序列不要求连续&#xff0c;而子数组或子字符串必须连续&#xff1b;对于子序列问题&#xff0c;第一种动态规划方法是&#xff0c;定义 dp 数组&#xff0c;其中 dp[i] 表示以 i 结尾的子序列的性质。在处理好每个…...

JRebel在IDEA中实现热部署 (JRebel实用版)

JRebel简介&#xff1a; JRebel是与应用程序服务器集成的JVM Java代理&#xff0c;可使用现有的类加载器重新加载类。只有更改的类会重新编译并立即重新加载到正在运行的应用程序中&#xff0c;JRebel特别不依赖任何IDE或开发工具&#xff08;除编译器外&#xff09;。但是&…...

uniapp微信小程序之分包异步化之组件分包

一、组件分包异步化解决的问题 日渐增加的通用组件造成的主包空间不足; 提升小程序访问速度,降低白屏率; 二、开启组件分包异步化过程中遇到的问题 如何进行占位组件配置; 如何解决通过$refs访问异步组件报错; 如何判断所有异步组件都已加载完毕; 多分包组件之间互相调用…...

Nacos(替代Eureka)注册中心

Nacos初步学习 Nacos 是一个开源的服务注册和配置中心&#xff0c;它允许您注册、注销和发现服务实例&#xff0c;并提供了配置管理的功能。下面是Nacos的最基础用法&#xff1a; 1. 服务注册和发现&#xff1a; 首先&#xff0c;您需要将您的应用程序或服务注册到Nacos中。…...

FHRP首跳冗余的解析

首跳冗余的解析 个人简介 HSRP hot standby router protocol 热备份路由协议 思科设备上 HSRP VRRP 华为设备上 VRRP HSRP v1 version 1 HSRP v2 version 2 虚拟一个HSRP虚拟IP地址 192.168.1.1 开启HSRP的抢占功能 通过其他参数 人为调整谁是主 谁是从 &a…...

垂直分表为什么能够加快查询效率?

前言 垂直分表是分库分表中分表操作上一个重要的实现方式&#xff0c;利用垂直分表可以提高数据的处理效率和查询速度&#xff0c;本节主要围绕 垂直分表为什么能够加快查询速度 展开说明&#xff0c;以mysql查询的底层流程为例。 垂直分表是将一张表按列分为多张表&#xff0c…...

Linux网络基础知识全面总结

文章目录 linux网络基础知识1.1 IP地址和子网掩码1.2 网关和路由1.3 域名系统 (DNS)1.4 端口和协议 Linux网络配置2.1 ifconfig命令2.2 网络接口配置文件2.3 DHCP自动获取IP地址2.4 静态IP地址配置2.5 网络重启和应用配置3. 网络工具和命令3.1 ping命令3.2 traceroute和mtr命令…...

【arm实验2】按键中断事件控制实验

设置按键中断&#xff0c;按键1按下&#xff0c;LED亮&#xff0c;再次按下&#xff0c;灭 按键2按下&#xff0c;蜂鸣器叫&#xff0c;再次按下&#xff0c;停 按键3按下&#xff0c;风扇转&#xff0c;再次按下&#xff0c;停 主函数&#xff1a; linuxlinux:~/study/08-c$…...

【数据结构-栈 二】【单调栈】每日温度、接雨水

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【单调栈的应用】&#xff0c;使用【栈】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&am…...

基于Keil a51汇编 —— 控制语句

ALIGN ALIGN expression ALIGN 语句将位置计数器设置为下一个地址模 2^表达式。 这可用于确保下一条语句在 2^n 边界上对齐。例如&#xff0c;对齐缓存行中的代码或数据。如有必要&#xff0c;汇编程序会创建一个间隙。间隔字节的内容因各个部分而异&#xff1a; 在data中未定…...

单目标优化算法:火鹰优化算法(Fire Hawk Optimizer,FHO)求解23个函数--提供MATLAB代码

一、火鹰优化算法FHO 火鹰优化算法&#xff08;Fire Hawk Optimizer&#xff0c;FHO&#xff09;由Mahdi Azizi等人于2022年提出&#xff0c;该算法性能高效&#xff0c;思路新颖。 单目标优化&#xff1a;火鹰优化算法&#xff08;Fire Hawk Optimizer&#xff0c;FHO&#…...

数据集笔记:分析OpenCellID 不同radio/ create_time update_time可视化

1 读取数据 &#xff08;以新加坡的cellID为例&#xff09; import geopandas as gpd import pandas as pdopencellidpd.read_csv(OpenCellID_SG.csv,headerNone,names[radio,mcc,net,area,cell,unit,lon,lat,range,samples,changeable1,created1,updated,AveSignal]) opence…...