接口自动化测试_L3

news2024/11/19 2:17:00

目录:

  1. 整体结构响应断言
    1. 响应信息数据极为庞大,针对于“大响应数据”如何断言
    2. JSONSchema 简介
    3. JSONSchema 整体结构响应断言
    4. JSONSchema 的生成
    5. JSONSchema 的生成效果
    6. 界面工具生成
    7. 第三方库生成(Python)
    8. JSONSchema 验证(Python)
    9. JSONSchema 二次封装
  2. 数据库操作与断言
    1. 接口测试响应验证
    2. 接口测试数据清理
    3. 数据库操作注意事项
    4. 接口自动化测试常用的数据库操作
    5. 数据库信息
    6. 数据库封装(Python)
    7. 查询数据与数据库断言(Python)
  3. 接口鉴权的多种情况与解决方案
    1. 接口鉴权是什么?
    2. 接口鉴权通用的解决方案
    3. 后端接口鉴权常用方法
    4. cookie 鉴权
    5. token 鉴权
    6. auth 鉴权(了解即可)
    7. auth 鉴权-代码示例
  4. 电子商城接口自动化测试实战
    1. 电子商城需求分析
    2. 商城业务场景
    3. 研发技术评审
    4. 接口测试用例设计思路
    5. 添加购物车流程脚本编写
    6. 脚本优化-参数化(Python)
    7. 脚本优化-添加日志(Python)
    8. 脚本优化-数据清理(Python)
    9. 脚本优化-报告展示
    10. 项目地址:

1.整体结构响应断言

响应信息数据极为庞大,针对于“大响应数据”如何断言
  • 针对主要且少量的业务字段断言。
  • 其他字段不做数据正确性断言,只做类型与整体结构的校验。
  • 与前面的版本进行 diff,对比差异化的地方。
JSONSchema 简介
  • 使用 JSON 格式编写的
  • 可以用来定义校验 JSON 数据的结构
  • 可以用来校验 JSON 数据的一致性
  • 可以用来校验 API 接口请求和响应
 JSONSchema 整体结构响应断言
  1. 预先生成对应结构的 Schema。
  2. 将实际获取到的响应与生成的 Schema 进行对比。
JSONSchema 的生成
  • 通过界面工具生成。
  • 通过第三方库生成。
  • 通过命令行工具生成。
JSONSchema 的生成效果
// # 预期的 JSON 文档结构
{
  "name": "LiMing",
  "Courses": ["Mock", "Docker"]
}
// jsonschema
{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "$ref": "#/definitions/Welcome",
  "definitions": {
    "Welcome": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string"
        },
        "Courses": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": ["Courses", "name"],
      "title": "Welcome"
    }
  }
}
界面工具生成
  • 复制 JSON 数据
  • 粘贴到在线生成工具中
  • 自动生成 JSON Schema 数据

JSON Schema 在线生成工具:https://app.quicktype.io 

第三方库生成(Python)
  1. 安装:pip install genson
  2. 调用方法生成对应的 JSONSchema 数据结构。
from genson import SchemaBuilder


def gernerate_jsonschema(obj):
    builder = SchemaBuilder()
    builder.add_object(obj)
    return builder.to_schema()


def test_generate_jsonschema():
    print(gernerate_jsonschema({"name": 1}))

运行结果:

 

 JSONSchema 验证(Python)
  1. 安装:pip install jsonschema
  2. 调用 validate() 进行验证。
def schema_validate(obj, schema):
    '''
    对比 python 对象与生成的 JSONSchame 的结构是否一致
    '''
    try:
        validate(instance=obj, schema=schema)
        return True
    except Exception as e:
        return False

 代码示例:

import json

from genson import SchemaBuilder
from jsonschema.validators import validate


def gernerate_jsonschema(obj):
    builder = SchemaBuilder()
    builder.add_object(obj)
    return builder.to_schema()


def test_generate_jsonschema():
    print(gernerate_jsonschema({"name": 1}))


def gernerate_jsonschema_file(obj, file_path):
    res = gernerate_jsonschema(obj)
    with open(file_path, 'w') as f:
        json.dump(res, f)


def test_generate_jsonschema_file():
    gernerate_jsonschema_file({"name": 1}, "./datas/validate.json")


def schema_validate(obj, schema):
    try:
        validate(instance=obj, schema=schema)
        return True
    except Exception as e:
        return False


def test_schema_validate():
    with open("./datas/validate.json", 'r') as f:
        res = json.load(f)
    schema_validate({"name": 1}, res)
 JSONSchema 二次封装
  • 生成JSONSchema
  • 验证JSONSchema
class JSONSchemaUtils:
    @classmethod
    def generate_schema(cls, obj):
        # 实例化jsonschem
        builder = SchemaBuilder()
        # 传入被转换的对象 
        builder.add_object(obj)
        # 转换成 schema 数据
        return builder.to_schema()

    @classmethod
    def schema_validate(cls, obj, schema):
        '''
        对比 python 对象与生成的 json schame 的结构是否一致
        '''
        try:
            validate(instance=obj, schema=schema)
            return True
        except Exception as e:
            return False

 代码示例:

test_utils_use.py

import requests

from interface_automation_testing.接口自动化测试_L3.接口鉴权的多种情况与解决方案.jsonschema_utils import JSONSchemaUtils


def test_httpbin_generate_schema():
    r = requests.get("https://httpbin.ceshiren.com/get", verify=False)
    JSONSchemaUtils.generate_jsonschema_by_file(r.json(), "./datas/httpbin.json")


def test_httpbin_req():
    r = requests.get("https://httpbin.ceshiren.com/get", verify=False)
    validate_res = JSONSchemaUtils.validate_schema_by_file(r.json(), "./datas/httpbin.json")
    assert validate_res == True

jsonschema_utils.py

import json
from genson import SchemaBuilder
from jsonschema.validators import validate


class JSONSchemaUtils:

    @classmethod
    def validate_schema(cls, data_obj, schema):
        try:
            validate(data_obj, schema=schema)
            return True
        except Exception as e:
            print(f"结构体验证失败,失败原因是{e}")
            return False

    @classmethod
    def generate_jsonschema(cls, obj):
        builder = SchemaBuilder()
        builder.add_object(obj)
        return builder.to_schema()

    @classmethod
    def validate_schema_by_file(cls, data_obj, schema_file):
        with open(schema_file) as f:
            schema_data = json.load(f)
        return cls.validate_schema(data_obj, schema_data)

    @classmethod
    def generate_jsonschema_by_file(cls, obj, file_path):
        json_schema_data = cls.generate_jsonschema(obj)
        with open(file_path, "w") as f:
            json.dump(json_schema_data, f)

 项目结构:

2.数据库操作与断言

接口测试响应验证

如何在测试过程中验证接口没有 Bug?

  1. 通过接口响应值
  2. 通过查询数据库信息辅助验证
接口测试数据清理 

自动化测试过程中,会产生大量的脏数据,如何处理?

  1. 通过 Delete 接口删除
  2. 自动化测试使用干净的测试环境,每次自动化测试执行完成之前或之后做数据还原。
数据库操作注意事项 

直接对数据库做查询之外的操作是非常危险的行为

  1. 权限管理严格的公司数据库权限给的非常低
  2. 表结构复杂,随便删除数据会影响测试,甚至会导致系统出现异常
接口自动化测试常用的数据库操作 
  • 连接与配置
  • 查询数据与断言
数据库信息 
  • 主机: litemall.hogwarts.ceshiren.com
  • 端口: 13306
  • 用户名: test
  • 密码: test123456

注意:只有查询权限 

数据库封装(Python) 
  • 封装数据库配置
  • 封装 sql 查询操作
  • 调用方法执行 sql 语句
import pymysql


# 封装建立连接的对象
def get_connnect():
    conn = pymysql.connect(
        host="litemall.hogwarts.ceshiren.com",
        port=13306,
        user="test",
        password="test123456",
        database="litemall",
        charset="utf8mb4"
    )
    return conn


# 执行sql语句
def execute_sql(sql):
    connect = get_connnect()
    cursor = connect.cursor()
    cursor.execute(sql)  # 执行SQL
    record = cursor.fetchone()  # 查询记录
    return record


if __name__ == '__main__':
    ret = execute_sql("select * from litemall_cart where goods_name='竹语丝麻印花四件套'")
    print(ret)
 查询数据与数据库断言(Python)
  • 查询数据,添加查询条件
  • 断言结果不为 None
import json
import pytest
import requests

from interface_automation_testing.接口自动化测试_L3.数据库操作与断言.db_config import execute_sql
from interface_automation_testing.接口自动化测试_L3.数据库操作与断言.utils.log_util import logger


class TestLitemall:
    def setup_class(self):
        # 1. 管理端登录接口
        url = "http://litemall.hogwarts.ceshiren.com/admin/auth/login"
        user_data = {"username": "admin123", "password": "admin123", "code": ""}
        r = requests.post(url, json=user_data, verify=False)
        self.token = r.json()["data"]["token"]
        # 问题: 没有执行test_get_admin_token这个方法,所以self.token 就不会被声明就会报错'TestLitemall' object has no attribute 'token'
        # 解决, self.token 的声明一定要在test_add_goods方法执行之前完成,可以使用setup_class 提前完成变量的声明
        # 2. 用户端登录接口
        url = "http://litemall.hogwarts.ceshiren.com/wx/auth/login"
        client_data = {"username": "user123", "password": "user123"}
        r = requests.post(url, json=client_data, verify=False)
        self.client_token = r.json()["data"]["token"]

    # ======= 数据清理,建议使用delete接口不要直接删表中的数据
    def teardown(self):
        url = "http://litemall.hogwarts.ceshiren.com/admin/goods/delete"
        r = requests.post(url, json={"id": self.goods_id}, headers={"X-Litemall-Admin-Token": self.token}, verify=False)
        logger.debug(f"删除商品的响应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

    # 上架商品接口调试
    # ====问题2: goods_name 不能重复,所以需要添加参数化
    @pytest.mark.parametrize("goods_name", ["ADcarry12", "ADcarry13"])
    def test_add_goods(self, goods_name):
        # 3. 上架商品接口
        url = "http://litemall.hogwarts.ceshiren.com/admin/goods/create"
        goods_data = {
            "goods": {"picUrl": "", "gallery": [], "isHot": False, "isNew": True, "isOnSale": True, "goodsSn": "9001",
                      "name": goods_name}, "specifications": [{"specification": "规格", "value": "标准", "picUrl": ""}],
            "products": [{"id": 0, "specifications": ["标准"], "price": "66", "number": "66", "url": ""}],
            "attributes": []}
        # 问题: token 是 手动复制进去的,一旦发生变化,还需要再次修改
        # 解决方案: token 需要自动完成获取,并且赋值
        r = requests.post(url, json=goods_data, headers={"X-Litemall-Admin-Token": self.token}, verify=False)
        # 打印响应体内容
        # print(r.json())
        # logger.debug(f"上架商品接口接口的相应信息为{r.json()}")
        logger.debug(f"上架商品接口接口的相应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")
        # 4. 获取商品列表
        goods_list_url = "http://litemall.hogwarts.ceshiren.com/admin/goods/list"
        # 是一个get请求,参数需要通过params也就是url参数传递
        goods_data = {
            "name": goods_name,
            "order": "desc",
            "sort": "add_time"
        }
        r = requests.get(goods_list_url, params=goods_data,
                         headers={"X-Litemall-Admin-Token": self.token}, verify=False)
        self.goods_id = r.json()["data"]["list"][0]["id"]
        logger.debug(f"获取商品列表接口的响应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

        # 5.获取商品详情接口=========
        goods_detail_url = "http://litemall.hogwarts.ceshiren.com/admin/goods/detail"
        r = requests.get(goods_detail_url, params={"id": self.goods_id},
                         headers={"X-Litemall-Admin-Token": self.token}, verify=False)
        product_id = r.json()["data"]["products"][0]["id"]
        logger.debug(f"获取商品详情接口的响应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

        # 6. 添加购物车接口
        url = "http://litemall.hogwarts.ceshiren.com/wx/cart/add"
        # 问题: goodsId 和 productId 是写死的,变量的传递没有完成
        # 解决方案: goodsId 和 productId 从其他的接口获取,并传递给添加购物车接口
        cart_data = {"goodsId": self.goods_id, "number": 1, "productId": product_id}
        r = requests.post(url, json=cart_data, headers={"X-Litemall-Token": self.client_token}, verify=False)
        res = r.json()
        logger.info(f"添加购物车接口响应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

        # ===============问题1: 缺少断言
        ret = execute_sql(f"select * from litemall_cart where user_id=1 and deleted=0 and goods_name='{goods_name}'")

        assert ret is not None
        # ===============解决: 添加断言
        assert res["errmsg"] == "成功"

项目结构:

3.接口鉴权的多种情况与解决方案

接口鉴权是什么?

接口鉴权是指对通过接口进行的数据访问进行权限验证,以防止未授权的访问和恶意攻击。具体来说,接口鉴权可以在数据访问请求到达服务器之前,通过验证请求中的用户身份、角色、令牌等信息来确认请求者是否有权访问该接口。如果请求没有通过鉴权验证,服务器将拒绝该请求并返回相应的错误信息。

在实现接口鉴权时,需要考虑以下几个因素:

  1. 安全性:要保证接口鉴权的安全性,需要对用户的敏感信息进行加密处理,同时对服务器和数据库等核心资产进行安全防护,以防止恶意攻击和数据泄露。
  2. 可扩展性:随着业务的发展和用户数量的增加,接口鉴权的复杂度和工作量也会逐渐增加。因此,在实现接口鉴权时需要考虑可扩展性,以便于后续的升级和维护。
  3. 可维护性:接口鉴权需要有良好的可维护性,以便于在出现异常情况时快速定位和解决问题。同时,也需要对用户反馈和系统日志进行实时监控,以便于及时发现和处理潜在问题。

总之,接口鉴权是保障数据访问安全的重要组成部分,可以有效防止未授权的访问和恶意攻击,保护系统的稳定性和可靠性。

接口鉴权通用的解决方案
  • 认证信息的获取
  • 认证信息的携带

 

后端接口鉴权常用方法 

cookie 鉴权 
  1. cookie 的获取(根据接口文档获取)
  2. 发送携带 cookie 的请求
    • 直接通过 cookies 参数
    • 通过 Session() 对象
import requests


class TestVerify:
    def test_cookies_by_write(self):
        # 简单场景,直接写入cookie
        url = "https://httpbin.ceshiren.com/cookies"
        r = requests.get(url, verify=False, cookies={"teacher": "LiMing"})
        print(r.json())

    def test_cookies_without_session(self):
        # 第一次登陆,植入cookie
        set_url = "https://httpbin.ceshiren.com/cookies/set/teacher/LiMing"
        r1 = requests.get(set_url, verify=False)
        print(r1.json())

        # 第二次请求的时候没有携带cookie信息
        url = "https://httpbin.ceshiren.com/cookies"
        r2 = requests.get(url, verify=False)
        print(r2.json())

    def test_cookies_session(self):
        req = requests.Session()

        # 第一次登陆,植入cookie
        set_url = "https://httpbin.ceshiren.com/cookies/set/teacher/LiMing"
        r1 = req.get(set_url, verify=False)
        print(r1.json())

        # 第二次请求的时候即可携带cookie信息
        url = "https://httpbin.ceshiren.com/cookies"
        r2 = req.get(url, verify=False)
        print(r2.json())
token 鉴权
  1. token 的获取(根据接口文档获取)
  2. 发送携带 token 的请求(根据接口文档获取)
import requests


class TestVerify:
    def test_token(self):
        # 1. 前端登录进去以后,会拿到服务器给的tocken
        url = "http://litemall.hogwarts.ceshiren.com/admin/auth/login"
        user_data = {"username": "admin123", "password": "admin123", "code": ""}
        r = requests.post(url,
                          json=user_data,
                          verify=False)
        self.token = r.json()["data"]["token"]
        print(r.json())

        # 2. 之后的请求均携带token
        goods_list_url = "http://litemall.hogwarts.ceshiren.com/admin/goods/list"
        goods_data = {"name": "LiMing", "order": "desc", "sort": "add_time"}
        r = requests.get(goods_list_url,
                         params=goods_data,
                         headers={"X-Litemall-Admin-Token": self.token},
                         verify=False)
        print(r.json())
 auth 鉴权(了解即可)
  • 在基本 HTTP 身份验证中,请求包含格式为 的标头字段Authorization: Basic
  • 其中credentials是 ID 和密码的Base64编码,由单个冒号连接:。

 

auth 鉴权-代码示例 
import requests
from requests.auth import HTTPBasicAuth


class TestVerify:
    def test_basic_auth(self):
        # 正确示例
        r = requests.get("https://httpbin.ceshiren.com/basic-auth/admin/666666",
                         verify=False,
                         auth=HTTPBasicAuth("admin", "666666"))
        print(r.json())

        # 错误示例
        # r = requests.get("https://httpbin.ceshiren.com/basic-auth/admin/666666",
        #                  verify=False,
        #                  auth=HTTPBasicAuth("admin2", "666666"))
        # print(r.json())

 

4.电子商城接口自动化测试实战

接口测试流程
  • 需求分析->测试设计->测试用例评审->测试执行->验收->预发布->上线
  • 地址一:https://litemall.hogwarts.ceshiren.com/#/login
  • 地址二: https://litemall.hogwarts.ceshiren.com/vue#/
电子商城需求分析
  • 商城管理后台

  • 商城客户端

商城业务场景
  • 商品上架
  • 商品查询
  • 加入购物车

研发技术评审
  • 管理后台接口文档
  • https://litemall.hogwarts.ceshiren.com/swagger-ui.html#
 接口测试用例设计思路

添加购物车流程脚本编写 
  1. 上架商品
  2. 查询商品列表,获取商品ID
  3. 查询商品详情,获取商品库存ID
  4. 加入购物车

 

脚本优化-参数化(Python) 
  • 使用pytest parametrize装饰器实现商品名称的参数化
  • @pytest.mark.parametrize("goods_name", ["name1", "name2"])  
脚本优化-添加日志(Python) 
  • 新建日志配置
  • 在用例中使用配置好的日志实例
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()
脚本优化-数据清理(Python)
  • 在用例执行完成之后调用删除接口完成数据清理
import json
import pytest
import requests

from interface_automation_testing.接口自动化测试_L3.电子商城接口自动化测试实战.utils.log_util import logger


class TestLitemall:
    def setup_class(self):
        # 1. 管理端登录接口
        url = "http://litemall.hogwarts.ceshiren.com/admin/auth/login"
        user_data = {"username": "hogwarts", "password": "test12345", "code": ""}
        r = requests.post(url, json=user_data, verify=False)
        self.token = r.json()["data"]["token"]

        # 2. 用户端登录接口
        url = "http://litemall.hogwarts.ceshiren.com/wx/auth/login"
        client_data = {"username": "user123", "password": "user123"}
        r = requests.post(url, json=client_data, verify=False)
        self.client_token = r.json()["data"]["token"]

    def teardown(self):
        url = "http://litemall.hogwarts.ceshiren.com/admin/goods/delete"
        r = requests.post(url,
                          json={"id": self.goods_id},
                          headers={"X-Litemall-Admin-Token": self.token},
                          verify=False)
        logger.info(f"删除商品的响应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

    @pytest.mark.parametrize("goods_name", ["ADcarry12", "ADcarry13"])
    def test_add_goods(self, goods_name):
        # 上架商品
        url = "http://litemall.hogwarts.ceshiren.com/admin/goods/create"
        goods_data = {
            "goods": {"picUrl": "", "gallery": [], "isHot": False, "isNew": True, "isOnSale": True, "goodsSn": "9001",
                      "name": goods_name},
            "specifications": [{"specification": "规格", "value": "标准", "picUrl": ""}],
            "products": [{"id": 0, "specifications": ["标准"], "price": "66", "number": "66", "url": ""}],
            "attributes": []
        }
        r = requests.post(url, json=goods_data, headers={"X-Litemall-Admin-Token": self.token})
        logger.info(f"上架商品接口接口的相应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

        # 获取商品列表
        goods_list_url = "http://litemall.hogwarts.ceshiren.com/admin/goods/list"
        goods_data = {
            "name": goods_name,
            "order": "desc",
            "sort": "add_time"
        }
        r = requests.get(goods_list_url,
                         params=goods_data,
                         headers={"X-Litemall-Admin-Token": self.token},
                         verify=False)
        self.goods_id = r.json()["data"]["list"][0]["id"]
        logger.info(f"获取商品列表接口的响应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

        # 获取商品详情
        goods_detail_url = "http://litemall.hogwarts.ceshiren.com/admin/goods/detail"
        r = requests.get(goods_detail_url,
                         params={"id": self.goods_id},
                         headers={"X-Litemall-Admin-Token": self.token},
                         verify=False)
        product_id = r.json()["data"]["products"][0]["id"]
        logger.info(f"获取商品详情接口的响应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

        # 添加购物车接口
        url = "http://litemall.hogwarts.ceshiren.com/wx/cart/add"
        cart_data = {"goodsId": self.goods_id, "number": 1, "productId": product_id}
        r = requests.post(url, json=cart_data, headers={"X-Litemall-Token": self.client_token})
        res = r.json()
        logger.info(f"添加购物车接口响应信息为{json.dumps(r.json(), indent=2, ensure_ascii=False)}")

        # 断言
        assert res["errmsg"] == "成功"
 脚本优化-报告展示
  • 安装allure相关依赖
# 生成报告信息
pytest .\test_litemall.py --alluredir=./datas/report
# 生成报告在线服务,查看报告
allure serve ./datas/report

运行结果:

项目结构:

 

项目地址:https://gitee.com/coderPatrickStar/template/tree/master/python_software_testing

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

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

相关文章

scratch躲避陨石 2023年9月电子学会图形化编程scratch编程等级考试三级真题和答案解析

目录 scratch躲避陨石 一、题目要求 1、准备工作 2、功能实现 二、案例分析

【java学习—七】多态性(34)

文章目录 1. 概念2. 对象的多态2.1. 一2.2. 二 3. 虚拟方法的调用4. 总结 1. 概念 多态性,是面向对象中最重要的概念,在 java 中有两种体现: (1)方法的重载 (overload) 和重写 (overwrite) 。 重载:本类中…

Go TLS服务端绑定证书的几种方式

随着互联网的发展,网站提供的服务类型和规模不断扩大,同时也对Web服务的安全性提出了更高的要求。TLS(Transport Layer Security)[1]已然成为Web服务最重要的安全基础设施之一。默认情况下,一个TLS服务器通常只绑定一个证书[2],但…

GEE 18:基于GEE平台的土地荒漠化监测与分析【论文复现】

Desertification 1. 研究背景1.1 参考论文1.2 参数获取1.2.1 NDVI1.2.2 Albedo1.2.3 Normalizing indices1.2.4 Calculating the quantitative relationship1.2.5 Calculating DDI2. GEE2.1 数据2.2 GEE code2.2.1 Study region2.2.2 Reomove cloud for Landsat-82.2.3 Calcula…

Rollup failed to resolve import

问题描述 我在打包vue3的项目的时候报了以下错误 问题原因 打包时&#xff0c;静态资源目录没有识别出来&#xff0c;导致打包终止并报错 问题解决 需要把路径改为跟路径&#xff0c;就可以打包啦 错误资源路径写法 <img src"src/assets/image/底部导航背景/book2…

UE5蓝图-事件、函数、事件分发器

UE5蓝图中的事件、函数、事件分发器理解及学习 1 事件 蓝图的事件在事件图表中。 事件可以进行自定义。 1.1 首先自定义一个事件HelloUE 1.2 为事件指定具体的执行体 1.3 运行事件 1.4 绑定事件到 Actor被点击 先进行事件绑定&#xff0c;绑定完成后&#xff0c;BBBB被点击…

JAVA总结01

1.变量在定义的时候可以不赋初始值&#xff0c;但在使用的时候变量必须有值 2.数据类型 数据类型字节数整型byte1short2int4long8浮点型float4double8字符型char2布尔型boolean1 浮点数默认都是double类型 上面代码报错的原因就是5.0是double类型&#xff0c;不是float类型 当…

【随笔】论多线程CPU离线渲染器的实现:A CPU BASED OFFLINE RENDERING ENGINE

前言 小熊挺喜欢玩游戏的&#xff0c;对于游戏画面有所追求&#xff0c;记得高中第一次玩战地的时候&#xff0c;惊叹于画面细腻的表现&#xff0c;并且还能开坦克车&#xff0c;这样的事情深深吸引了我。我是一个画面党&#xff0c;为了追求更好的画质表现我开始研究设置面板…

windows server 2012 查看已打了哪些补丁

打开控制面板 点击卸载程序 点击 查看已安装的更新 下图是已安装的补丁

Java反射调用jar包

反射作为托管语言的特性&#xff0c;很多框架都依赖反射来实现容器和面向接口编程&#xff0c;对架构程序很重要&#xff0c;首先试验Java的反射部分。 首先创建一个ZLZJar的工程&#xff0c;让他打包成jar包&#xff0c;代码如下 public class Test {//加两个整数public int…

WAF绕过-漏洞发现之代理池指纹探针 47

工具 工具分为综合性的&#xff0c;有awvs&#xff0c;xray&#xff0c;单点的比如wpscan专门扫描wordpress的。而我们使用工具就可能会触发waf&#xff0c; 触发点 第一个就是扫描速度&#xff0c;太快了&#xff0c;可以通过演示&#xff0c;开代理池&#xff0c;白名单绕…

美国市场三星手机超苹果 中国第一属华为

报告显示&#xff0c;截至5月份的三个月&#xff0c;iOS系统在美国、澳大利亚以及日本表现不俗。Android系统份额则在英国、德国以及法国实现增长。在中国城市地区&#xff0c;iOS份额同比基本持平&#xff0c;而Android份额则达到80.5%&#xff0c;同比增长1个百分点。 三星在…

2023-2024-1 for循环-1(1-14)

7-1 求N分之一序列前N项和 本题要求编写程序&#xff0c;计算序列 1 1/2 1/3 ... 的前N项之和。 输入格式: 输入在一行中给出一个正整数N。 输出格式: 在一行中按照“sum S”的格式输出部分和的值S&#xff0c;精确到小数点后6位。题目保证计算结果不超过双精度范围。…

主流接口测试框架对比

公司计划系统的开展接口自动化测试&#xff0c;需要我这边调研一下主流的接口测试框架给后端测试&#xff08;主要测试接口&#xff09;的同事介绍一下每个框架的特定和使用方式。后端同事根据他们接口的特点提出一下需求&#xff0c;看哪个框架更适合我们。 需求 1、接口编写…

如何设计一个自动化测试平台

平台解决了什么问题 一般在企业内&#xff0c;技术团队如果规模比较小&#xff0c;很少会专门投入资源去做平台化的事情&#xff0c;特别是测试团队&#xff0c;无论是成本预算还是技术能力&#xff0c;先天技术能力不足&#xff0c;后天可投入的资源缺乏。 而平台的特点在于…

杭州亚运会用到哪些黑科技?

Spring实战系列文章&#xff1a; Spring实战 | Spring AOP核心秘笈之葵花宝典 Spring实战 | Spring IOC不能说的秘密&#xff1f; 国庆中秋特辑系列文章&#xff1a; 国庆中秋特辑&#xff08;八&#xff09;Spring Boot项目如何使用JPA 国庆中秋特辑&#xff08;七&#…

Studio one 6.5中文直装版最新版,一键安装丨无套路分享丨宿主软件丨机架直播

Studio One 6.5 具有最先进的沉浸式混音和集成的空间音频制作工作流程。还有新的插件&#xff0c;改进的乐谱功能和对 DAWproject 的支持。 PreSonus 的“.5”更新通常都有比较大的变化&#xff0c;这次也不例外。Studio One 6.5 增加了一种全新的工作方式&#xff0c;完全集成…

博弈论——博弈信息结构

博弈信息结构 0 引言 在一个博弈构成中&#xff0c;博弈信息结构是不可或缺要素。博弈信息&#xff0c;顾名思义&#xff0c;就是在博弈中&#xff0c;博弈方对于信息的了解。知己知彼&#xff0c;百战不殆。和短兵相接的战争一样&#xff0c;只有充分了解自己的优劣势&#x…

python---求面积练习:提示用户输入圆的半径,根据公式S = πr2求圆的面积

求面积练习&#xff1a;提示用户输入圆的半径&#xff0c;根据公式S πr2求圆的面积 r float(input(‘请输入要计算圆的半径&#xff1a;’)) PI 3.14 s PI * r ** 2 print(f’圆的面积为&#xff1a;{s}) r float(input(‘请输入要计算圆的半径&#xff1a;’)) ------…

NetSuite ERP系统健康检查

这个题目来自最近的一个项目感受&#xff0c;“上线即停滞”。这是在中小型企业十分普遍的一个情况&#xff0c;一旦上线后&#xff0c;基本上信息化的建设就停止了。这是一个中小企业信息化的一个特点&#xff0c;因为其IT力量比较弱&#xff0c;所以在信息化的推动中缺乏话语…