Python+requests+pytest+allure自动化测试框架

news2024/9/24 1:21:40

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快

1、核心库

  1. requests request请求

  2. openpyxl excel文件操作

  3. loggin 日志

  4. smtplib 发送邮件

  5. configparser

  6. unittest.mock mock服务

2、目录结构

  • base

  • utils

  • testDatas

  • conf

  • testCases

  • testReport

  • logs

  • 其他

图片

2.1base

  • base_path.py 存放绝对路径,dos命令或Jenkins执行时,防止报错

  • base_requests.py 封装requests,根据method选择不同的方法执行脚本,同时处理请求异常

2.1.1 base_path.py
import os

# 项目根路径
_root_path = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0]

# 报告路径
report_path = os.path.join(_root_path, 'testReport', 'report.html')

# 日志路径
log_path = os.path.join(_root_path, 'logs/')

# 配置文件路径
conf_path = os.path.join(_root_path, 'conf', 'auto_test.conf')

# 测试数据路径
testdatas_path = os.path.join(_root_path, 'testDatas')

# allure 相关配置
_result_path = os.path.join(_root_path, 'testReport', 'result')
_allure_html_path = os.path.join(_root_path, 'testReport', 'allure_html')
allure_command = 'allure generate {} -o {} --clean'.format(_result_path, _allure_html_path)
2.1.2 base_requests.py
import json
import allure
import urllib3
import requests
import warnings
from bs4 import BeautifulSoup
from base.base_path import *
from requests.adapters import HTTPAdapter
from utils.handle_logger import logger
from utils.handle_config import handle_config as hc


class BaseRequests:

    def __init__(self, case, proxies=None, headers=None, cookies=None, timeout=15, max_retries=3):
        '''
        :param case: 测试用例
        :param proxies: The result is displayed in fiddler:
        {"http": "http://127.0.0.1:8888", "https": "https://127.0.0.1:8888"}
        :param headers: 请求头
        :param cookies: cookies
        :param timeout: 请求默认超时时间15s
        :param max_retries: 请求超时后默认重试3次
        '''
        self.case = case
        self.proxies = proxies
        self.headers = headers
        self.cookies = cookies
        self.timeout = timeout
        self.max_retries = max_retries
        self.base_url = hc.operation_config(conf_path, 'BASEURL', 'base_url')

    def get_response(self):
        '''获取请求结果'''
        response = self._run_main()
        return response

    def _run_main(self):
        '''发送请求'''
        method = self.case['method']
        url = self.base_url + self.case['url']
        if self.case['parameter']:
            data = eval(self.case['parameter'])
        else:
            data = None

        s = requests.session()
        s.mount('http://', HTTPAdapter(max_retries=self.max_retries))
        s.mount('https://', HTTPAdapter(max_retries=self.max_retries))
        urllib3.disable_warnings()  # 忽略浏览器认证(https认证)警告
        warnings.simplefilter('ignore', ResourceWarning)    # 忽略 ResourceWarning警告

        res=''
        if method.upper() == 'POST':
            try:
                res = s.request(method='post', url=url, data=data, verify=False, proxies=self.proxies, headers=self.headers, cookies=self.cookies, timeout=self.timeout)
            except Exception as e:
                logger.error('POST请求出错,错误信息为:{0}'.format(e))

        elif method.upper() == 'GET':
            try:
                res = s.request(method='get', url=url, params=data, verify=False,proxies=self.proxies, headers=self.headers, cookies=self.cookies, timeout=self.timeout)
            except Exception as e:
                    logger.error('GET请求出错,错误信息为:{0}'.format(e))
        else:
            raise ValueError('method方法为get和post')
        logger.info(f'请求方法:{method},请求路径:{url}, 请求参数:{data}, 请求头:{self.headers}, cookies:{self.cookies}')

        # with allure.step('接口请求信息:'):
        #     allure.attach(f'请求方法:{method},请求路径:{url}, 请求参数:{data}, 请求头:{headers}')

        # 拓展:是否需要做全量契约验证?响应结果是不同类型时,如何处理响应?
        return res


if __name__ == '__main__':
    # case = {'method': 'get', 'url': '/article/top/json', 'parameter': ''}
    case = {'method': 'post', 'url': '/user/login', 'parameter': '{"username": "xbc", "password": "123456"}'}
    response = BaseRequests(case).get_response()
    print(response.json())

2.2 utils

(只取核心部分)

  • handle_excel.py
    - excel的操作,框架要求,最终读取的数据需要保存列表嵌套字典的格式[{},{}]
    - 其他操作

  • handle_sendEmail.py
    - python发送邮件使用smtp协议,接收邮件使用pop3
    - 需要开启pop3服务功能,这里的password为授权码,启用服务自行百度

  • handle_logger.py 日志处理

  • handle_config.py
    配置文件处理,这里只将域名可配置化,切换环境时改域名即可

  • handle_allure.py
    allure生成的报告需要调用命令行再打开,这里直接封装命令

  • handle_cookies.py(略)
    在git中补充,处理cookiesJar对象

  • handle_mock.py(略)
    在git中补充,框架未使用到,但是也封装成了方法

  • param_replace(略)
    将常用的参数化操作封装成类

2.2.1 handle_excel.py

import openpyxl
from base.base_path import *

class HandleExcel:
    def __init__(self, file_name=None, sheet_name=None):
        '''
        没有传路径时,默认使用 wanadriod接口测试用例.xlsx 文件
        :param file_name:  用例文件
        :param sheet_name: 表单名
        '''
        if file_name:
            self.file_path = os.path.join(testdatas_path, file_name)
            self.sheet_name = sheet_name
        else:
            self.file_path = os.path.join(testdatas_path, 'wanadriod接口测试用例.xlsx')
            self.sheet_name = 'case'
        # 创建工作簿,定位表单
        self.wb = openpyxl.load_workbook(self.file_path)
        self.sheet = self.wb[self.sheet_name]
        # 列总数,行总数
        self.ncols = self.sheet.max_column
        self.nrows = self.sheet.max_row

    def cell_value(self, row=1, column=1):
        '''获取表中数据,默认取出第一行第一列的值'''
        return self.sheet.cell(row, column).value

    def _get_title(self):
        '''私有函数, 返回表头列表'''
        title = []
        for column in range(1, self.ncols+1):
            title.append(self.cell_value(1, column))
        return title

    def get_excel_data(self):
        '''
        :return: 返回字典套列表的方式 [{title_url:value1, title_method:value1}, {title_url:value2, title_method:value2}...]
        '''
        finally_data = []
        for row in range(2, self.nrows+1):
            result_dict = {}
            for column in range(1, self.ncols+1):
                result_dict[self._get_title()[column-1]] = self.cell_value(row, column)
            finally_data.append(result_dict)
        return finally_data

    def get_pytestParametrizeData(self):
        '''
        选用这种参数方式,需要使用数据格式 列表套列表 @pytest.mark.parametrize('', [[], []]), 如 @pytest.mark.parametrize(*get_pytestParametrizeData)
        将 finally_data 中的 title 取出,以字符串形式保存,每个title用逗号(,)隔开
        将 finally_data 中的 value 取出,每行数据保存在一个列表,再集合在一个大列表内
        :return: title, data
        '''
        finally_data = self.get_excel_data()
        data = []
        title = ''
        for i in finally_data:
            value_list = []
            key_list = []
            for key, value in i.items():
                value_list.append(value)
                key_list.append(key)
            title = ','.join(key_list)
            data.append(value_list)
        return title, data

    def rewrite_value(self, new_value, case_id, title):
        '''写入excel,存储使用过的数据(参数化后的数据)'''
        row = self.get_row(case_id)
        column = self.get_column(title)
        self.sheet.cell(row, column).value = new_value
        self.wb.save(self.file_path)

    def get_row(self, case_id):
        '''通过执行的 case_id 获取当前的行号'''
        for row in range(1, self.nrows+1):
            if self.cell_value(row, 1) == case_id:
                return int(row)

    def get_column(self, title):
        '''通过表头给定字段,获取表头所在列'''
        for column in range(1, self.ncols+1):
            if self.cell_value(1, column) == title:
                return int(column)


if __name__ == '__main__':
    r = HandleExcel()
    print(r.get_excel_data())
2.2.2 handle_sendEmail.py
import smtplib
from utils.handle_logger import logger
from email.mime.text import MIMEText    # 专门发送正文邮件
from email.mime.multipart import MIMEMultipart  # 发送正文、附件等
from email.mime.application import MIMEApplication  # 发送附件

class HandleSendEmail:

    def __init__(self, part_text, attachment_list, password, user_list, subject='interface_autoTestReport', smtp_server='smtp.163.com', from_user='hu_chunpu@163.com', filename='unit_test_report.html'):
        '''
        :param part_text: 正文
        :param attachment_list: 附件列表
        :param password: 邮箱服务器第三方密码
        :param user_list: 收件人列表
        :param subject: 主题
        :param smtp_server: 邮箱服务器
        :param from_user: 发件人
        :param filename: 附件名称
        '''
        self.subject = subject
        self.attachment_list = attachment_list
        self.password = password
        self.user_list = ';'.join(user_list)    # 多个收件人
        self.part_text = part_text
        self.smtp_server = smtp_server
        self.from_user = from_user
        self.filename = filename

    def _part(self):
        '''构建邮件内容'''
        # 1) 构造邮件集合体:
        msg = MIMEMultipart()
        msg['Subject'] = self.subject
        msg['From'] = self.from_user
        msg['To'] = self.user_list

        # 2) 构造邮件正文:
        text = MIMEText(self.part_text)
        msg.attach(text)  # 把正文加到邮件体里面

        # 3) 构造邮件附件:
        for item in self.attachment_list:
            with open(item, 'rb+') as file:
                attachment = MIMEApplication(file.read())
            # 给附件命名:
            attachment.add_header('Content-Disposition', 'attachment', filename=item)
            msg.attach(attachment)

        # 4) 得到完整的邮件内容:
        full_text = msg.as_string()
        return full_text

    def send_email(self):
        '''发送邮件'''
        # qq邮箱必须加上SSL
        if self.smtp_server == 'smtp.qq.com':
            smtp = smtplib.SMTP_SSL(self.smtp_server)
        else:
            smtp = smtplib.SMTP(self.smtp_server)
        # 登录服务器:.login(user=email_address,password=第三方授权码)
        smtp.login(self.from_user, self.password)
        logger.info('--------邮件发送中--------')
        try:
            logger.info('--------邮件发送成功--------')
            smtp.sendmail(self.from_user, self.user_list, self._part())
        except Exception as e:
            logger.error('发送邮件出错,错误信息为:{0}'.format(e))
        else:
            smtp.close()    # 关闭连接

if __name__ == '__main__':
    from base.base_path import *
    part_text = '附件为自动化测试报告,框架使用了pytest+allure'
    attachment_list = [report_path]
    password = ''
    user_list = ['']
    HandleSendEmail(part_text, attachment_list, password, user_list).send_email()
2.2.3 handle_logger.py
import sys
import logging
from time import strftime
from base.base_path import *

class Logger:

    def __init__(self):
        # 日志格式
    custom_format = '%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s: %(message)s'
        # 日期格式
        date_format = '%a, %d %b %Y %H:%M:%S'

        self._logger = logging.getLogger()  # 实例化
        self.filename = '{0}{1}.log'.format(log_path, strftime("%Y-%m-%d")) # 日志文件名
        self.formatter = logging.Formatter(fmt=custom_format, datefmt=date_format)
        self._logger.addHandler(self._get_file_handler(self.filename))
        self._logger.addHandler(self._get_console_handler())
        self._logger.setLevel(logging.INFO)  # 默认等级

    def _get_file_handler(self, filename):
        '''输出到日志文件'''
        filehandler = logging.FileHandler(filename, encoding="utf-8")
        filehandler.setFormatter(self.formatter)
        return filehandler

    def _get_console_handler(self):
        '''输出到控制台'''
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(self.formatter)
        return console_handler

    @property
    def logger(self):
        return self._logger

'''
日志级别:
critical    严重错误,会导致程序退出
error        可控范围内的错误
warning        警告信息
info        提示信息
debug        调试程序时详细输出的记录
'''
# 实例
logger = Logger().logger


if __name__ == '__main__':
    import datetime
    logger.info(u"{}:开始XXX操作".format(datetime.datetime.now()))
2.2.4 handle_config.py
import configparser

# 配置文件类
class HandleConfig:
    def operation_config(self, conf_file, section, option):
        cf = configparser.ConfigParser()    # 实例化
        cf.read(conf_file)
        value = cf.get(section, option)    # 定位
        return value


handle_config = HandleConfig()
if __name__ == '__main__':
    from base.base_path import *
    base_url = handle_config.operation_config(conf_path, 'BASEURL', 'base_url')
    print(base_url)
2.2.5 handle_allure.py
import subprocess
from base.base_path import *

class HandleAllure(object):

    def execute_command(self):
        subprocess.call(allure_command, shell=True)

handle_allure = HandleAllure()

2.3testDatas

excel测试用例文件,必须是.xlsx结尾,用例结构如下:

图片

2.4conf

放置配置文件 .conf结尾

2.5 testCases

  • conftest.py
    - fixture功能,用例前置后置操作
    - 构造测试数据
    - 其他高级操作
    - 注意邮件中的password和user_list需要换成自己测试的邮箱及服务密码

  • test_wanAndroid.py 测试用例脚本
    - 参数化: pytest.mark.parametrize('case',[{},{}])
    - 接口关联:
        - 将关联的参数配置成全局变量
       - 在用例执行前使用全局变量替换参数
       - 使用 is_run 参数指明有参数化的用例,并取出,再赋值给全局变量
    - cookies:
       - 和接口关联的处理方式一样处理cookies
    - 步骤
       - 收集用例
       - 执行用例
       - 断言
       - 构造测试报告
       - 发送邮件

2.5.1 conftest.py
import pytest
from base.base_path import *
from utils.handle_logger import logger
from utils.handle_allure import handle_allure
from utils.handle_sendEmail import HandleSendEmail

'''
1. 构造测试数据??
2. fixture 替代 setup,teardown
3. 配置 pytest
'''

def pytest_collection_modifyitems(items):
    """
    测试用例收集完成时,将收集到的item的name和nodeid的中文显示在控制台上
    """
    for item in items:
        item.name = item.name.encode("utf-8").decode("unicode_escape")
        item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape")
        # print(item.nodeid)

@pytest.fixture(scope='session', autouse=True)
def send_email():
    logger.info('-----session级,执行wanAndroid测试用例-----')
    yield
    logger.info('-----session级,wanAndroid用例执行结束,发送邮件:-----')
    """执行alllure命令 """
    handle_allure.execute_command()
    # 发邮件
    part_text = '附件为自动化测试报告,框架使用了pytest+allure'
    attachment_list = [report_path]
    password = ''
    user_list = ['']
    HandleSendEmail(part_text, attachment_list, password, user_list).send_email()
2.5.2 test_wanAndroid.py
import json
import pytest
import allure
from base.base_requests import BaseRequests
from utils.handle_logger import logger
from utils.handle_excel import HandleExcel
from utils.param_replace import pr
from utils.handle_cookies import get_cookies

handle_excel = HandleExcel()
get_excel_data = HandleExcel().get_excel_data()
ID = ''
COOKIES = {}
PAGE = ''

class TestWanAndroid:

    @pytest.mark.parametrize('case', get_excel_data)
    def test_wanAndroid(self, case):
        global ID
        global COOKIES
        # 参数替换
        case['url'] = pr.relevant_parameter(case['url'], '${collect_id}', str(ID))

        if case['is_run'].lower() == 'yes':
            logger.info('------执行用例的id为:{0},用例标题为:{1}------'.format(case['case_id'], case['title']))
            res = BaseRequests(case, cookies=COOKIES).get_response()
            res_json = res.json()

            # 获取登录后的cookies
            if case['case_id'] == 3:
                COOKIES = get_cookies.get_cookies(res)

            if case['is_depend']:
                try:
                    ID = res_json['data']['id']
                    # 将使用的参数化后的数据写入excel
                    handle_excel.rewrite_value('id={}'.format(ID), case['case_id'], 'depend_param')
                except Exception as e:
                    logger.error(f'获取id失败,错误信息为{e}')
                    ID = 0

            # 制作 allure 报告
            allure.dynamic.title(case['title'])
            allure.dynamic.description('<font color="red">请求URL:</font>{}<br />'
                                       '<font color="red">期望值:</font>{}'.format(case['url'], case['excepted']))
            allure.dynamic.feature(case['module'])
            allure.dynamic.story(case['method'])

            result=''
            try:
                assert eval(case['excepted'])['errorCode'] == res_json['errorCode']
                result = 'pass'
            except AssertionError as e:
                logger.error('Assert Error:{0}'.format(e))
                result = 'fail'
                raise e
            finally:
                # 将实际结果格式化写入excel
                handle_excel.rewrite_value(json.dumps(res_json, ensure_ascii=False, indent=2, sort_keys=True), case['case_id'], 'actual')
                # 将用例执行结果写入excel
                handle_excel.rewrite_value(result, case['case_id'], 'test_result')


    def test_get_articleList(self):
        '''翻页,将page参数化'''
        global PAGE
        pass


    def test_mock_demo(self):
        '''使用mock服务模拟服务器响应'''
        pass


if __name__ == '__main__':
    pytest.main(['-q', 'test_wanAndroid.py'])

2.6 testReport

  • 存放html测试报告,安装插件pip install pytest-html

  • 存放allure测试报告,插件安装pip install allure-pytest

2.7 logs

存放日志文件

2.8 其他文件

  • run.py 主运行文件

  • pytest.ini 配置pytest的默认行为,运行规则等

  • requirements.txt 依赖环境
    - 自动生成 pip freeze
    - 安装 pip -r install requirements.

3、总结

  1. allure有很多有趣的操作,甚至控制用例执行行为,有兴趣可以拓展

  2. 实现框架的难点在接口依赖

  3. 接口自动化应避免复杂的接口依赖,复杂的依赖只会造成测试的不可控性

  4. 注意频繁的操作excel会消耗性能

  5. 有兴趣可以将本框架集合在Jenkins中

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

这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。

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

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

相关文章

如何使用ssm实现社区流浪动物救助领养系统的设计与开发+vue

TOC ssm666社区流浪动物救助领养系统的设计与开发vue 第一章 课题背景及研究内容 1.1 课题背景 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安…

kafka 消费者线程安全问题详细探讨

内容概要 主要内容 常见错误案例 下面这段代码大概逻辑 初始化时 实例化KafkaConsumer, 开启线程拉取消息并且处理 资源释放回调 停止线程、调用kafkaConsumer.close进行资源释放 表面上没有问题&#xff0c;但实际上可能出现线程安全问题&#xff0c;因为poll 和 close 两…

python按照财年分组案例

有如下数据&#xff1a;需要按照如下要求进行分组。 需求是对Site进行分组 条件当值是Act得时候&#xff0c;分组名字就是 条件当值是Rebase*得时候&#xff0c;分组名字就是FY?1/?1 条件当值是FIRM 得时候&#xff0c;分组名字就是 每年得7月到次年得6月为一个财年&#xff…

C++之初识STL(概念)

STL&#xff08;标准模板库&#xff09; STL广义分类为&#xff1a;容器&#xff0c;算法&#xff0c;迭代器 * **容器**和**算法**之间通过**迭代器**进行无缝连接 意义&#xff1a;C的**面向对象**和**泛型编程**思想&#xff0c;目的就是**复用性的提升** STL六大组件 1. 容…

MODELS 2024:闪现奥地利,现场直击报道

周末出逃&#xff01;小编闪现至奥地利林茨&#xff0c;亲临第27届MODELS 2024国际会议&#xff0c;以第一视角引领你深入会议现场&#xff0c;领略其独特风采。利用午饭时间&#xff0c;小编紧急码字&#xff0c;只为第一时间将热点资讯呈现给你~ 会议介绍&#xff1a; MODEL…

计算机毕业设计之:微信小程序的校园闲置物品交易平台(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

JavaEE: 深入探索TCP网络编程的奇妙世界(六)

文章目录 TCP核心机制TCP核心机制九: 面向字节流TCP核心机制十: 异常处理 小小的补充(URG 和 PSH)~TCP小结TCP/UDP 对比用UDP实现可靠传输(经典面试题) 结尾 TCP核心机制 上一篇文章JavaEE: 深入探索TCP网络编程的奇妙世界(五) 书接上文~ TCP核心机制九: 面向字节流 TCP是面…

开关频率与谐振频率对应的模态图

当fsfr时 当fr2<fs<fr1时 当fs>fr1时 开关频率对应输入电压的频率 谐振频率对应的是谐振电流的频率

JavaSE - 面向对象编程05

01 正则表达式 【1】概念&#xff1a;正则表达式是由一些特定字符组成的&#xff0c;代表的是一个规则。 【2】可以用来做什么&#xff1f; ① 用于校验数据格式的合法性 ② 用于在文本中爬取满足要求的内容 ③ 用于String类的replace方法&#xff0c;split方法的替换和分割 …

动态时间【JavaScript】

这个代码实现了一个动态显示当前日期和时间的功能。具体来说&#xff0c;它会每秒更新一次时间并在页面上显示出来。 实现效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><…

GUI编程之MATLAB入门详解(01)

⛄前言 图形用户界面的设计是MATLAB的核心应用之一。当用户与计算机之间或用户与计算机程序之间进行交互操作时&#xff0c;舒服高效的用户接口功能则会对用户产生极大的吸引力。图形用户界面&#xff08;GUI&#xff09;则通过窗口、图标、按钮、菜单、文本等图形对象构成用户…

美业SaaS收银系统如何收银?博弈美业实操/美业门店管理系统源码

1.打开博弈美业APP 2.工作台上方的【收银台】、【扫码核销】、【密码核销】均可完成收银 3.【收银台】可直接选择商品/服务/课程&#xff0c;再选择客户后提交订单收款 4.【扫码核销】【密码核销】可直接扫描二维码、输入核销码进行收银

大模型日报|7 篇必读的大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.中科大团队提出人像视频编辑方法 PortraitGen 中国科学技术大学团队提出了 PortraitGen&#xff0c;这是一种功能强大的人像视频编辑方法&#xff0c;它能通过多模态提示实现一致且富有表现力的风格化。 传统的人…

SLAM面经1(百度)

百度面经 百度共三面,如果面试效果俱佳,会增加一个hr面。前二面主要是技术面,分为在线coding+代码知识+专业知识+工程能力。第三面是主管面,偏向于管理方面,和hr面相似。 一面 1)在线coding 在线coding的考试内容为下面力扣的变种。 2)专业面 (1)VINS-FUSION与ORB…

鲲鹏计算这五年:硬生态基本盘稳住,才能放手进击软生态

文 | 智能相对论 作者 | 叶远风 数智化深入发展、新质生产力成为主旋律的当下&#xff0c;本土计算产业的发展被寄予越来越多的关注和期待。自2019年开启以来&#xff0c;鲲鹏计算产业生态已经整整走过5个年头。 因此&#xff0c;今年华为全联接大会的鲲鹏之夜&#xff0c;在…

【网络安全】依赖混淆漏洞实现RCE

未经许可&#xff0c;不得转载。 文章目录 正文 依赖混淆是一种供应链攻击漏洞&#xff0c;发生在企业的内部依赖包错误地从公共库&#xff08;如npm&#xff09;下载&#xff0c;而不是从其私有注册表下载。攻击者可以在公共注册表中上传一个与公司内部包同名的恶意包&#xf…

java基础(2)方法的使用

目录 1.前言 2.正文 2.1方法的定义 2.2方法的调用过程 2.3方法的实参与形参 2.3.1形参 2.3.2实参 2.3.3参数传递 2.4方法的重载 3.小结 1.前言 哈喽大家好啊&#xff0c;今天博主继续带领大家学习java的基本语法&#xff0c;java的基础语法部分打算用六到七篇博文完…

关于uniapp wifi调用走过的坑

1. uniapp老脚手架与uni-wif带来的兼容性问题 且几乎找不到解决方法 2. uni-wif需要插件市场安装 3.还有一种可以使用导入安卓类的方式&#xff0c;可以正常获取到已经连接ssid&#xff08;wifi名称&#xff09;&#xff0c;也可以获取到wifi列表 &#xff0c; 但ScanResul…

p18 docker镜像原理之联合文件系统,p19 docker镜像分层的理解

镜像是什么 镜像其实就是一种轻量级的&#xff0c;可执行的一种软件包&#xff0c;用来打包基于环境开发的软件&#xff0c;里面可以包括代码&#xff0c;环境&#xff0c;数据库&#xff0c;配置文件等信息 如何得到镜像&#xff1f; 可以从镜像仓库下载比方说dockerhub 比…

道路车辆功能安全 ISO 26262标准(2)—功能安全管理

写在前面 本系列文章主要讲解道路车辆功能安全ISO26262标准的相关知识&#xff0c;希望能帮助更多的同学认识和了解功能安全标准。 若有相关问题&#xff0c;欢迎评论沟通&#xff0c;共同进步。(*^▽^*) 1. 道路车辆功能安全ISO 26262标准 2. ISO 26262-2 功能安全管理 IS…