做测试,不会接口测试怎么能行?

news2024/9/22 15:41:53

接口测试的测试点

功能测试:单接口功能、业务场景功能

性能测试:响应时长、错误率、吞吐量、服务器资源使用率

安全测试:敏感数据是否加密、SQL注入、其他

本篇文章以接口功能测试为主。

接口用例设计方法:

单接口测试用例设计:

正向用例设计:

(1)必选参数。所有必选参数给正确数据

(2)组合参数:所有必选+任意可选,给正确数据

(3)全部参数:所有必选+所有可选,给正确参数

反向用例设计:

(1)功能异常:数据格式正确,不能履行接口功能

(2)数据异常:数据格式不正确(空格、特殊字符、字母、长度----等价类,边界值)

(3)参数异常:(多参、少参、无参、错误参数)

业务场景接口测试

(1)尽量模拟用户实际使用场景

(2)尽量用最少的用例,覆盖最多的接口请求

(3)一般情况下,覆盖正向的测试即可

案例1:登录接口用例设计(以下用例只是部分)

image.png

案例2:添加用户用例设计(以下用例只是部分)

image.png

接口测试工具-postman

关于postman的详细操作见:

接口测试工具之postman juejin.cn/post/695424…

使用requests库实现接口测试

Requests库 是 Python编写的,基于urllib 的 HTTP库,使用方便。

安装:pip install requests

或者指定国内镜像源安装:pip install requests -i https://pypi.douban.com/simple/

设置http请求语法

resp = requests.请求方法(url='URL地址', params={k:v}, headers={k:v},data={k:v}, json={k:v}, cookies='cookie数据'(如:令牌))

入门案例:访问百度接口

image.png

我们在练习过程中,可以使用开源商城tpshop来进行练习,具体安装在百度上搜索即可

案例:开源商城tpshop的登录接口

import requests

# 发送 post 请求,指定url、请求头、请求体,并获取响应结果
resp = requests.post(url="http://127.0.0.1/index.php?m=Home&c=User&a=do_login&t=0.04841131938292054",
                     headers={"Content-Type": "application/x-www-form-urlencoded"},
                     data={"username": "13012345678", "password": "1234567", "verify_code": "8888"})

# 打印响应结果 - 文本
print(resp.text)
# 打印响应结果 - json
print(resp.json())

案例:商城调用登录接口,增加cookie参数(tpshop项目:cookie+Session认证。

image.png

import requests

resp_v = requests.get(url="http://127.0.0.1/index.php?m=Home&c=User&a=verify&r=0.47350402574416184")

my_cookie = resp_v.cookies

resp = requests.post(url="http://127.0.0.1/index.php?m=Home&c=User&a=do_login&t=0.04841131938292054",
                     headers={"Content-Type": "application/x-www-form-urlencoded"},
                     data={"username": "18800000000", "password": "1234567", "verify_code": "8888"},
                     cookies=my_cookie)

print(resp.json())

image.png

以下方式是使用session认证,不需要获取cookie--掌握

import requests

# 1. 创建一个 Session 实例。
session = requests.session()
# 2. 使用 Session 实例,调 get方法,发送获取验证码请求。
session.get(url="http://127.0.0.1/index.php?m=Home&c=User&a=verify&r=0.47350402574416184")
# 3. 使用 同一个 Session 实例,调用 post方法,发送登录请求。
resp = session.post(url="http://127.0.0.1/index.php?m=Home&c=User&a=do_login&t=0.04841131938292054",
                    headers={"Content-Type": "application/x-www-form-urlencoded"},
                    data={"username": "18892089999", "password": "123456", "verify_code": "8888"})

print(resp.json())

面试题 Cookie 和 Session 区别

  1. 数据存储位置:

cookie存储在浏览器;session存储在服务器。

  1. 安全性:

cookie中的数据可以随意获取,没有安全性可言。Session的数据多为加密存储,安全较高!

  1. 数据类型:

cookie支持的数据类型受浏览器限制,较少;Session直接使用服务器存储,支持所有数据类型

  1. 大小:

cookie大小默认 4k; Session 大小约为服务器存储空间大小

Unittest框架集成Requests库

Unittest的相关详细知识见下面文档:

Python框架之UnitTest: juejin.cn/post/712533…

案例:登录接口,单个测试方法

import unittest
import requests


class TestLogin(unittest.TestCase):
    def test01_login(self):
        resp = requests.post(url="http://127.0.0.1/index.php?m=Home&c=User&a=do_login&t=0.04841131938292054",
                             headers={"Content-Type": "application/x-www-form-urlencoded"},
                             data={"username": "18892081111", "password": "123456", "verify_code": "8888"})
        print(resp.json())

        # 断言状态码
        self.assertEqual(200, resp.status_code)

        # 断言 success的值为True
        self.assertEqual(True, resp.json().get("success"))

PyMySQL操作数据库

应用场景:

校验测试数据:接口发送请求之后,明确会对数据库中的某个字段进行修改,但是响应结果中不体现

构造测试数据:比如测试数据使用一次就失败(用手机号添加员工);测试前,无法保证测试数据一定存在(比如:列表查询)

安装PyMySQLpip install PyMySQL

或者pip install PyMySQL -i https://pypi.douban.com/simple/

操作数据库的基本流程:

1、导包;import pymysql

2、创建数据库连接(connection);conn = pymysql.connect()

3、获取游标对象(cursor);cursor = conn.cursor()

4、执行操作;cursor.execute('sql语句')

(4.1)查询语句:不会对数据库产生影响,有结果集返回,使用fetch提取返回数据;

(4.2)增删改语句:会对数据库产生影响。成功:提交事务:conn.commit();失败:回滚事务:conn.rollback()

5、关闭游标对象(cursor);cursor.close()

6、关闭数据库连接(connection);conn.close()

案例:

# 1、导包;`
import pymysql
# 2、创建数据库连接(connection);`conn = pymysql.connect()
conn = pymysql.connect(host="localhost",port=3306,user="root",password="root",database="mysql",charset="utf8")
# 3、获取游标对象(cursor);`cursor = conn.cursor()
cursor = conn.cursor()
# 4、执行操作;`cursor.execute('sql语句')`
cursor.execute('select version()')
# 提取一行结果
res = cursor.fetchone()
print(res) # 返回元组
print(res[0]) #取返回的第一个值
# 5、关闭游标对象(cursor);`cursor.close()`
cursor.close()
# 6、关闭数据库连接(connection);`conn.close()`
conn.close()

常用方法说明:

fetchone():从结果集中提取一行

fetchmany(size):从结果集中提取size行

fetchall():提取所有结果集

属性rownumber:可以设置游标位置(cursor.rownumber = 0(设置游标归零))

数据库工具类封装:

(1)获取、关闭连接

import pymysql
# 封装数据库工具类
class DBUtil(object):
    # 添加类属性
    conn = None

    @classmethod
    def __get_conn(cls):
        # 判断 conn 是否为空, 如果是,再创建
        if cls.conn is None:
            cls.conn = pymysql.connect(host="localhost",port=3306,user="root",password="root",database="mysql",charset="utf8")
        # 返回非空连接
        return cls.conn

    @classmethod
    def __close_conn(cls):
        # 判断conn 不为空,需要关闭。
        if cls.conn is not None:
            cls.conn.close()
            cls.conn = None

(2)查询一条记录

# 常用方法:查询一条结果
    @classmethod
    def select_one(cls, sql):
        cursor = None
        res = None
        try:
            # 获取连接
            cls.conn = cls.__get_conn()
            # 获取游标
            cursor = cls.conn.cursor()
            # 执行 查询语句
            cursor.execute(sql)
            # 提取一条结果
            res = cursor.fetchone()
        except Exception as err:
            print("查询sql错误:", str(err))
        finally:
            # 关闭游标
            cursor.close()
            # 关闭连接
            cls.__close_conn()
            # 将查询sql执行的 结果,返回
            return res

if __name__ == '__main__':
    res = DBUtil.select_one("select * from person;")
    print("查询结果为:", res)

(3)增删改数据时方法封装

# 常用方法:增删改数据
    @classmethod
    def uid_db(cls, sql):
        cursor = None
        try:
            # 获取连接
            cls.conn = cls.__get_conn()
            # 获取游标
            cursor = cls.conn.cursor()
            # 执行 uid 语句
            cursor.execute(sql)
            print("影响的行数:", cls.conn.affected_rows())
            # 提交事务
            cls.conn.commit()
        except Exception as err:
            # 回滚事务
            cls.conn.rollback()
            print("增删改 SQL 执行失败:", str(err))
        finally:
            # 关闭游标
            cursor.close()
            # 关闭连接
            cls.__close_conn()

if __name__ == '__main__':
    DBUtil.uid_db("update person set age = 30 where id = 2;")

接口对象封装

核心思想:代码分层思想,分为接口对象层和测试脚本层

(1)接口对象层:对接口进行封装,封装好之后,给测试用例层调用,面向对象类封装实现。

(2)测试用例层:调用接口对象层封装的方法,获取响应结果,断言进行接口测试,借助unittest框架实现。

封装思想:

(1)将动态变化的数据设计到方法的参数;

(2)将固定不变的,直接写成方法的实现;

(3)将响应结果通过返回值传出;

我们以TPshop开源商城为例,在没有封装之前的代码为:

import unittest
import requests


class TestTpshopLogin(unittest.TestCase):
    # 测试登录成功
    def test01_login_ok(self):
        # 创建 session 实例
        session = requests.Session()
        # 使⽤实例,调⽤get 发送获取验证码请求
        session.get(url="http://127.0.0.1/index.php?m=Home&c=User&a=verify&r=0.47350402574416184")
        # 使⽤实例,调⽤post 发送登录请求
        resp = session.post(url="http://127.0.0.1/index.php?m=Home&c=User&a=do_login&t=0.04841131938292054",
                            headers={"Content-Type": "application/x-www-form-urlencoded"},
                            data={"username": "18892089999", "password": "123456", "verify_code": "8888"})
        print("响应结果 =", resp.json())
        # 断⾔:
        self.assertEqual(200, resp.status_code)
        self.assertEqual(1, resp.json().get("status"))
        self.assertEqual("登陆成功", resp.json().get("msg"))

    # 测试⼿机号不存在
    def test02_tel_not_exists(self):
        # 创建 session 实例
        session = requests.Session()
        # 使⽤实例,调⽤get 发送获取验证码请求
        session.get(url="http://127.0.0.1/index.php?m=Home&c=User&a=verify&r=0.47350402574416184")
        # 使⽤实例,调⽤post 发送登录请求
        resp = session.post(url="http://127.0.0.1/index.php?m=Home&c=User&a=do_login&t=0.04841131938292054",
                            headers={"Content-Type": "application/x-www-form-urlencoded"},
                            data={"username": "18892099999", "password": "123456", "verify_code": "8888"})
        print("响应结果 =", resp.json())
        # 断⾔:
        self.assertEqual(200, resp.status_code)
        self.assertEqual(-1, resp.json().get("status"))
        self.assertEqual("账号不存在!", resp.json().get("msg"))

    # 测试密码错误
    def test03_pwd_err(self):
        # 创建 session 实例
        session = requests.Session()
        # 使⽤实例,调⽤get 发送获取验证码请求
        session.get(url="http://127.0.0.1/index.php?m=Home&c=User&a=verify&r=0.47350402574416184")
        # 使⽤实例,调⽤post 发送登录请求
        resp = session.post(url="http://127.0.0.1/index.php?m=Home&c=User&a=do_login&t=0.04841131938292054",
                            headers={"Content-Type": "application/x-www-form-urlencoded"},
                            data={"username": "18892089999", "password": "999999", "verify_code": "8888"})
        print("响应结果 =", resp.json())
        # 断⾔:
        self.assertEqual(200, resp.status_code)
        self.assertEqual(-2, resp.json().get("status"))
        self.assertEqual("密码错误!", resp.json().get("msg"))

对以上代码进行封装:

封装接口对象层:

class TpshopLoginApi(object):

    # 发送验证码请求
    @classmethod
    def get_verify(cls, session):
        session.get(url="http://127.0.0.1/index.php?m=Home&c=User&a=verify&r=0.47350402574416184")

    # 发送登录请求
    @classmethod
    def login(cls, session, login_data):
        resp = session.post(
            url="http://127.0.0.1/index.php?m=Home&c=User&a=do_login&t=0.04841131938292054",
            data=login_data)
        return resp

断言方法封装:

def common_assert(self, resp, status_code, status, msg):
    # 断⾔:
    self.assertEqual(status_code, resp.status_code)
    self.assertEqual(status, resp.json().get("status"))
    self.assertEqual(msg, resp.json().get("msg"))

测试用例层封装结果:

import unittest
import requests
from TPshop_login_api import TpshopLoginApi
from tp_shop_assert import common_assert


class TestShopLogin(unittest.TestCase):
    # 添加类属性
    session = None

    @classmethod
    def setUpClass(cls) -> None:
        cls.session = requests.Session()

    def setUp(self) -> None:
        TpshopLoginApi.get_verify(self.session)

    # 测试登录成功
    def test01_login_ok(self):
        login_data = {"username": "18892089999", "password": "123456", "verify_code": "8888"}
        resp = TpshopLoginApi.login(self.session, login_data)
        print("登录成功的结果:", resp.json())
        common_assert(self, resp, 200, 1, "登陆成功")

    # 测试⼿机号不存在
    def test02_tel_not_exists(self):
        login_data = {"username": "18892099999", "password": "123456", "verify_code": "8888"}
        resp = TpshopLoginApi.login(self.session, login_data)
        print("登录成功的结果:", resp.json())
        # 断⾔:
        common_assert(self, resp, 200, -1, "账号不存在!")

    # 测试密码错误
    def test03_pwd_err(self):
        login_data = {"username": "18892089999", "password": "999999", "verify_code": "8888"}
        resp = TpshopLoginApi.login(self.session, login_data)
        print("登录成功的结果:", resp.json())
        # 断⾔:
        common_assert(self, resp, 200, -2, "密码错误!")

以上代码参数化:

# 参数化的数据,实际项目中需要单独保存
json_data = [
    {
        "req_body": {"username": "18892080505", "password": "123456", "verify_code": "8888"},
        "status_code": 200,
        "status": 1,
        "msg": "登陆成功"
    },
    {
        "req_body": {"username": "18892099999", "password": "123456", "verify_code": "8888"},
        "status_code": 200,
        "status": -1,
        "msg": "账号不存在!"
    },
    {
        "req_body": {"username": "18892080505", "password": "999999", "verify_code": "8888"},
        "status_code": 200,
        "status": -2,
        "msg": "密码错误!"
    }
]


# 封装函数,将 数据 转换为 元组列表。
def read_json_data():
    # 将[{},{},{},{}]格式转化成[(),(),(),()]
    list_data = []
    for item in json_data:
        tmp = tuple(item.values())
        list_data.append(tmp)

    print(list_data)
    return list_data

在通用方法中实现参数化:

class TestShopLogin(unittest.TestCase):
    # 添加类属性
    session = None

    @classmethod
    def setUpClass(cls) -> None:
        cls.session = requests.Session()

    def setUp(self) -> None:
        TpshopLoginApi.get_verify(self.session)

    # 测试登录
    @parameterized.expand(read_json_data())
    def test_tpshop_login(self, req_body, status_code, status, msg):
        resp = TpshopLoginApi.login(self.session, req_body)
        print("登录成功的结果:", resp.json())
        common_assert(self, resp, status_code, status, msg)

接口自动化测试框架思想

目录结构

5个目录、2个文件:

api/: 存储接口对象层(自己封装的 接口)

scripts/: 存储测试脚本层 (unittest框架实现的 测试类、测试方法)

data/: 存储 .json 数据文件

report/: 存储 生成的 html 测试报告

common/: 存储 通用的 工具方法

confifig.py: 存储项目的配置信息(全局变量)

run_suite.py: 组装测试用例、生成测试报告的 代码

日志

日志的级别

logging.DEBUG:调试级别【高】

logging.INFO:信息级别【次高】

logging.WARNING:警告级别【中】

logging.ERROR:错误级别【低】

logging.CRITICAL:严重错误级别【极低】

特性:日志级别设定后,只有比该级别低的日志会写入日志。

日志代码,无需手写实现。会修改、调用即可!

import logging.handlers
import logging
import time


def init_log_config(filename, when='midnight', interval=1, backup_count=3):
    # 1. 创建日志器对象
    logger = logging.getLogger()

    # 2. 设置日志打印级别
    logger.setLevel(logging.DEBUG)
    # logging.DEBUG 调试级别
    # logging.INFO 信息级别
    # logging.WARNING 警告级别
    # logging.ERROR 错误级别
    # logging.CRITICAL 严重错误级别

    # 3.1 创建 输出到控制台 处理器对象
    st = logging.StreamHandler()
    # 3.2 创建 输出到日志文件 处理器对象
    # when 字符串,指定日志切分间隔时间的单位。midnight:凌晨:12点。
    # interval 是间隔时间单位的个数,指等待多少个 when 后继续进行日志记录
    # backupCount 是保留日志文件的个数
    fh = logging.handlers.TimedRotatingFileHandler(filename, when=when, interval=interval, backupCount=backup_count, encoding='utf-8')

    # 4. 创建日志信息格式
    fmt = "%(asctime)s %(levelname)s [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s"
    formatter = logging.Formatter(fmt)

    # 5.1 日志信息格式 设置给 控制台处理器
    st.setFormatter(formatter)
    # 5.2 日志信息格式 设置给 日志文件处理器
    fh.setFormatter(formatter)

    # 6.1 给日志器对象 添加 控制台处理器
    logger.addHandler(st)
    # 6.2 给日志器对象 添加 日志文件处理器
    logger.addHandler(fh)


if __name__ == '__main__':
    # 初始化日志
    init_log_config('tp_shop_log.log', interval=3, backup_count=5)
    # 打印输出 日志信息
    logging.warning("这是警告日志的信息")
    logging.debug("这是debug日志信息")
    a = 9999
    logging.error(f"这是error级别的信息a = {a}")

全量字段的校验-对断言的补充

流程:

(1)定义json语法校验格式

(2)⽐对接口实际响应数据是否符合json校验格式

全量字段校验需要安装jsonschema

pip install jsonschema -i https://pypi.douban.com/simple/

在线工具校验:www.jsonschemavalidator.net

image.png

python代码入门:

# 1. 导包
import jsonschema

# 2. 创建校验规则
schema = {
  "type": "object",
  "properties": {
    "success": {
      "type": "boolean"
    },
    "code": {
      "type": "integer"
    },
    "message": {
      "type": "string"
    }
  },
  "required": ["success","code","message"]
}

# 准备待校验的数据
data = {
  "success": True,
  "code": 200,
  "message": "操作成功"
}

# 3. 调用 validate 方法,实现校验

result = jsonschema.validate(instance = data,schema=schema)
print("result = ", result)
# None: 代表校验通过
# ValidationError:数据与校验规则不符
# SchemaError: 校验规则语法有误

JSON Schema语法中常用的关键字(来源某视频课程):

image.png

(1)type关键字:约束数据类型

integer —— 整数
string —— 字符串
object —— 对象
array —— 数组 --> python:list 列表
number —— 整数/⼩数
null —— 空值 --> python:None
boolean —— 布尔值

语法:
{
    "type": "数据类型"
}

(2)properties关键字:是 type关键字的辅助。用于 type 的值为 object 的场景。指定对象中 每个字段的校验规则。 可以嵌套使用。

语法:
{
    "type": "object",
    "properties":{
    "字段名1":{规则},
    "字段名2":{规则},
......
}
}

(3)required关键字:校验对象中必须存在的字段。字段名必须是字符串,且唯⼀

语法:
{
"required": ["字段名1", "字段名2", ...]
}

(4)const关键字:校验字段值是⼀个固定值。

语法:
{
"字段名":{"const": 具体值}
}

(5)pattern关键字:指定正则表达式,对字符串进行模糊匹配

语法:

{
"字段名":{"pattern": "正则表达式"}
}

补充中......

行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

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

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

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

相关文章

在网上打印资料多少钱一张

随着互联网的普及和线上服务的完善,越来越多的人选择在网上打印资料。这种方式不仅方便快捷,而且通常价格更为透明和实惠。那么,在网上打印资料到底多少钱一张呢?这主要取决于您选择的打印平台、纸张规格、打印质量以及打印数量等…

SpringBoot的旅游管理系统+论文+ppt+免费远程调试

项目介绍: 基于SpringBoot旅游网站 旅游管理系统 本旅游管理系统采用的数据库是Mysql,使用SpringBoot框架开发。在设计过程中,充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。 (1&…

ModuleNotFoundError: No module named ‘llama_index.readers“解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Day55 动态规划 part15

Day55 动态规划 part15 392.判断子序列 我的思路: 自己还是只能想到双指针法 解答: class Solution {public boolean isSubsequence(String s, String t) {if(s.length() 0) {return true;}if(s.length() > t.length() || t.length() 0) {return false;}ch…

牛客小白月赛90(A,B,C,D,E,F)

比赛链接 官方题解(视频) 这场偏思维,感觉好像没啥算法。E需要动态维护前 k k k 小,F是个离散化加dp,状态和递推方程比较 非常规,建议还是看一下涨涨姿势。 A 小A的文化节 思路: 签到 cod…

都2024年了,还不知道怎么学习网络安全?来看看吧,很难找全的

前言 最近收到不少关注朋友的私信和留言,大多数都是零基础小友入门网络安全,需要相关资源学习。其实看过的铁粉都知道,之前的文里是有过推荐过的。新来的小友可能不太清楚,这里就系统地叙述一遍。 01.简单了解一下网络安全 说白…

CUDA编程---全局内存

CUDA内存模型概述 内存的访问和管理是所有编程语言的重要部分。在现代加速器中,内存管理对高性能计算有着很大的影响。因为多数工作负载被加载和存储数据的速度所限制,所以有大量低延迟、高带宽的内存对性能是十分有利的。 然而,大容量、高性…

如何做信创测试

信创测试是一种系统化的方法,旨在评估和验证创意和创新项目的潜力和可行性。进行信创测试可以帮助企业在投入大量资源之前,对创意进行客观、科学的评估,以减少失败的风险并最大化成功的可能性。以下是一般性的信创测试步骤: 确定…

Linux的学习之路:11、地址空间

摘要 本章主要是说一下地址空间,我也只是按照我的理解进行解释,可能说不清楚,欢迎指正 目录 摘要 一、空间布局图 二、代码测试一下 三、进程地址空间 四、测试代码 一、空间布局图 如下方图片可以看出地址空间有几种,这里…

成都欣丰洪泰文化传媒有限公司领航电商新纪元

在当今数字化飞速发展的时代,电商行业异军突起,成为推动经济增长的重要力量。在这股浪潮中,成都欣丰洪泰文化传媒有限公司以其专业的电商服务脱颖而出,成为业界的佼佼者。本文将带您一探这家公司的独特魅力和专业服务,…

MySQL查看表大小

1、使用SHOW TABLE STATUS命令: SHOW TABLE STATUS LIKE table_name;上述命令会返回包含表格信息的一行结果,其中有一个列为Data_length,表示表格占用的数据空间大小(以字节为单位)。 2、使用INFORMATION_SCHEMA库的…

Docker 学习笔记(五):梳理 Docker 镜像知识,附带 Commit 方式提交镜像副本,安装可视化面板 portainer

一、前言 记录时间 [2024-4-10] 前置文章: Docker学习笔记(一):入门篇,Docker概述、基本组成等,对Docker有一个初步的认识 Docker学习笔记(二):在Linux中部署Docker&…

吴恩达2022机器学习专项课程(一) 第二周课程实验:使用 scikit-learn 进行线性回归(Lab_05 Lab_06)

目标 使用scikit-learn实现线性回归(SGDRegressor和LinearRegression)。 1.什么是scikit-learn? 一个用于 Python 编程语言的开源机器学习库,用于实现各种机器学习算法。 2.特征缩放(Z标准化) 第一步先使用Z标准化处理训练样本,减少训练…

人员聚集监测识别摄像机

随着科技的不断发展,人员聚集监测识别摄像机已经成为了现代社会安全管理的重要工具。这种摄像机能够对人员聚集的情况进行实时监测和识别,帮助相关部门及时发现和处理潜在的安全风险。 人员聚集监测识别摄像机可以通过高清晰度的摄像头和先进的人脸识别技…

使用DockerCompose配置基于哨兵模式的redis主从架构集群

文章目录 一、注意事项(坑点!!!)二、配置Redis主从架构集群第一步:创建目录文件结构第二步:编写DockerCompose配置文件第三步:编写redis.conf第四步:启动redis主从集群 三…

LeetCode 59.螺旋矩阵II

LeetCode 59.螺旋矩阵II 1、题目 力扣题目链接:59. 螺旋矩阵 II - 力扣(LeetCode) 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1…

02_按键控制LED

按键控制LED 按键控制LED 按键控制LED while (1){//按键控制LEDif(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_5)GPIO_PIN_RESET)//读取PC5引脚状态,即检测按键是否按下{while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_5)GPIO_PIN_RESET);//松手检测HAL_GPIO_WritePin(GPIOA,GPIO_PI…

使用IT-Tools+Cpolar在Windows搭建自己的IT工具箱并实现远程在线使用

文章目录 1. 使用Docker本地部署it-tools2. 本地访问it-tools3. 安装cpolar内网穿透4. 固定it-tools公网地址 本篇文章将介绍如何在Windows上使用Docker本地部署IT- Tools,并且同样可以结合cpolar实现公网访问。 在前一篇文章中我们讲解了如何在Linux中使用Docker搭…

Java-多线程-并发知识点02(面试/学习)

本文主要介绍了Java多线程中的线程池、Java中的锁、synchronized锁及相关问答等知识点 Java-多线程-并发知识点02 线程池如何创建线程池使用 ThreadPoolExecutor 类创建线程池使用 Executors 工厂类创建线程池 线程池有些什么参数?线程池的使用方法线程池常用的阻塞…

测试知识1

瀑布模型 瀑布模型是一个经典的软件开发生命周期模型,它将开发过程分为一系列顺序执行的阶段,每个阶段都有特定的任务和产出物。这些阶段通常包括需求分析、系统设计、实现、测试、部署和维护等。 在瀑布模型中,每个阶段的输出都作为下一个…