目录
1 认识软件测试
1.1 什么是软件
软件,在中国大陆及香港用语中被称为"软件",台湾则称作"软体",英文为"software"。
它是一系列按照特定顺序组织的计算机数据和指令的集合。简单来说,软件可以视为【程序、数据和文档】的集合体。
国标中对软件的定义为:与计算机系统操作有关的计算机程序、规程、规则,以及可能有的文件、文档及数据。软件并不仅限于可以在计算机上运行的电脑程序,与这些电脑程序相关的文档也通常被认为是软件的一部分。
常见的软件有:Windows、macOS、Linux、Microsoft Office、WPS Office、Chrome、抖音、金山毒霸、拼多多、QQ、微信等。
1.2 什么是软件测试
早期的定义:
早期定义:软件测试是对程序能够按预期运行建立起一种信心。 —— Bill Hetzel,1973
经典定义:测试是为发现错误而执行程序的过程。 —— Myers , 1979
标准的定义:
软件测试是指对软件系统进行评估和验证的过程,以发现软件中存在的缺陷、错误和不符合规范的行为。
官方的定义:
软件测试的标准定义(IEEE)是:使用人工或自动的手段来运行或测定某个软件系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别。这个定义明确指出,软件测试不仅仅是一个发现错误的过程,它还包括对软件质量的度量,是软件质量保证(SQA)的主要职能之一。
1.3 软件测试的发展历程
在最初的时候,测试与调试的概念是相似的,目的主要是纠正已知的软件故障,并且这一工作常常由开发人员自己完成。随着时间的推移,软件测试的概念开始发生转变。
- 1957年:软件测试开始与调试区分开来,成为一种专门的发现软件缺陷的活动。
- 1972年:在北卡罗来纳大学,历史上第一次以软件测试为主题的正式会议被举行,标志着软件测试开始进入学术界的视野。
- 1979年:Glenford J. Myers在其经典著作《软件测试的艺术》中,给出了软件测试的经典定义,即测试是为发现错误而执行的一个程序或者系统的过程。
- 20世纪80年代早期:软件测试的定义进一步扩展,不再仅限于发现错误,而是包含了对软件质量的全面评价。
- 20世纪90年代:随着软件行业的快速发展,测试能力成熟度模型(TMM)等理论被提出,为软件测试的标准化和规范化提供了指导。
- 21世纪初:敏捷开发方法的兴起推动了软件测试的变革。Kent Beck在极限编程(XP)方法论中提出了测试驱动开发(TDD)的理念,强调在编写功能代码之前先编写测试用例。
1.4 软件测试的重要性
一款软件从有到无会经历很多的开发阶段,由不同的人来参于开发,所以最终产出的功能可能会存在问题,因此为了保证软件的功能是可用的,我们必须对软件进行测试。
当前的软件行业已经不在是以功能为王,用户不仅仅只盯住软件的功能是否满足需求,还会对软件是否容易上手,执行效率是否高效等一系列的其它的一些需求进行要求,所以这也需要我们对软件进行大量的测试。
通过软件测试,可以确保软件的功能、性能、安全性等方面满足用户需求,降低软件发布后的风险,提高用户体验。软件测试还有助于支持项目决策,促进团队协作,并持续改进开发流程。因此,软件测试在保障软件质量、提升用户体验和满足用户需求方面发挥着重要作用。
1.5 软件测试职业规划
2 软件测试的分类
2.1 按开发阶段划分
单元测试
单元测试(Unit Testing)又称模块测试,针对软件设计中的最小单位——程序模块,进行正确性检查的测试工作。
单元测试需要从程序的内部结构出发设计测试用例。多个模块可以平行地独立进行单元测试。
单元测试的目的是找出单元模块中存在的错误,确保每个单元都能正常工作。
这个阶段的测试对象通常是函数、方法或类等,确保它们的功能和性能符合设计要求。单元测试一般由开发人员(结合JUnit、UnitTest等框架)完成,主要关注代码内部的逻辑正确性。
单元定义:C语言中指一个函数,Java中指一个类,在图形化的软件中,单元一般指1个窗口或1个菜单。
常见问题
1.什么时候进行单元测试?
单元测试通常在某个模块代码编写完成后立即进行。
2.由谁来做单元测试?
单元测试通常由开发人员自己进行。这是因为开发人员对代码的内部逻辑和结构有深入的了解,能够更准确地设计和执行测试用例。此外,开发人员在进行单元测试的过程中,可以及时发现和修复代码中的错误,从而提高代码质量。
3.单元测试的依据?
单元测试的依据主要是基于软件的需求文档、设计文档和编码规范。开发人员根据这些文档和规范编写测试用例,以确保代码中的每个单元(如函数、方法、类等)都能按照预期工作。
4.单元测试的通过标准?
单元测试的通过标准主要包括两个方面:首先,所有的测试用例都应成功执行,没有失败或错误;其次,这些测试用例应全面覆盖软件的需求和功能点,确保没有遗漏。
5.国内单元测试的现状?
在国内,单元测试在软件开发过程中的重视程度逐渐提高。越来越多的企业和团队开始意识到单元测试的重要性,并将其纳入软件开发流程中。然而,与一些发达国家相比,国内在单元测试的实践和普及程度上仍存在一定的差距。一些团队可能由于时间、资源或认知上的限制,对单元测试的执行不够充分或不够规范。
6.如何进行单元测试?
- 确定测试范围:
- 识别需要进行单元测试的模块或代码单元(如函数、方法、类等)。
- 确定每个代码单元的功能和预期行为。
- 编写测试用例:
- 根据代码单元的功能和预期行为编写测试用例。
- 考虑不同的输入场景,包括正常情况和边界情况,以确保测试的全面性。
- 每个测试用例都应包含一个明确的测试目的、输入数据和预期输出。
- 准备测试环境:
- 设置测试环境,确保测试所需的数据、依赖项和工具都已准备就绪。
- 如有需要,可以使用模拟对象或桩代码来替代外部依赖。
- 编写测试代码:
- 使用测试框架(如JUnit、pytest等)编写测试代码。
- 测试代码应调用被测试的代码单元,并验证其输出是否符合预期。
- 使用断言(assertions)来检查实际输出与预期输出是否一致。
- 执行测试:
- 运行测试代码,观察测试结果。
- 测试框架将自动执行测试用例,并报告每个测试用例的成功或失败情况。
- 分析测试结果:
- 分析测试结果,查找失败或错误的测试用例。
- 检查失败的测试用例的输入和输出,找出可能的问题原因。
- 根据需要调整测试用例或修复代码中的错误。
- 重构和迭代:
- 如果在测试过程中发现代码设计或实现上的问题,进行必要的重构。
- 迭代进行单元测试,确保代码的质量和稳定性。
- 集成到开发流程:
- 将单元测试集成到开发流程中,确保每次代码更改后都能自动运行测试。
- 使用持续集成(CI)工具来自动执行单元测试,并在发现问题时及时通知开发人员。
集成测试
集成测试(Integration Testing)又叫组装测试,通常在单元测试的基础上,将所有程序模块进行有序的、递增的测试,重点测试不同模块的接口部分。
它是在单元测试之后进行的,测试的重点在于检查模块之间的接口是否正确、数据传递是否正常,以及验证集成后的系统是否稳定可靠。
单元测试主要关注软件的最小可测试单元(通常是单个模块或函数)的功能和正确性,而集成测试则关注这些单元如何协同工作。
常见问题
1.什么时候进行集成测试?
集成测试通常在单元测试完成之后进行。这是因为单元测试确保了单个模块或组件的功能正确性,而集成测试则关注这些模块在组合在一起时的交互和整体性能。在进行集成测试之前,需要确保所有参与集成的模块都已经通过了单元测试,并且达到了预定的质量标准。此外,集成测试也可以在某些模块开发完成后就开始,采用增量集成的方式,这样可以更早地发现和解决问题。
2.由谁来做集成测试?
集成测试主要由测试人员来执行。测试人员负责设计并执行集成测试用例,验证不同模块之间的接口和交互是否符合预期。
3.集成测试的依据?
集成测试的依据主要包括软件系统的需求规格说明文档和设计文档。
需求规格说明文档描述了系统的功能需求、性能需求、安全需求等,集成测试需要验证系统在集成后是否满足这些需求。而设计文档则描述了系统的整体结构、模块之间的关系以及接口定义等,集成测试需要根据设计文档来验证模块之间的接口是否正确、模块之间的数据传递是否正常,并确保模块的集成不会影响系统的功能和性能。
系统测试
系统测试(System Testing)是对已经集成好的软件系统进行完整性检查和验证,将整个软件系统看为一个整体进行测试,包括对功能、性能、以及软件所运行的软硬件环境进行测试。以确保软件系统能够正常运行,并且能够满足软件开发阶段定义的功能和性能需求。
系统测试在系统集成完毕后进行测试,前期主要测试系统的功能是否满足需求,后期主要测试系统运行的性能是否满足需求,以及系统在不同的软硬件环境中的兼容性等。
系统测试的目的是验证软件系统是否满足用户需求,以及系统的性能、安全性、稳定性等方面是否符合预期。
验收测试
验收测试(Acceptance Testing)是部署软件之前的最后一个测试操作,也被称为交付测试。它是在软件产品完成了单元测试、集成测试和系统测试之后,产品发布之前所进行的软件测试活动。
它的主要目的是确保软件符合业务需求并且可以满足用户的期望。在这个过程中,相关的用户和独立测试人员根据测试计划和结果对系统进行测试和接收,从而决定是否接收该系统。
验收测试是一项确定产品是否能够满足合同或用户所规定需求的测试。
α测试
α测试是由一个用户在开发环境下进行的测试,可以是公司内部的用户在模拟实际操作环境下进行的受控测试。
它不能由程序员和测试员完成,参与测试的用户可以是公司内的非开发和测试成员或者实际用户,有无经验均可。
α测试发现的错误可以在测试现场立即反馈给开发人员,以便其进行分析和处理。
Alpha 是内测版本,即现在所说的CB,此版本表示该软件仅仅是一个初步完成品,通常只在软件开发者内部交流,也有很少一部分发布给专业测试人员。一般而言,该版本软件的bug较多,普通用户最好不要安装。
β测试
β测试由软件的多个用户在实际使用环境下进行,开发者通常不在测试现场。
这种测试不能由程序员或测试员完成,一般由最终用户或其他人员完成。
β测试的目标是发现软件在实际使用环境中可能存在的问题,并在最终发行前找到并修复这些问题。
Beta是公测版本,是对所有用户开放的测试版本。该版本相对于α 版已有了很大的改进,消除了严重的错误,但还是存在着一些缺陷,需要经过大规模的发布测试来进一步消除。
这一版本通常由软件公司免费发布,用户可从相关的站点下载。通过一些专业爱好者的测试,将结果反馈给开发者,开发者们再进行有针对性的修改。该版本也不适合一般用户安装。
γ测试
Gamma版本,指的是软件版本正式发行的候选版。
γ测试的优点在于它结合了底层测试(如单元测试,检验源代码质量)和高层测试(如系统测试,检验整个系统的需求),能够清楚地标识开发和测试的各个阶段。然而,其缺点在于自上而下的顺序可能导致错误不能及时地进行修改,同时实际的开发过程中,用户需求可能难以完全明确,导致返工量大和灵活度较低。
在实际操作中,为了改进测试流程和提高软件质量,每个步骤都可以进行小的迭代模型,以更及时地发现和修复问题。此外,γ测试通常是由第三方进行的软件测试,以确保测试的客观性和公正性。
该版本已经相当成熟了,与即将发行的正式版相差无几, 成为正式发布的候选版本。
2.2 按是否查看源代码
黑盒测试
黑盒测试(Black-box Testing)又称数据驱动测试,完全不考虑程序内部结构和内部特性,注重于测试软件的功能需求,只关心软件的输入数据和输出数据。
黑盒测试能发现以下几类错误:
- 功能不对或功能遗漏。
- 界面错误。
- 数据库访问或者处理错误。
- 性能问题。
黑盒测试的优点
- 简单直观:黑盒测试不需要深入了解软件的内部逻辑和代码结构,只需关注输入和输出,因此测试设计相对简单直观。
- 与开发者独立:黑盒测试可以独立于开发团队进行,测试人员不需要具备编程技能或了解软件的内部实现,这有助于实现开发与测试的分离。
- 关注用户需求:黑盒测试主要关注软件是否满足用户的需求和规格说明,因此能够更直接地反映软件的实际使用效果。
- 易于自动化:由于黑盒测试主要关注输入和输出,因此相对容易实现自动化测试,提高测试效率。
黑盒测试的缺点
- 测试覆盖度有限:由于只能覆盖部分功能和场景,无法穷尽所有代码路径和边界条件,存在漏测风险。
- 难以发现内部缺陷:不涉及内部结构和代码实现,难以发现与内部逻辑相关的缺陷,如性能问题等。
- 依赖规格说明:测试的有效性受需求规格说明书准确性和完整性的影响,规格缺陷可能导致测试用例设计问题。
- 问题定位困难:由于不了解内部逻辑,发现缺陷时难以准确定位问题原因和位置,增加修复难度。
- 未执行代码问题:无法发现因未执行代码而隐藏的问题,如条件分支未覆盖、异常处理未触发等情况下的缺陷。
- 无法实现穷举测试:由于输入和输出组合可能无限或庞大,无法测试所有情况,可能导致边缘或特殊情况被遗漏。
黑盒测试的分类
功能测试
功能测试(function testing)是黑盒测试的一方面,主要检查实际软件的功能是否符合用户的需求。
- 逻辑功能测试(function testing)
- 界面测试(UI testing)
- 易用性测试(usability testing)
- 安装测试(installation testing)
- 兼容性测试(compatibility testing)
性能测试
性能测试(performance testing)是软件测试的高端领域,性能测试工程师的待遇和白盒测试工程师不相上下,通常我们所说的高级软件测试工程师一般就是指性能测试或是白盒测试工程师。
- 时间性能(事务响应时间等)
- 空间性能(系统资源消耗)
- 一般性能测试
- 稳定性测试
- 负载测试:
- 定义:负载测试是对系统施加正常工作条件下的预期负载进行测试,以评估系统在这种负载下的性能和行为。
- 目的:负载测试旨在确定系统在正常操作条件下的性能水平,包括响应时间、吞吐量和资源利用率等指标。
- 特点:负载测试通常会模拟实际使用场景下的用户行为和系统负载,以评估系统是否能够满足预期的性能需求。
- 压力测试:
- 定义:压力测试是在系统达到或超过其正常工作极限的情况下进行的测试,以验证系统在极端条件下的稳定性和可靠性。
- 目的:压力测试旨在测试系统在负载增加、资源不足或其他极端条件下的表现,并确定系统是否能够保持稳定运行或适当地处理这些条件。
- 特点:压力测试通常会模拟大量用户同时访问系统、大数据量的输入或频繁的请求,以测试系统在高负载下的性能表现。
白盒测试
白盒测试(White-box Testing)指的是把盒子打开,去研究里面的源代码和程序结构。
在软件公司,往往采用黑盒测试&白盒测试相结合的方式。
对软件的整体功能和性能进行黑盒测试。
对软件的源代码采用白盒测试。
灰盒测试
灰盒测试(Gray-box Testing)是介于白盒测试与黑盒测试之间的一种测试,既可保证黑盒的关注点又可掌控白盒的内部结构,但不会去对内部程序功能和运作做详细了解,灰盒测试结合了白盒测试和黑盒测试的要素。
2.3 按是否运行分类
静态测试
定义:静态测试(Static testing)是在不实际运行被测软件的情况下,通过检查程序代码、界面或文档等静态资源,发现可能存在的错误和问题的过程。
特点:静态测试通常包括代码审查(Code Review)、静态分析(Static Analysis)和文档审查(Document Review)等方法,旨在在软件进入动态测试阶段之前尽早发现和修复问题。
优势:静态测试可以在开发早期发现问题,有助于减少后期的修复成本和测试工作量,同时提高代码质量和软件稳定性。
动态测试
定义:动态测试(Dynamic testing)是在实际运行被测程序的情况下,通过输入测试数据,检查实际输出结果与预期结果是否相符的过程。
特点:动态测试通常涉及执行测试用例,模拟用户操作,检查软件的功能、性能和稳定性等方面,以确认软件的正确性和可靠性。
优势:动态测试可以全面地验证软件的行为,包括用户界面交互、业务逻辑处理、性能响应等方面,确保软件符合需求并具备预期的功能。
2.4 按是否自动化分类
人工测试
定义:人工测试是由测试人员手动执行的测试过程,包括手动输入测试数据、手动操作软件界面、手动验证功能等。
特点:人工测试通常需要测试人员的直接参与,对软件的功能、性能、用户体验等方面进行全面的手动验证和评估。
优势:人工测试可以发现一些难以自动化的问题,如视觉和用户体验方面的问题,同时可以灵活地应对变化和复杂的测试场景。
自动化测试
定义:自动化测试是通过编写测试脚本和使用自动化测试工具,以自动化的方式执行测试用例,检查软件的功能、性能和稳定性等方面。
特点:自动化测试可以提高测试效率和重复性,减少人工测试的工作量,同时可以在短时间内执行大量的测试用例,并提供可靠的测试结果。
优势:自动化测试可以在持续集成和持续交付流程中实现自动化测试执行,加速软件发布周期,同时可以提高测试覆盖率和质量。
2.5 其他
随机测试
定义:随机测试(Random Testing)是一种测试方法,通过随机选择测试用例来执行测试,目的是发现系统中的潜在错误和异常行为。
目的:随机测试的主要目标是发现系统中未被覆盖到的错误,尤其是在程序员和测试人员未能预料到的情况下。
特点:随机测试的测试用例通常是根据随机生成的输入数据生成的,而不是基于具体的需求或功能规格。
随机测试可以通过以下方式实现:
- 随机输入:通过随机生成输入数据,对软件系统进行测试。例如,对于一个计算器软件,可以随机产生各种各样的算式进行测试,包括整数、小数、正数、负数、较大的数、较小的数等。
- 随机操作:通过随机生成各种各样的操作序列,来测试软件系统的鲁棒性和正确性。例如,在一个应用系统中,可以随机进行各种操作,如点击按钮、输入文本、打开文件等,观察软件系统的反应并检查是否存在错误和异常情况。
- 随机位置:随机选择软件系统中的位置进行测试,以检测系统的缺陷和错误。例如,在一个迷宫游戏中,可以随机选择出口的位置,然后利用随机生成的步骤来测试系统以检查其正确性和鲁棒性。
随机测试主要是对被测软件的一些重要功能进行复测,也包括测试那些当前的测试用例没有覆盖到的部分。另外,对于软件更新和新增加的功能要重点测试。重点对一些特殊点情况点、特殊的使用环境、并发性、进行检查。尤其对以前测试发现的重大Bug,进行再次测试,可以结合回归测试一起进行。
回归测试
定义:回归测试(Regression Testing)是在对软件进行修改、更新或修复后重新执行先前执行过的测试,以确保修改没有引入新的错误或导致现有功能失效。
目的:回归测试的主要目标是验证系统的修改对现有功能的影响,并确保系统在修改后仍然能够如预期般正常工作。
特点:回归测试通常是针对已有的测试用例集合进行的,重点是检查修改点附近的功能是否受到影响。
冒烟测试
定义:冒烟测试(Smoke Testing)是一种简单的测试方法,旨在快速验证软件的关键功能是否能够正常工作,以便在正式的测试流程开始之前,尽早发现潜在的严重问题。
目的:冒烟测试的主要目标是快速检查系统的基本功能是否可用,以便在更深入的测试之前快速发现严重的问题。
特点:冒烟测试通常涉及系统的主要功能或核心流程,测试用例简单且易于执行,目的是在最短的时间内发现系统中的主要问题。
在测试开始之前,我们会进行冒烟测试,如果冒烟测试不通过,我们就不会进行下面的测试,而是打回开发让其先进行修改,以达到冒烟测试的要求
3 测试原则
- 测试证明软件存在缺陷:无论我们执行何种测试操作,都无法断言软件完美无缺。测试的目的在于发现软件的缺陷,而不是证明其完美。
- 避免穷尽测试:由于软件的复杂性和多样性,我们无法实现穷尽测试,即测试所有可能的输入和场景。因此,我们需要根据风险评估和优先级来制定测试计划,确保关键和常用功能得到充分测试,同时平衡测试资源和时间。
- 缺陷的群集性(二八原则):在软件测试中,我们常常发现缺陷往往集中在少数核心功能模块中。这意味着尽管核心功能可能只占整个软件功能的20%,但它们中的缺陷比例却可能高达80%。因此,我们应该优先关注这些核心功能的测试,以最大限度地发现缺陷。
- 测试环境的重要性:某些测试需要依赖特定的环境或配置。为了确保测试结果的准确性和可靠性,我们必须确保测试环境与实际运行环境尽可能一致,并且满足测试需求。这包括硬件、操作系统、数据库、网络等方面的配置和设置。
- 尽早开始测试:为了尽早发现和解决软件中的缺陷,测试工作应该尽早介入。这意味着在软件开发周期的早期阶段,测试人员就应该开始制定测试计划、编写测试用例,并与开发人员密切合作,确保测试工作顺利进行。通过尽早开始测试,我们可以减少后期修复缺陷的成本和风险,提高软件的整体质量。