七天搞定软件测试,这一篇教程就够了,学完最少能拿13k

前言

在软件开发的世界中,软件测试是不可或缺的一部分。它是确保软件质量、功能完整性和用户满意度的关键环节。本文小编将为大家介绍各类软件测试的奥秘,并提供入门级的指导和见解。

本文内容概要:

  • 软件测试是什么?
  • 黑盒测试vs白盒测试
  • 自动化测试vs手工测试
  • 功能测试方法论
  • 非功能测试方法论
  • 软件测试生命周期
  • 软件测试最佳实践

软件测试是什么?

软件测试是在开发流程中被开发者用来持续地评估和纠正特性的功能性的一个循环进行的步骤。软件测试比对软件的当前构建和软件需求,以确认没有疏漏的需求。同样需要验证的是,软件在跨越不同媒介时、与现有软件集成时运行正确。

软件测试是如何运作的?

测试软件有不少办法。通常来讲,开发者首先决定一个需要验证的行为或者特性,创建一个测试来确认特性,接着要么修改特性,要么通过测试就直接继续后面事情了。

在早期软件设计哲学中,测试经常完全被忽视。现在软件已经变得更加复杂,在更大规模被实现,而且在不同设备与操作系统间各不相同。现代的开发周期中,软件测试已经是必要的部分了。它扮演着QA一种不断发展的形式,验证软件可以对各种可能的使用场景和环境正常响应。

黑盒测试vs白盒测试

软件测试有很多不同类型,每种类型在测试中专攻特定的缺陷。所有的测试类型可以宽泛描述为黑盒或白盒测试。这个区分描述软件测试人员需要掌握的背景知识。

黑盒测试:测试人员知道软件产品应该实现什么而不知道是如何实现的。测试人员仅仅目睹了编程的结果或行为,他们自己不必成为程序员。测试人员经常是开发步骤外部的某些人,给出外部的观点。黑盒测试主要用于测试程序行为和评估用户体验。

白盒测试:白盒测试是黑盒测试的反面,测试人员的确知道软件的内部结构。这些测试人员通过特性测试用例输入的使用来评估源代码里面程序的逻辑。通过追踪这些输入的流动,测试人员可以验证这些测试用例在屏幕背后被正确处理。白盒测试人员常常是开发步骤内的程序员,他们被用于检查源代码的效率。

手工测试vs自动化

测试方法另一个主要分类是手工测试vs自动化测试。很多特定测试方法论可以同时被手工或自动化测试完成。这个区别描述测试是如何被完成的。

手工测试:

手工测试需要一个人类测试人员来扮演终端用户的角色,一次检查一个测试用例。这是测试的传统形式,可以找到自动化测试框架难以识别的问题(web应用元素的表现,令人困惑的布局等)。

自动化测试

自动化测试(或测试自动化)是使用软件的步骤,调用一个测试框架来创建使用期望输出对比当前程序输出的自动的测试用例。最常见的框架是Selenium和Cucumber。

自动测试框架的两个最常见的测试步骤是图形用户接口测试和API测试,前者模拟诸如点击或按键的用户接口事件,后者绕开用户接口来验证底层行为。自动化测试被用于快速执行输出驱动的测试或者为维护测试执行重复的测试用例。

功能测试方法论

现在我们将会讨论通过更加广泛类型区分的测试方法论,功能测试或非功能测试。这个区别描述测试关注的是软件行为还是内部运作。

功能测试

黑盒QA测试的一种类型测试的是从软件需求和说明书生成的测试用例。下方是不同功能测试方法论的一些常见类型。

最常见的功能方法论:

  • 单元测试
  • 集成测试
  • 系统测试
  • 验收测试
  • 回归测试
  • 冒烟测试

常见功能测试步骤

绝大多数基础测试经历同样的四步,每个步骤测试范围更加宽广。步骤始于评估单一组件的单元测试,终于评估产品和初始计划关联性的验收测试。

单元测试:

单元测试被用于测试和其他组件分离开的程序组件。举个例子,面向对象程序中,你会在尝试连接到其他类前单元测试一个单独的类。这种类型的测试经常是开发者完成的,用于在无需等待完整测试周期下捕捉缺陷。单元测试绝大多数情况是自动执行的,用于快速获取到结果,但是也能手动进行。

集成测试:

集成测试用于测试诸多互相连接的程序组件的协同运行。这个测试经常是在单元测试后进行的,首先独立验证单一组件,然后验证组件协同的运行。

举个例子,你可以集成测试一个父类和两个关联子类来确保测试用于所有预期属性的用例的输入被分配给预期的类。集成测试,通常都是自动化的测试,是开发者完成的,用于验证互相关联的组件无缝衔接。

系统测试:

系统测试是一起使用所有组件来测试完整产品的构建的。当集成测试测试了互相连接的组件的模块后,系统测试测试所有组件集成后程序如何运作,并且在模块内部操作中捕捉缺陷。

验收测试:

验收测试(或用户验收测试)是一个在开发过程后期执行的,用来评估是否所有初始的特定需求是被最终产品构建满足的测试。内部和外部测试者都要评审初始产品说明书和业务需求,然后当他们使用产品时候逐一检查。使用最常见的apha测试(内部)和beta测试(外部)去做验收测试有很多途径。

专门的功能方法论

在上面步骤之外去测试一个程序的特定层面,也有经过微调的功能测试手段。下面是最常见的专门的功能方法论

回归测试

回归测试是在一个更新或改变后用于测试产品集成性的手段。回归测试套件要么在整个程序,要么仅仅在程序变了的部分运行自动测试。套件接着把输出和早期产品构建记录的输出进行比对。如果输出是匹配的,那么测试成功。如果它们以预期方式改变了,那么测试验证了功能有回归或还原。

回归测试是维护测试最常见的形式,因为其检查程序发布后表现如何。回归测试可以被定期执行来提供持续测试。

冒烟测试

冒烟测试(Smoke Testing)是软件测试中的一种测试方法,旨在快速验证系统的基本功能是否正常工作,以确保软件在进入更详细的测试阶段之前是可用的。

冒烟测试通常在软件构建或发布后的早期阶段进行,它会对软件的核心功能进行一系列的简单测试,以发现可能的严重问题或错误。这些测试通常是预先定义的基本功能测试用例,涵盖了软件的主要功能点。

冒烟测试的目标是在系统经过基本构建之后,对其进行表面层次的测试,以确保没有明显的错误或问题。如果冒烟测试失败,即发现了关键功能的严重问题,那么可能需要回退到先前的开发阶段并解决问题,以避免在后续的详细测试中浪费时间和资源。

冒烟测试的优点包括:

  1. 快速验证:冒烟测试可以在短时间内快速验证软件的基本功能,帮助发现可能的严重问题。
  2. 提早发现问题:通过在早期阶段发现问题,可以节省后续测试阶段的时间和资源。
  3. 提高软件质量:通过确保软件的基本功能正常工作,可以提高软件的质量和稳定性。

非功能测试方法

非功能测试方法测试一个程序如何运行,而不是特定程序表现的成功运行,举个例子,一个非功能测试可能测试的是一个程序在更大规模下如何的运行良好或者当系统运行很长一段时间后表现如何。由于非功能测试定义的主体性,很多非功能测试方法论关注点有所重叠。

常见非功能测试方法论:

  • 性能测试
  • 安全测试
  • 可用性测试
  • 兼容性测试
  • 压力测试

让我们深入了解下这些方法论

性能测试:

性能测试是测试的一种常见形式,评估在预设负载下软件的运行速度、响应和可靠性等。如果软件正常运行,但是在这些分类里面任意一个没有满足期望标准,在继续其软件开发周期前,软件将会把打回开发者去提升性能。

安全测试:

安全测试被用于在使用了诸如基于账号的系统或金融系统软件的敏感信息的信息系统或软件中寻找缺点。下面是安全测试中的一些要求:

  • 保密性:敏感信息是受约束的。
  • 完整性:数据不能被拷贝或修改。
  • 认证:用户比如被验证为是期望的用户。
  • 鉴权:用户必须拥有权限来查看敏感信息。
  • 可用性:当授权用户需要信息时,必须是可用的。
  • 不可否认性:通信两端的用户在发生通信前必须校验各自凭证

易用性测试:

易用性测试用于识别真正的终端用户会在哪里遇到困难或困惑。这个主要是在研究者观察下由一群受控的终端用户进行的。测试者被要求去执行特定任务,比如“创建一个账号”,但是却没有被告诉怎么去完成。他们然后使用产品来完成任务并给出关于体验的高质量反馈。这个方法论允许开发者获取到关于他们程序可用性和直观反应的真实反馈,并且无需很多的说明。

这个与a11y测试联系紧密,a11y测试记录能力各不相同的终端用户能多容易地操作软件。举个例子,文字转语音软件和web应用的可视化元素的交互如何。

兼容性测试:

兼容性测试评估在不同计算环境下软件表现如何。这个通常使用一个测试框架完成的。这种框架使用模拟不同目标设备的很多虚拟机器来执行同样的输入。每个VM的输出被记录和比对,以确认是否所有输出都是一样的并且跨越不同平台时候表现是否有所不同。这种测试确保无论终端用户在哪里使用,都有一致的体验。

举个例子:如果你曾经为iOS和安卓创建了一个移动端APP,你将会需要一个兼容测试,来验证那个APP在两个平台上以相同的预设级别运行。

压力测试:

压力测试是开发者把听他们的软件推送到一个极端测试用例,来验证软件的断点。最常见的压力测试是最大化并发用户来找出当前构建能承载的极限。整个压力测试中性能被完整记录,因此开发者可以发现软件断点,指出可接受级别下合适用户体验会降级。极限情况下,压力测试致力于找出系统在哪里会失效,因此你可以在当前产品版本下规避这些失效条件。

举个例子,设想你正在开发一个在线视频游戏。你可以通过在这个游戏中单次尽可能获得多的在线玩家来进行压力测试。你可以然后记录服务器平台的表现(速率、响应等),同样也能发现何时服务器会崩溃(断点)。

压力测试和负载测试高度重叠。负载测试记录软件在预期负载下的运行。压力测试记录软件在最大负载下的运行。

软件测试生命周期

无论你使用何种方法论,你总是被期望遵循一个特定的测试生命周期。软件测试生命周期帮助你关注产品需求并一次开发一个特性。

让我们深入看看这六步:

需求分析

你和你的开发团队与产品、市场团队会面来讨论产品的最终需求和特性。对每个需求,小组进行头脑风暴,形成一个可以指示需求是否已经被实现的可测试的说明书。这些说明书可以是诸如“运行时间必须低于X”或“客户必须能很容易操作用户界面”等事情。你后面步骤将会用到这些说明书。

测试计划

这个步骤里,你和你的开发团队进行头脑风暴,讨论说明书里如何进行测试的内容。一些常见的点是“我们将会需要什么资源?”,“我们可以用什么量化指标来测试我们的需求?”和“可能影响测试结果的关键风险因素是什么?”。这步最重要的方面是留存测试指标/用例说明并植入进产品说明书。

测试用例开发

测试用例开发是软件测试过程中的一个关键活动,它涉及编写和设计测试用例,以验证软件系统的功能、性能和可靠性。

测试用例开发的目标是为了在系统中发现潜在的问题和错误,以确保软件的质量和稳定性。通过编写测试用例,测试人员可以明确测试的目标、步骤和预期结果,并使用这些测试用例来执行系统测试。

测试用例通常包括以下几个方面:

  1. 测试目标:明确测试的目标和测试的覆盖范围。确定要测试的功能、特性或场景。
  2. 测试步骤:定义具体的测试步骤,包括输入数据、操作或操作流程。
  3. 预期结果:指定每个测试步骤的预期结果,即在正确的情况下预期系统的行为或输出。
  4. 环境设置:确定测试执行所需的测试环境和配置,包括硬件、软件和网络环境等。
  5. 前置条件:指定执行测试用例之前的特定条件或状态,以确保测试的正确性和一致性。
  6. 后置条件:定义执行测试用例之后所期望的系统状态或结果。

测试环境配置

这个步骤里,你将会创建你的测试环境。绝大多数产品是发布在多平台的,这意味着你至少需要一个平台创建一个环境。这个主要是通过测试框架和多个虚拟机来完成的。

你同样将会在这个步骤创建能经过整个程序也能产生稳定输出的测试输入。好的测试输入覆盖测试用例的全部范围,就算反复运行结果也是一致的。

测试执行

这个步骤里,你和你的团队将会执行测试并记录所有决定了的指标。绝大多数团队会进行运行测试以得到多个可以对比的数据点位。请注意所有严重的和不严重的程序缺陷将会在下个开发周期被再次处理。

你也可能认可你的指标并没有记录所有你需要的数据。这是一个评估你为后面测试选择的指标的好机会。

测试用例关闭与分析

这个步骤是关于从测试中回收固化的、可报告的测试结果。绝大多数公司将会要求你书写日报或周报,汇总每个测试的运行和测试后要改变什么。

从这里开始,你可以选择下面一个:

  • 调整测试并重复来获取更多信息(不同指标,优化的测试环境等)
  • 使用测试结果,返回来为产品开发解决方案(优化运行时间,提升量级等)

使用敏捷测试实践,你将在你创造产品代码前和后完成测试周期。这允许你在产品开发中加速开发,因为你把说明书记在脑中了。

软件测试最佳实践

  • **不要完全依赖自动测试。**确保最少要有一套人工测试来捕捉未预期的缺陷。
  • **编码同时以常见语言或伪代码书写测试用例。**你的经理和新进成员将会感激你节省了他们解析测试脚本的时间。
  • **仅仅用受控的、隔离的测试环境来避免外部因素。**使用一个个人机器或公用的云实例运行测试来去掉可能影响性能或输出的变量。
  • **选择特定的量化指标。**对于说明书和测试用例,确保你的指标仅仅衡量单一属性,可以通过数字来追踪,能帮助到回报。
  • **增量测试。**在你的测试中创建子条件来追踪测试中程序哪里失效了。
  • **让团队成员为单元和集成测试准备测试工作。**避免发生让另一个开发者为你的程序创造测试的确认偏差。当外部测试不可用时候这是个好法子。
  • **使用有帮助的测试名称。**以测试的套件或需求来名称测试。规避诸如Test1或performanceTest的无效名称,换成StressTest_10000user。
  • **使用诸如Selenium和Reflect的软件测试工具。**测试可能是很难追踪的。使用测试框架/工具来简化你的测试,在组内共享它们。

总结

通过本文的深入探索,我们全面了解了软件测试的奥秘和其在软件开发中的重要性。不同类型的软件测试方法为我们提供了多种手段来保证软件的质量、可靠性和稳定性。无论是功能测试、非功能测试、手工测试还是自动化测试,它们都在不同方面提供了有力的验证和保障。通过合理选择和应用这些测试方法,我们能够发现和解决潜在的问题,并为用户提供高质量的软件产品。软件测试不仅是一项技术活动,更是一种质量文化的体现,它对于整个软件开发生命周期的成功至关重要。

  自动化测试相关教程推荐:

2023最新自动化测试自学教程新手小白26天入门最详细教程,目前已有300多人通过学习这套教程入职大厂!!_哔哩哔哩_bilibili

2023最新合集Python自动化测试开发框架【全栈/实战/教程】合集精华,学完年薪40W+_哔哩哔哩_bilibili

测试开发相关教程推荐

2023全网最牛,字节测试开发大佬现场教学,从零开始教你成为年薪百万的测试开发工程师_哔哩哔哩_bilibili

postman/jmeter/fiddler测试工具类教程推荐

讲的最详细JMeter接口测试/接口自动化测试项目实战合集教程,学jmeter接口测试一套教程就够了!!_哔哩哔哩_bilibili

2023自学fiddler抓包,请一定要看完【如何1天学会fiddler抓包】的全网最详细视频教程!!_哔哩哔哩_bilibili

2023全网封神,B站讲的最详细的Postman接口测试实战教学,小白都能学会_哔哩哔哩_bilibili

  总结:

 光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

如果对你有帮助的话,点个赞收个藏,给作者一个鼓励。也方便你下次能够快速查找。

如有不懂还要咨询下方小卡片,博主也希望和志同道合的测试人员一起学习进步

在适当的年龄,选择适当的岗位,尽量去发挥好自己的优势。

我的自动化测试开发之路,一路走来都离不每个阶段的计划,因为自己喜欢规划和总结,

测试开发视频教程、学习笔记领取传送门!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023-12-13 VsCode + CMake + Qt环境搭建

点击 <C 语言编程核心突破> 快速C语言入门 VsCode CMake Qt环境搭建 前言一、前期准备二、具体设置总结 前言 要解决问题: 最近研究 Qt, 使用 qtcreator, 发现在搭建 UI 界面时候很方便, 但到编码和调试就比较有问题了. 想到的思路: 用 VSCode 进行编码及调试. 其它…

基于SSM实现的精品课程网站

一、系统架构 前端&#xff1a;jsp | js | css | jquery | bootstrap 后端&#xff1a;spring | springmvc | mybatis 环境&#xff1a;jdk1.7 | mysql | maven | tomcat 二、代码及数据库 三、功能介绍 01. 登录页 02. web端-首页 03. web端-视频教程 04. web端-资料…

Flutter在Android Studio上创建项目与构建模式

一、安装插件 1、前提条件&#xff0c;安装配置好Android Studio环境 2、安装Flutter和Dart插件 Linux或者Windows平台&#xff1a; 1&#xff09;、打开File > Settings。 2&#xff09;、在左侧列表中&#xff0c;选择"Plugins"右侧上方面板选中 "Market…

Redis - 做缓存时高并发问题:缓存穿透、击穿、雪崩,数据库缓存双写不一致

缓存穿透 当用户访问的数据既不在缓存也不在数据库中时&#xff0c;就会导致每个用户查询都会“穿透” 缓存“直抵”数据库。这种情况就称为缓存穿透。当高度发的访问请求到达时&#xff0c;缓存穿透不 仅增加了响应时间&#xff0c;而且还会引发对 DBMS 的高并发查询&…

Python + Appium 自动化操作微信入门看这一篇就够了!

简介 Appium 是一个开源的自动化测试工具&#xff0c;支持 Android、iOS 平台上的原生应用&#xff0c;支持 Java、Python、PHP 等多种语言。 Appium 封装了 Selenium&#xff0c;能够为用户提供所有常见的 JSON 格式的 Selenium 命令以及额外的移动设备相关的控制命令&#x…

K8S(五)—命名空间与资源配额

目录 命名空间(Namespace)命令计算资源配额创建命名空间绑定一个ResourceQuota资源将命名空间和资源限制对象进行绑定尝试创建第二个 Pod查看ResourceQuota 绑定第二个ResourceQuota为命名空间配置默认的 CPU 、memory请求和限制&#xff08;1&#xff09;Pod 中所有容器都没有…

【C++进阶篇】二叉搜索数

目录 前言&#xff1a; 以后我们要学map&#xff0c;set&#xff0c;AVL&#xff0c;红黑数所以必须要有二叉搜索数做铺垫 1、二叉搜索树概念 2.二叉搜索树操作 1.二叉搜索树的查找 a、从根开始比较&#xff0c;查找&#xff0c;比根大则往右边走查找&#xff0c;比根小则…

感知机(perceptron)

一、感知机 1、相关概念介绍 感知机&#xff08;perceptron&#xff09;是二分类的线性分类模型&#xff0c;属于监督学习算法。输入为实例的特征向量&#xff0c;输出为实例的类别&#xff08;取1和-1&#xff09;。 2、&#xff08;单层&#xff09;感知机存在的问题 感知机…

上课犯困怎么办

我们小时候都有过这样的经历&#xff1a;在课堂上&#xff0c;突然感到困倦&#xff0c;无法集中精力听讲。这不仅影响了学习效果&#xff0c;还可能错过重要的知识点。那么&#xff0c;上课犯困怎么办呢&#xff1f;下面就给大家提供几点建议。 保证充足的睡眠 保证充足的睡眠…

节流防抖:提升前端性能的秘密武器(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

【音视频 | H.264】H.264编码详解

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

VMware安装ContOS 7 提示“客户机操作系统已禁用 CPU。请关闭或重置虚拟机。”

目录 实验环境报错截图报错原因猜测&#xff08;根据实验现象&#xff09;解决办法如下 实验环境 Vmware Workstation 17.5 CentOS7 镜像版本&#xff1a;2207-02版本 注意&#xff1a;2009版本并无该错误 报错截图 报错原因猜测&#xff08;根据实验现象&#xff09; CentO…

MIT6.824-Raft笔记6:不一致log处理、日志快照

本部分主要是关于不一致的日志是怎么决策和取舍的。同时对于日志的恢复&#xff0c;通过快照的方式提高恢复的效率。 1. 不一致log的处理 在我们分析之前&#xff0c;我们需要明白这个场景是否真的存在&#xff0c;因为有些场景不可能存在我们也就没必要考虑它。即需要思考这种…

使用PM2,在生产环境稳定运行你的node项目

PM2 一个 node&#xff0c;本身就用几行代码&#xff0c;就可以启动个 server 进程&#xff0c;监听个端口&#xff0c;为大家提供 Web 服务 一、依赖安装 npm install pm2 -g 二、命令行启动 普通执行启动 pm2 start <js 文件路径 >.js 携带参数启动 pm2 start < 某种…

k8s debug 浅谈

一 k8s debug 浅谈 说明&#xff1a; 本文只是基于对kubectl debug浅显认识总结的知识点,后续实际使用再补充案例 Kubernetes 官方出品调试工具上手指南(无需安装&#xff0c;开箱即用) debug-application 简化 Pod 故障诊断: kubectl-debug 介绍 1.18 版本之前需要自己…

什么是主动学习(Active Learning)?定义,原理,以及主要方法

数据是训练任何机器学习模型的关键。但是&#xff0c;对于研究人工智能的企业和团队而言&#xff0c;数据仍是实现成功的最大障碍之一。首先&#xff0c;您需要大量数据来创建高性能模型。更重要的是&#xff0c;您需要标注准确的数据。虽然许多团队一开始都是手动标注数据集&a…

使用 Taro 开发鸿蒙原生应用 —— 当 Taro 遇到纯血鸿蒙 | 京东云技术团队

纯血鸿蒙即将到来 在今年 8 月的「2023年华为开发者大会&#xff08;HDC.Together&#xff09;」上&#xff0c;华为正式官宣「鸿蒙Next」&#xff0c;这个更新的版本将移除所有的 AOSP 代码&#xff0c;彻底与 Android 切割&#xff0c;使其成为一个完全自主研发的操作系统&a…

JAVA实体类集合该如何去重?

JAVA实体类集合该如何去重&#xff1f; 最近在工作中经常遇到需要去重的需求&#xff0c;所以特意系统的来梳理一下 有目录&#xff0c;不迷路 JAVA实体类集合该如何去重&#xff1f;单元素去重方法一&#xff1a;利用Set去重方法二&#xff1a;利用java 8的stream写法&#xf…

预测性维护对制造企业设备管理的作用

制造企业设备管理和维护对于生产效率和成本控制至关重要。然而&#xff0c;传统的维护方法往往无法准确预测设备故障&#xff0c;导致生产中断和高额维修费用。为了应对这一挑战&#xff0c;越来越多的制造企业开始采用预测性维护技术。 预测性维护是通过传感器数据、机器学习和…

【教3妹学编程-算法题】消除相邻近似相等字符

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 3妹&#xff1a;好冷啊&#xff0c; 冻得瑟瑟发抖啦 2…