测试基础 01001 软件测试基础 - 基础知识篇

花花花次元 · 2021年08月02日 · 483 次阅读

软件测试:

使用人工 or 自动化的方式,来验证系统在各种应用场景下的功能是否符合设计要求,发现软件实际运行结果和预期结果之间的偏差。

软件测试的方法:

黑盒测试
黑盒测试也称功能测试 or 数据驱动测试,在测试时,把程序看作一个不能打开的黑盒子,着眼于程序外部结构,完全不考虑程序内部逻辑结构,针对软件界面和软件功能进行测试。在进行黑盒测试时需要注意不仅要测试所有合法的输入,而且还要对那些不合法的输入进行测试。

白盒测试
白盒测试也称结构测试 ot 逻辑驱动测试,是针对被测单元内部逻辑结构是否正确工作的测试。白盒测试会根据程序的内部逻辑结构设计测试用例,对所有的逻辑路径进行测试。在进行白盒测试时需要注意,白盒测试只能验证代码的逻辑是否正确,无法验证出代码是否实现了需求功能。

软件测试的分类:

单元测试:
单元测试是指,在与程序其他部分相隔离的情况下,对软件中最小可测试单元进行检查和验证的工作,这里的最小可测试单元通常时指函数 or 类。单元测试属于白盒测试。

单元测试的作用:

  1. 单元测试通常由开发工程师完成,一般会伴随开发代码一起递交至代码库。单元测试属于最严格的软件测试手段,是最接近代码底层实现的验证手段,可以在软件开发的早期以最小的成本保证局部代码的质量。
  2. 单元测试都是以自动化的方式执行,所以在大量回归测试的场景下更能带来高收益。
  3. 单元测试的实施过程还可以帮助开发工程师改善代码的设计与实现,并能在单元测试代码里提供函数的使用示例,因为单元测试的具体表现形式就是对函数以各种不同输入参数组合进行调用,这些调用方法构成了函数的使用说明。

如何做好单元测试:

  1. 做好输入参数的等价类划分: a. 如果要实现正确的功能逻辑,会有哪几种正常的输入; b. 是否有需要特殊处理的多种边界输入; c. 各种潜在非法输入的可能性以及如何处理。
  2. 正确的识别输入参数和输出参数: 输入数据
    • 被测试函数的输入参数;
    • 被测试函数内部需要读取的全局静态变量;
    • 被测试函数内部需要读取的成员变量;
    • 函数内部调用子函数获得的数据;
    • 函数内部调用子函数改写的数据;
    • 嵌入式系统中,在中断调用时改写的数据; 预计输出
    • 被测试函数的返回值;
    • 被测试函数的输出参数;
    • 被测试函数所改写的成员变量;
    • 被测试函数所改写的全局变量;
    • 被测试函数中进行的文件更新;
    • 被测试函数中进行的数据库更新;
    • 被测试函数中进行的消息队列更新;
  3. 理解驱动代码,桩代码和 Mock 代码之间的逻辑关系:
    • 驱动代码(Driver)指调用被测函数的代码,在单元测试过程中,驱动模块通常包括调用被测函数前的数据准备、调用被测函数以及验证相关结果三个步骤。驱动代码的结构,通常由单元测试的框架决定。
    • 桩代码(Stub)是用来代替真实代码的临时代码。在单元测试阶段,由于函数 B 尚未实现,但是为了不影响对函数 A 自身实现逻辑的测试,你可以用一个假的函数 B 来代替真实的函数 B,那么这个假的函数 B 就是桩函数。桩代码的应用首先起到了隔离和补齐的作用,使被测代码能够独立编译、链接,并独立运行。同时,桩代码还具有控制被测函数执行路径的作用。
    • Mock 代码和桩代码非常类似,都是用来代替真实代码的临时代码,起到隔离和补齐的作用。

Mock 代码和桩代码的本质区别
-Mock 代码和桩代码的本质区别在于测试期待结果的验证 Assert and Expectiation。对于 Mock 代码来说,我们的关注点是 Mock 方法有没有被调用,以什么样的参数被调用,被调用的次数,以及多个 Mock 函数的先后调用顺序。所以,在使用 Mock 代码的测试中,对于结果的验证(也就是 assert),通常出现在 Mock 函数中。
-对于桩代码来说,我们的关注点是利用 Stub 来控制被测函数的执行路径,不会去关注 Stub 是否被调用以及怎么样被调用。所以,你在使用 Stub 的测试中,对于结果的验证(也就是 assert),通常出现在驱动代码中。

实际项目中如何开展单元测试:

  • 1.并不是所有的代码都要进行单元测试,通常只有底层模块或者核心模块的测试中才会采用单元测试。
  • 2.确定单元测试框架的选型,这和开发语言直接相关。比如,Java 最常用的单元测试框架是 Junit 和 TestNG;C/C++ 最常用的单元测试框架是 CppTest 和 Parasoft C/C++test;框架选型完成后,你还需要对桩代码框架和 Mock 代码框架选型,选型的主要依据是开发所采用的具体技术栈。通常,单元测试框架、桩代码 /Mock 代码的选型工作由开发架构师和测试架构师共同决定。
  • 3.为了能够衡量单元测试的代码覆盖率,通常你还需要引入计算代码覆盖率的工具。不同的语言会有不同的代码覆盖率统计工具,比如 Java 的 JaCoCo,JavaScript 的 Istanbul。
  • 4. 最后需要把单元测试执行、代码覆盖率统计和持续集成流水线做集成,以确保每次代码递交,都会自动触发单元测试,并在单元测试执行过程中自动统计代码覆盖率,最后以 “单元测试通过率” 和 “代码覆盖率” 为标准来决定本次代码递交是否能够被接受。

实际单元测试中的困难

  1. 紧密耦合的代码难以隔离
  2. 隔离后,编译连接运行困难
  3. 代码本省的可测试性较差,通常代码的可测试性和代码的规模成正比
  4. 无法通过桩代码直接模拟系统底层函数的调用
  5. 代码覆盖率越往后越难提高

集成测试:
集成测试,也叫组装测试或联合测试,是单元测试的逻辑扩展。在单元测试的基础上,将所有模块按照设计要求(如根据结构图)组装成为子系统或系统,进行集成测试,重点是测试测试模块之间的接口。一些模块虽然能够单独地工作,但并不能保证连接起来也能正常的工作。一些局部反映不出来的问题,在全局上很可能暴露出来。在集成测试之前,单元测试应该已经完成,集成测试中所使用的对象应该是已经经过单元测试的软件单元。这一点很重要,因为如果不经过单元测试,那么集成测试的效果将会受到很大影响,并且会大幅增加软件单元代码纠错的代价。

系统测试:
是基于系统整体需求说明书的黑盒类测试,应覆盖系统所有联合的部件。系统测试是针对整个产品系统进行的测试,目的是验证系统是否满足了需求规格的定义,找出与需求规格不相符合或与之矛盾的地方。系统测试的对象不仅仅包括需要测试的产品系统的软件,还要包含软件所依赖的硬件、外设甚至包括某些数据、某些支持软件及其接口等。因此,必须将系统中的软件与各种依赖的资源结合起来,在系统实际运行环境下来进行测试。

回归测试:
回归测试是指在发生修改之后重新测试先前的测试用例以保证修改的正确性。理论上,软件产生新版本,都需要进行回归测试,验证以前发现和修复的错误是否在新软件版本上再次出现。根据修复好了的缺陷再重新进行测试。回归测试的目的在于验证以前出现过但已经修复好的缺陷不再重新出现。一般指对某已知修正的缺陷再次围绕它原来出现时的步骤重新测试。

验收测试:
验收测试是指系统开发生命周期方法论的一个阶段,这时相关的用户或独立测试人员根据测试计划和结果对系统进行测试和接收。它让系统用户决定是否接收系统。它是一项确定产品是否能够满足合同或用户所规定需求的测试。验收测试包括 Alpha 测试和 Beta 测试。
Alpha 测试:是由用户在开发者的场所来进行的,在一个受控的环境中进行。
Beta 测试:由软件的最终用户在一个或多个用户场所来进行的,开发者通常不在现场,用户记录测试中遇到的问题并报告给开发者,开发者对系统进行最后的修改,并开始准备发布最终的软件。

什么才算是好的测试用例:

好的测试用例一定是一个完备的集合,它能够覆盖所有等价类以及各种边界值,而跟能否发现缺陷无关。一个好的测试用例,必须具备以下三个特征:
- 整体完备性: “好的” 测试用例一定是一个完备的整体,是有效测试用例组成的集合,能够完全覆盖测试需求。
- 等价类划分的准确性: 指的是对于每个等价类都能保证只要其中一个输入测试通过,其他输入也一定测试通过。
- 等价类集合的完备性: 需要保证所有可能的边界值和边界条件都已经正确识别。

常用的测试用例设计方法:

  • 等价类划分法:是将所有可能的输入数据划分成若干个子集,在每个子集中,如果任意一个输入数据对于揭露程序中潜在错误都具有同等效果,那么这样的子集就构成了一个等价类。

  • 边界值分析法:是选取输入、输出的边界值进行测试,是对等价类划分的补充。从工程实践经验中可以发现,大量的错误发生在输入输出的边界值上,所以需要对边界值进行重点测试,通常选取正好等于、刚刚大于或刚刚小于边界的值作为测试数据。

  • 错误推测法:是指基于对被测试软件系统设计的理解、过往经验以及个人直觉,推测出软件可能存在的缺陷,从而有针对性地设计测试用例的方法。这个方法强调的是对被测试软件的需求理解以及设计实现的细节把握,当然还有个人的能力。这个方法的缺点是难以系统化,并且过度依赖个人能力。

如何才能设计出好的测试用例:

在真实的工程实践中,不同的软件项目在研发生命周期的各个阶段都会有不同的测试类型。对于每一种不同的测试类型,设计出 “好的” 测试用例的关注点和方法论可能会有很大的差异。在具体的用例设计时,首先需要搞清楚每一个业务需求所对应的多个软件功能需求点,然后分析出每个软件功能需求点对应的多个测试需求点,最后再针对每个测试需求点设计测试用例。

  1. 从软件功能需求出发,全面地、无遗漏地识别出测试需求是至关重要的,这将直接关系到用例的测试覆盖率。
  2. 对于识别出的每个测试需求点,需要综合运用等价类划分、边界值分析和错误推测方法来全面地设计测试用例。
  3. 只有深入理解被测试软件的架构,你才能设计出 “有的放矢” 的测试用例集,去发现系统边界以及系统集成上的潜在缺陷。
  4. 必须深入理解被测软件的设计与实现细节,深入理解软件内部的处理逻辑。
  5. 需要引入需求覆盖率和代码覆盖率来衡量测试执行的完备性,并以此为依据来找出遗漏的测试点。

测试用例的设计

测试用例是为了发现软件中存在的问题而编写的一组包含测试输入,执行条件,预期结果的文档,用于合适软件产品是否满足需求。

** 测试用例需要包含的要素:**
测试用例的唯一编号
被测试模块
测试功能点
测试用例的优先级
测试的前提条件
测试步骤
期望的测试结果

面试测试用例设计的思维导图

App 登陆测试用例设计的思维导图

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册