unittest自动化测试实战
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快
为什么要学习unittest
按照测试阶段来划分,可以将测试分为单元测试、集成测试、系统测试和验收测试。单元测试是指对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,通常指函数或者类,一般是开发完成的。
单元测试可以将测试工作前移,及早发现问题,降低解决问题的成本。同时单元测试还可以保证单个模块的功能没有问题,为后续的集成测试提供准备,可以减少合成后的出现的问题。
对于测试来说,单元测试就是执行用例。为了更好的管理用例,我们需要学习Python自带的单元测试框架unittest.
unittest框架及原理
unittest是python自带的一套测试框架,学习起来也相对容易,unittest框架最核心的概念有四个:
(1)test case:测试用例。unittest中提供了一个基本类TestCase,可以用来创建新的测试用例,一个TestCase的示例就是一个测试用例;unittest中测试用例的方法都是以 test开头的,且执行顺序会按照方法名的ASCII值排序。
(2)test fixure:测试夹具。用于测试用例换进的搭建和销毁,即用例测试前环境的大件(SetUp前置条件),测试后环境的恢复(TearDown后置条件)。比如测试前需要登陆获取token等就是测试用例需要的环境,运行完成后执行下一个用例前需要还原环境,以免影响下一条用例的测试结果。
(3)test suit:测试套件。用来把需要一起执行的测试用例几种放到一块执行,相当于一个篮子。我们一般使用 TestLoader来加载测试用例到测试套件中。
(4)test runner:测试运行。用来执行测试用例的,并返回测试用例的执行结果。可以结合图形或者文本接口,把返回的测试结果更形象的展示出来,如 HTMLTestRunner。
unittest断言
断言是测试用例的中很重要的一部分内容,可以用来检查操作是否正确。比如说登入处理,成功后的页面一定有类似于用户名称之类的元素,这个时候我们就可以使用断言判断预期结果与实际是否一致,如果吻合,就可以认为测试用例通过。
在Python基础中,有一个 assert断言方法,基本使用格式为 assert 表达式,基本信息。在unittest框架中,也提供了一个自带的断言方式,如果断言失败即不通过就会抛出一个 AssertionError断言错误;成功则标识通过。
以下的断言方法都有一个 msg=None参数(表中只列出了第一个,其实都有),默认返回 None。但是如果指定msg参数的值,则将该信息作为失败的错误信息返回。

TestCase测试用例
编写测试用例前,我们需要创建一个类继承unittest里面的TestCase类,之后我们才能真正的使用unittest框架去编写测试用例.
步骤如下:
(1)导入unittest模块
(2)创建一个测试类,继承unittest.TestCase类
(3)定义测试方法,方法名必须以test_开头
(4)调用unittest.main()方法来运行测试用例。unittest.main()方法会搜索该模块下所有以test开头的测试用例和方法,并自动执行。
代码示例
# 注册功能代码# users列表存储成功注册的用户
users = [{'username': 'testing', 'password': '123456'}] def register(username, password1, password2):if not all([username, password1, password2]):return {'code': 0, 'msg': '所有参数不能为空.'}# 注册for user in users:if username == user['username']:return {'code': 0, 'msg': '用户名已存在!'}else:if password1 != password2:return {'code': 0, 'msg': '两次密码输入不一致!'}else:if 6 <= len(username) <= 18 and 6 <= len(password1) <= 18:# 追加到users列表users.append({'username': username, 'password': password2})return {'code': 0, 'msg': '注册成功.'}else:return {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}import unittest
from demo import register # 导入被测试代码class RegisterTest(unittest.TestCase):'''注册接口测试类'''def test_register_success(self):'''注册成功'''data = ('palien', 'palien', 'palien') # 测试数据result = register(*data) # 测试结果expected = {'code': 0, 'msg': '注册成功.'} # 预期结果self.assertEqual(result, expected) # 断言测试结果与预期结果一致# passdef test_username_exist(self):'''注册失败-用户名已存在'''data = ('testing', '123456', '123456')result = register(*data)expected = {'code': 0, 'msg': '用户名已存在!'}self.assertEqual(result, expected)def test_username_isnull(self):'''注册失败-用户名为空'''data = ('', 'palien', 'palien')result = register(*data)expected = {'code': 0, 'msg': '所有参数不能为空.'}self.assertEqual(result, expected)# passdef test_username_lt18(self):'''注册失败-用户名长度大于18位'''data = ('palienpalienpalienpalien', 'palien', 'palien')result = register(*data)expected = {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}self.assertEqual(result, expected)# passdef test_password1_not_password2(self):'''注册失败-两次输入密码不一致'''data = ('palien', 'palien1', 'palien2')result = register(*data)expected = {'code': 0, 'msg': '两次密码输入不一致!'}self.assertEqual(result, expected)# pass# 如果要直接运行这个测试类,需要使用unittest中的main函数来执行测试用例
if __name__ == '__main__':unittest.main()# Output
Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。尝试新的跨平台 PowerShell https://aka.ms/pscore6PS D:\d_02_study\01_git> cd d:/d_02_study/01_git/papers/system/02automation
PS D:\d_02_study\01_git\papers\system\02automation> & C:/Users/TDH/AppData/Local/Programs/Python/Python310-32/python.exe d:/d_02_study/01_git/papers/system/02automation/demo.py
.....
----------------------------------------------------------------------
Ran 5 tests in 0.001sOK
PS D:\d_02_study\01_git\papers\system\02automation>
TestFixture测试夹具
unittest的测试夹具有两种使用方式,一种是以测试用例的方法为维度的:setUp()和 tearDown();另一种是以测试类为维度的:setUpClass()和 tearDownClass()。
代码示例:
# users列表存储成功注册的用户
users = [{'username': 'testing', 'password': '123456'}] def register(username, password1, password2):if not all([username, password1, password2]):return {'code': 0, 'msg': '所有参数不能为空.'}# 注册for user in users:if username == user['username']:return {'code': 0, 'msg': '用户名已存在!'}else:if password1 != password2:return {'code': 0, 'msg': '两次密码输入不一致!'}else:if 6 <= len(username) <= 18 and 6 <= len(password1) <= 18:# 追加到users列表users.append({'username': username, 'password': password2})return {'code': 0, 'msg': '注册成功.'}else:return {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}import unittest
from demo import register # 导入被测试代码class RegisterTest(unittest.TestCase):'''注册接口测试类'''@classmethod # 指明这是个类方法,以类为维度去执行的def setUpClass(cls) -> None:'''整个测试用例类中的用例执行之前,会先执行此方法'''print('-----setup---class-----')@classmethoddef tearDownClass(cls) -> None:'''整个测试用例类中的用例执行完成后,会执行此方法'''print('-----teardown---class-----')def setUp(self):'''每条测试用例执行前都会执行'''print('用例{}开始执行...'.format(self))def tearDown(self):'''每条测试用例执行结束后都会执行'''print('用例{}执行结束...'.format(self))def test_register_success(self):'''注册成功'''data = ('palien', 'palien', 'palien') # 测试数据result = register(*data) # 测试结果expected = {'code': 0, 'msg': '注册成功.'} # 预期结果self.assertEqual(result, expected) # 断言测试结果与预期结果一致# passdef test_username_exist(self):'''注册失败-用户名已存在'''data = ('testing', '123456', '123456')result = register(*data)expected = {'code': 0, 'msg': '用户名已存在!'}self.assertEqual(result, expected)def test_username_isnull(self):'''注册失败-用户名为空'''data = ('', 'palien', 'palien')result = register(*data)expected = {'code': 0, 'msg': '所有参数不能为空.'}self.assertEqual(result, expected)# passdef test_username_lt18(self):'''注册失败-用户名长度大于18位'''data = ('palienpalienpalienpalien', 'palien', 'palien')result = register(*data)expected = {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}self.assertEqual(result, expected)# passdef test_password1_not_password2(self):'''注册失败-两次输入密码不一致'''data = ('palien', 'palien1', 'palien2')result = register(*data)expected = {'code': 0, 'msg': '两次密码输入不一致!'}self.assertEqual(result, expected)# pass# 如果要直接运行这个测试类,需要使用unittest中的main函数来执行测试用例
if __name__ == '__main__':unittest.main()### Output
PS D:\d_02_study\01_git> cd d:/d_02_study/01_git/papers/system/02automation
PS D:\d_02_study\01_git\papers\system\02automation> & C:/Users/TDH/AppData/Local/Programs/Python/Python310-32/python.exe d:/d_02_study/01_git/papers/system/02automation/demo.py
-----setup---class-----
用例test_password1_not_password2 (__main__.RegisterTest)开始执行...
用例test_password1_not_password2 (__main__.RegisterTest)执行结束...
.用例test_register_success (__main__.RegisterTest)开始执行...
用例test_register_success (__main__.RegisterTest)执行结束...
.用例test_username_exist (__main__.RegisterTest)开始执行...
用例test_username_exist (__main__.RegisterTest)执行结束...
.用例test_username_isnull (__main__.RegisterTest)开始执行...
用例test_username_isnull (__main__.RegisterTest)执行结束...
.用例test_username_lt18 (__main__.RegisterTest)开始执行...
用例test_username_lt18 (__main__.RegisterTest)执行结束...
.-----teardown---class---------------------------------------------------------------------------
Ran 5 tests in 0.004sOK
PS D:\d_02_study\01_git\papers\system\02automation>
TestSuit测试套件
unittest.TestSuit()类用来表示一个测试用例集,把需要执行的用例类或模块集合在一起。
常用的方法:
(1)unittest.TestSuit()
(2)addTest():添加单个测试用例方法
(3)addTest([...]):添加多个测试用例方法,方法名存在一个列表
(4)unittest.TestLoader()
(5)loadTestsFromTestCase(测试类名):添加一个测试类
(6)loadTestsFromMdule(模块名):添加一个模块
(7)discover(测试用例所在的目录):指定目录去加载,会自动寻找这个目录下所有符合命名规则的测试用例
代码示例:
'''以下三个文件必须在同一文件夹下:demo.pytest_demo.pyrun_test.py
'''import os
import unittest
import test_demo# 第一步,创建一个测试套件
suit = unittest.TestSuite()# 第二步,将测试用例加载到测试套件中# # 方式一,添加单条测试用例
# case = test_demo.RegisterTest('test_register_success')
# '''
# 创建一个用例对象。
# 注意:通过用例类去创建测试用例对象的时候,需要传入用例的方法名(字符串类型)
# 这里不是像调用普通类中的方法那样通过类名.方法名调用,可以理解为unittest框架的特殊之处
# '''
# suit.addTest(case) # 添加用例到测试套件中# # 方式二:添加多条用例
# case1 = test_demo.RegisterTest('test_username_exist')
# case2 = test_demo.RegisterTest('test_username_isnull')
# suit.addTest([case1, case2]) # 添加用例到测试套件中。注意这里使用的是suit.addTest()方法而不是suit.addTests()方法# # 方式三:添加一个测试用例集
# loader = unittest.TestLoader() # 创建一个加载对象
# suit.addTest(loader.loadFromTestCase(test_demo.RegisterTest)) # 通过加载对象从测试类中加载用例到测试套件中# '''
# 通产我们使用方式4、5比较多,可以根据实际情况来运用。
# 其中方式5还可以自定义匹配规则,默认是会寻找目录下的test*.py文件,即所有以test开头命名的py文件。
# '''
# # 方式四:添加一个模块(其实就是一个后缀名为.py文件,这里就是test_demo.py文件)
# loader = unittest.TestLoader() # 创建一个加载对象
# suit.addTest(loader.loadTestsFromModule(test_demo)) # 通过加载对象从模块中加载测试用例到测试套件中# 方式五:指定测试用例的所在目录路径,进行加载
loader = unittest.TestLoader() # 创建一个加载对象
case_path = os.path.dirname(os.path.abspath(__file__)) # 文件路径
# print('用例所在的目录路径为:', case_path)
# suit.addTest(loader.discover(case_path)) # 通过加载对象从用例所在目录加载测试用例到测试套件
suit.addTest(loader.discover(start_dir=case_path, pattern='test_demo*.py')) # 两个参数:路径和匹配规则
TestRunner执行用例
testRunner用来执行用例,并且可以生成相应的测试报告。测试报告有两种形式:一种是 text文本;一种是 html格式。
html格式是 HTMLTestRunner插件辅助生成的,是Python标准库的unittest框架的一个拓展,可以生成一个清晰直观的html测试报告。使用的前提就是需要下载 HTMLTestRunner.py,下载完成后放在python安装目录下的scripts目录下即可。
text文本相对于html来说过于简陋,与输出控制台没有什么区别,也几乎不适用。
代码示例:
# demo.py,与test_demo.py和run_test.py在同一目录下# 导入模块
import unittest
import os
import test_demo
from HTMLTestReportCN import HTMLTestRunner# 用例文件所在目录
base_path = os.path.dirname(os.path.abspath(__file__))
# report_path = base_path + 'report.html'# 打开报告文件# 创建测试套件
suit = unittest.TestSuite()# 通过模块加载测试用例
loader = unittest.TestLoader()
suit.addTest(loader.discover(start_dir=base_path, pattern='test_demo*.py'))# 创建测试运行程序启动器
runner = HTMLTestRunner(stream=open('report.html', 'w', encoding='utf-8'), # 打开一个报告文件,并将句柄传给streamtester='palien', # 报告中显示的测试人员 description='注册接口测试报告', # 报告中显示的描述信息title='自动化测试报告' # 测试报告标题
)# 使用启动器去执行测试套件里面的测试用例
runner.run(suit)
相关参数说明:
stream:指定输出方式
tester:报告中要显示的测试人员的名字
description:报告中要显示的描述信息
title:测试报告的标题
verbosity:表示测试报告信息的详细程度,一共三个值,默认为2
0(静默模式):只能获得总的测试用例书和总的结果,如:总共100个,失败90
1(默认模式):类似静默模式,只是在在每个成功的用例面前有个. 每个失败的用例前面有个F
2(详细模式):测试结果会显示每个测试用例的所有相关信息
运行完毕,在项目目录下面会生成一个report.html文件,在浏览器中打开,就可以看到测试报告了。

问题记录
在学习的过程中遇到了一些问题,记录一下。
HTMLTestRunner下载
经验证,以下两个文件就支持生成上面截图的报告。

报错 TypeError: a bytes-like object is required, not 'str'解决
这是打开文件的方式不对造成的,附上问题解决博客:https://blog.csdn.net/Teresa_lqs/article/details/126250505?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-126250505-blog-116235034.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-126250505-blog-116235034.pc_relevant_default&utm_relevant_index=1
中文报告乱码问题
问题如图:

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

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

相关文章:
unittest自动化测试实战
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 为什么要学习unittest 按照测试阶段来划分,可以将测试分为单元测试、集成测试、系统测试和验收测试。单元测试是指对软件中的最小可测试单元在与程…...
leetcode3.无重复字符的最长字串
采用滑动窗口方法 class Solution { public:int lengthOfLongestSubstring(string s) {int ns.size();if(n0)return 0;int result0;unordered_set<char> set;set.insert(s[0]);for(int i0,j0;i<n;i){while(j1<n&&set.find(s[j1])set.end()){set.insert(s[…...
Android Compose 框架派生状态(derivedStateOf、rememberCoroutineScope)深入剖析(十五)
一、引言 在 Android 开发领域,高效的状态管理对于构建响应式、高性能的应用程序至关重要,在 Jetpack Compose 中,derivedStateOf 和 rememberCoroutineScope 这两个与派生状态相关的特性在状态管理方面发挥着关键作用。派生状态允许我们根据…...
3.25-2request库
request库 一、介绍request库 (1)requests是用python语言编写的简单易用的http库,用来做接口测试的库; (2)接口测试自动化库有哪些? requests、urllib 、urllib2、urllib3、 httplib 等&…...
《破解老龄化的智能密钥:机器人四维战略与未来养老生态》
一、引言:老龄化社会与智能机器人的必然性 全球老龄化趋势与老年人核心需求(健康管理、生活辅助、心理陪伴、安全保障) 全球正面临着严峻的老龄化挑战。根据联合国发布的数据,全球60岁及以上人口数量在过去几十年中持续增长&…...
Docker-Volume数据卷详讲
Docker数据卷-Volume 一:Volume是什么,用来做什么的 当删除docker容器时,容器内部的文件就会跟随容器所销毁,在生产环境中我们需要将数据持久化保存,就催生了将容器内部的数据保存在宿主机的需求,volume …...
SpringMVC 配置
一、MVC 模式简介 在软件开发的广袤天地中,MVC 模式宛如一座明亮的灯塔,指引着开发者构建高效、可维护的应用程序。Spring MVC 作为基于 Spring 框架的重要 web 开发模块,更是将 MVC 模式的优势发挥得淋漓尽致,堪称 Servlet 的强…...
Python 3.8 Requests 爬虫教程(2025最新版)
遵守网站的爬虫规则、避免爬取敏感信息、保护个人隐私! 一、环境配置与基础验证 # 验证 Python 版本(需 ≥3.8) import sys print(sys.version) # 应输出类似 3.8.12 的信息# 安装 requests 库(若未安装) # 命令行执…...
蓝桥杯备考之 最长上升子序列问题(挖地雷)
这道题其实就是正常的最长上升子序列问题,但是我们还要把最优方案输出出来,我们可以用个pre数组来维护就行了,每当我们更新以i为结尾的最长子序列,如果i是接在1到i-1某个点后面的话就把前面的点存到pre里面 最后我们把pre倒着打印…...
华为OD机试2025A卷 - 游戏分组/王者荣耀(Java Python JS C++ C )
最新华为OD机试 真题目录:点击查看目录 华为OD面试真题精选:点击立即查看 题目描述 2020年题: 英雄联盟是一款十分火热的对战类游戏。每一场对战有10位玩家参与,分为两组,每组5人。每位玩家都有一个战斗力,代表着这位玩家的厉害程度。为了对战尽可能精彩,我们需要…...
【Python Cookbook】字符串和文本(二)
字符串和文本(二) 6.字符串忽略大小写的搜索替换7.最短匹配模式8.多行匹配模式9.将 Unicode 文本标准化10.在正则式中使用 Unicode 6.字符串忽略大小写的搜索替换 你需要以忽略大小写的方式搜索与替换文本字符串。 为了在文本操作时忽略大小写…...
Redisson 实现分布式锁简单解析
目录 Redisson 实现分布式锁业务方法:加锁逻辑LockUtil 工具类锁余额方法:工具类代码枚举代码 RedisUtil 工具类tryLock 方法及重载【分布式锁具体实现】Supplier 函数式接口调用分析 Redisson 实现分布式锁 业务方法: 如图,简单…...
六十天Linux从0到项目搭建(第五天)(file、bash 和 shell 的区别、目录权限、默认权限umask、粘滞位、使用系统自带的包管理工具)
1. file [选项] 文件名 用于确定文件类型的实用工具。它会通过分析文件内容(而不仅仅是文件扩展名)来判断文件的实际类型 示例输出解析 $ file /bin/bash /bin/bash: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, i…...
信源的分类及数学模型
信源的分类及数学模型 按照信源发出的时间和消息分布分为离散信源和连续信源 按照信源发出符号之间的关系分为无记忆信源和有记忆信源 单符号离散信源(一维离散信源) 信源输出的消息数有限或可数,且每次只输出符号集的一个消息 样本空间&…...
嵌入式硬件工程师从小白到入门-PCB绘制(二)
PCB绘制从小白到入门:知识点速通与面试指南 一、PCB设计核心流程 需求分析 明确电路功能(如电源、信号处理、通信)。确定关键参数(电压、电流、频率、接口类型)。 原理图设计 元器件选型:匹配封装、电压、…...
抽象工厂设计模式及应用案例
引言 在软件开发中,合理的设计模式可以有效地提高代码的可维护性、可扩展性和可重用性。抽象工厂模式(Abstract Factory Pattern)便是一个重要的创建型设计模式,它允许我们在不指定具体类的情况下,创建一系列相关或相…...
LVS NAT模式实现三台RS的轮询访问
节点规划: 配置RS: RS1-RS3的网关配置均为 192.168.163.8 配置RS1: [rootlocalhost ~]# hostnamectl hostname rs1 [rootlocalhost ~]# nmcli c modify ens160 ipv4.method manual ipv4.addresses 192.168.163.7/24 ipv4.gateway 192.168.163.8 conne…...
LSM-Tree(Log-Structured Merge-Tree)详解
1. 什么是 LSM-Tree? LSM-Tree(Log-Structured Merge-Tree)是一种 针对写优化的存储结构,广泛用于 NoSQL 数据库(如 LevelDB、RocksDB、HBase、Cassandra)等系统。 它的核心思想是: 写入时只追加写(Append-Only),将数据先写入内存缓冲区(MemTable)。内存数据满后…...
uni-app jyf-parser将字符串转化为html 和 rich-text
uni-app jyf-parser将字符串转化为html-CSDN博客 方法二: rich-text | uni-app...
Docker+Ollama+Xinference+RAGFlow+Dify部署及踩坑问题
目录 一、Xinference部署 (一)简介 (二)部署 (三)参数 (四)错误问题 (五)Xinference配置Text-embedding模型 (六)Xinference配…...
CentOS 7 搭建基于匿名用户的 FTP 服务
1. 安装 VSFTPD yum install vsftpd -y 2. 配置 VSFTPD 编辑主配置文 vi /etc/vsftpd/vsftpd.conf 以下配置项存在或修改为对应值 anonymous_enableYES # 启用匿名用户 local_enableNO # 禁用本地用户 write_enableYES # 允许写入(若需要匿名上传࿰…...
【机器学习】什么是线性回归?
什么是线性回归? 线性回归是一种 监督学习算法,它通过拟合一个直线(或平面,高维空间下是超平面)来建立 输入特征 和 输出目标 之间的关系。简单来说,线性回归就是找出一个数学方程(通常是线性方…...
零、ubuntu20.04 安装 anaconda
1.anaconda下载 地址:Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 选择:Anaconda3-2023.07-2-Linux-x86_64.sh 2.anaconda安装 选择下载目录,选在在终端中打开,然后在终端输入安装命…...
Web纯前端实现在线打开编辑保存PPT幻灯片
很多项目中有时会需要在线打开PPT并编辑保存到服务器。猿大师办公助手可以完美调用本地office在线打开ppt文件,跟本地打开效果一样。还可以在线打开word、excel、pdf等文件,支持本机OFFICE完整嵌入模式,本机OFFICE所有功能基本都可以在网页上…...
LeetCode热题100精讲——Top3:最长连续序列【哈希】
你好,我是安然无虞。 文章目录 题目背景最长连续序列C解法Python解法 题目背景 如果大家对于 哈希 类型的概念并不熟悉, 可以先看我之前为此专门写的算法详解: 蓝桥杯算法竞赛系列第九章巧解哈希题,用这3种数据类型足矣 最长连续序列 题目链接&#x…...
vue2相关 基础命令
vue2 基础命令 vue简介,Vue 2 已于 2023 年 12 月 31 日停止维护。详见 Vue 2 终止支持 (EOL)。 安装完 Visual Studio Code后,打开项目目录, 在目录位置输入cmd,然后在命令行输入 code . 就可以在VScode打开项目。 公司的前后端…...
2025年渗透测试面试题总结-某 长亭(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 长亭 一、Spring SpEL表达式注入漏洞 1. 技术原理 2. 利用条件 3. 攻击方法 4. 防御策略 二、Jav…...
【web3】
检测钱包是否安装 方法一 // npm install metamask/detect-provider import detectEthereumProvider from metamask/detect-provider// 检测钱包是否安装 const isProvider await detectEthereumProvider() if(!isProvider) {proxy.$modal.msgError("请安装钱包")…...
Ubuntu部署Dufs文件服务器
安装dufs 安装cargo apt install cargo升级rust工具链 apt install rustup rustup update stable查看rust版本,需要>1.81 rustc --version安装dufs cargo install dufs将dufs加入环境变量 sudo vim ~/.bashrc export PATH"$HOME/.cargo/bin:$PATH" sou…...
速卖通API数据清洗实战:从原始JSON到结构化商品数据库
下面将详细介绍如何把速卖通 API 返回的原始 JSON 数据清洗并转换为结构化商品数据库。 1. 数据获取 首先要借助速卖通 API 获取商品数据,以 Python 为例,可使用requests库发送请求并得到 JSON 数据。 import requests# 替换为你的 API Key 和 Secret …...
