你一定要知道的unittest自动化测试框架详解

news2024/11/23 6:16:50

目录

框架的概念

Unittest单元测试框架

常用的assert语句

unittest创建测试代码的方式:

unittest构建测试套件(测试用例集合):

unittest忽略测试用例:

运行测试集

批量执行测试用例

生成HTMLTestRunner测试报告

不同文件中的用例构建测试套件

测试报告再优化

框架结构改进

用例读取改进


框架的概念

在系统开发过程中,框架是指对特定应用领域中的应用系统的部分设计和实现子系统的整体结构。
框架将应用系统划分为类和对象,定义类和对象的责任,类和对象如何相互协作,以及对象之间的控制线程。这些共有的设计因素由框架预先定义,应用开发人员只须关注于特定的应用系统特有部分。
自动化测试框架的定义为:
由一个或多个自动化测试基础模块、自动化测试管理模块、自动化测试统计模块等组成的工具集合。

  • 按框架的定义来分,自动化测试框架可以分为:基础功能测试框架、管理执行框架;
  • 按不同的测试类型来分,可以分为:功能自动化测试框架、性能自动化测试框架;
  • 按测试阶段来分,可以分为:单元自动化测试框架、接口自动化测试框架、系统自动化测试框架;
  • 按组成结构来分,可以分为:单机自动化测试框架、综合自动化测试框架。
  • 按部署方式来分,可以分为:单机自动化测试框架、分布式自动化测试框架。

Unittest单元测试框架

Unittest框架(又名PyUnit框架)为Python语言的单元测试框架。

Unittest测试框架使用介绍

1.用import语句引入unittest模块
2.让所有执行测试的类都继承于TestCase类,可以将TestCase看成是对特定类进行测试的方法的集合
3.setUp()方法中进行测试前的初始化工作,teardown()方法中执行测试后的清除工作,它们都是TestCase中的方法
4.编写测试的方法最好以test开头(可以直接运行)def test_add(self)、def test_sub(self)等,可以编写多个测试用例对被测对象进行测试
5.在编写测试方法过程中,使用TestCase class提供的方法测试功能点,比如:assertEqual等
6.调用unittest.main()方法运行所有以test开头的方法。

unittest自动化测试框架:3天精通Unittest自动化测试实战训练营,零基础小白都能学_哔哩哔哩_bilibiliicon-default.png?t=N3I4https://www.bilibili.com/video/BV1zg4y1g7it/?spm_id_from=333.999.0.0

 

应用实例:
对模块中的加法功能测试
存在一个calc.py的模块,里面存在一个加法功能:

def sum(a,b):
    return a+b
 
#encoding:utf-8
import unittest  #导入unittest
import calc  #导入被测模块
 
class mytest(unittest.TestCase):
    def setUp(self):  #初始化工作
        pass
    def tearDown(self):  #退出清理工作
        pass
    def testsum(self):  #具体的测试用例,一定要以test开头
        self.assertEqual(calc.sum(1,2),2,"testing sum")
if __name__ == "__main__":
    unittest.main()

实例:

#被测对象 a.py
def add(a,b):
    return a+b
 
#测试类 Test.py
import unittest
from common.a import add
 
class Test(unittest.TestCase):
    def setUp(self):  #重写父类setUp的方法,用于执行用例之前的准备工作。
        print("setUp")
        #pass
 
    def tearDown(self):  ##重写父类的tearDown的方法。用于执行用例之后的扫尾工作。
        print("tearDown")
        #pass
 
    #测试用例方法用于测试add的函数,这个方法必须以test开头
    def test_int_add(self):
        print("test_int_add")
        sum = add(10,20)
        #断言结果
        self.assertEqual(sum,30)
 
    def test_float_add(self):
        print("test_float_add")
        sum = add(10.2,20.8)
        #断言结果
        self.assertEqual(sum,31)
 
if __name__ == '__main__':
    unittest.main()

常用的assert语句

assertEqual(a,b) a==b
assertNotEqual(a,b) a!=b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a,b) a is b
assertIsNot(a,b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a,b) a in b
assertNotIn(a,b) a not in b
assertNotIsInstance(a,b) not isinstance(a,b)
assertGreater(a,b) a>b
assertGreaterEqual(a,b) a>=b
assertLess(a,b) a<b
assertLessEqual(a,b) a<=b

unittest创建测试代码的方式:

#方式一:创建子类继承unittest.TestCase,然后重写runTest方法
class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        pass
    def runTest(self):
        pass
    def tearDown(self):
        pass
 
#方式二:编写以test开头的方法
class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        pass
    def test_xx1(self)
    def test_xx2(self)
    ...
    def test_xxN(self)
    def tearDown(self):
        pass

unittest构建测试套件(测试用例集合):

前提Tester是继承了unittest.TestCase的子类

#方式一:
Suite=unittest.TestSuite()
Suite.addTest(Tester('test_default_size'))
Suite.addTest(Tester('test_resize'))
 
#方式二(推荐):
def suite():
    Suite=unittest.TestSuite()
    Suite.addTest(Tester('test_default_size'))
    Suite.addTest(Tester('test_resize'))
    return suite
 
#方式三(推荐):
def suite():
    tests=['test_default_size','test_resize']
    return unittest.TestSuite(map(Tester,tests))
 
#构建测试套件举例:
#存在如下类calc:
#encoding:utf-8
class calc():  #计算器类
    def __init__(self,a,b):  #初始化
        self.numa=a
        self.numb=b
    def sum(self):  #加法
        return self.numa+self.numb
    def sub(self):  #减法
        return self.numa-self.numb
    def multi(self):  #乘法
        pass
 
#测试方法
import unittest  #导入unittest
import calc
class mytest(unittest.TestCase):
    def setUp(self):  #初始化工作
        self.testnum=calc.calc(3,4)
    def tearDown(self):  #退出清理工作
        del self.testnum
    def testsum(self):  #具体的测试用例
        self.assertEqual(self.testnum.sum(),7,"testing sum")
    def testsub(self):  #具体的测试用例
        self.assertEqual(self.testnum.sub(),-1,"testing sub")
    def testmulti(self):  #具体的测试用例
        self.assertEqual(self.testnum.multi(),12,"testing multi")
    def suite():
        Suite=unittest.TestSuite()
        Suite.addTest(mytest('testsum'))
        Suite.addTest(mytest('testsub'))
        return suite
if __name__=="__main__":
    unittest.main(defaultTest='suite')

unittest忽略测试用例:

unittest支持忽略部分测试用例不执行,分无条件忽略和有条件忽略,通过装饰器实现。
使用unittest.skip装饰器族跳过test method或者test class,这些装饰器包括:
1.@unittest.skip(reason):无条件跳过测试,reason描述为什么跳过测试
2.@unittest.skipIf(condition,reason):condition为true时跳过测试
3.@unittest.skipUnless(condition,reason):condition不是true时跳过测试
4.@expected failure:使用@unittest.expectedFailure装饰器,如果test失败了,这个test不计入失败的case数目

举例:

def testsub(self):  #具体的测试用例
    self.assertEqual(self.testnum.sub(),-1,"testing sub")
@unittest.skip("test skipping")  #跳过测试用例
def testmulti(self):  #具体的测试用例
    self.assertEqual(self.testnum.multi(),12,"testing multi")

运行测试集

unittest使用TestRunner类作为测试用例的基本执行环境,来驱动整个单元测试过程,在单元测试时,一般不直接使用TestRunner类,而是使用其子类TextTestRunner来完成测试,并将结果以文本方式显示出来。

Runner = unittest.TestTestRunner()
runner.run(suite)

同时,在unittest模块中定义了一个名为main的全局方法,使用它可以很方便地将一个单元测试模块变成可以直接运行的测试脚本,main()方法使用TestLoader类来搜索所有包含在该模块中的测试方法,并自动执行它们。按照(以test开头)来命名所有测试方法,只需要在测试模块的最后加入如下几行代码:

if __name__=="__main__":
    unittest.main()

或者加参数如下:

unittest.main(defaultTest='suite')

批量执行测试用例

通过前面的介绍,我们可以在一个.py文件里面编写多个测试用例,然后执行文件里的所有测试用例,但是如果测试用例数量过多,放一文件里面就不合理了。
比较合理的做法是把相关的几条用例放到一个.py文件里,把所有.py的文件放到一个文件夹下,然后通过一个程序执行文件夹里面所有用例。

目录结构:

  • unittest
    • test_case
      • search.py
      • baidu.py
    • test_case.py

baidu.py内容如下:

#-*- coding:utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time,os,unittest
 
class baidu(unittest.TestCase):
    def setUp(self):
        Chromedi="D:\Google\Chrome\Application\chromedirver.exe"
os.enciron["webdriver.Chrome.driver"]=Chromedi
self.driver=webdriver.Chrome(Chromedi)
self.baseurl="http://www.baidu.com"
self.verificationErrors=[]
self.accpet_next_alert=True
#测试百度知道链接是否正确
def test_baidu_set(self):
    driver=self.driver
    driver.maxmize_window()
    driver.get(self.baseurl+"/")
    m=dirver.find_element_by_name("tj_briicon")
    ActionChains(driver).move_to_element(m).perform()
driver.find_element_by_partial_link_text("知道").click()
# self.assertEqual(driver.current_url,"http://zhidao.baidu.com/")
self.assertEqual(driver.title,u"百度知道-全球最大中文互动问答平台")
time.sleep(2)
def tearDown(self):
    self.driver.quit()
 
if __name__=="__main__":
    unittest.main()

search.py内容如下:

#-*- coding:utf-8 -*-
from selenium import webdriver
import time,os,unittest
 
class search(unittest.TestCase):
    def setUp(self):
        Chromedi="C:\Google\Chrome\Application\chromedriver.exe"
os.environ['webdriver.Chrome.driver']=Chromedi
self.driver=webdriver.Chrome(Chromedi)
self.baseurl="http://www.baidu.com"
self.verificationErrors=[]
self.accpet_next_alert=True
 
#测试百度搜索
def test_search(self):
    driver=self.driver
    driver.maximize_window()
    driver.get(self.baseurl+"/")
 
driver.find_element_by_css_selector("#kw").send_keys("12306")
driver.find_element_by_css_selector("#su1").click()
def tearDown(self):
    self.driver.quit()
    self.assertEqual([],self.verificationErrors)
 
if __name__=="__main__":
    unittest.main()

test_case.py内容如下:

import os
caselist=os.listdir("D:\\unittest\\test_case")
for a in caselist:
    s=a.split('.')[-1]
    if s=='py':
        os.system('python D:\\unittest\\test_case\\%s 1>>log.txt 1>>&1'%a)

caselist获取test_case目录下所有的文件列表做成列表
"baidu.py"为列表的一个元素,用split以"."分割为2个字符串,[-1]表示取出后面py的字符串,判断是否是测试用例文件。如果是用os.system执行DOS命令,DOS命令为执行测试用例并把日志打印到log.txt

至此,一个简单的单元自动化测试框架实现完毕。

unittest自动化测试框架:3天精通Unittest自动化测试实战训练营,零基础小白都能学_哔哩哔哩_bilibiliicon-default.png?t=N3I4https://www.bilibili.com/video/BV1zg4y1g7it/?spm_id_from=333.999.0.0

 

生成HTMLTestRunner测试报告

HTMLTestRunner是Python标准库的unittest模块的一个扩展。它能生成易于使用的HTML报告。
1、下载HTMLTestRunner.py文件:
2、将该文件保存在python安装路径下的lib文件夹中。在文件中能import HTMLTestRunner成功,即配置成功。
注:如果失败,在项目中新建一个这样的文件也是可以的,只要达到能引入和使用就行。

针对baidu.py文件修改如下:
import HTMLTestRunner #导入HTMLTestRunner报告

if __name__=="__main__":
    suite=unittest.TestSuite()  #构建测试套件
    suite.addTest(baidu("test_baidu_set"))  #添加测试用例到套件
    filename='D:\\unittest\\test_case\\result.html'  #建立HTML报告文件
    fp=file(filename,'wb')
    runner=HTMLTestRunner.HTMLTestRunner(stream=fp,title=u"百度知道测试报告",description=u"用例执行情况:")  #自定义测试报告
    runner.run(suite)  #运行测试用例

说明:
使用HTMLTestRunner配置参数,stream为输出报告路径、title为报告标题、description为描述信息

不同文件中的用例构建测试套件

生成HTMLTestRUnner测试报告的时候,会发现一个.py文件产生一个测试报告,那么对于测试用例的多个测试用例文件会产生多个测试报告,这在实际中会导致测试报告不方便阅读;如果把所有测试用例写在一个py文件里,会导致用例不好维护。
之前使用TestSuite只是在一个.py文件里添加多个测试用例,我们可以跨文件通过TestSuite来组织测试用例。

import unittest  #导入单元测试框架
import asearch,baidu  #导入测试用例py文件
 
alltest=unittest.TestSuite()  #构建测试套件
alltest.addTest(unittest.makeSuite(asearch.search))  #增加测试用例集
alltest.addTest(unittest.makeSuite(baidu.baidu))  #增加测试用例集
runner=unittest.TextTestRunner(verbosity=2)
runner.run(alltest)  #运行测试

makeSuite用于生产testsuite对象的实例,把所有的测试用例组装成TestSuite,最后把TestSuite传给TestRunner执行。

测试套件的语法:

suite1=module1.TheTestSuite()
suite2=module2.TheTestSuite()
alltests=unittest.TestSuite((suite1,suite2))

整合测试报告

import unittest  #导入单元测试框架
import asearch,baidu  #导入测试用例py文件
import HTMLTestRunner
 
alltest=unittest.TestSuite()  #构建测试套件
alltest.addTest(unittest.makeSuite(asearch.search))  #增加测试用例集
alltest.addTest(unittest.makeSuite(baidu.baidu))  #增加测试用例集
filename="D:\\unittest\\test_case\\result.html"
fp=file(filename,'wb')
runner=HTMLTestRunner.HTMLTestRunner(stream=fp,title=u"百度知道测试报告",description=u"执行测试用例情况test:")
runner.run(alltest)

备注:unittest.makeSuite()是直接从一个TestCase的类生成一个TestSuite。
测试套件运行每个测试用例的顺序是由测试方法名根据Python内建函数cmp所排序的顺序而决定的。

测试报告再优化

1、易读性优化:
可以给每个测试用例加上注释:

def test_baidu_self(self):
"""百度知道链接测试"""
driver=self.driver
driver.maximize_window()

2、测试报告名称加时间戳:
引入python的time模块给测试报告加自定义名称

import time
#生成格式化时间
now=time.strftime("%Y_%m_%d_%H_%M_%S",time.localtime(time.time()))
#now=time.strftime("%Y_%m_%d_%H_%M_%S")
#采取字符串拼接给测试报告加时间
filename='D:\\unittest\\test_case'+now+'_result.html'
 
#生成的报告文件名格式为:2019_01_01_10_30_59_result.html

框架结构改进

1、执行用例的主文件移出测试用例文件夹
执行用例的主文件是执行所有测试用例的程序,而并非是测试用例本身,把它移出来结构更为合理。
移出来执行用例的主文件后,会发现import测试用例类报错,这是需要使用python包。

在test_case下新建一个__init__.py的文件,文件内容可以为空,同时将test_case目录添加到sys.path中

import sys
sys.path.append("\test_case")
from test_case import baidu,asearch

sys.path.append 把test_case目录添加到path下,使用的是相对路径
当执行用例的主文件和测试用例放置在同一目录下,可以直接调用;移除出来之后就找不到模块了;python查找模块是先从当前目录查找,如果找不到再从安装python安装设置的相关路径下去查找,这里使用sys.path目的就是设置路径。
为了标识一个目录是可引用的包,需要在目录下创建__init__.py的文件

2、init.py文件的使用:
一个Python包是一个带有特殊文件__init__.py的目录。init.py文件定义了包的属性和方法,它控制着包的导入行为。
假如__init__.py为空,那么仅仅导入包是什么都做不了的。

对于from test_case import,asearch 把baidu和asearch文件导入到测试用例执行主文件,也可以在__init__.py文件实现导入:
在__init__.py中添加如下内容

import baidu
import asearch

然后在测试用例执行主文件中,可以如下方式调用baidu 和asearch文件:

from test_case import *

这样也跟编写from test_case import baidu,asearch的作用是一致的。

3、把用例中的公共模块移出
首先在test_case目录下创建一个Public 目录,然后把一些公共的模块用函数或者类实现,比如:登录模块,退出模块,同时把测试用例做相应修改

sys.path.append("\public")
from public import login
login.login()

用例读取改进

在实际过程中,可能我们需要组织成百上千条测试用例,虽然我们可以通过导入包文件的方式添加测试用例,但每创建一个新的测试用例都需要在测试套件中增加一条add Test语句,随着用例的增加,不便于管理和维护。

解决方法一:
首先把用例文件组装称为一个数组,然后使用for循环遍历的方式读取测试用例文件。示例如下:

testnames=[asearch.search,baidu.baidu]
alltest=unittest.TestSuite()  #构建测试套件
for testname in testnames:
    alltest.addTest(unittest.makeSuite(testname))  #增加测试用例集

然后,为了在增添或者删除测试用例时不必对执行测试用例的主文件做任何修改,可以把用例列表放置到一个单独的文件中通过执行测试用例的主文件导入。

解决方法二:
使用discover解决用例的读取。在使用解决方法一for循环处理用例读取的时候,如果新增测试用例文件testa.py,那么需要在__init__.py文件中编写import testa,还需要在测试用例列表文件的数据中增加相应测试用例名称,这样才能使新的测试用例添加到测试套件中执行,这样做显然不方便。
对于上述情况,可以使用TestLoader(测试用例加载器)中的加载多个测试用例方法来实现。

discover函数原型如下:
discover(start_dir,pattern='test*.py',top_level_dir=None)

递归查找指定目录(start_dir)及其子目录下的全部测试模块,将这些测试模块放入一个TestSuite对象并返回。只有匹配pattern的测试文件才会被加载到TestSuite中。
如果一个测试文件的名称符合pattern,将检查该文件是否包含load_tests()函数,如果load_tests()函数存在,则由该函数负责加载本文件中的测试用例。如果不存在,就会执行loadTestsFromModule(),查找该文件中派生自TestCase的类包含的test开头的方法。
top_level_dir=None:测试模块的顶级目录(指测试用例不是放在多级目录中),如果没有顶级目录,默认为空。

test_lists="D:\\unittest\\test_case"
def creatsuite():
    testunit=unittest.TestSuite()
    discover=unittest.defaultTestLoader.discover(
        test_lists,
        pattern='ok_*.py',
        top_level_dir=None
    )
    for testsu in discover:
        for testcase in testsu:
            testunit.addTests(testcase)
    return testunit
testnames=createsuite()
runner.run(testnames)

在实际测试用例开发过程中,我们可以使用约定,写好的用例用ok_或者其他标识开头,没有写好的暂时不用ok_开头。不然会影响测试用例的执行。

简单框架目录结构

  • unittest
    • test_case
      • ok_baidu.py 测试用例
      • ok_search.py 测试用例
      • init.py
      • Public
        • login.py 公共模块
        • quit.py 公共模块
        • init.py
    • report
      • time_result.html 测试报告
        -data
      • userinfo.csv 参数化文件
    • test_all.py 执行所有用例

总结:

感谢每一个认真阅读我文章的人!!!

我个人整理了我这几年软件测试生涯整理的一些技术资料,包含:电子书,简历模块,各种工作模板,面试宝典,自学项目等。欢迎大家点击下方链接免费领取,千万不要错过哦。

3天精通Unittest自动化测试实战训练营,零基础小白都能学_哔哩哔哩_bilibiliicon-default.png?t=N3I4https://www.bilibili.com/video/BV1zg4y1g7it/?spm_id_from=333.999.0.0&vd_source=6e2d6c374fd551babe1ac6a5e60c5a75

 

 

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

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

相关文章

【运维知识进阶篇】集群架构-Nginx基础(安装+启动+配置+多业务实现+日志管理)

本篇文章介绍下Nginx有关内容&#xff0c;Nginx是一个开源且高性能、可靠的Http Web服务、代理服务。 开源&#xff1a;直接获取源代码&#xff0c;高性能&#xff1a;支持海量并发&#xff0c;可靠&#xff1a;服务稳定 Web服务有很多&#xff0c;选择Nginx是因为他的轻量化…

【软件测试】测试开发的一生之敌-BUG

文章目录 1.前言2.如何描述/创建一个BUG3.BUG的级别4.BUG的生命周期5.跟开发产生争执怎么办 1.前言 BUG相比大家都知道,程序运行出错或者与预期不符就是BUG.现在我们来用测试人员的角度来看待BUG. 2.如何描述/创建一个BUG 测试人员要测试开发人员的代码,找出开发人员可能忽略…

敏态开发在大兴机场数字化转型中的实践

一、最大事业是育人 大兴机场是一个年轻的企业&#xff0c;作为一个企业来讲&#xff0c;最宝贵的就是人才。我们在2017年开始社招大学生&#xff0c;到目前为止&#xff0c;公司有一半都是30岁左右的年轻人&#xff0c;并且每年都会招几十个。年轻人特别想做事&#xff0c;而…

C++之内存管理及函数模版

C中的内存管理机制和C语言是一样的&#xff0c;但在具体内存管理函数上&#xff0c;C语言的malloc已经无法满足C面向对象销毁的需求&#xff0c;于是祖师爷在C中新增了一系列内存管理函数&#xff0c;即 new 和 delete 著名段子&#xff1a;如果你还没没有对象&#xff0c;那就…

( 位运算 ) 342. 4的幂 ——【Leetcode每日一题】

❓342. 4的幂 难度&#xff1a;简单 给定一个整数&#xff0c;写一个函数来判断它是否是 4 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 整数 n 是 4 的幂次方需满足&#xff1a;存在整数 x 使得 n 4 x n 4^x n4x。 示例 1&…

src学习记录(二)

学习目标&#xff1a; Apache Shiro ThinkPHP struts2 Apache Log4j Fastjson Weblogic 学习内容&#xff1a; 1.Apache Shiro 字段内容指纹信息请求包中&#xff0c;在Cookie信息中给 rememberMe变量赋任意值&#xff0c;收到返回包的Set-Cookie 值存在 rememberMedeleteMe …

类和对象【C++】【下篇】

目录 一、初始化列表 二、隐式类型转换 三、静态成员 四、友元 1、友元函数 2、友元类 五、内部类 六、匿名对象 一、初始化列表 下面是日期类的一个构造函数&#xff0c;调用该构造函数后&#xff0c;对象中已经有了一个初始值&#xff0c;但并不能将它称为对对象成员变…

实时操作系统内存管理-TLSF算法

内存管理-TLSF算法 前言TLSF算法&#xff1a;为什么内存又叫内存“块”&#xff1a;O(1)查找空闲块&#xff1a;确定fl&#xff1a;确定sl&#xff1a;提级申请&#xff1a;分割块&#xff1a; 空闲块如何串成链表&#xff1f;减少外部碎片&#xff1a;查找上下块&#xff1a; …

Java补充之MySQL入门必备知识

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。 文章目录 零基础学MySQL解决之道文件、数据库MySQL 数据库的安装和配置使用命令行窗口连接MYSQL 数据库操作示意图 数据库三层结构数…

使用Intellij IDEA创建新项目时,maven路径总是默认的,一创建maven就卡死

目录 使用Intellij IDEA创建新项目时&#xff0c;maven路径总是默认的 弄了老半天&#xff0c;终于把这个破玩意给弄好了&#xff0c;真的没有意思&#xff0c;真的很恶心 我经历了两个过程&#xff0c;一个是 使用Intellij IDEA创建新项目时&#xff0c;maven路径总是默认的…

用免费蜜罐工具配置Modbus工控蜜罐

导语&#xff1a;本文将用DecoyMini免费蜜罐工具来配置自定义的ModbusTCP工控仿真模板&#xff0c;并介绍部署后的Modbus蜜罐的使用效果。 DecoyMini是一个免费的蜜罐工具&#xff0c;其特色是仿真能力采用与软件松耦合的仿真模板来进行管理。通过一键式导入云端仿真模板库里的…

【Linux】多线程 --- 线程同步与互斥+生产消费模型

人生总是那么痛苦吗&#xff1f;还是只有小时候是这样&#xff1f; —总是如此 文章目录 一、线程互斥1.多线程共享资源访问的不安全问题2.提出解决方案&#xff1a;加锁&#xff08;局部和静态锁的两种初始化/销毁方案&#xff09;2.1 对于锁的初步理解和实现2.2 局部和全局锁…

计算机中丢失msvcr120.dll怎么办,电脑找不到msvcr120.dll怎么办

电脑提示msvcr120.dll丢失是一个常见的问题&#xff0c;这个问题通常会在你尝试打开某些程序或游戏时出现。这个问题的原因是因为你的电脑缺少了一个名为msvcr120.dll的文件&#xff0c;这个文件是微软Visual C Redistrle for Visualv 2013的一部分。如果你遇到了这个问题&…

算法设计 || 第5题:田忌赛马-杭州电子科技大学(贪心算法)

目录 &#xff08;一&#xff09;杭电原题 &#xff08;二&#xff09;Please speak Chinese: &#xff08;三&#xff09;手写草稿理解思路核心算法 第一款代码&#xff1a; 第二款代码&#xff1a; &#xff08;一&#xff09;杭电原题 Tian Ji -- The Horse Racing Pro…

【分治法】

目录 知识框架No.1 分治法基本思想No.2 合并排序No.3 快速排序一、基本思想三、效率分析四、快速排序不稳定例子 No.4 二叉树遍历及其相关特性一、基本概念二、中序遍历三、前序遍历四、二叉树的高度计算(高度不是深度) 知识框架 No.1 分治法基本思想 将规模为N的问题分解为k…

Spring MVC:常用参数(注解)的使用和参数绑定的验证

Spring MVC&#xff1a;常用参数&#xff08;注解&#xff09;的使用和参数绑定的验证 一、学习资源二、基础源码三、实验结果3.1 Spring MVC常用参数Controller和RequestMappingRequestMappingRequestParamPathVariableCookie ValueRequestHeader 3.2 Spring MVC参数绑定3.2.1…

一路对标顶级产品,奇遇XR为何仍不见起色?

临近6月&#xff0c;再度遇冷的XR行业&#xff0c;又让很多人充满期待。外界普遍认为&#xff0c;基于苹果酝酿多年的MR头显产品&#xff0c;将于6月举行的WWDC 2023全球开发者大会正式亮相&#xff0c;XR行业或将迎来“iPhone时刻”。 在一派期待中&#xff0c;一家国内XR企业…

代码审计之PHP基础铺垫

目录 1、标记 2、注释 3、输出语句 4、关键字 5、常量的定义与使用 6、预定义常量 7、变量的赋值&#xff08;传参赋值与引用赋值&#xff09; 8、可变变量 9、双引号和单引号的区别 10、heredoc结构和nowdoc结构 11、其他符号 1、标记 <?php 和 ?> 是PHP标…

第十一届蓝桥杯青少组省赛Python中/高级组编程题真题,包含答案解析

第十一届蓝桥杯青少组省赛Python中/高级组编程题真题 编程实现 第一题&#xff1a; 输入一个字符串&#xff0c;如果该字符串以er、Iy或者ing后缀结尾的&#xff0c;则删除该字符串后缀&#xff0c;并输出删除后的字符串&#xff0c;否者将原字符串输出。 输入描述 输入一个…