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

接口自动化测试实操

实现思路

使用excel管理用例用例信息,requests模块发送http请求,实现了记录日志,邮件发送测试报告的功能

目录结构如下:

下面直接上代码:

统筹脚本

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

# -*- coding:utf-8 -*-

import os

from interface import Interface

from testcase_get import Get_testcase

from result_save import Save_test_result

from result_send import Send_report

from config.config import Config

from logging_save import logger

if __name__ == "__main__":

    cur_path = os.path.split(os.path.realpath(__file__))[0]  # 获取当前文件绝对路径

    case_path = os.path.join(cur_path, "test_case""20170602.xls")

    test_case = Get_testcase(case_path).readExcel()  # 获取用例

    if not isinstance(test_case, list):  # 判断用例是否获取成功

        logger.info("Test_case get failed... \n Done!")

    else:

        logger.info("获取用例成功")

        # 调用接口

        test_result = Interface().interfaceTest(test_case)

        # 获取执行结果,用于发邮件

        count_success = test_result[3]

        count_failure = test_result[4]

        failed_case_detail = test_result[5]

        # 保存测试结果

        Save_test_result().save_result(case_path, test_result[0], test_result[1], test_result[2])

        logger.info("保存测试结果成功")

        # 获取邮件配置信息

        mail_config = Config(os.path.join(cur_path, "config""mail.conf")).get_mail_config()

        logger.info("获取邮箱配置成功")

        login_user = mail_config[0]

        login_pwd = mail_config[1]

        from_addr = mail_config[2]

        to_addrs = mail_config[3]

        smtp_server = mail_config[4]

        mail_send = Send_report(count_success, count_failure, failed_case_detail)

        # 获取最新测试报告

        last_report = mail_send.newest_report()

        logger.info("邮件发送结果")

        mail_send.send_result(login_user, login_pwd,from_addr, to_addrs,smtp_server,last_report)

        logger.info("DONE!")

请求封装

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

# coding:utf-8

import json

import requests

from logging_save import logger

from result_check import Result_check

from url_transform import urltransform

class Interface:

    def __init__(self, ):

        pass

    def interfaceTest(self, case_list):

        """

        接口调用主函数

        """

        # 用于存结果

        res_flags = []

        # 用于存请求报文

        request_urls = []

        # 用于存返回报文

        responses = []

        # 用户存失败的用例

        failed_case = []

        # 统计成功失败的用例数

        count_success = 0

        count_failure = 0

        for case in case_list:

            try:

                # 模块

                product = case[0]

                # 用例id

                case_id = case[1]

                # 用例标题

                interface_name = case[2].strip('\n')

                # 用例描述

                case_detail = case[3]

                # 请求方式

                method = case[4]

                # 请求url

                url = case[5]

                # 入参

                param = case[6]

                # 预期结果

                res_check = case[7]

            except Exception as e:

                return '测试用例格式不正确!%s' % e

            # 定义消息头信息

            headers = {'content-type''application/json',

                       'User-Agent''Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}

            # 对url进行封装

            new_url = urltransform().urltransform(url, method, param)

            if method.upper() == 'GET':

                results = requests.get(new_url).text

                logger.info(u'正在调用接口: %s' % interface_name)

                # print results

                responses.append(results)

                # 用于存储预期结果与实际结果的比较结果

                res = Result_check().interface_result_check(results, res_check)

                request_urls.append(new_url)

            else:

                request_urls.append(new_url)

                if param == '':

                    pass

                else:

                    data = json.loads(param)  # 将参数转化为json格式

                results = requests.post(new_url, data=json.dumps(data), headers=headers).text

                responses.append(results)

                res = Result_check().interface_result_check(results, res_check)

            if 'pass' in res:

                res_flags.append('pass')

                count_success += 1

            else:

                logger.warning(u'接口返回结果与预期结果不一致!失败URL: %s METHOD :%s' % (url, method))

                res_flags.append('fail')

                count_failure += 1

                failed_case.append((interface_name, method, url))

        logger.info(u'共执行 %s 条用例,PASS: %s,FAILED: %s' % (len(case_list), count_success, count_failure))

        return res_flags, request_urls, responses, count_success, count_failure, failed_case

日志封装

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

# coding=utf-8

import logging

import sys

import traceback

import time

class LoggingUtils:

    '''

    ===========封装日志工具类的基本操作=============

    '''

    def __init__(self,logfile):

        '''

        :param logfile:

        '''

        self.logger = logging.getLogger(logfile)

        self.hdlr = logging.FileHandler(logfile)

        formatter = logging.Formatter('%(asctime)s %(levelname)s - %(message)s')

        self.ch = logging.StreamHandler()

        self.ch.setLevel(logging.INFO)

        self.ch.setFormatter(formatter)

        self.hdlr.setFormatter(formatter)

        self.logger.addHandler(self.hdlr)

        self.logger.addHandler(self.ch)

        self.logger.setLevel(logging.DEBUG)

    def debug(self, msg):

        '''

        :param msg:

        :return:

        '''

        self.logger.debug(msg)

        self.hdlr.flush()

    def info(self, msg):

        '''

         

        :param msg:

        :return:

        '''

        self.logger.info(msg)

        self.hdlr.flush()

    def warning(self,msg):

        self.logger.warning(msg)

        self.hdlr.flush()

    def error(self, msg):

        '''

        :param msg:

        :return:

        '''

        self.logger.error(msg)

        # self.logger.removeHandler(logging.StreamHandler())

        self.logger.removeHandler(self.ch)

        self.hdlr.flush()

    def error_sys(self, limit=None):

        '''

        :param limit:

        :return:

        '''

        exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()

        if limit is None:

            if hasattr(sys, 'tracebacklimit'):

                limit = sys.tracebacklimit

        = 0

        eline = '\n'

        while exceptionTraceback is not None and (limit is None or n < limit):

            = exceptionTraceback.tb_frame

            lineno = exceptionTraceback.tb_lineno

            co = f.f_code

            filename = co.co_filename

            name = co.co_name

            eline += ' File "%s", line %d, in %s \n ' % (filename, lineno, name)

            exceptionTraceback = exceptionTraceback.tb_next

            = + 1

        eline += "\n".join(traceback.format_exception_only(exceptionType, exceptionValue))

        self.logger.error(eline)

        self.hdlr.flush()

timer = time.strftime('%Y-%m-%d',time.localtime())

logger = LoggingUtils('%s.log'%timer)

结果比对

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

#coding:utf-8

class result_check():

    def __init__(self):

        pass

    def result_check(self,results,res_check):

        '''

        结果对比函数

        '''

        #返回结果,将结果中的json数据转化为可以和预期结果比较的数据

        res = results.replace('":"','=').replace('" : "','=')

        #预期结果,是xx=11;xx=22

        res_check = res_check.split(';')

        for in res_check:

            if in res:

                pass

            else:

                return '结果不匹配 '+ str(s)

        return 'pass'

 result_save.py   保存测试结果的模块,复制原有的用例,保存为新的excel

#coding:utf-8

from xlutils import copy

import xlrd

import time

import os

class Save_test_result():

    def __init__(self):

        pass

    def save_result(self,file_path,res_flags,request_urls,responses):

        '''

        :return:

        '''

        book = xlrd.open_workbook(file_path)

        new_book = copy.copy(book)

        sheet = new_book.get_sheet(0)

        = 1

        for request_url, response, flag in zip(request_urls, responses, res_flags):

            sheet.write(i, 8, u'%s' % request_url)

            sheet.write(i, 9, u'%s' % response)

            sheet.write(i, 10, u'%s' % flag)

            += 1

        report_path = os.path.abspath(os.path.join('report'))

        if not os.path.exists(report_path):

            os.makedirs(report_path)

        new_book.save(os.path.abspath(os.path.join(report_path, 'Report@%s.xls' % time.strftime('%Y.%m.%d@%H%M%S'))))

结果邮件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

#coding:utf-8

import smtplib

from email.mime.text import MIMEText

from email.header import Header

from email.mime.multipart import MIMEMultipart

import os

from logging_save import  logger

class Send_report(object):

    def __init__(self,count_success,count_failure,failed_case):

        '''

        :param count_success:

        :param count_failure:

        :param failed_case:

        '''

        self.count_success = count_success

        self.count_failure = count_failure

        self.failed_case = failed_case

    def newest_report(self,testreport='report'):

        '''

        获取最新的测试报告

        :param testreport:

        :return:

        '''

        lists = os.listdir(testreport)

        lists.sort(key=lambda fn: os.path.getmtime(os.path.join(testreport,fn)))

        file_new = os.path.join(testreport, lists[-1])

        logger.info('获取最新附件报告成功')

        return file_new

    def send_result(self,username,passwd,from_addr,to_addrs,smtpserver,*args):

        '''

        :param username:

        :param passwd:

        :param from_addr:

        :param to_addrs:

        :param smtpserver:

        :param args:

        :return:

        '''

        sender = from_addr

        subject = '财富港接口测试结果'

        username = username

        passwd = passwd

        '''邮件内容'''

        tille = (u'用例名称', u'请求方式', u'url')

        details = (u'成功: ' + str(self.count_success) + u'失败: ' + str(self.count_failure)) + '\n' + u'失败的用例如下 :' + \

                  '\n' + '\n'.join(str(zip(tille, i)) for in self.failed_case).decode('unicode-escape')

        logger.info('邮件附件为: %s' %(args[0].split('\\')[1]))

        if args != None#判断是否添加附件

            msg = MIMEMultipart()

            msg.attach(MIMEText(details, 'plain''utf-8'))

            = 0

            while i < len(args): #可以添加多个附件

                part = MIMEText(open(args[i], 'rb').read(), 'base64''utf-8')

                part["Content-Type"= 'application/octet-stream'

                part["Content-Disposition"= 'attachment; filename="%s"'%args[i]

                msg.attach(part) #添加附件

                += 1

            msg['subject'= Header(subject, 'utf-8')

            msg['From'= from_addr

            msg['To'= ','.join(eval(to_addrs)) #兼容多个收件人

            smtp = smtplib.SMTP()

            try:

                smtp.connect(smtpserver)

                smtp.login(username, passwd)

                smtp.sendmail(sender, eval(to_addrs), msg.as_string())

                smtp.close()

                logger.info('带附件测试报告发送成功!')

            except smtplib.SMTPAuthenticationError,e:

                logger.error('邮箱账户或密码错误: '+ str(e))

        else:

            msg = MIMEText(details, 'plain''utf-8')

            msg['subject'= Header(subject, 'utf-8')

            msg['From'= from_addr

            msg['To'=  ','.join(eval(to_addrs))

            smtp = smtplib.SMTP()

            try:

                smtp.connect(smtpserver)

                smtp.login(username, passwd)

                smtp.sendmail(sender, eval(to_addrs), msg.as_string())

                logger.info('测试报告发送成功!')

                smtp.close()

            except smtplib.SMTPAuthenticationError,e:

                logger.error('邮箱账户或密码错误 : '+str(e))

用例获取及数据格式化

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

#coding:utf-8

import xlrd

from logging_save import logger

class Get_testcase(object):

    def __init__(self, file_path):

        '''

        :param file_path: 用例文件路径

        '''

        self.file_path = file_path

    def readExcel(self):

        '''

        读取用例函数

        :return: 测试用例列表

        '''

        try:

            book = xlrd.open_workbook(self.file_path)  # 打开excel

        except Exception, error:

            logger.error('路径不在或者excel不正确 : ' + str(error))

            return error

        else:

            sheet = book.sheet_by_index(0)  # 取第一个sheet页

            rows = sheet.nrows  # 取这个sheet页的所有行数

            case_list = []  # 用于保存用例信息

            for in range(rows):

                if i != 0:

                    case_list.append(sheet.row_values(i)) # 把每一条测试用例添加到case_list中

            return case_list

请求url转换

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#coding:utf-8

class urltransform(object):

    def __init__(self):

        pass

    def urltransform(self, url, method, param):

        '''

        :return:

        '''

        if param == '':

            new_url = url

        else:

            if method.upper() == 'GET':

                new_url = url + '?' + param.replace(';''&')  #如果有参数,且为GET方法则组装url

            else:

                new_url = url

        return new_url

测试用例excel结构

config目录下,config.py   获取配置文件信息的模块

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#conding:utf-8

import ConfigParser

class Config(object):

    def __init__(self,file_path):

        self.config = ConfigParser.ConfigParser()

        self.config.read(file_path)

    def get_mail_config(self):

        login_user = self.config.get('SMTP''login_user')

        login_pwd = self.config.get('SMTP''login_pwd')

        from_addr = self.config.get('SMTP''from_addr')

        to_addrs = self.config.get('SMTP''to_addrs')

        smtp_server = self.config.get('SMTP''smtp_server')

        port = self.config.get('SMTP''port')

        return login_user, login_pwd , from_addr, to_addrs,smtp_server, port

    def report_save_config(self):

        pass

mail.conf

1

2

3

4

5

6

7

8

[SMTP]

login_user = 18******@163.com

login_pwd = ******

from_addr =  BI<18******@163.com>

to_addrs = ['18******@163.com']

#to_addrs = ['1******@qq.com','******.com']

smtp_server = smtp.163.com

port = 25

测试报告

邮件接收结果

Python接口自动化测试零基础入门到精通(2023最新版)

相关文章:

接口自动化测试实操

实现思路 使用excel管理用例用例信息&#xff0c;requests模块发送http请求&#xff0c;实现了记录日志&#xff0c;邮件发送测试报告的功能 目录结构如下&#xff1a; 下面直接上代码&#xff1a; 统筹脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24…...

Virtual DOM

目录 Virtual DOM 前言 用法 代码 理解 Virtual DOM的工作原理&#xff1a; 为什么使用Virtual DOM? 哪些库/框架使用Virtual DOM? 总结 Virtual DOM&#xff08;虚拟DOM&#xff09;是一种编程概念&#xff0c;它是对真实DOM的轻量级抽象表示。在前端开发中&#x…...

数据结构与算法-二叉树的遍历

&#x1f31e; “少年没有乌托邦&#xff0c;心向远方自明朗&#xff01;” 二叉树 &#x1f388;1.二叉树的遍历&#x1f52d;1.1先序遍历&#x1f52d;1.2中序遍历&#x1f52d;1.3后序遍历&#x1f52d;1.4层次遍历&#x1f52d;1.5二叉树遍历的递归算法&#x1f4dd;1.5.1先…...

Qt之普通项目如何生成DLL(含源码+注释)

文章目录 一、示例图二、普通项目需要改造的内容三、源码&#xff08;创建了一个TestDLL的项目&#xff0c;更改内容主要在pro文件和maindow.h文件&#xff09;TestDLL.promainwindow.hmainwindow.cppmainwindow.ui 总结 一、示例图 使用不同的编译模式编译&#xff0c;会在对…...

Java注解及自定义注解

注解/元数据&#xff08;Annotation&#xff09;&#xff0c;是对代码级别的说明&#xff1b;在JDK1.5及以后版本引入的一个特性&#xff0c;与类、接口、枚举是在同一个层次。可以声明在包、类、字段、方法、局部变量、方法参数等的前面&#xff0c;用来对这些元素进行说明、注…...

ps2024滤镜插件Portraiture

Photoshop 是最常用到的综合性的设计工具&#xff0c;虽然PS一直在迭代升级&#xff0c;但是在细节功能上&#xff0c;PS总是无法完全满足全部所有的用户需求&#xff0c;今天coco玛奇朵推荐一个个截至目前最受欢迎的免费的PS插件&#xff0c;有了这些功能扩展的插件后PS如虎添…...

Vue 实战项目(智慧商城项目): 完整的订单购物管理功能 内涵资源代码 基于Vant组件库 Vuex态管理 基于企业级项目开发规范

鹏鹏老师的实战开发项目 文章目录 智慧商城项目01. 项目功能演示1.明确功能模块2.项目收获 02. 项目创建目录初始化vue-cli 建项目 03. 调整初始化目录结构1.删除文件2.修改文件3.新增目录 04. vant组件库及Vue周边的其他组件库05. 全部导入和按需导入的区别06. 全部导入07. 按…...

JVM——一些零散的概念(后续学习深入了再补充)

Native 凡是带了native关键字的&#xff0c;说明Java的作用范围的达不到了&#xff0c;需要调用底层C语言的库 调用native方法&#xff0c;会进入本地方法栈&#xff0c;调用本地接口(JNI) JNI的作用&#xff1a;扩展Java的使用&#xff0c;融合不同的编程语言为Java所用 它在内…...

OpenCV学习(三)——响应鼠标事件(获取点击点坐标和颜色,利用鼠标进行绘图)

响应鼠标事件 3. 响应鼠标事件3.1 获取鼠标点击的坐标3.2 获取鼠标点击像素点的颜色3.3 在鼠标点击的位置生成圆3.4 通过拖动鼠标来绘制填充矩形3.5 通过拖动鼠标绘制未填充矩形3.6 使用鼠标选点绘制多边形3.7 按住鼠标左键进行绘图 3. 响应鼠标事件 使用OpenCV读取图像&#…...

基于安卓android微信小程序的投票系统

项目介绍 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;投票系统小程序被用户普遍使用&#xff0c;为方便用户…...

没有上司的舞会

有了上一篇博客&#xff0c;没有看上一篇博客的可以看看上一篇博客&#xff0c;我们对没有上司的舞会这道题会有更好的理解~ 所以关键的思路就是确定对于每一个节点我们应该维护什么内容才是最合适的&#xff0c;这个题目和上一篇博客的最后一道题目很相似&#xff0c;我们思考…...

2.18每日一题(不直接给f(x)的定积分及变上限积分)

...

RHCE8 资料整理(四)

RHCE8 资料整理 第四篇 存储管理第13章 硬盘管理13.1 对磁盘进行分区13.2 交换分区&#xff08;swap分区&#xff09; 第14章 文件系统14.1 了解文件系统14.2 了解硬链接14.3 创建文件系统14.4 挂载文件系统14.5 设置永久挂载14.6 查找文件14.7 find的用法 第15章 逻辑卷管理15…...

目标跟踪ZoomTrack: Target-aware Non-uniform Resizing for Efficient Visual Tracking

论文作者&#xff1a;Yutong Kou,Jin Gao,Bing Li,Gang Wang,Weiming Hu,Yizheng Wang,Liang Li 作者单位&#xff1a;CASIA; University of Chinese Academy of Sciences; ShanghaiTech University; Beijing Institute of Basic Medical Sciences; People AI, Inc 论文链接&…...

Flink Data Sink

本专栏案例代码和数据集链接: https://download.csdn.net/download/shangjg03/88477960 1. Data Sinks 在使用 Flink 进行数据处理时,数据经 Data Source 流入,然后通过系列 Transformations 的转化,最终可以通过 Sink 将计算结果进行输出,Flink Data Sinks 就是用于定义…...

机器学习——正则化

正则化 在机器学习学习中往往不知道需要不知道选取的特征个数&#xff0c;假如特征个数选取过少&#xff0c;容易造成欠拟合&#xff0c;特征个数选取过多&#xff0c;则容易造成过拟合。由此为了保证模型能够很好的拟合样本&#xff0c;同时为了不要出现过拟合现象&#xff0…...

【c++】打家劫舍(动态规划)

打家劫舍 题目难度&#xff1a;高阶 时间限制&#xff1a;1000ms 内存限制&#xff1a;256mb 题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff…...

eslint提示 xxx should be listed in the project's dependencies

有时候手动安装了一个npm包A&#xff0c;npm包A里面包含了npm包B&#xff0c;这时候如果 import xxx from npm包B;eslint会报错&#xff0c;提示 npm包B 不在 package.json 里面 解决方法&#xff1a;在 eslintrc.js 增加配置 module.exports {rules: {import/no-extraneous-d…...

H3C LC-5120-52SC-HI配置管理IP

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、MGMT是什么&#xff1f;二、配置步骤1.连接ConsoleWindowsLinux1.配置minicom2.使用minicom 2.配置管理端口3.配置Web管理4.http其它配置项 总结 前言 最近…...

数据结构与算法之排序: 归并排序 (Javascript版)

排序 排序&#xff1a;把某个乱序的数组变成升序或降序的数组 (这里用数组来做举例) 归并排序 该排序属于 分治 策略将一个问题分解为两个问题来计算&#xff0c;计算完成之后&#xff0c;就会得到子任务的解&#xff0c;这些解不是最终问题的解&#xff0c;还需要merge起来…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...