接口自动化测试_L2

news2024/10/6 18:28:08

目录:

  1. 接口请求体-文件
    1. 文件上传接口场景
    2. 使用 requests 如何上传
  2. 接口请求体-form表单
    1. ​​​​​​​什么是 FORM 请求
    2. 如何使用?
  3. 接口请求体-xml​​​​​​​
  4. xml响应断言
    1. ​​​​​​​​​​​​​​什么是 XML
    2. XML 断言
    3. XPath 断言
    4. XML 解析
  5. cookie处理
    1. Cookie简介​​​​​​​
  6. 超时处理
    1. ​​​​​​​请求超时
    2. 为什么接口测试需要请求超时处理?
    3. 如何设置
  7. 代理配置
    1. ​​​​​​​使用代理之前
    2. 使用代理之后
    3. 代理在接口自动化的使用场景
    4. Requests 代理
    5. 如何使用
  8. 多层嵌套响应断言
    1. ​​​​​​​什么是多层嵌套结构
    2. 复杂场景响应提取
    3. JSONPath 简介
    4. JSONPath 对比
    5. JSONPath 如何使用
    6. JSONPath 语法
    7. JSONPath 的练习环境
    8. JSONPath 练习题目
    9. JSONPath 练习
    10. JSONPath 与代码结合(Python)
  9. 宠物商店接口自动化测试实战
    1. ​​​​​​​​​​​​​​被测产品
    2. 需求说明
    3. 相关知识点
    4. 实战思路
    5. 需求分析
    6. 宠物管理接口业务流程测试用例
    7. 编写自动化测试脚本思路
    8. 编写自动化测试脚本
    9. 脚本优化 - 配置代理查看接口数据
    10. 脚本优化 - 添加日志
    11. 脚本优化 - 使用 jsonpath 断言
    12. 生成测试报告
    13. 总结
    14. 项目结构:
    15. 项目地址:

1.接口请求体-文件

 文件上传接口场景
  • 1867 文档中说明文件上传是一种常见的需要求,但是使用 html 中的 form 表单格式却不支持,
  • 提出了一种兼容此需求的 mime type。
  • 解决接口测试流程中文件上传的问题
    • 指定 name
    • 指定 filename
    • 指定 content-type
使用 requests 如何上传 
import requests


# key值需要替换为文件名
# value 对应为文件二进制流
def test_file():
    r = requests.post("https://httpbin.ceshiren.com/post",
                      # files={"request_file": open("./datas/1.txt", "rb")},
                      files={"request_file": ("hello.txt", open("./datas/1.txt", "rb"))},
                      verify=False
                      )

    print(r.text)

抓包看请求体:(学会使用charles或者fiddler抓包,看请求和响应)

2.接口请求体-form表单

什么是 FORM 请求
  • 数据量不大
  • 数据层级不深的情况
  • 通常以键值对传递
如何使用?
import requests


def test_form():
    data = {"hello": "form"}
    r = requests.post("https://httpbin.ceshiren.com/post", verify=False, data=data)
    print(r.text)


def test_json():
    data = {"hello": "form"}
    r = requests.post("https://httpbin.ceshiren.com/post", verify=False, json=data)
    print(r.text)

3.接口请求体-xml

import requests
import xml.etree.ElementTree as ET


def test_xml():
    # 读取XML文件
    tree = ET.parse('./datas/test.xml')
    root = tree.getroot()

    # 创建一个空列表来保存数据
    datas = []

    # 遍历XML文件的每个元素
    for elem in root.iter():
        # 将元素的标签和文本内容添加到列表中
        datas.append((elem.tag, elem.text))

    data = datas
    r = requests.post("https://httpbin.ceshiren.com/post", verify=False, data=data)
    print(r.text)

运行抓包:

4.xml响应断言

 什么是 XML
  • 可扩展标记语言(Extensible Markup Language)的缩写
  • 也是一种结构化的数据
XML 断言 
from requests_xml import XMLSession


def test_xml():
    session = XMLSession()
    r = session.get('https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss')
    print(r.text)
    print(r.xml.links)
    print(r.raw_xml)
    print(r.xml.text)
XPath 断言 
from requests_xml import XMLSession

session = XMLSession()

r = session.get('https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss')

r.xml.links

item = r.xml.xpath('//item', first=True)

print(item.text)
from requests_xml import XMLSession
import xml.etree.ElementTree as ET


def test_xml():
    session = XMLSession()
    r = session.get('https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss')
    print(r.text)
    print(r.xml.links)
    print(r.xml.raw_xml)
    print(r.xml.text)


def test_xpath_assert():
    session = XMLSession()
    r = session.get('https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss')
    item = r.xml.xpath('//link')
    result = []
    for i in item:
        print(i.text)
        result.append(i.text)
    print(result)
    assert "https://www.nasa.gov/image-of-the-day/" in result

XML 解析 
import xml.etree.ElementTree as ET

root = ET.fromstring(countrydata)

root.findall(".")

root.findall("./country/neighbor")

root.findall(".//year/..[@name='Singapore']")

root.findall(".//*[@name='Singapore']/year")

root.findall(".//neighbor[2]")
from requests_xml import XMLSession
import xml.etree.ElementTree as ET


def test_xml():
    session = XMLSession()
    r = session.get('https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss')
    print(r.text)
    print(r.xml.links)
    print(r.xml.raw_xml)
    print(r.xml.text)


def test_xpath_assert():
    session = XMLSession()
    r = session.get('https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss')
    item = r.xml.xpath('//link')
    result = []
    for i in item:
        print(i.text)
        result.append(i.text)
    print(result)
    assert "https://www.nasa.gov/image-of-the-day/" in result


def test_xml_assert():
    session = XMLSession()
    r = session.get('https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss')
    root = ET.fromstring(r.text)
    item = root.findall(".")
    print(item)
    items = root.findall(".//link")
    print(items)

    for i in items:
        print(i.text)

5.cookie处理

Cookie简介

Cookie使用场景,在接口测试过程中,很多情况下,需要发送的请求附带cookies,才会得到正常的响应的结果。所以使用python+requests进行接口自动化测试也是同理,需要在构造接口测试用例时加入cookie。传递Cookie的两种方式

  • 通过请求头信息传递
  • 通过请求的关键字参数cookies传递
import requests


def test_cookie1():
    url = "https://httpbin.testing-studio.com/cookies"
    header = {"Cookie": "LiMing=teacher", "User-Agent": "hdc"}
    r = requests.get(url=url, headers=header, verify=False)
    print(r.request.headers)


def test_cookie2():
    url = "https://httpbin.testing-studio.com/cookies"
    header = {"User-Agent": "hdc"}
    cookie_data = {"today": "20231013"}
    r = requests.get(url=url, headers=header, verify=False, cookies=cookie_data)
    print(r.request.headers)

6.超时处理

请求超时

为什么接口测试需要请求超时处理?

不设置请求超时:

设置请求超时: 

如何设置
import requests

class TestReq:

    def test_timeout(self):
        r = requests.get('http://github.com', timeout = 0.01)

代码示例:

import requests


class TestReq:

    def test_timeout(self):
        r = requests.get('http://github.com', timeout=0.01)
        # r = requests.get('http://github.com', timeout=5000)

7.代理配置

使用代理之前

使用代理之后 

代理在接口自动化的使用场景 
  • 测试脚本,更直观的排查请求错误,相当于编写代码时的 debug
  • 获取没有错误的,真实的接口请求响应信息
  • 通过代理获取自动化测试的请求响应
  • 对比两次请求响应的区别
Requests 代理 

通过 proxies 参数,监听请求与响应信息

如何使用
  1. 设定代理格式
  2. 通过 proxies 参数传递代理设置
  3. 开启代理工具监听请求

 

import requests


def test_proxy():
    proxy = {
        "http": "http://127.0.0.1:6666",
        "https": "http://127.0.0.1:6666"
    }
    url = "https://httpbin.testing-studio.com/post"
    r = requests.post(url=url, proxies=proxy, verify=False)
    print(r.text)

8.多层嵌套响应断言

什么是多层嵌套结构
// - 层级多。
// - 嵌套关系复杂。
{
  "errcode": 0,
  "errmsg": "ok",
  "userid": "zhangsan",
  "name": "张三",
  "department": [1, 2],
  "order": [1, 2],
  "position": "后台工程师",
  "mobile": "13800000000",
  "gender": "1",
  "email": "zhangsan@gzdev.com",
  "biz_mail": "zhangsan@qyycs2.wecom.work",
  "is_leader_in_dept": [1, 0],
  "direct_leader": ["lisi", "wangwu"],
  "avatar": "http://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0",
  "thumb_avatar": "http://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/100",
  "telephone": "020-123456",
  "alias": "jackzhang",
  "address": "广州市海珠区新港中路",
  "open_userid": "xxxxxx",
  "main_department": 1,
  "extattr": {
    "attrs": [
      {
        "type": 0,
        "name": "文本名称",
        "text": {
          "value": "文本"
        }
      },
      {
        "type": 1,
        "name": "网页名称",
        "web": {
          "url": "http://www.test.com",
          "title": "标题"
        }
      }
    ]
  },
  "status": 1,
  "qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx",
  "external_position": "产品经理",
  "external_profile": {
    "external_corp_name": "企业简称",
    "wechat_channels": {
      "nickname": "视频号名称",
      "status": 1
    },
    "external_attr": [
      {
        "type": 0,
        "name": "文本名称",
        "text": {
          "value": "文本"
        }
      },
      {
        "type": 1,
        "name": "网页名称",
        "web": {
          "url": "http://www.test.com",
          "title": "标题"
        }
      },
      {
        "type": 2,
        "name": "测试app",
        "miniprogram": {
          "appid": "wx8bd80126147dFAKE",
          "pagepath": "/index",
          "title": "my miniprogram"
        }
      }
    ]
  }
}
复杂场景响应提取 
场景方式
提取 errcode 对应的值res["errcode"]
提取 title 对应的值res["extattr"]["external_profile"]["external_attr"][1]["web"]["title"]
提取 type 为 0 的 name编码实现
提取 attrs 下的所有的 name编码实现
JSONPath 简介
  • 在 JSON 数据中定位和提取特定信息的查询语言。
  • JSONPath 使用类似于 XPath 的语法,使用路径表达式从 JSON 数据中选择和提取数据。
  • 相比于传统的提取方式,更加灵活,并且支持定制化。
JSONPath 对比
场景对应实现JSONPath 实现
提取 errcode 对应的值res["errcode"]$.errcode
提取 title 对应的值res["extattr"]["external_profile"]["external_attr"][1]["web"]["title"] 等$..title
提取 type 为 0 的 name编码实现$..external_attr[?(@.type==0)].name
提取 attrs 下的所有的 name编码实现$..attrs..name
JSONPath 如何使用
  • 语法知识。
  • 第三方库调用。
JSONPath 语法 
符号描述
$查询的根节点对象,用于表示一个 json 数据,可以是数组或对象
@过滤器(filter predicate)处理的当前节点对象
*通配符
.获取子节点
..递归搜索,筛选所有符合条件的节点
?()过滤器表达式,筛选操作
[start:end]数组片段,区间为[start,end),不包含 end
[A]或[A,B]迭代器下标,表示一个或多个数组下标
JSONPath 的练习环境  

https://jsonpath.hogwarts.ceshiren.com/

{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  },
  "expensive": 10
}
JSONPath 练习题目
  • 获取所有书籍的作者
  • 获取所有作者
  • 获取 store 下面的所有内容
  • 获取所有的价格
  • 获取第三本书
  • 获取所有包含 isbn 的书籍
  • 获取所有价格小于 10 的书
  • 获取所有书籍的数量
 JSONPath 练习
需求JsonPath
所有书籍的作者$.store.book[*].author
所有作者$..author
store 下面的所有内容$.store.
所有的价格$.store..price
第三本书$..book[2]
所有包含 isbn 的书籍$..book[?(@.isbn)]
所有价格小于 10 的书$.store.book[?(@.price < 10)]
所有书籍的数量$..book.length
JSONPath 与代码结合(Python) 
  • 环境安装:pip install jsonpath
# 具体的使用。
jsonpath.jsonpath(源数据对象, jsonpath表达式)

代码示例:

import jsonpath
import requests


def test_jsonpath():
    url = "https://httpbin.ceshiren.com/post"
    req_body = {"teacher": "ad", "school": "hdc"}
    r = requests.post(url, json=req_body, verify=False)
    print(r.json()["headers"]["Content-Type"])
    res = jsonpath.jsonpath(r.json(), "$..Content-Type")
    print(res)

    assert res[0] == r.json()["headers"]["Content-Type"]

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

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

需求说明
  • 完成宠物商城宠物管理功能接口自动化测试。
    • 编写自动化测试脚本。
    • 完成复杂断言。
相关知识点
形式章节描述
知识点代理配置利用代理分析测试脚本,排查请求错误
知识点多层嵌套响应断言利用 jsonpath 进行多层嵌套的响应断言
实战思路

需求分析
  • 被测产品:宠物商店系统 - 宠物管理。
  • 宠物商店接口文档:https://petstore.swagger.io/
  • 宠物管理业务场景:
    • 添加宠物。
    • 查询宠物信息。
    • 修改宠物信息。
    • 删除宠物。

宠物管理接口业务流程测试用例

编写自动化测试脚本思路

编写自动化测试脚本
import requests


class TestPetstorePetmanager:
    def setup_class(self):
        self.base_url = "https://petstore.swagger.io/v2/pet"
        self.search_url = self.base_url + "/findByStatus"
        self.pet_id = 9223372000001084222
        self.delete_url = self.base_url + f'/{self.pet_id}'
        self.pet_status = "available"
        self.add_pet_info = {
            "id": self.pet_id,
            "category": {
                "id": 1,
                "name": "cat"
            },
            "name": "miao",
            "photoUrls": [
                "string"
            ],
            "tags": [
                {
                    "id": 5,
                    "name": "cute"
                }
            ],
            "status": self.pet_status
        }
        self.update_name = "miao-hdc"
        self.update_pet_info = {
            "id": self.pet_id,
            "category": {
                "id": 1,
                "name": "cat"
            },
            "name": self.update_name,
            "photoUrls": [
                "string"
            ],
            "tags": [
                {
                    "id": 5,
                    "name": "cute"
                }
            ],
            "status": self.pet_status
        }
        self.search_param = {
            "status": self.pet_status
        }

    def test_pet_manager(self):
        # 新增宠物接口
        add_r = requests.post(self.base_url, json=self.add_pet_info, verify=False)
        # 查询宠物
        search_r = requests.get(self.search_url, params=self.search_param, verify=False)
        # 修改宠物
        update_r = requests.put(self.base_url, json=self.update_pet_info, verify=False)
        # 删除宠物
        delete_r = requests.delete(self.delete_url, verify=False)

脚本优化 - 配置代理查看接口数据
  • 在脚本中配置代理。
  • 抓包查看接口测试中的接口请求和响应数据。
proxy = {
    "http": "http://127.0.0.1:8888",
    "https": "http://127.0.0.1:8888"
}

requests.post(url, json=pet_info, proxies=proxy, verify=False)
 脚本优化 - 添加日志
  • 新建日志配置。
  • 在用例中使用配置好的日志实例。
import logging
import os

from 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()
 脚本优化 - 使用 jsonpath 断言
  • 使用 jsonpath 实现多层嵌套响应的断言。 
jsonpath.jsonpath(r.json(), "$..id")
import jsonpath
import requests

from interface_automation_testing.接口自动化测试_L2.宠物商店接口自动化测试实战.utils.log_util import logger


class TestPetstorePetmanager:
    def setup_class(self):
        self.base_url = "https://petstore.swagger.io/v2/pet"
        self.search_url = self.base_url + "/findByStatus"
        self.pet_id = 9223372000001084222
        self.delete_url = self.base_url + f'/{self.pet_id}'
        self.pet_status = "available"
        self.add_pet_info = {
            "id": self.pet_id,
            "category": {
                "id": 1,
                "name": "cat"
            },
            "name": "miao",
            "photoUrls": [
                "string"
            ],
            "tags": [
                {
                    "id": 5,
                    "name": "cute"
                }
            ],
            "status": self.pet_status
        }
        self.update_name = "miao-hdc"
        self.update_pet_info = {
            "id": self.pet_id,
            "category": {
                "id": 1,
                "name": "cat"
            },
            "name": self.update_name,
            "photoUrls": [
                "string"
            ],
            "tags": [
                {
                    "id": 5,
                    "name": "cute"
                }
            ],
            "status": self.pet_status
        }
        self.search_param = {
            "status": self.pet_status
        }

    def test_pet_manager(self):
        # 新增宠物接口
        add_r = requests.post(self.base_url, json=self.add_pet_info, verify=False)
        logger.info(f"新增宠物接口响应为:{add_r.text}")

        assert add_r.status_code == 200

        # 查询宠物
        search_r = requests.get(self.search_url, params=self.search_param, verify=False)
        logger.info(f"查询宠物接口的响应为:{search_r.text}")

        assert search_r.status_code == 200
        assert self.pet_id in jsonpath.jsonpath(search_r.json(), "$..id")

        # 修改宠物
        update_r = requests.put(self.base_url, json=self.update_pet_info, verify=False)
        logger.info(f"修改宠物接口的响应为:{update_r.text}")

        assert update_r.status_code == 200
        search_r = requests.get(self.search_url, params=self.search_param, verify=False)
        assert search_r.status_code == 200
        assert self.update_name in jsonpath.jsonpath(search_r.json(), "$..name")

        # 删除宠物
        delete_r = requests.delete(self.delete_url, verify=False)
        logger.info(f"删除宠物接口的响应为:{delete_r.text}")

        assert delete_r.status_code == 200
        search_r = requests.get(self.search_url, params=self.search_param, verify=False)
        assert search_r.status_code == 200
        assert self.pet_id not in jsonpath.jsonpath(search_r.json(), "$..id")

 

生成测试报告
  • 安装 allure 相关依赖。
# 生成报告信息
pytest --alluredir=./report
# 生成报告在线服务,查看报告
allure serve ./report/
pytest -vs .\test_petstore.py --alluredir=./datas/report --clean-alluredir

allure serve ./datas/report

 运行结果:

 

总结
  • 通过 Swagger 文档获取接口信息。
  • 使用 Requests 发出请求。
  • 添加代理,抓包查看接口请求和响应数据。
  • 使用 Jsonpath 提取复杂结构响应数据,然后进行断言。
  • 添加 Log 日志。
  • 生成 Allure 测试报告。
项目结构:

项目地址:

 https://gitee.com/coderPatrickStar/template/tree/master/python_software_testing

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全渗透测试工具AWVS14.6.2的安装与使用(激活)

AWVS介绍 Acunetix Web Vulnerability Scanner&#xff08;AWVS&#xff09;是一款用于检测网站和Web应用程序中安全漏洞的自动化工具。它的主要功能包括&#xff1a; 漏洞扫描&#xff1a;AWVS能够自动扫描目标网站和Web应用程序&#xff0c;以发现各种安全漏洞&#xff0c;如…

水质在线监测解决方案:数据采集终端的应用

​ 随着社会的发展,河流、湖泊等水环境的保护日益受到关注。但是传统的人工采样检测水质的方法低效且监测数据不连续,无法实时全面掌握水质动态。采用水质在线监测系统,可以实时监测水质参数,并将数据通过无线网络实时传输,以便水务部门监控水质变化,并快速采取应对措施,保护水…

网工配置命令基础总结(2)----VRRP配置

目录 1.配置VRRP主备备份 2.配置VRRP负载分担 3.配置VRRP域BFD联动实现快速切换 VRRP 虚拟路由冗余协议 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;通过把几台路由设备联合组成一台虚拟的路由设备&#xff0c;将虚拟网关设备的 IP 地址作为用户的默认…

推荐一款正在用的配音软件(免费)~

最近在做账号&#xff0c;遇到的最大的难题就是&#xff0c;口播的能力一般&#xff0c;用电脑收声以后&#xff0c;总有许多语气词&#xff0c;发音不标准或吞字的情况&#xff0c;而且念稿也是个非常消耗时间的事儿。身边的朋友给我推荐了悦音配音这款AI配音软件&#xff0c;…

向量化操作简介和Pandas、Numpy示例

Pandas是一种流行的用于数据操作的Python库&#xff0c;它提供了一种称为“向量化”的强大技术可以有效地将操作应用于整个列或数据系列&#xff0c;从而消除了显式循环的需要。在本文中&#xff0c;我们将探讨什么是向量化&#xff0c;以及它如何简化数据分析任务。 什么是向量…

appium---如何判断原生页面和H5页面

目前app中存在越来越多的H5页面了&#xff0c;对于一些做app自动化的测试来说&#xff0c;要求也越来越高&#xff0c;自动化不仅仅要支持原生页面&#xff0c;也要可以H5中进行操作自动化&#xff0c; webview是什么 webview是属于android中的一个控件&#xff0c;也相当于一…

GFD233A103 3BHE022294R0103 串行和并行通信的区别

GFD233A103 3BHE022294R0103 串行和并行通信的区别 串行通信和并行通信的关键区别在于&#xff0c;在串行通信中&#xff0c;一条通信链路用于将数据从一端传输到另一端。与并行通信相反&#xff0c;使用多个并行链路同时传输每位数据。 由于只有一条通信链路&#xff0c;串行…

到底什么是5G-R?

近日&#xff0c;工信部向中国国家铁路集团有限公司&#xff08;以下简称“国铁集团”&#xff09;批复5G-R试验频率的消息&#xff0c;引起了行业内的广泛关注。 究竟什么是5G-R&#xff1f;为什么工信部会在此时批复5G-R的试验频率&#xff1f; 今天&#xff0c;小枣君就通过…

win10取消ie浏览器自动跳转edge浏览器

建议大家看完整篇文章再作操作 随着windows10 日渐更新&#xff0c;各种不同的操作&#xff0c;规避IE浏览器跳转Edge浏览器的问题 算了&#xff0c;找了台云机装的server 有自带的IE 1.&#xff08;失败&#xff09;思路 协助Edge浏览器 管理员身份打开 PowerShell 一般e…

一个有趣的观点:用To C的思路来做To B

大数据产业创新服务媒体 ——聚焦数据 改变商业 在传统商业模式中&#xff0c;B端市场和C端市场被视为截然不同的两个领域&#xff0c;各自有各自的战略和运营模式。但随着技术的迅速发展和市场环境的变化&#xff0c;这两个领域之间的界限正在逐渐模糊。 尽管B端软件的目标客…

外卖跑腿系统的关键功能和技术要点

1. 用户注册和登录 首先&#xff0c;用户需要能够注册新账户并登录。以下是使用Python和Django框架的代码示例&#xff0c;展示如何创建用户注册和登录功能。 # Django视图代码 from django.contrib.auth import login, authenticate from django.contrib.auth.forms import…

需求评审如何一次过?

需求评审是产品经理一项绕不过去的工作&#xff0c;但对于产品新人来说&#xff0c;可能不是一件简单的事情&#xff0c;方案准备的是否充分&#xff0c;能否经受住项目其他成员的灵魂拷问&#xff0c;都极大的考验着产品经理的技能和抗压能力&#xff0c;今天就来说说如何做好…

kettle应用-数据库表插入/更新

本文介绍从pg数据库中抽取数据&#xff0c;插入/更新到另一个表中 数据流转逻辑设计 【表输入】--》【增加序列】--》【插入/更新】 一、表输入&#xff1a;关联多表查询获取数据 “核心对象”区域--“输入”中&#xff0c;拖入“表输入” 二、增加序列&#xff1a;生成序列…

我的创作日

目录 机缘 收获 日常 成就 憧憬 机缘 《AR助教奇迹人总结》这是最开始大佬叫我写的文章&#xff0c;大佬说写完发到CSDN&#xff0c;刚开始我还纳闷什么叫CSDN呢&#xff0c;无意间我看到我的码龄竟然是两年&#xff0c;哈哈可能是无意间自己注册的吧&#xff0c;连我自己…

linux内存、cpu、进程、端口、硬盘管理

这里讲解一下linux内存、cpu、进程、端口、硬盘管理命令操作,更多linux常用命令见:一些经常使用的linux命令 一、内存、cup 管理 top 命令 1、top 命令的第一行 top - 10:11:23 up 12:10, 2 users, load average: 0.00, 0.02, 0.05 依次对应&#xff1a; 系统当前时间 10:11:…

Linux定时任务 crond

crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程;这是一个后台程序。 crontab是一个工具&#xff0c;用用编辑crond的配置文件。 **硬件支持型号 点击 查看 硬件支持 详情** DTU701 产品详情 DTU702 产品详情 DTU801 产品详情 DTU802 产品详情 …

vmware ubuntu 虚拟机 网卡图片消失处理办法

如图&#xff0c;这个图标消失处理办法&#xff1a; 输入如下指令&#xff1a;sudo service network-manager stop sudo rm /var/lib/NetworkManager/NetworkManager.state sudo service network-manager start

GEE错误——利用selector选择指定的属性列表进行表格的导出(相关错误解析)

本文主要是利用目的是利用selector选择指定的属性列表进行表格的导出,这里的目的是我们就用这个表格选取指定的属性列表即可。 相关错误: 我正在尝试获取每个点的平均土壤值。代码运行良好,但我得到一个空白列。我可能必须添加 .set 或 .get 或其他东西,我尝试过但没有运气…

服务器中了mkp勒索病毒怎么办?mkp勒索病毒特点,解密数据恢复

Mkp勒索病毒是最近比较流行的勒索病毒&#xff0c;从10月份国庆节假期结束以来&#xff0c;云天数据恢复中心陆续收到很多企业的求助&#xff0c;企业的服务器被mkp勒索病毒攻击&#xff0c;导致企业的众多软件无法正常使用&#xff0c;像用友与金蝶软件都有遭受过mkp勒索病毒的…

Redis 第二章:通用命令

Redis 提供了 5 种数据结构&#xff0c;理解每种数据结构的特点对于 Redis 开发运维⾮常重要&#xff0c;同时掌握每种数据结构的常⻅命令&#xff0c;会在使⽤ Redis 的时候做到游刃有余。 目录 2.1 预备知识 2.1.1 基本全局命令 2.1.2 数据结构和内部编码 2.1.3 单线程架…