软件测试之单元测试自动化入门基础

news2024/11/25 6:40:58

单元测试自动化

所谓的单元测试(Unit Test)是根据特定的输入数据,针对程序代码中的最小实体单元的输入输出的正确性进行验证测试的过程。所谓的最小实体单元就是组织项目代码的最基本代码结构:函数,类,模块等。在Python中比较知名的单元测试模块:

  • unittest

  • pytest

  • doctest

  • nose

测试用例

所谓的测试用例(Test Case),就是执行测试的依据和记录,把测试应用程序的操作步骤用文档的形式描述出来的一份文档。文档的格式可以是Excel、markdown、html、xmind网页。

一份合格的测试用例有利于测试人员理清测试思路,确保需要测试的功能周全没有遗漏,方便测试工作的开展和评估测试工作量,同时还可以便于测试人员记录测试数据和测试工作进度,为后续的回归测试提供样本参考,提升测试效率以及后续测试工作的交接。

那么一份合格的测试用例长什么样子或有什么内容呢?

一份合格的测试用例,应该包含测试时间、测试人员、测试模块名功能点名称用例ID用例说明(测试目的)前置条件输入数据预期结果测试结果(输出结果、实际结果)等。注意:加粗内容为必备的测试用例八要素。

参考文档:

在实际工作中,因为缺陷报告与测试用例作用相似,因此有时候会合并一起或只选择其中一种。

设计方法

那么在工作中,我们一般都应该编写测试用例或者应该怎么设计测试用例来完成我们的测试工作呢?实际上在工作中,测试人员都是基于测试用例的7种基本设计方法来设计与编写测试用例的:

  • 等价类划分法:根据输入数据的有效性与无效性设计测试用例。

  • 边界值分析法:对等价类划分法的一个补充,从等价类的边缘值(临界点)去寻找错误,基于这些错误来设计测试用例。

  • 判定表法:把输入数据的各种可能情况进行组合罗列成一个判断表,以判断表来设计测试用例。

  • 因果图法:用图解的方式表示输入数据的各种组合关系,以此写出判定表,从而设计相应的测试用例。

  • 正交表法:基于正交表来设计测试用例。

  • 场景法:基于流程图展示业务流程或功能的调用流程,对流程图的走向路径设计测试用例。

  • 错误推测法:基于经验和直觉,找出程序中认为可能出现的错误来设计测试用例。

一般在工作中,我们比较常用的是等价类划分法与判定表法。

等价类划分法

等价类划分法就是按照测试要求,把具有共同特征的测试数据划分为2类:有效等价类和无效等价类,把测试数据进行分类以后设计测试用例。

  • 有效等价类,就是符合程序使用要求或调用代码要求的,能正确使用程序或调用代码的一类数据。

  • 无效等价类,就是不符合程序使用要求或调用代码要求的,会导致程序出现异常或结果不正确的一类数据。

使用等价类划分法,可以让我们设计的测试工作更加科学有依据,避免出现穷举测试的情况,减少测试用例的数量。

例如,注册功能中用户名的测试用例,如果功能需求中,要求用户名必须长度为3-11个长度的字符。

系统模块功能点用例ID测试目的前置条件输入预期结果
会员模块用户注册01验证用户名打开用户注册页面"abc"正确
会员模块用户注册02验证用户名打开用户注册页面"abdefgthssaaaaa"错误

判定表法

判定表是分析和表达多逻辑条件下执行不同操作的情况的工具。而软件测试中的判定表法,就是把输入数据的各种可能情况进行组合罗列成一个判断表格,以判断表来设计测试用例。

判定表的表结构一般有如下2种:横向判断表与纵向判定表。

横向判断表:

条件桩条件项
动作桩动作项

纵向判定表:

条件桩动作桩
条件项动作项

例子,测试一个功能是否能修改文件。

如果使用纵向判定表:
条件1:是否有权限条件2:是否存在结果1:可以修改结果2:不能修改

如果使用横向判断表:
条件桩:是否有权限
条件桩:是否存在
动作桩:可以修改
动作桩:不能修改

单元测试框架-Unittest

Unittest是Python开发中常用于单元测试的内置框架,免安装使用简单方便,其设计的灵感来源于Java的单元测试框架-Junit。

Unittest具备完整的测试结构,支持自动化测试的执行,对测试用例进行组织,并且提供了丰富的断言方法,还提供生成测试报告。

官方文档:unittest --- 单元测试框架 — Python 3.11.5 文档

import unittest
print(dir(unittest))

上面的代码中,我们就引入了Unittest模块, 同时可以通过打印发现Unittest框架中内置了大量的工具成员。这些工具成员中除了以下5个以外,其他的都不怎么常用。

  • TestCase(测试用例)

    是unittest中最重要的一个类,用于编写测试用例类,是所有测试用例类的父类,实现了测试用例的基本代码。

  • TestSuite(测试套件、测试集)

    可以把多个TestCase组织、打包集成到一个测试集中一起执行,TestSuite可以实现多个测试用例的执行。

  • TextTestRunner(测试运行器)

    TestSuite本身不具备执行的功能,所以使用TextTestRunner执行测试套件和输出测试结果。

  • TestLoader(测试加载器)

    用于加载测试用例TestCase,并生成测试套件TestSuite,实现自动从代码中加载大量测试用例到测试套件中。

  • TestFixture(测试脚手架)

    所谓的测试脚手架就是为了开展一项或多项测试所需要进行的准备工作,以及所有相关的清理操作。测试脚手架实际上会在执行一些测试代码之前与之后,让我们编写一些初始化和销毁的代码。

快速入门

测试用例-TestCase

前面讲到TestCase就是提供给我们编写测试用例的测试代码的,那么怎么编写一个测试用例?需要4个步骤即可。

  1. 导入unittest模块

import unittest

2.定义测试用例类

import unittest
class 测试用例类名(unittest.TestCase): # 所有的测试用例类都必须直接或者间接继承unittest.TestCase.
    """测试用例"""
    pass

3.定义测试用例方法(此处的测试用例方法,就是上面所说的测试用例设计方法中的一行信息的测试代码)

import unittest
class 测试用例类名(unittest.TestCase):
    """测试用例"""
    # ....
    def test_测试方法名(参数):  # 测试方法必须以test开头或test_开头
        pass
    # ....

4.执行测试用例

unittest.main()

在实际工作中,我们肯定是在项目中进行测试代码的编写或单独编写一个测试项目,但是我们现在刚开始学习,所以我们可以先编写一个例子代码,对其进行测试,以达到学习的目的。

unittest_01_测试用例的编写.py,代码:

import unittest

# 被测试的代码单元
def add(x,y):
    return x+y

class FuncTest(unittest.TestCase):
    """测试用例"""
    def test_01(self):
        print(add(10, 20))

    def test_02(self):
        print(add("hello", "world"))

    # def test_03(self):
    #     print(add("hello", 20))


# 因为pycharm本身内置了执行unittest的功能,所以不适用以下代码也能执行,但是终端下或者使用其他的代码编辑器时,则需要加上。
if __name__ == '__main__':
    unittest.main()

运行结果:

测试套件-TestSuite

前面我们将到测试套件,主要用于把多个测试用例类打包集成到一个测试集中一起执行。工作中,一个项目往往需要编写非常多的测试用例,而那么多的测试用例也不可能只编写在一个文件中,此时就需要使用测试套件了。2个步骤:

  1. 通过unittest.TestSuite实例化测试套件对象

    suite = unittest.TestSuite()

  2. 通过addTest方法添加测试用例

    • 添加测试用例方法

      # 添加测试用例方法
      suite.addtest(测试用例类名("测试用例方法名"))
      ​
      # 批量添加测试用例方法
      test_data = (测试用例类名("测试用例方法名1"), 测试用例类名("测试用例方法名2"))
      suite.addtests(test_data)

    • 添加测试用例类(一次性添加测试用例的所有test_方法)

      # 添加测试用例类
      suite.addtest(unittest.makeSuite(测试用例类名))
      ​
      # 批量添加测试用例类
      test_data = (unittest.makeSuite(测试用例类名1),  unittest.makeSuite(测试用例类名2))
      suite.addTests(test_data)

unittest_02_测试套件的基本使用.py,代码:

import unittest
​
import unittest_01_测试用例的编写 as unittest_01
​
suite = unittest.TestSuite()
​
# # 添加测试用例方法
# suite.addTest(unittest_01.FuncTest("test_01"))
# suite.addTest(unittest_01.FuncTest("test_02"))
​
# # 批量添加测试用例方法
# test_data = (unittest_01.FuncTest("test_01"), unittest_01.FuncTest("test_02"))
# suite.addTests(test_data)
​
​
# # 添加测试用例类
# suite.addTest(unittest.makeSuite(unittest_01.FuncTest))
​
​
# 批量添加测试用例类
test_data = (unittest.makeSuite(unittest_01.FuncTest),  unittest.makeSuite(unittest_01.FuncTest))
suite.addTests(test_data)

TestSuite的作用仅仅是把多个测试用例打包集成到一块,但是并没有提供批量执行测试用例的方法,所以我们需要使用TextTestRunner了。

测试运行器-TextTestRunner

前面说过,TextTestRunner是用于执行测试用例、测试套件和输出测试结果的。2个步骤:

  • 实例化运行器对象

  • 通过run方法执行测试

unittest_03_测试运行器基本使用.py,代码:

import unittest

import unittest_01_测试用例的编写 as unittest_01

suite = unittest.TestSuite()

# # 添加测试用例方法
# suite.addTest(unittest_01.FuncTest("test_01"))
# suite.addTest(unittest_01.FuncTest("test_02"))

# # 批量添加测试用例方法
# test_data = (unittest_01.FuncTest("test_01"), unittest_01.FuncTest("test_02"))
# suite.addTests(test_data)


# # 添加测试用例类
# suite.addTest(unittest.makeSuite(unittest_01.FuncTest))


# 批量添加测试用例类
test_data = (unittest.makeSuite(unittest_01.FuncTest),  unittest.makeSuite(unittest_01.FuncTest))
suite.addTests(test_data)

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite)

运行结果:

测试加载器-TestLoader

前面说过,用于加载测试用例TestCase,并生成测试套件TestSuite,实现自动从代码中加载大量测试用例到测试套件中。2个步骤:

  • 实例化unittest.TestLoader对象

    loader = unittest.TestLoader()
  • 使用discover方法自动搜索指定目录下指定文件格式的python模块,并把查找到的测试用例组装打包集成到测试组件作为返回值。

    loader.discover(目录路径, pattern="文件名格式")

    注意:pattern支持*号表示0到多个字符。

unittest_04_测试加载器基本使用.py,代码:

import unittest
loader = unittest.TestLoader()
# 在当前目录下,搜索以unittest开头作为文件名的所有python文件,并把文件中的测试用例类打包集成到测试套件中
suite =loader.discover("./", pattern="unittest*.py")

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite)

运行结果:

测试脚手架-TestFixture

前面提到,测试脚手架会在执行一些测试代码之前与之后,让我们编写一些初始化和销毁的代码,主要分三个级别:

  • 方法级别:在方法执行前与执行后都提供自动调用的实例方法

    setUp和tearDown

  • 类级别:在类执行前与执行后都提供自动调用的类方法,不管类中有多少方法,只执行一次。

    setUpClass和tearDownClass

  • 模块级别:在模块执行前与执行后都提供自动调用的函数,不管模块中有多少类或方法,只执行一次。

    setUpModule和tearDownModule

方法级别的脚手架

在测试用例类中提供了2个固定名字的实例方法(setUp与tearDown),用于完成方法执行前与执行后的操作。

unittest_05测试脚手架方法级别的脚手架.py,代码:

import unittest

# 被测试的代码单元
def add(x,y):
    return x+y

class AddTest(unittest.TestCase):
    """测试用例"""
    def setUp(self):
        print("每个方法执行前都会执行一遍setUp实例方法,用于完成通用的前置操作或初始化工作")

    def tearDown(self):
        print("每个方法执行后都会执行一遍tearDown实例方法,用于完成通用的后置操作或销毁工作")

    def test_01(self):
        print(add(10, 20))

    def test_03(self):
        print(add("hello", 20))


# 因为pycharm本身内置了执行unittest的功能,所以不适用以下代码也能执行,但是终端下或者使用其他的代码编辑器时,则需要加上。
if __name__ == '__main__':
    unittest.main()

运行尝试:

类级别的脚手架

在测试用例类中提供了2个固定名字的类方法(setUpClass与tearDownClass),用于完成类执行前与执行后的操作。

unittest_06测试脚手架类级别的脚手架.py,代码:

import unittest

# 被测试的代码单元
def add(x,y):
    return x+y

class AddTest(unittest.TestCase):
    """测试用例"""
    @classmethod
    def setUpClass(cls):
        print("当前类执行前都会执行一遍setUpClass类方法,用于完成通用的前置操作或初始化工作")

    @classmethod
    def tearDownClass(cls):
        print("当前类执行后都会执行一遍tearDownClass类方法,用于完成通用的后置操作或销毁工作")

    def test_01(self):
        print(add(10, 20))

    def test_03(self):
        print(add("hello", 20))


# 因为pycharm本身内置了执行unittest的功能,所以不适用以下代码也能执行,但是终端下或者使用其他的代码编辑器时,则需要加上。
if __name__ == '__main__':
    unittest.main()
模块级别的脚手架

在测试用例类中提供了2个固定名字的函数(setUpModule与tearDownModule),用于完成类执行前与执行后的操作。

unittest_07测试脚手架模块级别的脚手架.py,代码:

import unittest


def setUpModule():
    print("当前模块执行前都会执行一遍setUpModule函数,用于完成通用的前置操作或初始化工作")


def tearDownModule():
    print("当前模块执行前都会执行一遍tearDownModule函数,用于完成通用的前置操作或初始化工作")


# 被测试的代码单元
def add(x, y):
    return x + y


class AddTest1(unittest.TestCase):
    """测试用例"""

    @classmethod
    def setUpClass(cls):
        print("当前类执行前都会执行一遍setUpClass类方法,用于完成通用的前置操作或初始化工作")

    @classmethod
    def tearDownClass(cls):
        print("当前类执行后都会执行一遍tearDownClass类方法,用于完成通用的后置操作或销毁工作")

    def test_01(self):
        print(add(10, 20))


class AddTest2(unittest.TestCase):
    """测试用例"""

    @classmethod
    def setUpClass(cls):
        print("当前类执行前都会执行一遍setUp方法,用于完成通用的前置操作或初始化工作")

    @classmethod
    def tearDownClass(cls):
        print("当前类执行后都会执行一遍tearDown方法,用于完成通用的后置操作或销毁工作")

    def test_03(self):
        print(add("hello", 20))


# 因为pycharm本身内置了执行unittest的功能,所以不适用以下代码也能执行,但是终端下或者使用其他的代码编辑器时,则需要加上。
if __name__ == '__main__':
    unittest.main()
生成HTML格式测试报告(很少使用,基本不使用)

使用HTMLTestRunner模块可以直接生成HTML格式的报告。HTMLTestRunner是一个不再维护的第三方的模块,通过pip工具安装不了,只能下载后手动导入。

HTMLTestRunner官网:HTMLTestRunner - tungwaiyip's software

HTMLTestRunner下载:http://tungwaiyip.info/software/HTMLTestRunner_0_8_2/HTMLTestRunner.py

(我就先跳过)

断言

断言(assertion)是一种在程序中的判断测试用例执行结果是否符合预期结果的方式,所以断言也被称之为“期望”。当程序执行到断言的位置时,对应的断言应该为真。若断言不为真时,程序会中止执行,并给出错误信息。

unittest中常用的断言方法(加粗为重要方法):

断言方法断言描述
assertEqual(arg1, arg2, msg=None)验证arg1=arg2,不等则fail
assertNotEqual(arg1, arg2, msg=None)验证arg1 != arg2, 相等则fail
assertTrue(expr, msg=None)验证expr是true,如果为false,则fail
assertFalse(expr,msg=None)验证expr是false,如果为true,则fail
assertIs(arg1, arg2, msg=None)验证arg1、arg2是同一个对象,不是则fail
assertIsNot(arg1, arg2, msg=None)验证arg1、arg2不是同一个对象,是则fail
assertIsNone(expr, msg=None)验证expr是None,不是则fail
assertIsNotNone(expr, msg=None)验证expr不是None,是则fail
assertIn(arg1, arg2, msg=None)验证arg1是arg2的子串,不是则fail
assertNotIn(arg1, arg2, msg=None)验证arg1不是arg2的子串,是则fail
assertIsInstance(obj, cls, msg=None)验证obj是cls的实例,不是则fail
assertNotIsInstance(obj, cls, msg=None)验证obj不是cls的实例,是则fail

unittest_09_断言.py,代码:

import unittest

def add(x ,y):
    return x + y


class AddTest(unittest.TestCase):
    def test_01(self):
        res = add(1,2)
        # 断言结果是否与预期内容相同
        # self.assertEqual(res, 3, msg="断言失败!一般会错误的结果与原因")
        # self.assertEqual(res, 2, msg="断言失败!一般会错误的结果与原因")
        self.assertIn(res, [1, 2], msg="断言失败!一般会错误的结果与原因")

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

跳过

针对开发中有时候针对不同环境或者不同的时间段,不同的代码版本,有时候部分测试用例不希望被执行,则可以使用跳过。

@unittest.skipIf(判断条件表达式, 跳过原因)

unittest_10_跳过.py,代码:

import unittest


def add(x, y):
    return x + y


version = (2, 7, 0)

class AddTest(unittest.TestCase):
    def setUp(self):
        print("setUP执行....")

    @unittest.skipIf(version <= (3, 5, 0), "版本低于3.5,所以不测试test_01")
    def test_01(self):
        res = add(1, 2)
        self.assertIn(res, [1, 3], msg="断言失败!一般会错误的结果与原因")

    def test_02(self):
        res = add("a", "B")
        self.assertEqual(res, "aB", msg="断言失败!一般会错误的结果与原因")


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

参数化

当需要使用多组不同的测试数据测试同一个方法时,可以使用unittest参数化来解决。常用的参数化方法有ddt、paramunittes

pip install parameterized

unittest_11_参数化.py,代码:

import unittest
from parameterized import parameterized

def add(x, y):
    return x + y


version = (2, 7, 0)

class AddTest(unittest.TestCase):
    def setUp(self):
        print("setUP执行....")

    @parameterized.expand([(10,20), ("a","B"), (50, 20)])
    def test_00(self, x, y):
        res = add(x, y)
        self.assertIn(res, [1, 30, "aB", 70], msg="断言失败!一般会错误的结果与原因")


    # def test_01(self):
    #     res = add(1, 2)
    #     self.assertIn(res, [1, 3], msg="断言失败!一般会错误的结果与原因")
    #
    # def test_02(self):
    #     res = add("a", "B")
    #     self.assertEqual(res, "aB", msg="断言失败!一般会错误的结果与原因")
    #
    # def test_03(self):
    #     print(add("a", 20))

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

数据驱动测试

Data-Driven Tests(DDT)即数据驱动测试,可以实现多个数据对同一个方法进行测试,达到数据和测试代码分离,目的是为了减少测试用例的数量。

基本安装

pip install ddt

直接传递单个数据

unittest_12参数化基于ddt直接传递数据.py,代码:

import unittest
from ddt import ddt, data

def add(a,b):
    return a+b

@ddt
class AddTest(unittest.TestCase):
    # # 单次传递一个数据到测试用例方法中
    # @data(100)
    # @data([1,2,3,4])
    # @data({"a":1,"b":2})
    # @data((1,2,3))

    # # 多次传递一个数据到测试用例方法中
    # @data(*["a","b","c"]) # 字符串
    # @data(*[{"a":1}, {"a":2}, {"a":3}]) # 字典
    # @data(*[[1, 1, 1], [1, 1, 2], [1, 1, 3]])
    @data([1, 1, 1], [1, 1, 2], [1, 1, 3])
    def test_01(self, a):
        print(a)


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

unittest_13_参数化-基于ddt解包传递多个数据.py,使用unpack装饰器解包数据

import unittest
from ddt import ddt, data, unpack

def add(a, b, c):
    return a + b + c

@ddt
class AddTest(unittest.TestCase):
    @data((1,2,3),(1,2,1),(1,3,1),(1,1,3))
    @unpack
    def test_01(self,a,b,c):
        add(a,b,c)

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

最后:

我感觉还是测试岗位相对机会多一点,对于我这种普通人,开发的话大家需要认真考量自己的实力,希望大家也能在秋招之际找到一个好工作!

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

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

相关文章

picoctf_2018_got_shell

picoctf_2018_got_shell Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)32位&#xff0c;只开了NX int __cdecl __noreturn main(int argc, const char **argv, const char **envp) {_DWOR…

DeepFace【部署 02】轻量级人脸识别和面部属性分析框架(实时分析+API+Docker部署+命令行接口)

轻量级人脸识别和面部属性分析框架 2.10 Real Time Analysis2.11 API2.12 Dockerized Service2.13 Command Line Interface 2.10 Real Time Analysis 你也可以运行deepface实时视频。流功能将访问您的网络摄像头&#xff0c;并应用面部识别和面部属性分析。如果能连续聚焦5帧&…

2023-9-29 LCR 083 全排列

题目链接&#xff1a;全排列 class Solution {int [] nums;List<List<Integer>> res new ArrayList<>();List<Integer> path;boolean[] st;public List<List<Integer>> permute(int[] nums) {this.nums nums;path Arrays.asList(new In…

DAMA-DMBOK2重点知识整理CDGA/CDGP——第14章 大数据与数据科学

目录 一、分值分布 二、重点知识梳理 1、引言 1.1 业务驱动因素 1.2 原则 1.3 基本理念 2、活动 2.1 定义大数据战略和业务需求 2.2 选择数据源 2.3 获得和接收数据源 2.4 制定数据假设和方法 2.5 集成和调整数据进行分析 2.6 使用模型探索数据 2.7 部署和监控 …

09链表-单链表移除元素

目录 链表&#xff08;Linked List&#xff09; 链表的数据结构 单链表 双链表 循环链表 链表的存储方式 删除节点 添加节点 LeetCode之路——203. 移除链表元素 分析&#xff1a; 链表&#xff08;Linked List&#xff09; 链表是一种线性数据结构&#xff0c;用于…

C运算符和控制语句

几乎每一个程序都需要进行运算&#xff0c;对数据进行加工处理&#xff0c;否则程序就没有意义了。要进行运算&#xff0c;就需规定可以使用的运算符。 C语言的运算符范围很宽&#xff0c;把除了控制语句和输人输出以外的几乎所有的基本操作都作为运算符处理。 运算符分类1 除…

Scala第六章节

Scala第六章节 scala总目录 章节目标 掌握类和对象的定义掌握访问修饰符和构造器的用法掌握main方法的实现形式掌握伴生对象的使用掌握定义工具类的案例 1. 类和对象 Scala是一种函数式的面向对象语言, 它也是支持面向对象编程思想的&#xff0c;也有类和对象的概念。我们依…

【Linux指令集】---git命令的基本使用

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Linux专栏】&#x1f388; 本专栏旨在分享学习Linux的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 演示环境&#xff1…

Spring修炼之路(1)基础入门

一、简介 1.1Spring概述 Spring框架是一个轻量级的Java开发框架&#xff0c;它提供了一系列底层容器和基础设施&#xff0c;并可以和大量常用的开源框架无缝集成&#xff0c;可以说是开发Java EE应用程序的必备。Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器&…

51单片机音乐闹钟秒表倒计时整点报时多功能电子钟万年历数码管显示( proteus仿真+程序+原理图+报告+讲解视频)

51单片机音乐闹钟秒表倒计时整点报时多功能电子钟万年历数码管显示( proteus仿真程序原理图报告讲解视频&#xff09; 讲解视频1.主要功能&#xff1a;2.仿真3. 程序代码4.原理图5. 设计报告6. 设计资料内容清单 51单片机音乐闹钟秒表倒计时整点报时多功能电子钟万年历数码管显…

Scala第一章节

Scala第一章节 scala总目录 章节目标 理解Scala的相关概述掌握Scala的环境搭建掌握Scala小案例: 做最好的自己 1. Scala简介 1.1 概述 ​ Scala(斯嘎拉)这个名字来源于"Scalable Language(可伸缩的语言)", 它是一门基于JVM的多范式编程语言, 通俗的说: Scala是一…

面向对象【递归方法】

文章目录 递归编写递归函数递归的工作原理常见的递归应用场景递归注意点 递归 递归是一种解决问题的方法&#xff0c;其中一个函数调用自身以解决较小的实例&#xff0c;直到达到基本情况&#xff08;停止条件&#xff09;&#xff0c;然后开始返回结果。递归可以让我们更容易地…

CSS详细基础(五)选择器的优先级

本节介绍选择器优先级&#xff0c;优先级决定了元素最终展示的样式~ 浏览器是通过判断CSS优先级&#xff0c;来决定到底哪些属性值是与元素最为相关的&#xff0c;从而作用到该元素上。CSS选择器的合理组成规则决定了优先级&#xff0c;我们也常常用选择器优先级来合理控制元素…

038:vue页面头部提示低版本浏览器升级问题

第038个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

一例疑似MMCore下载器分析

概述 这是一例文件夹病毒&#xff0c;手法相对比较高级&#xff0c;通过域名关联到MMCore样本&#xff0c;可能与印度方向APT组织有关联。 这个病毒使用了分离免杀技术&#xff0c;有2个样本&#xff0c;一个加载器&#xff0c;一个payload。 加载器(文件名为dwm22.exe)的主要…

并发——中断机制

1.中断概述 中断只是一种协商机制&#xff0c;如果要中断一个线程&#xff0c;需要手动调用该线程的interrupt方法&#xff0c;将此线程对象的中断标识设为true(默认中断标志位为false)&#xff0c;接着我们需要手动写代码去不断的检测要中断线程的标识位&#xff0c;如果为tr…

阿木实验室PrometheusV1.1安装+Ubuntu 20.04

1. 安装ros-noetic 2. 安装Mavros包 sudo apt-get install ros-noetic-mavros ros-noetic-mavros-extras3. GeographicLib wget https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh这里可以使用代理 &#xff1a;wg…

笔训day1

目录 选择题 1、%m.ns 编程题 第一题 第二题 选择题 1、%m.ns m&#xff1a;字符串的宽度。 n&#xff1a;左起截取目标字符串n个字符&#xff0c;右对齐&#xff0c;补空格。 1、字符串长度>n>m : 受n控制&#xff0c;左起截取n个字符&#xff0c;右对齐&#x…

什么是Times New Roman 字体

如何评价 Times New Roman 字体&#xff1f;&#xff1a;https://www.zhihu.com/question/24614549?sortcreated 新罗马字体是Times New Roman字体&#xff0c;是Office Word默认自带的英文字体之一。 中英文字体 写作中&#xff0c;英文和数字的标准字体为 Times New Roma…

什么是AI客流量算法?如何应用在实际场景中?

客流量分析算法简而言之就是一种利用数据分析和机器学习技术进行人流量统计、预测和分析的算法。它能够根据不同的数据来源&#xff0c;如摄像头、传感器等&#xff0c;对特定区域内的客流量进行实时监测和分析&#xff0c;并通过对历史数据的综合分析&#xff0c;提供客流趋势…