参考答案

我们无法保证答案的正确性,如果你对参考答案有任何疑问,请联系助教!

黑盒测试

题目 I:百分制成绩转换

等价类划分

期望返回只是方便阅读,不要求在实际作答中写出

等价类输入范围期望返回
无效低分grade < 0E
F 等级0 <= grade < 60F
D 等级60 <= grade < 65D
C 等级65 <= grade < 75C
B 等级75 <= grade < 85B
A 等级85 <= grade <= 100A
无效高分grade > 100E
非普通浮点值NaNE

边界值分析

关键边界为 060657585100。每个边界都应测试边界点本身,以及边界点左右两侧的值。样例中用 0.1 的偏移表示“略小于/略大于”。

测试样例

期望返回只是方便阅读,不要求在实际作答中写出 覆盖点只是为了方便阅读,不要求在实际作答中写出。

输入 grade期望返回覆盖点
-0.1E无效低分
0F下边界有效
0.1FF 等级内部
59.9F60 左侧
60DD 下边界
60.1D60 右侧
64.9D65 左侧
65CC 下边界
65.1C65 右侧
74.9C75 左侧
75BB 下边界
75.1B75 右侧
84.9B85 左侧
85AA 下边界
85.1A85 右侧
99.9A100 左侧
100A上边界有效
100.1E无效高分
NaNE非普通浮点值

题目 II:容器去重并排序

这道题目因为没有提具体的要求,比较开放,意思对即可。 答案仅供参考,并没有涵盖所有可能的作答角度。

等价类划分

container 的等价类:

输入条件有效等价类无效等价类
容器类型顺序容器非顺序容器
容器规模空容器,单元素容器,多元素容器-
是否有元素重复无,有部分元素重复,所有元素都重复-
容器初始是否已经有序是、否-
元素类型支持 < 运算符的元素,不支持的元素-
元素值因元素类型而异

cmp 的等价类:

输入条件有效等价类无效等价类
是否缺省是、否-
是否满足弱序严格弱序,弱序不满足弱序
格式是否正确

格式正确指比较函数类型应为 bool(const Elem&, const Elem&) 或能与其进行隐式转换的类型。

边界值分析

container 的等价类:

输入条件边界值
容器类型
容器规模容器中有0,1,2个元素
是否有元素重复容器中有0,1,2种重复元素,容器中除了0,1个元素外都是重复元素
容器初始是否已经有序除0,1个位置外都有序,除0,1个位置外都逆序
元素类型
元素值因元素类型而异

cmp的等价类都没有边界值。

测试样例

期望返回和期望container,以及说明只是方便阅读,不要求在实际作答中写出 如果你试图去把各种等价类做完全的组合,那你应该深刻地理解到了为什么我们不会去那么做。一般只对那些明显有关的等价类做部分或者完全的组合。

输入 container输入 cmp期望返回期望 container说明
set<int>{1, 2, 3, 4}缺省false-关联容器
deque<int>{2, 1, 2}缺省true{1, 2}另一种有效顺序容器
vector<int>{}缺省true{}空容器
vector<int>{1}缺省true{1}单元素容器
vector<int>{1, 2}缺省true{1, 2}单元素容器边界
vector<int>{6, 4, 1, 3, 5, 2}缺省true{1, 2, 3, 4, 5, 6}多元素容器
vector<int>{1, 1, 2, 3, 4, 5}缺省true{1, 2, 3, 4, 5}单元素重复
vector<int>{1, 1, 2, 2, 3, 4, 5}缺省true{1, 2, 3, 4, 5}单元素重复边界
vector<int>{1, 1, 1, 1, 1, 1}缺省true{1}全部重复
vector<int>{1, 1, 1, 3, 1, 1}缺省true{1, 3}全部重复边界
vector<int>{4, 6, 9, 10, 23, 43}缺省true{4, 6, 9, 10, 23, 43}已经有序
vector<int>{4, 6, 10, 9, 23, 43}缺省true{4, 6, 9, 10, 23, 43}去除一个元素后有序
vector<int>{43, 23, 10, 9, 6, 4}缺省true{4, 6, 9, 10, 23, 43}完全逆序
vector<int>{43, 23, 9, 10, 6, 4}缺省true{4, 6, 9, 10, 23, 43}去除一个元素后完全逆序
vector<vector<int>>{{1}, {2}, {3}}缺省false-不支持 < 的元素
vector<vector<int>>{{1}, {2}, {3}}[](const vector<int>& lhs, const vector<int>& rhs){ return lhs[0] < rhs[0]; }true{{1}, {2}, {3}}不支持 < 的元素但是传入了正确的比较器
vector<int>{43, 23, 9, 10, 6, 4}[](const int& lhs, const int& rhs){ return lhs <= rhs; }true{4, 6, 9, 10, 23, 43}传入比较器满足弱序但非严格弱序
vector<int>{43, 23, 9, 10, 6, 4}[](const int& lhs, const int& rhs){ return true; }未定义未定义传入比较器不满足弱序
vector<int>{43, 23, 9, 10, 6, 4}[](const string& lhs, const string& rhs){ return lhs[0] < rhs[0]; }false-传入非法比较器

白盒测试

说明:覆盖代码行中的 T/F 表示对应判定行取真/取假;复合条件表中列出的是各原子条件的逻辑取值。

题目 I

待测代码

void exercise_wb_1(int param1, int param2, int param3)
{
    int res = -1;
    if (param1 > 0 && param2 > 0 && param3 > 0)
    {
        if (param1 > param2)
        {
            if (param2 > param3)
            {
                res = 3;
            }
            else if (param1 > param3)
            {
                res = 2;
            }
            else
            {
                res = 1;
            }
       }
       else
       {
            if (param2 > param3)
            {
                if (param1 > param3)
                {
                    res = 2;
                }
                else
                {
                    res = 1;
                }
            }
            else
            {
                res = 0;
            }
        }
    }
    cout << res << endl;
}

语句覆盖

期望输出和覆盖代码行只是方便阅读,不要求在实际作答中写出

要覆盖所有赋值语句,需要进入每个内层路径。以下 6 个样例可以覆盖所有行。

编号(param1, param2, param3)期望输出主要覆盖目标代码行
WB1-L1(3, 2, 1)3L10
WB1-L2(3, 1, 2)2L14
WB1-L3(2, 1, 3)1L18
WB1-L4(2, 3, 1)2L27
WB1-L5(1, 3, 2)1L31
WB1-L6(1, 2, 3)0L36

分支覆盖

期望输出和覆盖分支只是方便阅读,不要求在实际作答中写出

在语句覆盖样例基础上增加一个外层条件为假的样例即可覆盖外层 if 的假分支。

编号(param1, param2, param3)期望输出覆盖分支
WB1-B1(3, 2, 1)3L04(T), L06(T), L08(T)
WB1-B2(3, 1, 2)2L04(T), L06(T), L08(F), L12(T)
WB1-B3(2, 1, 3)1L04(T), L06(T), L08(F), L12(F)
WB1-B4(2, 3, 1)2L04(T), L06(F), L23(T), L25(T)
WB1-B5(1, 3, 2)1L04(T), L06(F), L23(T), L25(F)
WB1-B6(1, 2, 3)0L04(T), L06(F), L23(F)
WB1-B7(0, 1, 1)-1L04(F)

条件组合覆盖

只有L04是复杂条件,其余都是简单条件。简单条件的真值组合就是他自己取真值或者假值。

对于复杂条件,先列出组成它的所有简单条件:

P1 = param1 > 0
P2 = param2 > 0
P3 = param3 > 0

需要覆盖 8 种组合。除此之外,还要覆盖到剩余简单条件的真假值,能进入内层循环的只有一组真值组合,在满足这个真值组合的前提下直接复用之前的样例就行。

编号(param1, param2, param3)L04(A, B, C)其他覆盖代码行期望输出
WB1-C1(3, 2, 1)(T, T, T)L06(T), L08(T)3
WB1-C2(3, 1, 2)(T, T, T)L06(T), L08(F), L12(T)2
WB1-C3(2, 1, 3)(T, T, T)L06(T), L08(F), L12(F)1
WB1-C4(2, 3, 1)(T, T, T)L06(F), L23(T), L25(T)2
WB1-C5(1, 3, 2)(T, T, T)L06(F), L23(T), L25(F)1
WB1-C6(1, 2, 3)(T, T, T)L06(F), L23(F)0
WB1-C7(0, 1, 1)(F, T, T)L04(F)-1
WB1-C8(1, 0, 1)(T, F, T)L04(F)-1
WB1-C9(1, 1, 0)(T, T, F)L04(F)-1
WB1-C10(0, 0, 1)(F, F, T)L04(F)-1
WB1-C11(0, 1, 0)(F, T, F)L04(F)-1
WB1-C12(1, 0, 0)(T, F, F)L04(F)-1
WB1-C13(0, 0, 0)(F, F, F)L04(F)-1

题目 II

待测代码

void exercise_wb_2(int param1, int param2)
{
    int param3 = param1 + param2;
    if (param3 > 0)
    {
        ++param1;
    }
    if (param3 < 0)
    {
        ++param2;
    }
    if (param1 > param2 || param1 > param3)
    {
        if (param1 <= param2 || param1 <= param3)
        {
            param3 += param1;
        }
    }
    if (param3 != 0)
    {
        param3 += param2;
    }
    cout << param3 << endl;
}

语句覆盖

编号(param1, param2)期望输出主要覆盖目标代码行
WB2-L1(1, 1)5L06, L16, L21
WB2-L2(-1, -1)-3L10

分支覆盖

编号(param1, param2)期望输出覆盖分支
WB2-B1(1, 1)5L04(T), L08(F), L12(T), L14(T), L19(T)
WB2-B2(0, -2)-3L04(F), L08(T), L12(T), L14(F), L19(T)
WB2-B3(0, 0)0L04(F), L08(F), L12(F), L19(F)

条件组合覆盖

第三个判断的外层复合条件记为(这里的 param1param2param3 都指执行完前两个 if 后的当前值):

P = param1 > param2
Q = param1 > param3

内层复合条件等价于:

R = param1 <= param2 = !P
S = param1 <= param3 = !Q

因此当 (R, S) = (T, T) 时,外层 (P || Q) 必为假,内层判断不可达。但条件覆盖与条件组合覆盖无需考虑可达性,只要将对应真假值取到即可。下面样例覆盖外层 P/Q 的 4 种组合,并覆盖内层所有的条件组合。

编号(param1, param2)外层 (P, Q)内层 (R, S)期望输出
WB2-C1(0, -2)L12: (T, T)L14: (F, F)-3
WB2-C2(1, 1)L12: (T, F)L14: (F, T)5
WB2-C3(0, -1)L12: (F, T)L14: (T, F)-1
WB2-C4(0, 0)L12: (F, F)L14: (T, T) 不可达,但依然覆盖0

本题虽然内层条件 (T, T) 取值不可达,但依然达到了100%的条件组合覆盖

题目 III

待测代码

用人脑理解复杂的代码逻辑是很困难的,特别是没有注释的时候!

void exercise_wb_3(vector<int> params)
{
    bool flag = true;
    int res = 0;
    int pos = 0;
    int sz = params.size();
    while (pos != sz)
    {
        if (flag)
        {
            res += params[pos];
        }
        else
        {
            res -= params[pos];
        }
        if (params[pos] > 0)
        {
            flag = !flag;
        }
        ++pos;
    }
    if (res > 0)
    {
        res = res * res;
    }
    if (res < 0)
    {
        res = -(res * res);
    }
    cout << res << endl;
}

语句覆盖

编号params期望输出主要覆盖目标代码行
WB3-L1{2, 1, 0}1L11, L15, L19, L21, L25
WB3-L2{1, 2}-1L29

分支覆盖

编号params期望输出覆盖分支
WB3-B1{2, 1, 0}1L07(T&F), L09(T&F), L17(T&F), L23(T), L27(F)
WB3-B2{1, 2}-1L23(F), L27(T)

条件组合覆盖

本题没有复合条件,条件组合覆盖和条件覆盖是等价的,也和分支覆盖是等价的。

编号params期望输出覆盖条件
WB3-C1{2, 1, 0}1L07(T&F), L09(T&F), L17(T&F), L23(T), L27(F)
WB3-C2{1, 2}-1L23(F), L27(T)
Last Updated:
Contributors: 1-rambo