【Unittest】自动化测试框架核心要素
【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程,刷完面试就稳了,你也可以当高薪软件测试工程师(自动化测试)
1、什么是Unittest框架?
python自带一种单元测试框架
2、为什么使用UnitTest框架?
>批量执行用例
>提供丰富的断言知识
>可以生成报告
3、核心要素:
1). TestCase(测试用例)
2). TestSuite(测试套件)
3). TestRunner(测试执行,执行TestUite测试套件的)
4). TestLoader(批量执行测试用例-搜索指定文件夹内指定字母开头的模块) 【推荐】
5). Fixture(固定装置(两个固定的函数,一个初始化时使用,一个结束时使用))
接下来会展开 核心要素来认识unittest框架:
首先介绍下unittest的用例规则:
1、测试文件必须导包:import unittest
2、测试类必须继承 unittest.TestCase
3、测试方法必须以 test_开头
一、TestCase(测试用例)
1、是一个代码文件,在代码文件中来书写真正的用例代码 (里面的print均是模拟测试用例)
# 1、导包
# 2、自定义测试类
# 3、在测试类中书写测试方法 采用print 简单书写测试方法
# 4、执行用例import unittest# 2、自定义测试类,需要继承unittest模块中的TestCase类即可
class TestDemo(unittest.TestCase):# 书写测试方法,测试用例代码,书写要求,测试方法必须test_ 开头def test_method1(self):print('测试方法1-1')def test_method2(self):print('测试方法1-2')# 4、执行测试用例
# 4.1 光标放在类后面执行所有的测试用例
# 4.2 光标放在方法后面执行当前的方法测试用例
说明:def 定义的test_ 是测试用例,只有执行 if __name__ == '___mian___' 的时候会执行测试用例,其他普通函数则不执行,通过 self 来调用执行。
二、TestSuite(测试套件)和TestRunner(测试执行)
1、TestSuite(测试套件):用来组装,打包 ,管理多个TestCase(测试用例)文件的
2、TestRunner(测试执行):用来执行 TestSuite(测试套件的)
代码:首先要准备多个测试用例的文件才可以实现TestSuite和TestRunner,以下代码是已经准备了unittest_Demo2和unittest_Demo1两个测试用例文件
# 1、导包
# 2、实例化(创建对象)套件对象
# 3、使用套件对象添加用例方法
# 4、实例化对象运行
# 5、使用运行对象去执行套件对象import unittestfrom unittest_Demo2 import TestDemo
from unittest_Demo1 import Demosuite = unittest.TestSuite()# 将⼀个测试类中的所有⽅法进⾏添加
# 套件对象.addTest(unittest.makeSuite(测试类名))
suite.addTest(unittest.makeSuite(TestDemo))
suite.addTest(unittest.makeSuite(Demo))# 4、实例化运行对象
runner = unittest.TextTestRunner();
# 5、使用运行对象去执行套件对象
# 运⾏对象.run(套件对象)
runner.run(suite)
三、TestLoader(测试加载)
说明:
将符合条件的测试方法添加到测试套件中
2. 搜索指定目录文件下指定字母开头的模块文件下test开始的方法,并将这些方法添加到测试套件中,最后返回测试套件
3. 与Testsuite功能一样,对他功能的补充,用来组装测试用例
一般测试用例是写在Case这个文件夹里面,当测试用例超多的时候就可以考虑 TestLoader
写法:
1. suite = unittest.TestLoader().discover("指定搜索的目录文件","指定字母开头模块文件")
2. suite = unittest.defaultTestLoader.discover("指定搜索的目录文件","指定字母开头模块文件") 【推荐】
注意:如果使用写法1,TestLoader()必须有括号。
# 1. 导包
# 2. 实例化测试加载对象并添加用例 ---> 得到的是 suite 对象
# 3. 实例化 运行对象
# 4. 运行对象执行套件对象import unittest# 实例化测试加载对象并添加用例 ---> 得到的是 suite 对象
# unittest.defaultTestLoader.discover('用例所在的路径', '用例的代码文件名')
# 测试路径:相对路径
# 测试文件名:可以使用 * 通配符,可以重复使用
suite = unittest.defaultTestLoader.discover('./Case', 'cs*.py')
runner = unittest.TextTestRunner()
runner.run(suite)
TestSuite与TestLoader区别:共同点:都是测试套件不同点:实现方式不同TestSuite: 要么添加指定的测试类中所有test开头的方法,要么添加指定测试类中指定某个test开头的方法TestLoader: 搜索指定目录下指定字母开头的模块文件中以test字母开头的方法并将这些方法添加到测试套件中,最后返回测试套件
四、Fixture(测试夹具)
是一种代码结构,在某些特定情况下,会自动执行。
4.1 方法级别
在每个测试方法(用例代码)执行前后都会自动调用的结构
def setUp(),每个测试方法执行之前都会执行 (初始化)
def tearDown(),每个测试方法执行之后都会执行 (释放)
特性:几个测试函数,执行几次。每个测试函数执行之前都会执行 setUp,执行之后都会执行tearDwon
# 初始化
def setUp(self):# 每个测试方法执行之前执行的函数pass# 释放
def tearDown(self):# 每个测试方法执行之后执行的函数pass
场景:当你要登录自己的用户名账户的时候,都会输入网址,当你准备不用这个页面了,都会关闭当前页面;1、输入网址 (方法级别)2、关闭当前页面 (方法级别)
4.2 类级别
在每个测试类中所有方法执行前后 都会自动调用的结构(在整个类中 执行之前执行之后各一次)
def setUpClass() ,类中所有方法之前
def tearDownClass(),类中所有方法之后
特性:测试类运行之前运行一次setUpClass ,类运行之后运行一次tearDownClass
注意:类方法必须使用 @classmethod修饰
@classmethoddef setUpClass(cls):print('-----------1.打开浏览器')@classmethoddef tearDownClass(cls):print('------------5、关闭浏览器')
案列模板:结合了类级别和方法级别实现的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GBxQV2uP-1647245316010)(C:/Users/15277/AppData/Roaming/Typora/typora-user-images/image-20220303153824329.png)]
提示:无论使用函数级别还是类级别,最后常用场景为:初始化:1. 获取浏览器实例化对象2. 最大化浏览器3. 隐式等待结束:关闭浏览器驱动对象
五、断言 ☆
1、什么是断言:
让程序代替人工自动的判断预期结果和实际结果是否相符
断言的结果:
1)、True,用例通过
2)、False,代码抛出异常,用例不通过
3)、在unittest中使用断言,需要通过 self.断言方法
2、为什么要断言:
自动化脚本执行时都是无人值守,需要通过断言来判断自动化脚本的执行是否通过
注:自动化脚本不写断言,相当于没有执行测试一个效果。
3、常用的断言:
self.assertEqual(ex1, ex2) # 判断ex1 是否和ex2 相等
self.assertIn(ex1, ex2) # ex2是否包含 ex1 注意:所谓的包含不能跳字符
self.assertTrue(ex) # 判断ex是否为True重点讲前两个assertEqual 和 assertIn
方法:
assertEqual:self.assertEqual(预期结果,实际结果) 判断的是预期是否相等实际
assertIn:self.assertIn(预期结果,实际结果) 判断的是预期是否包含实际中
assertIn('admin', 'admin') # 包含
assertIn('admin', 'adminnnnnnnn') # 包含
assertIn('admin', 'aaaaaadmin') # 包含
assertIn('admin', 'aaaaaadminnnnnnn') # 包含
assertIn('admin', 'addddddmin') # 不是包含
# Login 函数我已经封装好了,这里直接导包调用就可以了。import unittestfrom login import Loginclass TestLogin(unittest.TestCase):"""正确的用户名和密码: admin, 123456, 登录成功"""def test_success(self):self.assertEqual('登录成功', Login('admin', '123456'))def test_username_error(self):"""错误的用户名: root, 123456, 登录失败"""self.assertEqual('登录失败', Login('root', '123456'))def test_password_error(self):"""错误的密码: admin, 123123, 登录失败"""self.assertEqual('登录失败', Login('admin', '123123'))def test_error(self):"""错误的用户名和错误的密码: aaa, 123123, 登录失败"""# self.assertEqual('登录失败',Login('登陆失败','123123'))self.assertIn('失败', Login('登录失败', '123123'))
六、跳过
对于一些未完成的或者不满足测试条件的测试函数和测试类, 不想执行,可以使用跳过
"""
使用方法,装饰器完成
代码书写在 TestCase 文件
"""
# 直接将测试函数标记成跳过
@unittest.skip('跳过条件')
# 根据条件判断测试函数是否跳过 , 判断条件成立, 跳过
@unittest.skipIf(判断条件,'跳过原因')
import unittestversion = 20class TestDemo1(unittest.TestCase):@unittest.skip('直接跳过')def test_method1(self):print('测试用例1-1')@unittest.skipIf(version > 19, '版本大于19,测试跳过')def test_method2(self):print('测试用例1-2')
结果
七、数据驱动(unittest ddt)☆
ddt:data-driver tests
数据驱动:是以数据来驱动整个测试用例的执行, 也就是测试数据决定测试结果
数据驱动解决的问题是:
1)、代码和数据分离,避免代码冗余
2)、不写重复的代码逻辑;
在python解释器中需要安装 ddt 这个包才能用:
要检查是否安装上,在cmd当中 输入 pip list命名,有ddt说明安装成功
语法:
1、使用数据驱动,要在class前加上修饰器 @ddt
说明:方法里面使用 print ,为了方便,模拟测试用例,主要是为了学习数据驱动,实际中方法里面写的是测试用例的代码
import unittest
from ddt import ddt, data@ddt
class TestDemo(unittest.TestCase):# 单一参数@data('17611110000', '17611112222')def test_1(self, phone):print('测试一电话号码:', phone)if __name__ == '__main__':unittest.main()
else:pass
1)、结合 selenium 使用 ddt
"""
unittest + selenium
"""
import unittest
from time import sleepfrom ddt import ddt, data
from selenium import webdriver@ddt
class TestBaidu(unittest.TestCase):def setUp(self) -> None:self.driver = webdriver.Chrome()self.driver.get('https://www.sogou.com/')def tearDown(self) -> None:sleep(3)self.driver.quit()# 单一参数@data('易烊千玺', '王嘉尔')def test_01(self, name):self.driver.find_element_by_id('query').send_keys(name)self.driver.find_element_by_id('stb').click()if __name__ == '__main__':unittest.main()
self:相当于java中的this,当前对象的引用,self.driver定义了driver这个变量。
2、在实际中不可能是单一参数进行传参,将会使用多个参数进行传参:
注意事项:
1)、多个数据传参的时候@data里面是要用列表形式
2)、会用到 @unpack 装饰器 进行拆包,把对应的内容传入对应的参数;
import unittest
from ddt import ddt, data, unpack@ddt
class TestDemo(unittest.TestCase):# 多参数数据驱动@data(['admin', '123456'])# unpack 是进行拆包,不然会把列表里面的数据全部传到username这个一个参数,我们要实现列表中的两个数据分别传入对应的变量中@unpackdef test_2(self, username, password):print('测试二:', username, password)if __name__ == '__main__':unittest.main()
else:pass
但是以上步骤都是数据在代码当中的,假如要测试n个手机号这样的数据,全部写在 @data 装饰器里面就很麻烦,这就引出了数据驱动里面的代码和数据的分离。
3、将数据放入一个文本文件中,从文件读取数据, 如JSON、 excel、 xml、 txt等格式文件 ,这里演示的是json文件类型.
json文件处理, 这个链接介绍了json文件和Python文件基本操作
(1)、在json文件驱动
[{"username": "admin","password": "123456"},{"username": "normal","password": "45678"}
]
(2)、在测试代码中读取json文件
import json
import unittest
from ddt import ddt, data, unpack# 用json多个参数读取
def reads_phone():with open('user.json', encoding='utf-8') as f:result = json.load(f) # 列表return result@ddt
class TestDemo(unittest.TestCase):# 多参数数据驱动@data(*reads_phone())# unpack 是进行拆包,不然会把列表里面的数据全部传到username这个一个参数,我们要实现列表中的两个数据分别传入对应的变量中@unpackdef test_2(self, username, password):print('测试二:', username, password)if __name__ == '__main__':unittest.main()
else:pass
注意事项:
1、with open里面默认是 ”r“
2、@data 里面的 * 含义是实现每个json对象单个传入方法执行,不然会吧json文件里面所用数据全部传入 > * 是元祖;> ** 是字典;
3、参数不能传错,要对应
执行结果:
(3)、txt文件驱动
一行表示一组:
admin,123456
normal,456789
import unittest
def read():lis = []with open('readtext.txt', 'r', encoding='utf-8') as f:for line in f.readlines():# lis.append(line) # ['admin,123456\n', 'normal,456789\n']# lis.append(line.strip('\n')) ['admin,123456', 'normal,456789'] 两个字符串lis.append(line.strip('\n').split(',')) # [['admin', '123456'], ['normal', '456789']]return lisclass TestDome(unittest.TestCase):def test_01(self):li = read()print(li)if __name__ == '__main__':unittest.main()
"""
split():一个字符串里面用某个字符分割,返回列表
strip():去掉两边的字符或者字符串,默认删除空白符(包括'\n', '\r', '\t', ' ')
"""
(3)、csv 文件驱动
供应商名称,联系人,移动电话
英业达,张三,13261231234
阿里巴巴,李四,13261231231
日立公司,王五,13261231233
写法一:
"""
编写 csvv.py脚本读取csv中的测试数据
"""
import csv
class ReadCsv():def read_csv(self):lis = []# 用csv的API的reader方法!!!!data = csv.reader(open('testdata.csv', 'r')) #!!!!next(data, None)for line in data:lis.append(line)# lis.append(line[0]) # 二维数组可以省略行,列不可以省略# lis.append(line[1])return lis# 实例化类
readCsv = ReadCsv()
# 打印类中的方法
print(readCsv.read_csv())
写法二:推荐
def csvTest():li = []with open('user.csv', 'r', encoding='utf-8') as f:filename = csv.reader(f)next(filename, None)for r in filename:li.append(r)return li
(4) 、yaml文件驱动
-username: admin9password: 123456
-username: normalpassword: 789456
对应的json文件
[{"username": "admin9","password": 123456},{"username": "normal","password": 7894}
]
写法:
"""
使用yaml数据驱动
"""import unittest
from time import sleepfrom selenium import webdriver
from ddt import ddt, data, unpack, file_data@ddt
class YamlTest(unittest.TestCase):def setUp(self) -> None:self.driver = webdriver.Chrome()self.driver.get('file:///D:/%E6%A1%8C%E9%9D%A2/page/%E6%B3%A8%E5%86%8CA.html')self.driver.maximize_window()def tearDown(self) -> None:driver = self.driversleep(3)driver.quit()# file_data 传入多个参数的时候,@unpack 的解包不起作用@unittest.skip@file_data('../user.yaml')@unpackdef test_yaml01(self, username, password):driver = self.driverdriver.find_element_by_id('userA').send_keys(username)driver.find_element_by_id('passwordA').send_keys(password)# 注意:传的参数名称要与yaml文件对应# 在yaml数据中文件中采用对象(键值对)的方式来定义数据内容@file_data('../user1.yaml')def test_yaml02(self, username, password):driver = self.driverdriver.find_element_by_id('userA').send_keys(username)driver.find_element_by_id('passwordA').send_keys(password)if __name__ == '__main__':unittest.main()
注意:file_date 装饰器,可以直接读取yaml和json文件
(4)、Excel文件驱动
建立excel表的时候需要退出pychram在根目录下创建excel表保存,否则会报错
def read_excel():xlsx = openpyxl.load_workbook("../excel.xlsx")sheet1 = xlsx['Sheet1']print(sheet1.max_row) # 行print(sheet1.max_column) # 列print('=======================================================')allList = []for row in range(2, sheet1.max_row + 1):rowlist = []for column in range(1, sheet1.max_column + 1):rowlist.append(sheet1.cell(row, column).value)allList.append(rowlist)return allList
用excel登录csdn操作
"""
测试excel数据驱动
"""import unittest
from time import sleepimport openpyxl as openpyxl
from ddt import ddt, data, unpack
from selenium import webdriver# 读取excel表中的数据,使用xlrd,openpyxl
def read_excel():xlsx = openpyxl.load_workbook("../excel.xlsx")sheet1 = xlsx['Sheet1']print(sheet1.max_row) # 行print(sheet1.max_column) # 列print('=======================================================')allList = []for row in range(2, sheet1.max_row + 1):rowlist = []for column in range(1, sheet1.max_column + 1):rowlist.append(sheet1.cell(row, column).value)allList.append(rowlist)return allList@ddt
class ExcelText(unittest.TestCase):def setUp(self) -> None:self.driver = webdriver.Chrome()self.driver.get('https://passport.csdn.net/login?code=applets')self.driver.maximize_window()def tearDown(self) -> None:driver = self.driversleep(3)driver.quit()@data(*read_excel())@unpackdef test_excel01(self, flag, username, password):print(flag, username, password)driver = self.driversleep(2)driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[2]/div[1]/div/div[1]/span[4]').click()driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[2]/div[1]/div/div[2]/div/div[1]/div/input').send_keys(username)driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[2]/div[1]/div/div[2]/div/div[2]/div/input').send_keys(password)driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[2]/div[1]/div/div[2]/div/div[4]/button').click()if __name__ == '__main__':unittest.main()
十、截图操作
用例不可能每一次运行都成功,肯定运行时候有不成功的时候。如果可以捕捉到错误,并且把错误截图保存,这将 是一个非常棒的功能,也会给我们错误定位带来方便
截图方法:driver.get_screenshot_as_file
"""
捕捉异常截图测试
"""
import os.path
import time
import unittest
from time import sleepfrom selenium import webdriverclass ScreeshotTest(unittest.TestCase):def setUp(self) -> None:self.driver = webdriver.Chrome()self.driver.get('https://www.sogou.com/')self.driver.maximize_window()def tearDown(self) -> None:sleep(3)driver = self.driverdriver.quit()def test_01(self):driver = self.driverdriver.find_element_by_id('query').send_keys("易烊千玺")driver.find_element_by_id('stb').click()sleep(3)print(driver.title)try:self.assertEqual(driver.title, u"搜狗一下你就知道", msg="不相等")except:self.saveScreenShot(driver, "shot.png")sleep(5)def saveScreenShot(self, driver, filename):if not os.path.exists("./imge"):os.makedirs("./imge")# 格式十分重要,小写大写敏感 %Y%m%d-%H%M%Snow = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))driver.get_screenshot_as_file("./imge/" + now + "-" + filename)sleep(3)if __name__ == '__main__':unittest.main()
十一、测试报告
有两种测试报告:
1、自带的测试报告 2、生成第三方测试报告
9.1 自带测试报告
只有单独运行 TestCase 的代码,才会生成测试报告
10.2 生成第三方测试报告
这里需要第三方的测试运行类模块,然后放在代码的目录中
就像这两个模块一样放进代码目录中
步骤:1. 获取第三方的 测试运行类模块 , 将其放在代码的目录中2. 导包 unittest3. 使用 套件对象, 加载对象 去添加用例方法4. 实例化 第三方的运行对象 并运行 套件对象HTMLTestRunner()
复制
写法一:
import unittestfrom HTMLTestRunner import HTMLTestRunnersuite = unittest.defaultTestLoader.discover('.', 'Uni*.py')
file = 'report1.html'
with open(file, 'wb') as f:runner = HTMLTestRunner(f, 2, '测试报告', 'python3.10') # 运行对象# 运行对象执行套件, 要写在 with 的缩进中runner.run(suite)
写法二:
"""
生成测试报告
"""
import os.path
import sys
import time
import unittest
from time import sleepfrom HTMLTestRunner import HTMLTestRunnerdef createsuite():discovers = unittest.defaultTestLoader.discover("./cases", pattern="cs*.py")print(discovers)return discoversif __name__ == '__main__':# 当前路径# sys.path 是一个路径的集合curpath = sys.path[0]print(sys.path)print(sys.path[0])# 当前路径文件resultreport不存在时,就创建一个if not os.path.exists(curpath+'/resultreport'):os.makedirs(curpath+'/resultreport')# 2、解决重名问题now = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time()))print(time.time())print(time.localtime(time.time()))# 文件名是 路径 加上 文件的名称filename = curpath+'/resultreport/'+now+'resultreport.html'# 打开文件html,是用wb以写的方式打开with open(filename, 'wb') as f:runner = HTMLTestRunner(f, 2, u"测试报告", u"测试用例情况")suite = createsuite()runner.run(suite)
这里面的当前路径也可以用 ./
来表示!!!
"""
生成测试报告
"""
import os.path
import sys
import time
import unittest
from time import sleep
from HTMLTestRunner import HTMLTestRunnerdef createsuite():discovers = unittest.defaultTestLoader.discover("./cases", pattern="cs*.py")print(discovers)return discoversif __name__ == '__main__':# 当前路径文件resultreport不存在时,就创建一个if not os.path.exists('./resultreport'):os.makedirs('./resultreport')# 2、解决重名问题# 格式十分重要 %Y-%m-%d-%H %M %Snow = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time()))print(time.time())print(time.localtime(time.time()))# 文件名是 路径 加上 文件的名称filename = './resultreport/'+now+'resultreport.html'# 打开文件html,是用wb以写的方式打开with open(filename, 'wb') as f:runner = HTMLTestRunner(f, 2, u"测试报告", u"测试用例情况")suite = createsuite()runner.run(suite)
注意:
实例化 第三方的运行对象,HTMLTestRunner()的初始化有多种可以自定义设置
HTMLTestRunner()1、stream=sys.stdout, 必填,测试报告的文件对象(open ), 注意点,要使用 wb 打开2、verbosity=1, 可选, 报告的详细程度,默认 1 简略, 2 详细3、title=None, 可选, 测试报告的标题4、description=None 可选, 描述信息, Python 的版本, pycharm 版本
最后生成结果
unittest框架就本上就是这些知识了,里面记得东西很多,多敲代码,形成记忆...
下面是配套学习资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!
软件测试面试小程序
被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!
涵盖以下这些面试题板块:
1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux
6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础
文档获取方式:
这份文档,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!
以上均可以分享,只需要你搜索vx公众号:程序员雨果,即可免费领取
相关文章:

【Unittest】自动化测试框架核心要素
【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程,刷完面试就稳了,你也可以当高薪软件测试工程师(自动化测试) 1、什么是Unittest框架? python自带一种单元测试框架 2、为什么使用UnitTest框架࿱…...

Hyperloglog
一,前言 在互联网行业中存在两个比较重要的指标:PV(页面访问量)和 UV(用户访问量) 如果有这样的一个业务: 统计PV,那么你会怎么做? 我们可以使用Redis的incr、incrby指…...

如何自动获取短信验证码?
点击下方关注我,然后右上角点击...“设为星标”,就能第一时间收到更新推送啦~~~ 这篇文章通过解决实际项目开发中遇到的如何自动获取短信验证码的问题,进一步讲述在Java中如何使用正则。 Java中如何使用正则 Java中正则相关类位于java.util.r…...

Linux 本地 Docker Registry本地镜像仓库远程连接【内网穿透】
Linux 本地 Docker Registry本地镜像仓库远程连接 文章目录 Linux 本地 Docker Registry本地镜像仓库远程连接1. 部署Docker Registry2. 本地测试推送镜像3. Linux 安装cpolar4. 配置Docker Registry公网访问地址5. 公网远程推送Docker Registry6. 固定Docker Registry公网地址…...

基于Yolov8的工业小目标缺陷检测(4):SPD-Conv,低分辨率图像和小物体涨点明显
💡💡💡本文改进:SPD-Conv,处理低分辨率图像和小物体等更困难的任务时效果明显。 SPD-Conv | 亲测在工业小目标缺陷涨点明显,原始mAP@0.5 0.679提升至0.775 收录专栏: 💡💡💡深度学习工业缺陷检测 :http://t.csdn.cn/fVSgs ✨✨✨提供工业缺陷检测性能提升…...

平均精度(AP)
什么是平均精度(AP) 平均精度 (AP)并不是精度 (P)的平均值。 平均精度 (AP) 是按类别计算的。 mAP(mean average precision)是一个平均值,常用作目标检测中的检测精度指标mAP 指标通过对于一个平均目标来检测任务中多个目标所对应不同 AP&a…...

建议收藏《Verilog代码规范笔记_华为》(附下载)
华为verilog编程规范是坊间流传出来华为内部的资料,其贴合实际工作需要,是非常宝贵的资料,希望大家善存。至于其介绍,在此不再赘述,大家可看下图详细了解,感兴趣的可私信领取《Verilog代码规范笔记_华为》。…...

Nginx环境搭建、负载均衡测试
Nginx环境搭建、负载均衡测试 系统环境: win10,IDEA2020,JDK8 一、nginx环境搭建 1.ngxin下载 Nginx官网下载: http://nginx.org/en/download.html Nginx有三种版本,分别是Mainline version(开发版&…...

软件工程知识总结梳理
🔥🔥宏夏Coding网站,致力于为编程学习者、互联网求职者提供最需要的内容!网站内容包括求职秘籍,葵花宝典(学习笔记),资源推荐等内容。在线阅读:https://hongxiac.com&…...

Mybatis自动映射Java对象 与 MySQL8后的JSON数据
文章目录 Mybatis自动映射Java对象 与 MySQL8后的JSON数据1.转化成为正常Json类型1.1 JsonTypeHander1.2 ListJsonTypeHandler 负责List<T> 类型1.3 实体类1.4 mapper1.5 测试类 2. 存储为携带类型的Json Mybatis自动映射Java对象 与 MySQL8后的JSON数据 1.转化成为正常…...
【JavaScript】深拷贝和浅拷贝
在 JavaScript 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是两种不同的对象复制方法,它们涉及到如何复制对象的属性以及如何处理对象内部的嵌套引用。以下是它们的解释: 浅拷贝(S…...

【SLAM】10.纵观SLAM,对比方案和未来方向
"天下谁人配白衣” SLAM方案研究方向 SLAM方案 站在历史角度,看一下为SLAM的发展带来贡献的方案: 2007年—A.J.Davison—MonoSLAM 视觉SLAM的先驱,建立在EKF基础上,此前基本无法在线运行,意义较大;…...
PyTorch中DistributedDataParallel使用笔记
1. 基本概念 在使用DistributedDataParallel时有一些概率必须掌握 多机多卡含义world_size代表有几台机器,可以理解为几台服务器rank第几台机器,即第几个服务器local_rank某台机器中的第几块GPU 单机多卡含义world_size代表机器一共有几块GPUrank第几…...
前端面试的话术集锦第 18 篇博文——高频考点(HTTP协议 TLS协议)
这是记录前端面试的话术集锦第十八篇博文——高频考点(HTTP协议 & TLS协议),我会不断更新该博文。❗❗❗ 1. HTTP 请求中的内容 HTTP请求由三部分构成,分别为: 请求行 首部 实体 请求行大概长这样GET /images/logo.gif HTTP/1.,基本由请求方法、URL、协议版本组成,…...

SQL Server 数据库变成单个用户怎么办
参考技术A 1、首先我们打开SQL SERVER的管理控制台,找到一个要设置角色的用户。 2、下面我们将为这个用户赋予创建数据库的角色,我们先用这个用户登录管理工具看一下是否具有创建用户的权限。 3、进行数据库创建的时候,提示如下的错误&…...

错过成考报名,今年你还有这两种方式升学!
2023年广东成人高考已经报名结束啦 错过报名或没有抢到考位的同学不用伤心 你还有另外两个提升学历的机会 开放大学or小自考 今天一起来了解一下吧~ 什么是开放大学? 开放教育其实也就是开放大学,也就是我们所说的中央广播电视大学,现在…...

【2023】从事务的特征以及解决方式上分析MySQL是如何保证事务的
----以MySQL的InnoDB介绍 目录 前言事务,事务到底是什么? 一、事务的特征:二、事务特征具体保证1、Redo Log(重做日志) ---保证事务的持久性1.1、🟡刷盘时机1.2、redo log记录形式1.3、redo log日志的好处 2、undo log(回滚日志)…...

MTR 网络连通性测试工具 基础入门 整理
MTR MTR的全称是 my traceroute,是一个集合了 ping 与 traceroute 功能的网络诊断工具,广泛应用于链路测试。相对于 traceroute 只会做一次链路跟踪测试,mtr会对链路上的相关节点做持续探测并给出相应的统计信息。因此,mtr能避免…...
Linux安装mysql数据库并实现主从搭建
一.环境说明 【环境说明】: 192.168.110.161 mysql-master ##网络配置到位,防火墙关闭,selinux关闭 192.168.110.162 mysql-slave ##网络配置到位,防火墙关闭,selinux关闭 两台主机,操作系统是centos7…...

windows使用小技巧之windows照片查看器无法显示此图片
碰到过好几次了,以前没有理会,今天特意去查了一下解决方法,不然确实不太方便。 1、打开“颜色管理”-“高级”: 2、将“设备配置文件”选择为“Agfa:Swop Standard” 3、关闭,重新打开图片,好…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...