# 软件构造 关于软件测试

    技术2025-02-27  15

    即使是最好的测试,也无法达到100%的无错误

    怎样是一个好的测试?

    能发现错误不冗余最佳特性别太复杂也别太 简单

    测试的几个层级:

    单元测试: 是指对软件中的最小可测试单元进行检查和验证,Java里单元指一个类或一个方法集成测试:也叫组装测试或联合测试。在单元测试的基础上,将所有模块按照设计要求(如根据结构图)组装成为子系统或系统,进行测试系统测试:是对整个系统的测试,将硬件、软件、操作人员看作一个整体,检验它是否有不符合系统说明书的地方。

    回归测试:指修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误验收测试:是部署软件之前的最后一个测试操作。在软件产品完成了单元测试、集成测试和系统测试之后,产品发布之前所进行的软件测试活动。

    黑盒测试&白盒测试

    白盒测试:对程序内部代码结构的测试 ,要考虑内部实现细节黑盒测试:对程序外部表现出来的行为的测试,黑盒测试完 全从函数spec导出测试用例,不考虑函数内部实现

    测试的等价类

    基于等价类划分的测试:将被测函数的输入域划分为等价类, 从等价类中导出测试用例 针对每个输 入数据需要满足的约束条件,划分等价类 每个等价类代表着对输入约束加以满足/违反的有效 /无效数据的集合 。 而相似的输入,将会展示相似的行为。 故可从每个等价类中选一个代表作为 测试用例即可

    可以按照下面的准则划分:

    输入数据限定了数值范围输入数据指明了特定的值输入数据确定了一组数输入数据是Y/N

    案例:对 BigInteger.multiply()的测试:

    /** @param val another BigInteger @return a BigInteger whose value is (this * val). */ public BigInteger multiply(BigInteger val) E.g., BigInteger a = ...; BigInteger b = ...; BigInteger ab = a.multiply(b);

    方法的输入和输出是一个 BigInteger × BigInteger → BigInteger 的映射, 从二维输入空间BigInteger × BigInteger可以对其划分 从正负的角度对二维空间进行 等价类划分

    a and b are both positivea and b are both negativea is positive, b is negativea is negative, b is positive

    同时需要考虑输入数据的特殊情况

    a 或 b 是 0, 1, 或 -1

    考虑输入的上限:很大的数是否仍正确?

    a和b都是较小的数a和b都是大数

    因此可以划分等价类:

    01-1small positive integersmall negative integerhuge positive integerhuge negative integer

    再进行笛卡尔乘积,一共7*7=49 种划分

    边界值分析方法

    程序的行为在边界的地方可能发生 “突变”某 些边界值是“特殊情况”,需要特殊处理程序员经常犯一些大小差1的错误 ,例如<和≤

    因此在等 价类划分时,将边界作为等价类之一加入考虑, 不仅要考虑边界,还要考虑边界的两侧 案例:对max函数的测试: max : int × int → int 可以将他们划分为: a与b之间的关系:

    a < ba = ba > b

    a的取值

    a = 0a < 0a > 0a = minimum integer 、a = maximum integer

    对b的取值和a同理 然后选取值来进行全覆盖

    (1, 2) covers a < b, a > 0, b > 0(-1, -3) covers a > b, a < 0, b < 0(0, 0) covers a = b, a = 0, b = 0(Integer.MIN_VALUE, Integer.MAX_VALUE) covers a < b, a = minint, b = maxint(Integer.MAX_VALUE, Integer.MIN_VALUE) covers a > b, a = maxint, b = minint…

    笛卡尔积和覆盖每个取值

    笛卡尔积:全覆盖 多个划分维度上的多个取值,要组合起来,每个组合都要有一个用例 例如对上面的max的测试,有三个维度,分布有 3,3,5个等价类,需要 3 × 5 × 5 = 75测试用例 因此笛卡尔积这种方式测试完备,但用例数量多,测试代价高 但是并非所有组合情况都可能

    覆盖每个取值:最少1次即可 每个维度的每个取值至少被1个测试用例覆 盖一次即可 测试用例少,代价低,但测试覆盖度未必高

    通常情况下在这两个方案之间选取一个折衷的方案

    一些问题

    1.要为某个方法A m(int b,String c)构造黑盒测试用例,那么设计实现Junit测试用例不需要依据的内容为

    m()的内部实现代码

    m()的pre-condition(该方法输入参数满足的条件)

    m()的post-condition(该方法执行后返回值满足的条件)

    类A的等价性判断方法A.equals()

    答案:A 黑盒测试无需测试内部实现


    关于JUnit的说法不正确的是: 如果一个Java测试类定义了多个@Test方法,那么它们按照在代码中出现的先后次序加以执行某方法前标注着@Test,意味着它是一个测试方法。@Test是Java中的annotation如果未通过测试,方法中的assertXXX()将抛出AssertionError一个Java测试类可以定义全局属性并在@Before方法中对属性进行数据准备,在@Test方法中使用数据

    答案:A JUnit中的测试并不是先后次序,而是随机的顺序,如何想要固定的顺序,添加一个: @FixMethodOrder 并且指定一个合适的MethodSorters。


    以下说法不正确的是: 如果某个bug已被正确修复并已经通过测试,那么为了降低后续测试的代价,应将该bug对应的测试用例从测试库中删除如果发现了一个新的bug,需要返回到版本仓库中对之前的各个版本进行测试,以确认该bug最早是在哪个历史版本中引入的代码覆盖度code coverage是指所有测试用例执行后有多大百分比覆盖了被测程序的所有的代码行可以从被测代码中寻找依据来设计处于“边界”上的测试用例

    答案:A 应该执行回归测试


    关于测试的说法,不正确的是___ A 再好的测试也无法证明代码里100%不存在bugB 测试用例的数量越多,则越容易发现潜在的bugC 设计测试用例时,需要给出输入数据和期望的输出结果D 测试用例具有优先级,应将最容易发现错误的用例先执行E TDD的思想是:先设计方法的spec,然后根据spec设计测试用例,然后再写代码并确保代码通过测试

    答案:B 显然不正确


    在使用等价类划分方法进行测试用例设计时,错误的是___ A 如果输入参数a在spec中仅被规定a>10且未说明a<=10应该如何,那么无需测试a<=10的情况B 如果输入参数a在spec中仅被规定a>10,那么仍然需要为a<=10的情况设计测试用例C 采用笛卡尔积“全覆盖”策略进行测试用例设计,会导致用例数量多,测试代价高D 采用“覆盖每个取值”的策略进行用例设计,测试代价低,但测试覆盖度可能较差

    正确答案:B 对于spec没有规定的情况,无需进行测试


    在编写任何代码之前,编写测试用例应该选择什么技术? A Black box 黑盒测试B RegressionC Static typingD Partitioning 等价类划分E Boundaries 边界值F White boxG Code coverage 代码覆盖度

    正确答案:ADE


    什么时候应该对 JUnit 测试全部重新运行 ? A Before doing git add/commit/pushB After rewriting a function to make it fasterC When using a code coverage tool such as EclEmmaD After you think you fixed a bug

    正确答案:ABCD

    Processed: 0.010, SQL: 9