接口测试(十)—— telnet和python代码测试dubbo接口

news2024/9/23 11:17:53

目录

一、传智健康项目介绍

1、项目描述

2、目标用户群体

3、项目模块

4、系统框架

二、Dubbo接口测试

1、RPC

2、Dubbo

3、查阅API文档

三、Telnet工具远程调用

1、启用telnet

2、telnet远程连接服务

3、telnet调用服务接口

四、python借助dubbo远程调用

1、安装dubboclient

2、实现步骤

3、会员服务(入门)

4、其他模块

5、分析bug来源

6、现有问题

五、接口自动化测试框架封装Dubbo接口

1、核心模块

2、基础服务对象封装

3、服务对象封装

4、测试用例对象封装

5、参数化

6、接口自动化框架封装

7、测试报告


一、传智健康项目介绍

1、项目描述

传智健康管理系统,是一款应用于健康管理机构的业务系统。采用可视化界面管理,提高健康管理师工作效率,加强与患者间的互动。

项目地址:传智健康

2、目标用户群体

3、项目模块

会员服务、预约服务、体检报告服务、健康评估服务、健康干预服务 

4、系统框架

前端:http://mobile-health-test.itheima.net
后端:http://manager-health-test.itheima.net
 

 

二、Dubbo接口测试

1、RPC

  • 远程过程调用(Remote Procedure Call):像调用本地方法一样,调用远程方法。
  • 常见的RPC框架有 Dubbo、Thrift、grpc 

2、Dubbo

  • Dubbo是一款高性能、轻量级、基于Java的开源RPC框架(最早由阿里开源,2018年贡献给了Apache组织)
  • Dubbo接口的作用:远程调用 java 写的方法。 需要传参、获取返回值。

3、查阅API文档

从中获取哪些信息?

  • 服务名
  • 方法名
  • 参数类型、返回值类型

java中 方法定义语法结构
返回值类型 方法名(数据类型 形参1,数据类型 形参2,....)
void:代表没有返回值、没有参数。

三、Telnet工具远程调用

1、启用telnet

2、telnet远程连接服务

连接语法:telnet IP 端口号

 

3、telnet调用服务接口

命令格式:invoke 服务名.方法名(实参)
示例:invoke MemberService.findByTelephone("13020210001")

四、python借助dubbo远程调用

Dubboclient,封装了 telnetlib 库。 telnetlib 是 python 内置模块,可实现远程调用 Dubbo 接口 

1、安装dubboclient

pip install dubboclient

查验:

  • 在 pip 中:pip list 或 pip show dubboclient
  • 在 pycharm中:file - settings - 项目名下的 python 解释器列表

2、实现步骤

1. 导包 from dubboclient import DubboClient
2. 创建 DubboClient类实例,指定 IP 和 port
3. 使用 实例调用 invoke() 方法。 传入 :服务名、方法名、实参(方法使用)。获取响应结果
4. 打印响应结果

3、会员服务(入门)

3.1 案例1

根据手机号,查询会员信息(传递 普通参数)

dubbo> ls -l MemberService
        com.itheima.pojo.Member findByTelephone(java.lang.String)

接口定义:Member findByTelephone(String telephone)

参数:
    字符串格式手机号。唯一
返回值:
    成功:返回 会员的信息内容。string类型 包裹的 字典数据。
    失败:返回 null。string类型

 实现代码:

# 1. 导包 from dubboclient import DubboClient
from dubboclient import DubboClient

# 2. 创建 DubboClient类实例,指定 IP 和 port
dubboclt = DubboClient("211.103.136.244", 6502)

# 3. 使用 实例调用 invoke() 方法。 传入 :服务名、方法名、实参(方法使用)。获取响应结果
resp = dubboclt.invoke("MemberService", "findByTelephone", "13020210001")

# 4. 打印响应结果
print("响应结果 =", resp)
print("type(resp) =", type(resp))

3.2 案例2

添加会员(传递 对象参数)

dubbo> ls -l MemberService
        void add(com.itheima.pojo.Member)

接口定义:void add(Member member)

参数:
    1. 自定义类 做 参数,根据接口文档,组织 “字典” 格式数据传参
    2. 给字典增加 键k:”class“ ,值v:指明 类 对应的 完整 包名和类名
        如:"class”:"com.itheima.pojo.Member"
        ls -l MemberService 可以查看完整包名和类名。
        区分自定义类: 包名不以“java.”开头。一般采用:com.公司名.项目名.类名
返回值:
    成功:返回 null
    失败:返回 Failed

 实现代码:

# 1. 导包
from dubboclient import DubboClient

# 2. 创建 dubboclient 实例
dubboclt = DubboClient("211.103.136.244", 6502)
# 准备 add 方法,所需要的数据
info = {"id": 911, "name": "杜甫", "phoneNumber": "13048379884"}
# 如果 class 已经存在,覆盖原有class值; 如果不存在 class,新增一组 元素到 字典中。
info["class"] = "com.itheima.pojo.Member"

# 3. 调用 invoke 传 服务名、方法名、实参。得响应结果
resp = dubboclt.invoke("MemberService", "add", info)

# 4. 打印
print("响应结果 =", resp)
print("type(resp) =", type(resp))

3.3 案例3

根据日期统计会员数(传递 字符串列表)

dubbo> ls -l MemberService
        java.util.List findMemberCountByMonths(java.util.List)

接口定义:List<Integer> findMemberCountByMonths(List<String> months)

参数:
    1. 字符串列表。用字符串表示年、月,用“.”衔接
    如:["2021.3", "2021.9"]
返回值:
    成功:返回列表,对应参数设置的月份的会员数。
    失败:Failed

 实现代码:

# 1. 导包
from dubboclient import DubboClient

# 2. 创建 dubboclient 实例
dubboclt = DubboClient("211.103.136.244", 6502)

# 3. 用实例 调用invoke() ,传入 服务名、方法名、实参。 得响应结果
months = ["2021-7"]
resp = dubboclt.invoke("MemberService", "findMemberCountByMonths", months)

# 4. 查看响应结果
print("响应结果 =", resp)
print("type(resp) =", type(resp))

4、其他模块

4.1 添加预约设置

dubbo> ls -l OrderSettingService
        void add(java.util.List)

接口定义:void add(List<OrderSetting> list)

参数:
    1. 字典列表。字典有 orderDate 和 number 两个字段。
        如:[{"orderDate":"2021-09-20 16:45:12","number":20}]
    2. 日期格式:"2021-09-20 16:45:12",必须包含时分秒,否则失败。

返回值:
    成功:null
    失败:Failed

 实现代码:

# 1. 导包
from dubboclient import DubboClient

# 2. 创建 dubboclient 实例
dubboclt = DubboClient("211.103.136.244", 6502)
# 准备 add 方法,所需要的数据
info = [{"orderDate": "2021-05-18 18:89:02", "number": 346}]

# 3. 调用 invoke 传 服务名、方法名、实参。得响应结果
resp = dubboclt.invoke("OrderSettingService", "add", info)

# 4. 打印
print("响应结果 =", resp)
print("type(resp) =", type(resp))

4.2 按月统计预约设置信息

dubbo> ls -l OrderSettingService
        java.util.List getOrderSettingByMonth(java.lang.String)

接口定义:List getOrderSettingByMonth(String date)

参数:
    字符串,如:"2021-09"

返回值:
    成功:返回字符串类型数据,字符串内容为列表
    失败:Failed

 实现代码:

# 1. 导包
from dubboclient import DubboClient

# 2. 创建 dubboclient 实例
dubboclt = DubboClient("211.103.136.244", 6502)
# 月份
moths = "2021.02"

# 3. 调用 invoke 传 服务名、方法名、实参。得响应结果
resp = dubboclt.invoke("OrderSettingService", "getOrderSettingByMonth", moths)

# 4. 打印
print("响应结果 =", resp)
print("type(resp) =", type(resp))

4.3 根据日期修改预约设置数量

dubbo> ls -l OrderSettingService
        void editNumberByDate(com.itheima.pojo.OrderSetting)

接口定义:void editNumberByDate(OrderSetting orderSetting)

参数:
    1. 自定义类,用 字典 根据接口文档组织数据
    2. 需要使用 class 指定参数对象的类型
    如:{"orderDate":"2021-10-13 21:04:33","number":15,
"class":"com.itheima.pojo.OrderSetting"}
    3. 日期格式为:"2021-10-13 21:04:33",必须包含时分秒

返回值:
    成功:null
    失败:Failed

实现代码:

# 1. 导包
from dubboclient import DubboClient

# 2. 创建 dubboclient 实例
dubboclt = DubboClient("211.103.136.244", 6502)
# 日期 和 设置数据
date = {"orderDate": "2021-06-15 16:99:77", "number": 120}
date["class"] = "com.itheima.pojo.OrderSetting"

# 3. 调用 invoke 传 服务名、方法名、实参。得响应结果
resp = dubboclt.invoke("OrderSettingService", "editNumberByDate", date)

# 4. 打印
print("响应结果 =", resp)
print("type(resp) =", type(resp))

4.4 根据用户名查询用户信息

dubbo> ls -l UserService
        com.itheima.pojo.User findByUsername(java.lang.String)

接口定义:User findByUsername(String username)

参数:字符串类型,如:'admin'

返回值:
    用户存在:返回用户信息
    用户不存在:返回 null

 实现代码:

# 1. 导包
from dubboclient import DubboClient

# 2. 创建 dubboclient 实例
dubboclt = DubboClient("211.103.136.244", 6502)
# 管理用户名
name = "admin"

# 3. 调用 invoke 传 服务名、方法名、实参。得响应结果
resp = dubboclt.invoke("UserService", "findByUsername", name)

# 4. 打印
print("响应结果 =", resp)
print("type(resp) =", type(resp))

5、分析bug来源

抓取接口数据,分析bug是前端还是后端。

6、现有问题

远程调用的 7个dubbo接口 存在的问题:
1. 代码有 大量冗余
2. 测试接口时,除了要给 测试数据之外, 还需要 指定 服务名、方法名
3. 传参时,除了要考虑测试数据外,还要分析是否要添加 class 字段 及 对应数据。
4. 返回的数据类型统一为 string(不具体)


封装目标
1. 只关心:测试数据、响应结果
2. 返回的结果 分别为 不同的 具体类型。

五、接口自动化测试框架封装Dubbo接口

1、核心模块

2、基础服务对象封装

from dubboclient import DubboClient

class BaseService(object):

    def __init__(self):
        self.dubbo_client = DubboClient("211.103.136.244", 6502)

3、服务对象封装

3.1 会员服务封装

"""
类名:MemberService,继承于 BaseService
实例属性:
    服务名称:service_name,赋值为 'MemberService'
实例方法:
    def __init__(self):
        # 先调父类__init__(),再添加实例属性 service_name

    def find_by_telephone(self, telephone):
        # 功能:根据手机号查询会员信息
        # :param telephone: 手机号
        # :return: 1. 会员存在,返回会员信息 2. 会员不存在,返回None

    def find_member_count_by_months(self, data_list):
        # 功能:根据日期统计会员数
        # :param date_list: 日期列表,格式如:["2021.7"]
        # :return: 返回列表,列表元素为对应月份的会员数,如:[10]

    def add(self, info): 添加会员
        # 功能:添加会员
        # :param info: 会员信息的字典格式数据,参考接口文档填入字段数据,手机号需要唯一
        # 如:{"fileNumber":"D0001", "name":"李白", "phoneNumber":"13020210002"}
        # :return: 添加成功返回True, 添加失败返回False

验证结果:
    # 1. 实例化对象
    # 2. 通过实例对象调用实例方法
    # 2.1 根据手机号查询会员信息
    # 2.2 根据日期统计会员数
    # 2.3 添加会员
"""
import json
from day02.base_service import BaseService

# 将 会员服务 封装成 会员服务类
class MemberService(BaseService):
    def __init__(self):
        super().__init__() # 调用父类 init 方法
        self.service_name = "MemberService"

    def find_by_telephone(self, tel):
        resp = self.dubbo_client.invoke(self.service_name, "findByTelephone", tel)
        if resp == "null":
            return None
        else:
            # 作用:将 string类型的 数据,还原回成 字典 或 列表 数据。
            return json.loads(resp)

    def find_member_count_by_months(self, months):
        resp = self.dubbo_client.invoke(self.service_name, "findMemberCountByMonths", months)
        # 作用:将 string类型的 数据,还原回成 字典 或 列表 数据。
        return json.loads(resp)

    def add(self, info):
        """
        :param info: 代表 用户 传入的 测试数据,没有 class 元素
        :return:
        """
        # 如果 class 已经存在,覆盖原有class值; 如果不存在 class,新增一组 元素到 字典中。
        info["class"] = "com.itheima.pojo.Member"
        # 3. 调用 invoke 传 服务名、方法名、实参。得响应结果
        resp = self.dubbo_client.invoke(self.service_name, "add", info)
        if resp == "null":
            return True
        else:
            return False

if __name__ == '__main__':
    ms = MemberService()
    resp = ms.find_by_telephone("13020210001")
    print("响应结果 =", resp)
    print("type(resp) =", type(resp))

    print("=" * 66)

    months = ["2021-6"]
    ms = MemberService()
    resp = ms.find_member_count_by_months(months)
    print("响应结果 =", resp)
    print("type(resp) =", type(resp))

    print("&" * 66)

    # 准备 add 方法,所需要的数据
    info = {"id": 911, "name": "杜甫", "phoneNumber": "13048379041"}
    ms = MemberService()
    resp = ms.add(info)
    print("响应结果 =", resp)
    print("type(resp) =", type(resp))

3.2 预约设置服务封装

"""
类名:OrderSettingService,继承于 BaseService
实例属性:
    服务名称:service_name,赋值为 'OrderSettingService'
实例方法:
    def __init__(self):
        # 先调父类__init__(),再添加实例属性 service_name

    def add(self, date_list):
        # 功能:添加预约设置
        # :param date_list:
            # 1. 日期列表,如:[{"orderDate":"2021-09-20 16:45:12","number":20}]
            # 2. 日期格式为:"2021-09-20 16:45:12",必须包括时分秒
        # :return: 设置成功返回True, 设置失败返回False

    def get_order_setting_by_month(self, date):
        # 功能:按月统计预约设置信息
        # :param date: 日期,如:"2021-08"
        # :return: 列表,指定月份的预约信息

    def edit_number_by_date(self, info): 根据日期修改预约设置数量
        # 功能:根据日期修改预约设置数量
        # :param info:
            # 1. 预约设置的字典格式数据,参考接口文档填入字段数据
            # 2. 如:{"orderDate":"2021-09-19 17:45:12","number":15}
            # 3. 日期格式为:"2021-09-19 17:45:12",必须包括时分秒
            # 4. 添加 "class":"com.itheima.pojo.OrderSetting"
        # :return: 修改成功返回 True, 修改失败返回 False
验证结果:
    # 1. 实例化对象
    # 2. 通过实例对象调用实例方法
    # 2.1 添加预约设置
    # 2.2 按月统计预约设置信息
# 2.3 根据日期修改预约设置数量
"""
import json
from day02.base_service import BaseService

# 封装 预约设置服务类
class OrderSettingService(BaseService):
    def __init__(self):
        super().__init__()
        self.service_name = "OrderSettingService"

    def add(self, date_list):
        # 功能:添加预约设置
        # :param date_list:
            # 1. 日期列表,如:[{"orderDate":"2021-09-20 16:45:12","number":20}]
            # 2. 日期格式为:"2021-09-20 16:45:12",必须包括时分秒
        # :return: 设置成功返回 True, 设置失败返回 False
        resp = self.dubbo_client.invoke(self.service_name, "add", date_list)
        if resp == "Failed":
            return False
        else:
            return True

    def get_order_setting_by_month(self, month):
        # 功能:按月统计预约设置信息
        # :param months: 日期,如:"2021-08"
        # :return: 列表,指定月份的预约信息
        resp = self.dubbo_client.invoke(self.service_name, "getOrderSettingByMonth", month)
        if resp == "Failed":
            return None
        else:
            return json.loads(resp)

    def edit_number_by_date(self, date):
        # 功能:根据日期修改预约设置数量
        # :param info:
            # 1. 预约设置的字典格式数据,参考接口文档填入字段数据
            # 2. 如:{"orderDate":"2021-09-19 17:45:12","number":15}
            # 3. 日期格式为:"2021-09-19 17:45:12",必须包括时分秒
            # 4. 添加 "class":"com.itheima.pojo.OrderSetting"
            # :return: 修改成功返回 True, 修改失败返回 False
        date["class"] = "com.itheima.pojo.OrderSetting"
        # 3. 调用 invoke 传 服务名、方法名、实参。得响应结果
        resp = self.dubbo_client.invoke(self.service_name, "editNumberByDate", date)
        if resp == "Failed":
            return False
        else:
            return True

if __name__ == '__main__':
    oss = OrderSettingService()

    # 准备 add 方法,所需要的数据
    info = [{"orderDate": "2021-05-18", "number": 346}]
    resp = oss.add(info)
    print("响应结果 =", resp)
    print("type(resp) =", type(resp))

    print("============== 按月统计预约设置信息 ===========")
    oss = OrderSettingService()
    # 月份
    months = "2021.02"
    resp = oss.get_order_setting_by_month(months)
    print("响应结果 =", resp)
    print("type(resp) =", type(resp))

    print("============== 根据日期修改预约设置数量 ===========")
    # 日期 和 设置数据
    date = {"orderDate": "2021-06-15 16:99:77", "number": 120}
    oss = OrderSettingService()
    resp = oss.edit_number_by_date(date)
    print("响应结果 =", resp)
    print("type(resp) =", type(resp))

3.3 用户服务封装

"""
类名:UserService,继承于BaseService
实例属性:
    服务名称:service_name,赋值为'UserService'
实例方法:
    def __init__(self):
        # 先调父类__init__(),再添加实例属性 service_name

    def find_by_username(self, username):
        # 功能:根据用户名查询用户信息
        # :param username: 用户名
        # :return: 1. 如果用户存在,返回用户信息 2. 如果不存在,返回 None
验证结果:
    # 1. 实例化对象
    # 2. 通过实例对象调用实例方法
"""
import json
from day02.base_service import BaseService

# 封装 用户服务类
class UserService(BaseService):
    def __init__(self):
        super().__init__()

    def find_by_user_name(self, name):
        # 3. 调用 invoke 传 服务名、方法名、实参。得响应结果
        resp = self.dubbo_client.invoke("UserService", "findByUsername", name)
        if resp == "null":
            return None
        else:
            return json.loads(resp)

if __name__ == '__main__':
    # 管理员用户名
    name = "李白"
    us = UserService()
    resp = us.find_by_user_name(name)
    print("响应结果 =", resp)
    print("type(resp) =", type(resp))

4、测试用例对象封装

import unittest
# 借助 unittest 框架,封装测试类,从 TestCase 继承
from day02.py02_会员服务类封装设计 import MemberService

class TestFindByTelephone(unittest.TestCase):
    ms = None
    @classmethod
    def setUpClass(cls) -> None:
        # 创建MemberService实例
        cls.ms = MemberService()

    def test01_tel_exists(self):
        tel = "13020210001"
        resp = self.ms.find_by_telephone(tel)
        print("手机号存在 =", resp)
        self.assertEqual("13020210001", resp.get("phoneNumber"))

    def test02_tel_not_exists(self):
        tel = "13020218973"
        resp = self.ms.find_by_telephone(tel)
        print("手机号不存在 =", resp)
        self.assertEqual(None, resp)

    def test03_tel_has_special_char(self):
        tel = "1302021abc#"
        resp = self.ms.find_by_telephone(tel)
        print("手机号含有字母特殊字符 =", resp)
        self.assertEqual(None, resp)

5、参数化

1. 导包 from parameterized import parameterized
2. 在 通用测试方法上一行,@parameterized.expand()
3. 给 expand() 传入 [(),(),()] 类型的数据。
4. 修改 通用测试方法,添加形参,个数、顺序与 () 数据一致。
5. 在 通用测试方法 使用形参

import unittest
from day02.py02_会员服务类封装设计 import MemberService
from parameterized import parameterized
# 借助 unittest 框架,封装测试类,从 TestCase 继承
class TestMemberService(unittest.TestCase):
    ms = None
    @classmethod
    def setUpClass(cls) -> None:
        cls.ms = MemberService() # 创建MemberService实例

    # 通用测试方法(参数化)
    @parameterized.expand([("13020210001", "13020210001"),
                            ("13020218973", None),
                            ("1302021abc#", None)])
    def test_findByTelephone(self, tel, except_data):
        # print("tel =", tel, "except_data =", except_data)
        resp = self.ms.find_by_telephone(tel)
        if resp is None:
            self.assertEqual(None, resp)
        else:
            self.assertEqual(except_data, resp.get("phoneNumber"))

    @parameterized.expand([(["2021.5"], [3]),
                            (["2017.4"], [0])])
    def test_findMemberCountByMonths(self, month, except_data):
        resp = self.ms.find_member_count_by_months(month)
        print("============ resp =============", resp)
        self.assertEqual(except_data, resp)

6、接口自动化框架封装

7、测试报告

# 导包
import unittest
from htmltestreport import HTMLTestReport

# 创建 suite 实例
from scripts.test_member_service import TestMemberService
suite = unittest.TestSuite()

# 添加测试用例
suite.addTest(unittest.makeSuite(TestMemberService))

# 创建 HTMLTestReport 类对象
runner = HTMLTestReport("./report/传智健康测试报告.html", description="描述", title="标题")

# 调用 run() 传入 suite
runner.run(suite)

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

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

相关文章

MySQL~JDBC

10、JDBC&#xff08;重点&#xff09; 10.1、数据库驱动 驱动&#xff1a;声卡、显卡、数据库 我们的程序会通过 数据库 驱动&#xff0c;和数据库打交道&#xff01; 10.2、JDBC SUN公司为了简化 开发人员的&#xff08;对数据库的统一&#xff09;操作&#xff0c;提供了…

剑指offer常见题 - 链表问题(一)

二叉树相关算法 链表相关知识点&#xff1a; 链表是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 知识点一&#xff1a;链表由一系列结点&#xff08;链表中每一个元素称为结点&#xff09;组成&#xff0c;…

IDEA中如何使用Vim?看完本教程,让你用IDEA用到爽~(建议收藏)

目录 前言 Vim有什么特点&#xff1f; 为什么我要安利你在 IEAD 中使用Vim? Vim 一、环境配置 二、Vim的使用 2.1、方向键 hjkl 2.2、​编辑复制&粘贴 2.3、选择代码块并删除 2.4、块级删除 2.5、各种插入模式 2.5.1、以下是gif演示 2.6、jump&#xff08;解放鼠…

毕业设计 stm32智能电子秤系统 - 物联网 嵌入式 单片机

文章目录0 前言1 简介2 主要器件3 实现效果4 设计原理4.1 STM32F103C8T64.2 HX711压力传感器5 部分核心代码6 最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&…

【OpenCV】Ubuntu配置OpenCV环境

1.从官网下载opencv包拷贝到虚拟机Ubuntu中&#xff0c; 虚拟机与主机传输文件可以采用 vmware tool、共享文件夹或者远程连接工具 2.解压得到对应版本号文件夹&#xff0c;我的是opencv-3.4.2 3.修改文件权限chmod -R 777 opencv-3.4.2 从win10进入Ubuntu中的文件压缩包解…

2022年云南省—信息安全管理与评估赛项竞赛规程

2022年云南省职业院校技能大赛 信息安全管理与评估赛项竞赛规程 一、赛项名称 赛项编号&#xff1a;No.11 赛项名称&#xff1a;信息安全管理与评估 英语翻译&#xff1a;Information Security Management and Evaluation 赛项组别&#xff1a;高职组 赛项归属产业&a…

本周大新闻|John Carmack从Meta离职,OPPO发布双目AR一体机仅38g

本周大新闻&#xff0c;AR方面&#xff0c;微软已向客户承诺新款HoloLens&#xff1b;NASA成立Joint AR项目&#xff0c;计划在宇航服头盔中加入AR功能&#xff1b;OPPO Air Glass 2发布&#xff0c;双目光波导仅38g&#xff1b;Rokid开设全球首家品牌旗舰店&#xff1b;谷歌为…

【数据结构】二叉树的节点总个数、叶子节点个数、第K层节点个数、二叉树的深度

目录 1.结点总个数 1.1 局部静态变量法 思维 代码 不足之处 2.传指针法 程序代码 3.递归法 思想 程序代码 详细过程 2.叶子节点个数 思想 程序代码 3.第K层节点个数 思想 程序代码 4.二叉树深度 思想 程序代码 求二叉树节点总个数、叶子节点个数、第k层节点…

汀丶的创作纪念日

机缘 csdn的博龄5年了&#xff0c;但实际创作时间只有两年&#xff1b;第一次接触csdn主要是用来查找代码bug并收藏一些有价值博客&#xff0c;但渐渐地自己也就习惯把自己学到的知识和技术分享出来&#xff0c;一起共建。 主要是关于机器学习、强化学习、数据挖掘、强化学习以…

ADI Blackfin DSP处理器-BF533的开发详解62:DSP控制ADXL345三轴加速度传感器-贪食蛇游戏(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 MEMS三轴加速度传感器 我做了一个三轴加速度传感器的子卡&#xff0c;插在这个板子上&#xff0c;然后写了一些有意思的应用程序。 代码实现功能…

Bootstrap5 侧边栏导航(Offcanvas)

Bootstrap5 侧边栏侧边栏类似于模态框&#xff0c;在移动端设备中比较常用。 创建滑动导航 我们可以通过 JavaScript 来设置是否在 .offcanvas 类后面添加 .show 类&#xff0c;从而控制侧边栏的显示与隐藏&#xff1a; .offcanvas 隐藏内容 (默认).offcanvas.show 显示内容…

JVM之native关键字与PC寄存器

native关键字&#xff1a; native关键字主要用于修饰方法&#xff1a; 被native关键字修饰的方法叫做本地方法&#xff0c;一个native方法就是一个Java调用非Java代码的接口&#xff0c;该方法的实现由非Java语言实现&#xff0c;而是使用C或C等其他编程语言实现 native方法…

Compose 和 Android 传统View 互相调用

1. 前言 Compose 具有超强的兼容性&#xff0c;兼容现有的所有代码&#xff0c;Compose 能够与现有 View 体系并存&#xff0c;可实现渐进式替换。这就很有意义了&#xff0c;我们可以在现有项目中一小块一小块逐步地替换Compose&#xff0c;或者在旧项目中实现新的需求的时候…

设计模式之外观模式

Facade design pattern 外观模式的概念、外观模式的结构、外观模式的优缺点、外观模式的使用场景、外观模式的实现示例、外观模式的源码分析 1、外观模式的概念 外观模式&#xff0c;为多个复杂的子系统提供一个统一的接口&#xff0c;使得这些子系统更加容易被访问。在现有的…

【AI with ML】第 11 章 :对序列模型使用卷积和递归方法

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

SAP Gateway Foundation 里的 batch 操作

SAP Gateway Foundation (SAP_GWFND) 是一个在 SAP NetWeaver 中可用的软件组件。 SAP Gateway Foundation 提供开发和生成工具来为各种客户端开发工具创建 OData 服务。 简而言之&#xff0c;它在应用程序或 SAP Business Suite 数据与目标客户、平台和编程框架之间建立连接。…

核心面试题:MVCC、间隙锁、Undo Log链、表级锁、行级锁、页级锁、共享锁、排它锁、记录锁等等

文章很长&#xff0c;而且持续更新&#xff0c;建议收藏起来&#xff0c;慢慢读&#xff01;疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 &#xff1a; 免费赠送 :《尼恩Java面试宝典》 持续更新 史上最全 面试必备 2000页 面试必备 大厂必备 涨薪必备 免费赠送 经典…

网页初学者,如何使用VS2005搭建编程环境(JavaScript及ASP调试)

一直想学一下网页编程&#xff0c;但是感觉要学的东西太多了。也没有人指导。只好一个人摸索。 尝试了一些常用的网页编程技术。得出自己的总结&#xff0c;写在这里做一个备份。 本文写个自己&#xff0c;也作为和我一样的初学者一个参考。 【工具准备】 一、服务器端学什…

大数据的基础知识上(大数据的概念和生态、linux系统与命令、虚拟机导入、虚拟机额配置和联网)

目录一、数据分析的方向二、数据分析步骤1.明确分析目的和思路2.数据传输收集过程3.数据处理4.数据分析5.数据展现6.报告撰写三、数据是什么 大数据时代大数据的应用有哪些四、分布式和集群1.概念&#x1f3a1;&#xff08;by the way&#xff09;大数据生态系统&#x1f3a1;&…

【Three.js入门】一文带你入坑前端3Dの妙妙屋

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端 &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;秋招&#xff09; &#x1f680;未…