【理论】测试框架体系TDD、BDD、ATDD、MBT、DDT介绍

一、测试框架是什么

测试框架是一组用于创建和设计测试用例的指南或规则。框架由旨在帮助 QA 专业人员更有效地测试的实践和工具的组合组成。 这些指南可能包括编码标准、测试数据处理方法、对象存储库、存储测试结果的过程或有关如何访问外部资源的信息。

A testing framework is a set of guidelines or rules used for creating and designing test cases. A framework is comprised of a combination of practices and tools that are designed to help QA professionals test more efficiently.
These guidelines could include coding standards, test-data handling methods, object repositories, processes for storing test results, or information on how to access external resources.

二、测试框架的价值

测试框架是任何成功的自动化测试过程的重要组成部分。它们可以降低维护成本和测试工作,并为寻求优化其敏捷流程的 QA 团队提供更高的投资回报率 (ROI)。

Testing frameworks are an essential part of any successful automated testing process. They can reduce maintenance costs and testing efforts and will provide a higher return on investment (ROI) for QA teams looking to optimize their agile processes.

一个好的框架(也可以理解成一个好的工具)可以让你事半功倍

三、测试框架的收益

Improved test efficiency 提高测试效率
Lower maintenance costs 降低维护成本
Minimal manual intervention 最少的人工干预
Maximum test coverage 最大测试覆盖率
Reusability of code 代码的可重用性

四、常见测试框架类型

在这里插入图片描述

(一)TDD

1.TDD 定义

测试驱动开发(TDD)是一个软件开发过程,在软件完全开发之前,将软件需求转换为测试用例,并通过针对所有测试用例重复测试软件来跟踪所有软件开发。这与首先 ​​ 开发软件和稍后创建测试用例相反

Test-driven development (TDD) is a software development process relying on software requirements being converted to test cases before software is fully developed, and tracking all software development by repeatedly testing the software against all test cases.

2.TDD 流程

TDD 来源于 XP 极限编程
在这里插入图片描述
单元测试
重构
覆盖率
可测性提升
模型驱动设计

3.代表作 JUnit TestNG

    @Testvoid standardAssertions() {assertEquals(2, calculator.add(1, 1));assertEquals(4, calculator.multiply(2, 2),"The optional failure message is now the last parameter");assertTrue('a' < 'b', () -> "Assertion messages can be lazily evaluated -- "+ "to avoid constructing complex messages unnecessarily.");}
(1)TestNG
package example1;import org.testng.annotations.*;public class SimpleTest {@BeforeClasspublic void setUp() {// code that will be invoked when this test is instantiated}@Test(groups = { "fast" })public void aFastTest() {System.out.println("Fast test");}@Test(groups = { "slow" })public void aSlowTest() {System.out.println("Slow test");}}

4.代表作 Pytest UnitTest

# content of test_sample.py
def inc(x):return x + 1def test_answer():assert inc(3) == 5
import unittestclass TestStringMethods(unittest.TestCase):def test_upper(self):self.assertEqual('foo'.upper(), 'FOO')def test_isupper(self):self.assertTrue('FOO'.isupper())self.assertFalse('Foo'.isupper())def test_split(self):s = 'hello world'self.assertEqual(s.split(), ['hello', 'world'])# check that s.split fails when the separator is not a stringwith self.assertRaises(TypeError):s.split(2)

(二)BDD Behavior Driven Development

1.BDD定义

在软件工程中,行为驱动开发 (BDD) 是一种敏捷软件开发过程,它鼓励软件项目中的开发人员、质量保证专家和客户代表之间进行协作。它鼓励团队使用对话和具体示例来形成对应用程序应该如何运行的共同理解。它源于测试驱动开发 (TDD)。行为驱动开发将 TDD 的通用技术和原则与领域驱动设计和对象的思想相结合面向分析和设计,为软件开发和管理团队提供共享工具和共享流程,以便在软件开发方面进行协作。

behavior-driven development (BDD) is an agile software development process that encourages collaboration among developers, quality assurance experts, and customer representatives in a software project. It encourages teams to use conversation and concrete examples to formalize a shared understanding of how the application should behave. It emerged from test-driven development (TDD). Behavior-driven development combines the general techniques and principles of TDD with ideas from domain-driven design and object-oriented analysis and design to provide software development and management teams with shared tools and a shared process to collaborate on software development.

2.BDD VS TDD

BDD
在这里插入图片描述
BDD 与 TDD
在这里插入图片描述

3.BDD 相关框架

JBehave
Cucumber
Mspec
Specflow

(1)Cucumber

Cucumber is a tool that supports Behaviour-Driven Development(BDD).
在这里插入图片描述
在这里插入图片描述

A.Cucumber 测试用例 Scenario 场景
Scenario: Finding some cheeseGiven I am on the Google search pageWhen I search for "Cheese!"Then the page title should start with "cheese"
B.Cucumber 测试用例步骤定义
public class ExampleSteps {private final WebDriver driver = new FirefoxDriver();@Given("I am on the Google search page")public void I_visit_google() {driver.get("https://www.google.com");}@When("I search for {string}")public void search_for(String query) {WebElement element = driver.findElement(By.name("q"));// Enter something to search forelement.sendKeys(query);// Now submit the form. WebDriver will find the form for us from the elementelement.submit();}@Then("the page title should start with {string}")public void checkTitle(String titleStartsWith) {// Google's search is rendered dynamically with JavaScript// Wait for the page to load timeout after ten secondsnew WebDriverWait(driver,10L).until(new ExpectedCondition<Boolean>() {public Boolean apply(WebDriver d) {return d.getTitle().toLowerCase().startsWith(titleStartsWith);}});}@After()public void closeBrowser() {driver.quit();}
}
C.cucumber 项目结构在这里插入图片描述

(三)ATDD Acceptance Test Driven Development

1.ATDD 定义

验收测试驱动开发 (ATDD) 是一种基于业务客户、开发人员和测试人员之间沟通的开发方法。ATDD 包含许多与示例规范 (SBE)、行为驱动开发 (BDD)、示例驱动开发 (EDD)、和支持驱动开发(也称为故事测试驱动开发(SDD)。所有这些流程都有助于开发人员和测试人员在实施之前了解客户的需求,并使客户能够使用他们自己的领域语言进行交流。

Acceptance test–driven development (ATDD) is a development methodology based on communication between the business customers, the developers, and the testers. ATDD encompasses many of the same practices as specification by example (SBE), behavior-driven development (BDD), example-driven development (EDD), and support-driven development also called story test–driven development (SDD). All these processes aid developers and testers in understanding the customer’s needs prior to implementation and allow customers to be able to converse in their own domain language.

2.ATDD 相关工具

  • FitNesse:The fully integrated standalone wiki and acceptance testing framework
    在这里插入图片描述

  • Robot Framework is a Python-based, extensible keyword-driven automation framework for acceptance testing, acceptance test driven development (ATDD), behavior driven development (BDD) and robotic process automation (RPA).在这里插入图片描述

(1)RobotFramework
A.Robotframework 介绍

在这里插入图片描述
Robot Framework is a generic open source automation framework. It can be used for test automation and robotic process automation (RPA). Robot Framework has an easy syntax, utilizing human-readable keywords. Its capabilities can be extended by libraries implemented with Python, Java or many other programming languages. Robot Framework has a rich ecosystem around it, consisting of libraries and tools that are developed as separate projects.

B.Robotframework 测试用例
*** Settings ***
Documentation     Simple example using SeleniumLibrary.
Library           SeleniumLibrary*** Variables ***
${LOGIN URL}      http://localhost:7272
${BROWSER}        Chrome*** Test Cases ***
Valid LoginOpen Browser To Login PageInput Username    demoInput Password    modeSubmit CredentialsWelcome Page Should Be Open[Teardown]    Close Browser*** Keywords ***
Open Browser To Login PageOpen Browser    ${LOGIN URL}    ${BROWSER}Title Should Be    Login PageInput Username[Arguments]    ${username}Input Text    username_field    ${username}Input Password[Arguments]    ${password}Input Text    password_field    ${password}Submit CredentialsClick Button    login_buttonWelcome Page Should Be OpenTitle Should Be    Welcome Page

3.数据驱动风格

*** Settings ***
Test Template    Login with invalid credentials should fail*** Test Cases ***                USERNAME         PASSWORD
Invalid User Name                 invalid          ${VALID PASSWORD}
Invalid Password                  ${VALID USER}    invalid
Invalid User Name and Password    invalid          invalid
Empty User Name                   ${EMPTY}         ${VALID PASSWORD}
Empty Password                    ${VALID USER}    ${EMPTY}
Empty User Name and Password      ${EMPTY}         ${EMPTY}

4.BDD 风格

*** Test Cases ***
Valid LoginGiven login page is openWhen valid username and password are insertedand credentials are submittedThen welcome page should be open

5.ATDD VS BDD

在这里插入图片描述
DSL:领域特定语言(Domain - Specific Language)

(1)定义

DSL 是一种专门为特定的应用领域设计的编程语言。它的语法和语义是根据特定领域的概念和操作来定制的,与通用编程语言(如 Java、Python 等)相比,DSL 更加聚焦于解决某一特定领域的问题。

(2)在 ATDD 中的作用

在 ATDD 过程中,DSL 用于编写验收测试用例。这些验收测试用例通常以一种接近自然语言的形式来描述系统的行为和功能需求。
例如,对于一个电商系统的订单处理功能,可能会有这样的 DSL 描述:“Given 一个包含商品 A 和商品 B 的购物车,When 用户点击结算按钮,Then 系统应该生成一个包含商品 A 和商品 B 的订单,并且计算出正确的总价”。这种 DSL 的描述方式使得业务人员、测试人员和开发人员都能够比较容易地理解系统的需求和预期行为。

(3)DSL 的特点

针对性强:它专注于特定的业务领域,只提供该领域所需的功能和操作。比如,用于金融交易系统的 DSL 可能会有专门用于处理交易订单、计算利息、风险评估等操作的语法,而不会涉及到像图形渲染这样与金融交易无关的功能。
简洁性:DSL 的语法通常比较简洁,能够以简洁的方式表达复杂的业务规则。因为它不需要像通用编程语言那样考虑各种各样的编程场景,而是专注于特定领域的常见操作。
易理解性:由于其语法和词汇是基于特定领域的术语,所以对于熟悉该领域的人员(如业务分析师、领域专家等)来说,DSL 编写的测试用例很容易理解。这有助于跨团队的沟通,使得业务需求能够更准确地转化为可执行的测试和代码。

(四)MBT Model Based Testing

1.Model-Based Testing GrapheWalker

  • model-based testing
  • GraphWalker, an open-source model-based testing tool
    在这里插入图片描述

2.edge 代表步骤

一条边代表一个动作,一个过渡。 操作可以是 API 调用、按钮单击、超时等。任何将您的被测系统移动到您想要验证的新状态的任何事情。但请记住,边缘没有进行验证。这只发生在顶点。

An edge represents an action, a transition. An action could be an API call, a button click, a timeout, etc. Anything that moves your System Under Test into a new state that you want to verify. But remember, there is no verification going on in the edge. That happens only in the vertex.

3.vertex 代表断言

一个顶点代表验证,一个断言。 验证是您的代码中有断言的地方。在这里,您可以验证 API 调用是否返回正确的值、按钮单击是否确实关闭了对话框,或者在应该发生超时时,被测系统触发了预期的事件。

A vertex represents verification, an assertion. A verification is where you would have assertions in your code. It is here that you verify that an API call returns the correct values, that a button click actually did close a dialog, or that when the timeout should have occurred, the System Under Test triggered the expected event.

4.graph 代表测试用例集

模型是一个图,它是一组顶点和边 从模型中,GrapWalker 将生成一条通过它的路径。一个模型有一个起始元素,一个规则如何生成路径的生成器,以及告诉 GraphWalker 何时停止生成路径的相关停止条件。

A model is a graph, which is a set of vertices and edges From a model, GrapWalker will generate a path through it. A model has a start element, and a generator which rules how the path is generated, and associated stop condition which tells GraphWalker when to stop generating the path.

5.测试用例样板生成

@GraphWalker(value = "random(edge_coverage(100))")
public class OwnerInformationTest extends ExecutionContext implements OwnerInformation {private static final Logger log = LoggerFactory.getLogger(OwnerInformationTest.class);@Overridepublic void v_OwnerInformation() {$(By.tagName("h2")).shouldHave(text("Owner Information"));setAttribute("numOfPets", Value.asValue($$x("//table/tbody/tr/td//dl").size()));log.info("Number of pets: " + getAttribute("numOfPets"));}@Overridepublic void e_UpdatePet() {$("button[type=\"submit\"]").click();}@Overridepublic void v_FindOwners() {$(By.tagName("h2")).shouldHave(text("Find Owners"));$(By.tagName("h2")).shouldBe(visible);}@Overridepublic void e_EditPet() {$(By.linkText("Edit Pet")).click();}@Overridepublic void e_AddNewPet() {$(By.linkText("Add New Pet")).click();}@Overridepublic void e_AddVisit() {$(By.linkText("Add Visit")).click();}@Overridepublic void e_FindOwners() {$("[title='find owners']").click();}@Overridepublic void e_AddPetSuccessfully() {Date date = new Faker().date().past( 365 * 20, TimeUnit.DAYS);SimpleDateFormat sdf;sdf = new SimpleDateFormat("yyyy-MM-dd");String birthData = sdf.format(date);$(By.id("birthDate")).clear();$(By.id("birthDate")).sendKeys(birthData + Keys.ENTER);$(By.id("name")).clear();$(By.id("name")).sendKeys(new Faker().name().fullName());$(By.id("type")).selectOption(new Faker().number().numberBetween(0,5));$(By.cssSelector("button[type=\"submit\"]")).click();}@Overridepublic void v_NewPet() {$(By.tagName("h2")).shouldHave(text("New Pet"));$(".has-feedback").shouldBe(visible);}@Overridepublic void e_VisitAddedSuccessfully() {$(By.id("description")).clear();$(By.id("description")).sendKeys(new Faker().lorem().word());$("button[type=\"submit\"]").click();}@Overridepublic void v_NewVisit() {$(By.tagName("h2")).shouldHave(text("New Visit"));}@Overridepublic void v_Pet() {$(By.tagName("h2")).shouldHave(text("Pet"));}@Overridepublic void e_AddPetFailed() {$(By.id("name")).clear();$(By.id("birthDate")).clear();$(By.id("birthDate")).sendKeys("2015/02/05" + Keys.ENTER);$(By.id("ui-datepicker-div")).shouldBe(not(visible));$(By.id("type")).selectOption("dog");$("button[type=\"submit\"]").click();}@Overridepublic void e_VisitAddedFailed() {$(By.id("description")).clear();$("button[type=\"submit\"]").click();}
}

(五)DDT Data Driven Testing

1.DDT定义

数据驱动测试(DDT),也称为表驱动测试或参数化测试,是一种软件测试方法,用于计算机软件的测试,用于描述使用条件表直接作为测试输入和可验证输出完成的测试以及测试环境设置和控制没有硬编码的过程

Data-driven testing (DDT), also known as table-driven testing or parameterized testing, is a software testing methodology that is used in the testing of computer software to describe testing done using a table of conditions directly as test inputs and verifiable outputs as well as the process where test environment settings and control are not hard-coded.

2.DDT 相关工具

  • DDT 是一种实践,可以跟很多框架结合
  • 单元测试结合 DDT:JUnit4 JUnit5 TestNG
  • RobotFramework DDT
  • YAML JSON CSV 驱动 HttpRunner

3.数据驱动应用案例

  • HttpRunner 可以根据代理抓包自动生成测试用例
  • YAPI、Swagger 等工具可以根据数据自动生成测试用例代码
  • JVM-Sandbox-Repeater Gor 录制工具可以把请求保存为测试用例并重放以实现快速回归测试

4.HttpRunner 测试框架

在这里插入图片描述

5.HttpRunner 测试用例

config:name: "request methods testcase with functions"variables:foo1: config_bar1foo2: config_bar2expect_foo1: config_bar1expect_foo2: config_bar2base_url: "https://postman-echo.com"verify: Falseexport: ["foo3"]teststeps:- name: get with paramsvariables:foo1: bar11foo2: bar21sum_v: "${sum_two(1, 2)}"request:method: GETurl: /getparams:foo1: $foo1foo2: $foo2sum_v: $sum_vheaders:User-Agent: HttpRunner/${get_httprunner_version()}extract:foo3: "body.args.foo2"validate:- eq: ["status_code", 200]- eq: ["body.args.foo1", "bar11"]- eq: ["body.args.sum_v", "3"]- eq: ["body.args.foo2", "bar21"]- name: post raw textvariables:foo1: "bar12"foo3: "bar32"request:method: POSTurl: /postheaders:User-Agent: HttpRunner/${get_httprunner_version()}Content-Type: "text/plain"data: "This is expected to be sent back as part of response body: $foo1-$foo2-$foo3."validate:- eq: ["status_code", 200]- eq:["body.data","This is expected to be sent back as part of response body: bar12-$expect_foo2-bar32.",]- name: post form datavariables:foo2: bar23request:method: POSTurl: /postheaders:User-Agent: HttpRunner/${get_httprunner_version()}Content-Type: "application/x-www-form-urlencoded"data: "foo1=$foo1&foo2=$foo2&foo3=$foo3"validate:- eq: ["status_code", 200]- eq: ["body.form.foo1", "$expect_foo1"]- eq: ["body.form.foo2", "bar23"]- eq: ["body.form.foo3", "bar21"]

6.数据驱动风格为什么广受欢迎

维护成本最低,录制回放技术越来越成熟,可以与数据驱动很好的结合。低代码、用例生成技术的流行,会让数据驱动风格更受欢迎。

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

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

相关文章

20250112面试鸭特训营第20天

更多特训营笔记详见个人主页【面试鸭特训营】专栏 250112 1. TCP 和 UDP 有什么区别&#xff1f; 特性TCPUDP连接方式面向连接&#xff08;需要建立连接&#xff09;无连接&#xff08;无需建立连接&#xff09;可靠性可靠的&#xff0c;提供确认、重传机制不可靠&#xff0c…

linux--防火墙 iptables 双网卡 NAT 桥接

linux--防火墙 iptables 双网卡 NAT 桥接 1 介绍1.1 概述1.2 iptables 的结构 2 四表五链2.1 iptables 的四表filter 表&#xff1a;过滤规则表&#xff0c;默认表。nat 表&#xff1a;地址转换表。mangle 表&#xff1a;修改数据包内容。raw 表&#xff1a;原始数据包表。 2.2…

oracle闪回表

文章目录 闪回表案例1&#xff1a;&#xff08;未清理回收站时的闪回表--成功&#xff09;案例2&#xff08;清理回收站时的闪回表--失败&#xff09;案例3&#xff1a;彻底删除表&#xff08;不经过回收站--失败&#xff09;案例4&#xff1a;闪回表之后重新命名新表总结1、删…

202506读书笔记|《飞花令·江》——余霞散成绮,澄江静如练,江梅一夜落红雪,便有夭桃无数开

202506读书笔记|《飞花令江》——余霞散成绮&#xff0c;澄江静如练&#xff0c;江梅一夜落红雪&#xff0c;便有夭桃无数开 摘录 《飞花令江》素心落雪编著&#xff0c;飞花令得名于唐代诗人韩翃《寒食》中的名句“春城无处不飞花”&#xff0c;类似于行酒令&#xff0c;是文人…

《系统爆破:MD5易破,后台登录可爆破?》

声明&#xff1a;笔记的只是方便各位师傅学习知识&#xff0c;以下代码、网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 爆破Sales系统 一、爆破MD5 场景&#xff1a;已知MD5的加密字符串&#xff0c;如何得知明…

Copula算法原理和R语言股市收益率相依性可视化分析

阅读全文&#xff1a;http://tecdat.cn/?p6193 copula是将多变量分布函数与其边缘分布函数耦合的函数&#xff0c;通常称为边缘。在本视频中&#xff0c;我们通过可视化的方式直观地介绍了Copula函数&#xff0c;并通过R软件应用于金融时间序列数据来理解它&#xff08;点击文…

DSP+Simulink——点亮LED灯(TMSDSP28379D)超详细

实现功能&#xff1a;DSP28379D-LED灯闪烁 :matlab为2019a :环境建立见之前文章 Matlab2019a安装C2000 Processors超详细过程 matlab官网链接&#xff1a; Getting Started with Embedded Coder Support Package for Texas Instruments C2000 Processors Overview of Creat…

APP上架之Android 证书 MD5 指纹

Android 证书 MD5 指纹 1. 什么是 Android 证书 MD5 指纹&#xff1f; Android 证书 MD5 指纹是对证书数据进行 MD5 哈希运算后得到的 128 位字符串。在 Android 开发中&#xff0c;每个证书在理论上都有一个唯一的 MD5 指纹&#xff0c;用于识别和验证证书的有效性。证书指纹…

【Rust自学】11.6. 控制测试运行:并行和串行(连续执行)测试

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.6.1. 控制测试的运行方式 cargo test和cargo run一样&#xff0c;cargo test也会编译代码并生成一个二进制文件用于测试&#xff0c;…

计算机网络学习笔记

第1课 绪论、传输介质 【知识点回顾】 两种导线可以减小电磁干扰&#xff1a; 双绞线&#xff08;分为非屏蔽双绞线、屏蔽双绞线&#xff09;&#xff08;RJ-45用&#xff09;同轴电缆&#xff08;短距离使用&#xff09;网络通信的基本单位&#xff1a;位&#xff08;bit&…

STM32之CAN通讯(十一)

STM32F407 系列文章 - CAN通讯&#xff08;十一&#xff09; 目录 前言 一、CAN 二、CAN驱动电路 三、CAN软件设计 1.CAN状态初始化 2.头文件相关定义 3.接收中断服务函数 4.用户层使用 1.用户层相关定义 2.发送数据 3.接收数据 1.查询方式处理 2.中断方式处理 3…

Java聊天小程序

拟设计一个基于 Java 技术的局域网在线聊天系统,实现客户端与服务器之间的实时通信。系统分为客户端和服务器端两类,客户端用于发送和接收消息,服务器端负责接收客户端请求并处理消息。客户端通过图形界面提供用户友好的操作界面,服务器端监听多个客户端的连接并管理消息通…

C#Halcon找线封装

利用CreateMetrologyModel封装找线工具时&#xff0c;在后期实际应用调试时容易把检测极性搞混乱&#xff0c;造成检测偏差&#xff0c;基于此&#xff0c;此Demo增加画线后检测极性的指引&#xff0c;首先看一下效果 加载测试图片 画线 确定后指引效果 找线效果 修改显示 UI代…

【linux系统之redis6】redis的基础命令使用及springboot连接redis

redis的基础命令很多&#xff0c;大部分我们都可以在官网上找到&#xff0c;真的用的时候可以去官网找&#xff0c;不用全部记住这些命令 redis通用的基础命令的使用 代码测试 string类型常见的命令 key值的结构&#xff0c;可以区分不同的需求不同的业务名字 hash类型 创建…

ISP各模块功能介绍

--------声明&#xff0c;本文为转载整理------- ISP各个模块功能介绍&#xff1a; 各模块前后效果对比&#xff1a; 黑电平补偿&#xff08;BLC&#xff09; 在理想情况下&#xff0c;没有光照射的像素点其响应值应为0。但是&#xff0c;由于杂质、受热等其它原因的影响&…

前缀和练习

【模版】前缀和 【模板】前缀和_牛客题霸_牛客网 思路 要想快速找出某一连续区间的和&#xff0c;我们就要使用前缀和算法。 其实本质是再创建一个dp数组&#xff0c;每进一次循环加上原数组的值&#xff08;dp代表arr的前n项和&#xff09;&#xff1a; vector<int>…

3. 【Vue实战--孢子记账--Web 版开发】--登录大模块

从这篇文章开始我们就进入到了孢子记账的前端开发&#xff0c;在本专栏中我默认大家的电脑上都已经配置好了开发环境。下面我们一起开始编写孢子记账的Web版吧。 一、功能 登录大模块功能包括注册、登录和找回密码功能&#xff0c;在本篇文章中我只会展示注册界面的实现&…

【2024年华为OD机试】 (A卷,100分)- 端口合并(Java JS PythonC/C++)

一、问题描述 题目描述 有 M 个端口组 (1 < M < 10)&#xff0c; 每个端口组是长度为 N 的整数数组 (1 < N < 100)&#xff0c; 如果端口组间存在 2 个及以上不同端口相同&#xff0c;则认为这 2 个端口组互相关联&#xff0c;可以合并。 输入描述 第一行输入端…

73.矩阵置零 python

矩阵置零 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解思路分析Python 实现代码代码解释提交结果 题目 题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例…

基于华为ENSP的OSPF状态机、工作过程、配置保姆级别详解(2)

本篇技术博文摘要 &#x1f31f; 基于华为enspOSPF状态机、OSPF工作过程、.OSPF基本配置等保姆级别具体详解步骤&#xff1b;精典图示举例说明、注意点及常见报错问题所对应的解决方法 引言 &#x1f4d8; 在这个快速发展的技术时代&#xff0c;与时俱进是每个IT人的必修课。我…