软件评测师

本篇文章是个人在备考过程中所记录的评测师相关知识点,因此并不能完全覆盖所有知识点

👏👏👏 欢迎大家在评论中补充修正

👏👏👏 如果大家有问题也

0. 计算机组成结构

0.1. 计算机硬件组成

  • 计算机的硬件系统基本由五大部分组成:运算器,控制器,存储器,输入设备,输出设备
    • CPU由运算器,控制器,寄存器和内部总线组成
      • CUP中最主要的部分是运算器和控制器
      • CPU的功能:实现程序控制,操作控制,时序控制,数据处理功能
      • 运算器
        • 运算器由算数逻辑单元ALC,累加寄存器AC,状态条件寄存器PSW,数据缓冲器DR组成
          • ALC:实现对数据的算术和逻辑运算
          • AC:运算结果或源操作数的存放区
          • PSW:保存指令运行结果的条件码内容,如溢出标志等
          • DR:暂时存放内存的指令或数据
        • 运算器功能:执行所有算术运算,执行所有逻辑运算并进行逻辑测试(如与,或,非)
      • 控制器
        • 控制器由指令寄存器IR,程序计数器PC,地址寄存器AR,指令译码器ID等组成
          • IR:暂存CPU执行指令
          • PC:存放下一条执行的指令的地址
          • AR:保存当前CPU所访问的内存地址
          • ID:分析指令操作码
        • 控制器功能:控制整个CPU的工作,最为重要,包括程序控制,时序控制等
    • 存储器分为内部存储器和外部存储器
      • 内部存储器:即内存,容量小,速度快,临时存放数据
      • 外部存储器:即硬盘,容量大,速度慢,长期保存数据
    • 输入设备和输出设备统称为外部设备,即外设
    • 主机:CPU+主存储器

0.2. 计算机体系结构分类

Flynn分类法

体系结构类型结构关键特征代表
单指令流单数据流SISD控制部分:一个单处理器系统
处理器:一个
主存模块:一个
单指令流多数据流SIMD控制部分:一个处理器以异步的形式执行同一条指令并行处理机器
处理器:多个陈列处理机
主存模块:多个超级向量处理机
多指令流单数据流MISD控制部分:多个被证实不可能实现,至少事不实际的目前没有,有文献称流水线计算机为此类
处理器:一个
主存模块:多个
多指令流多数据流MIMD控制部分:多个能够实现作业、任务、指令等各级全面并行多处理机系统
处理器:多个多计算机
主存模块:多个

0.3. 指令寻址方式

  • 指令寻址方式
    • 顺序寻址方式:当执行一段程序时,是一条指令接着一条指令地顺序执行
    • 跳跃寻址方式:指下一条指令的地址码不是由程序计数器给出,而是由本条指令直接给出。程序跳跃后,按新的指令地址开始顺序执行。因此,程序计数器的内容也必须相应改变,以便及时跟踪新的指令地址
  • 指令操作数的寻址方式
    • 立即寻址方式:指令的地址码字段指出操作数本身
    • 直接寻址方式:在指令的地址字段中直接指出操作数在主存中的地址
    • 隐含寻址方式:在指令的地址不是明显给出的,而是隐含在指令中
    • 寄存器寻址方式:指令地址码字段所指向的存储单元中存的是操作数
    • 间接寻址方式:指令地址码字段所指向的存储单元中存的是操作数的地址

0.4. CISC和RISC指令系统

指令系统类型指令寻址方式实现方法其他
CISC(复杂)数量多支持多种微程序控制技术(微码)研制周期长
使用频率差别大
可变长格式
RISC(精简)数量少支持方式太少增加了通用寄存器,硬布线逻辑控制为主优化编译
使用频率接近适合采用流水线有效支持高级语言
大部分为单周期指令
操作寄存器
只有Load/Store操作内存

0.5. 指令流水线

将指令分成不同段,每段由不同的部分去处理,因此可以产生叠加的效果,所有的部件去处理指令的不同段,如下图所示

  • 流水线周期:指令分成不同执行段,其中执行时间最长的段为流水线周期
  • 流水线执行时间:1条指令总执行时间+(总指令条数-1)*流水线周期
  • 流水线吞吐量:总指令条数/流水线执行时间
  • 流水线加速比:不使用流水线总执行时间/使用流水线总执行时间

0.6. 存储系统

计算机存储系统的层次结构如图所示,从上到下容量越来越大,速度越来越慢,价格越来越便宜

计算机采用分级存储体系的目的主要是为了解决存储容量、成本和速度之间的矛盾问题

  • 两级存储:主存-Cache,主存-辅存(虚拟存储体系)
  • 局部性原理
    • 时间局部性原理:如果一个数据正在被访问,那么在近期他很可能会再次被访问
    • 空间局部性原理:在近期的将来会用到的数据的地址和现在正在访问的数据地址很可能是相近的,即相邻的空间地址会被连续访问

0.6.1 高速缓存Cache

高速缓存Cache用来存储当前最活跃的程序和数据,直接与CPU交互,位于CPU和主存之间,容量小,速度为内存的5-10倍,其主要内容是主存的副本拷贝,对于程序员来说是透明的

Cache由控制部分和存储器组成,存储器存储数据,控制部分判断CPU要访问的数据是否在Cache中,在则命中,不在则依据一定的算法从主存中替换

在CPU工作时,送出的是主存单元的地址,而应从Cache存储器中读/写信息。这就需要将主存地址转换为Cache存储器地址,这种地址的转换称为地址映射,由硬件自动完成映射,有三种映射方式

  • 直接映射:将Cache存储器等分成块,主存也等分成块并编号,主存中的块与Cache中的块对应关系是固定的,也即两者块号相同才能命中。地址变换简单但不灵活,容易造成资源浪费
  • 全相联映射:同样等分成块并编号。主存中任意一块都与Cache中任意一块对应。因此可以随意调入Cache任意位置,但地址变换复杂,速度较慢。因为主存可以随意调入Cache任意块,只有当Cache满了才会发生块冲突,是最不容易发生冲突的映射方式
  • 组组相连映射:前面两种方式的结合,将Cache存储器先分块再分组,主存也同样先分块再分组,组间采用直接映射,即主存中组号与Cache中组号相同的组才能命中,但组内全相联映射,即组号相同的两个组内的所有块可以任意调换

0.7. 总线结构

从广义上讲,任何链接两个以上的电子元器件的导线都可以称之为总线,通常分为以下三类

  • 内部总线:内部芯片级别的总线,芯片与处理器之间通信的总线
  • 系统总线:是板级总线,用于计算机内部各个部分之间的链接,具体分为
    • 数据总线:并行数据传输位数
      • 数据总线宽度等于系统位数
    • 地址总线:系统可管理的内存空间大小
      • 存储容量 = 等于 2^n Byte(其中n为地址总线宽度)
    • 控制总线:传送控制命令
  • 外部总线:设备一级的总线,微机和外部设备的总线
某DRAM芯片的存储容量为512K*16位,则芯片的地址和数据线宽度分别为?

解:
1. 芯片为16位,因此数据线宽度为16
2. 芯片的存储容量位512K,512K = (2^9 * 2^10)Byte = 2^19Byte,因此地址总线宽度为19

0.8. 系统可靠性分析

  • 平均无故障时间:MTTF=1/失效率
  • 平均故障修复时间:MTTR=1/修复率
  • 平均故障间隔时间:MTBF=MTTF+MTTR
  • 系统可用性=MTTF/MTBF*100%

假设每个设备的可靠性为R1 R2 R3,则不同系统的可靠性R计算公式如下

  • 串联系统:R1 * R2 * R3
  • 并联系统:1 - (1-R1) * (1-R2) * (1-R3)

0.9. 进制转换

0.9.1 R进制向十进制转化

将R进制数的每一位数值用 R^k 形式表示,其中k与该位和小数点之间的距离有关。

当该位位于小数点左边,k值是该位和小数点之间数码的个数。

当该位位于小数点右边,k值是负值,其绝对值是该位和小数点之间数码的个数加1。

⚠️ 即小数点左侧k从0开始,小数点右侧k从-1开始

### 二进制 ###
10100.01 = 1*2^4 + 1*2^2 + 1*2^-2

### 七进制 ###
604.01 = 6*7^2 + 4*7^0 + 1*7^-2

0.9.2 十进制向R进制转化

我们使用短除法进行转换

⚠️ 结果由下往上写

0.9.3 二进制转八进制或十六进制

八进制:将二进制数由后向前每三位划分一组,分别计算每组的十进制值,最后组合得到的值便为转换后的八进制的值

十六进制:将二进制数由后向前每四位划分一组,分别计算每组的十进制值,最后组合得到的值便为转换后的十六进制的值

⚠️ 十六进制基数:1,2,3,4,5,6,7,8,9,A,B,C,D,E,F

### 八进制 ###
010001110 -> 010 001 110 -> 2 1 6 = 216

### 十六进制 ###
10001110 -> 1000 1110 -> 8 E = 8E

0.10. 数的表示

  • 机器数
    • 各种数值在计算机中表示的形式,其特点是使用二进制技术制,数的符号用0和1表示,小数点则隐含不占位置
    • 机器数有无符号数和带符号数之分
      • 无符号数表示正数,没有符号位
      • 带符号数最高位为符号位,正数符号位为0,负数符号位为1
  • 定点表示法分为纯小数和纯整数两种,其中小数点不占存储位
    • 纯小数(0.xxxx):约定小数点的位置在机器数的最高数值位之前
    • 纯整数:约定小数点的位置在机器数的最低数值位之后
  • 真值:机器数对应的实际数值
  • 浮点数
    • 表示方法为N=F*2^E,其中E称为阶码,F称为尾数
    • 阶码为带符号的纯整数
    • 尾数为带符号的纯小数
    • 数值范围由阶码确定,数值精度由尾数确定

0.11. 原码,反码,补码,移码

原码

  • 符号位(SF):为0表示正,为1表示负
  • 字长为n时范围:$-(2^{n-1}-1)$ ~ $2^{n-1}-1$

反码

  • 符号位:为0表示正,为1表示负
  • 正数的反码等于原码,负数的反码等于原码除符号位外按位取反
  • 字长为n时范围:$-(2^{n-1}-1)$ ~ $2^{n-1}-1$

补码

  • 符号位:为0表示正,为1表示负
  • 正数的补码等于原码,负数的补码等于反码末尾加1(注意需要进位,且溢出将不被需要)
  • 字长为n时范围:$-2^{n-1}$ ~ $2^{n-1}-1$

移码

  • 补码的符号位取反
  • 字长为n时范围:$-2^{n-1}$ ~ $2^{n-1}-1$
数值1数值-1
原码0000000110000001
反码0000000111111110
补码0000000111111111
移码1000000101111111

⚠️ 计算机中大多数情况下会用补码进行运算。 原码,反码和移码在计算过程中结果可能不符合预期,例如1+(-1)

0.12. 校验码

0.1.1 奇偶校验码

在编码中增加1位校验码来使编码中1的个数位奇数(奇校验)或者偶数(偶校验)从而使码距变为2。

  • 奇校验:编码中含有奇数个1发送给接收方,接收方收到后会计算收到的编码中有多少个1,如果是奇数个则无误
  • 偶校验:同理,只是编码中有偶数个1
假设现在有一段编码
10010
我们要使用奇校验,我们需要在编码最后增加1位,并且保证加1位之后的编码中有奇数个1
此时我们得到的编码是:100101

而当我使用偶校验,我们同样需要在编码最后增加1位,并且保证加1位之后的编码中有偶数个1
此时我们得到的编码是:100100

从上述可以看出,奇偶校验只能检1位错,且无法纠错

⚠️ 码距:就单个编码A:00而言,其码距为1,因为其只需要改变一位就变成了另一个编码。在两个编码中,从A码到B码的转换所需要改变的位数称为码距,如A:00要转换为B:11,码距为2。一般来说码距越大越利于纠错和检错。

0.1.2 循环冗余校验码CRC

CRC只能检错,不能纠错。

其原理是找出一个能整除多项式的编码,因此首先要将原报文除以多项式,将所得的余数作为校验位加在原始报文之后,将整体作为发送数据发送给接收方。

⚠️ 模2运算其实是将两数进行异或

原始报文为11001010101,其生成多项式为x^4+x^3+x+1。对其进行CRC编码后的结果为?

解:
	首先我们需要对多项式进行置换,将多项式从0次幂开始到最高次幂,若当前次幂存在则为1,不存在则为0
	x^4+x^3+x+1 则置换为 11011

	第二步我们要在原始报文后面加上多项式位数个0暂时充当校验位作为被除数
	此时的被除数为110010101010000
	
	将被除数和置换后的多项式进行模2除法
	得出一个四位余数:0011,将做为校验位
	我们发送出去的数据为原报文+校验位:110010101010011
	接收方将收到的数据110010101010011与多项式置换后的11011进行摸2运算,若余数为0说明校验正确,数据传输正常

-------------------------------------------------------------------------------------------------
110010101010000与11011进行模2运算

110010101010000
11011
---------------
   10010
   11011
---------------
    10011
    11011
---------------
     10000
     11011
---------------
      10111
      11011
---------------
       11000
       11011
---------------
          11000
          11011
---------------
		   0011

0.1.1 海明校验码

本质上也是利用奇偶性来检错和纠错的检验方法,构成方法是在数据位之间的确定的位置上(2^k位)插入k个校验位,通过扩大码距实现检错和纠错。

设数据位是n位,校验码是k位,则n和k必须满足 2^k-1≥n+k

求信息1011的海明码
解:
	首先我们要明确校验位和数据位之间的关系,校验码存在于第2^k位,且保证2^k-1>=n+k,如下表
	| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 位数
	|I4 |I3 |I2 |   |I1 |   |   | 信息位
	|   |   |   |r2 |   |r1 |r0 | 校验位

	换成当前题目数据为
	| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 位数
	| 1 | 0 | 1 |   | 1 |   |   | 信息位
	|   |   |   |r2 |   |r1 |r0 | 校验位

	接下来进行校验位的计算
	首先我们需要确定每一位校验码到底校验那些信息位,将信息位(位数)拆分成二进制表示
		- 7=4+2+1, 由第4位的校验位(r2),第2位的校验位(r1)和第1位的校验位(r0)共同校验
		- 6=4+2,由第4位的校验位(r2)和第2位的校验位(r1)共同校验
		- 5=4+1, 由第4位的校验位(r2)和第1位的校验位(r0)共同校验
		- 3=2+1,由第2位的校验位(r1)和第1位的校验位(r0)共同校验
	此时我们可以知道第4位的校验位校验第7,6,5位的数据,因此第4位的校验位r2等于7,6,5这三个位置数据的值进行异或运算的结果
		- r2 = 1,0,1进行异或 = 0
	同理我们可以得出
		- r1 = 0
		- r0 = 1
	如下表所示
	| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 位数
	| 1 | 0 | 1 |   | 1 |   |   | 信息位
	|   |   |   | 0 |   | 0 | 1 | 校验位

	最终我们得到的海明吗为:1010101

海明码的检错和纠错原理如下:

  • 检错

    接收方收到海明码之后,会将每一位校验位的值与其校验的位数的值分别异或,即做如下三组运算 r2 ⊕ I4 ⊕ I3 ⊕ I2 ,r1 ⊕ I4 ⊕ I3 ⊕ I1, r0 ⊕ I4 ⊕ I2 ⊕ I1,如果是偶校验,那么运算得到的结果应全为0表明传输正确,如果是奇校验得到的结果应全为1表明传输正确

    • 以偶校验举例。我们在得到海明码时,校验位的值是通过其校验的位数的值异或得来的,即做了如下三组运算 I4 ⊕ I3 ⊕ I2,I4 ⊕ I3 ⊕ I1,I4 ⊕ I2 ⊕ I1(我们接下来称这三组运算的结果为A1,A2,A3)。因此当传输过程无误时,校验位的值必定等于其对应运算方法的结果,即 r2=A1 r1=A2 r0=A3。所以两值再次异或之后结果为0证明传输前后数据一致
  • 纠错

    假设接收到的数据中第四位出错,此时三组运算 r2 ⊕ I4 ⊕ I3 ⊕ I2,r1 ⊕ I4 ⊕ I3 ⊕ I1,r0 ⊕ I4 ⊕ I2 ⊕ I1 的结果为 1, 0, 0

    证明r2中验证的某一位有问题,此时我们按照r2r1r0(高位到低位)的顺序将结果排列成2进制的值 100 转换为十进制为4,即第4位出错了

    纠错方法便是将出错的值取非

1. 操作系统

1.1. 操作系统基础知识

  • 操作系统的作用:通过资源管理提高计算机系统的效率;改善人机界面向用户提供友好的工作环境
  • 操作系统的特征:并发性、共享性、虚拟性、不确定性
  • 操作系统的功能:进程管理、存储管理、文件管理、设备管理、作业管理
  • 操作系统的分类:批处理操作系统、分时操作系统、实时操作系统、网络操作系统、分布式操作系统、微机操作系统、嵌入式操作系统
  • 计算机启动的基本流程:BIOS→主引导记录→操作系统

1.2. 进程的组成和状态

  • 进程的组成:进程控制块PCB(唯一标志)、程序(描述进程要什么)、数据(存放进程执行时所需数据)

  • 进程的基础状态如下三态图,这是系统自动控制时只有三种状态,而右侧途中的五态多了静止就绪和静止阻塞,需要 人为操作才会进入对应状态,活跃就绪即就绪,活跃阻塞即等待

由图可知,当人为干预后,进程将被挂起,进入静止状态,此时需要人为激活才能恢复到活跃状态,之后的本质依旧是三态图

1.3. 前趋图

用来表示那些任务可以并行执行,那些任务直接有顺序关系,如下图。

由图可知,ABC可以并行执行,但必须ABC都执行完后,才可以执行D。

这就确定了两点

  • 任务之间的并行
  • 任务间的先后顺序

1.4. 进程资源图

用来表示进程和资源之间的分配和请求关系,如下图。

P代表进程,R代表资源,R方框中有几个圆球就表示有几个这种资源,在图中R1指向P1,表示R1已经有一个资源分配给了P1,P1指向R2表示P1还需要请求一个R2资源才可以执行

  • 阻塞节点:某进程所请求的资源已经全部分配完毕,无法获取所需资源,该进程已经被阻塞了无法继续。如上图中P2
  • 非阻塞节点:某进程所请求的资源还有剩余,可以分配给该进程继续执行。如上图P1、P3
  • 当所有进程都是阻塞节点时,陷入死锁状态
    • 死锁产生的四个必要条件
      • 资源互斥
      • 每个进程占有资源并等待其他资源
      • 系统不能剥夺进程资源
      • 进程资源图是一个环路
    • 解决死锁的措施
      • 死锁预防:采用某种策略限制并发进程对于资源的请求,破坏死锁产生的四个条件之一。
      • 死锁避免:一般采用银行家算法来避免。银行家算法就是提前计算出一条不会死锁的资源分配方法才分配资源,否则不分配资源。
      • 死锁检测:允许死锁产生,但系统定时运行一个检测死锁的程序,若监测到系统中发生死锁,则设法加以解除
      • 死锁解除:死锁发生后的解除办法,如强制剥夺资源,撤销进程等
    • 死锁计算:系统内有n个进程,每个进程都需要R个资源
      • 其发生死锁的最大资源数为n*(R-1)
      • 其不发生死锁的最小资源数为n*(R-1)+1

1.5. 同步与互斥

  • 同步:多个任务可以并发执行,只不过有速度上的差异,在一定情况下停下等待,不存在资源是否单独共享的问题;如自行车和汽车
    • 同步信号量:对共享资源的访问控制,初值一般是共享资源的数量
  • 互斥:某资源(即临界资源)在同一时间内只能由一个任务单独使用,使用时需要加锁(互斥信号量),使用完后解锁才能被其他任务使用;如打印机
    • 临界资源:进程间需要以互斥的方式访问的资源
    • 临界区:进程中对临界资源实施操作的那段程序。本质是一段程序代码
    • 互斥信号量:对临界资源采用互斥访问,使用互斥信号量后其他进程无法访问,初值为1

1.6. 信号量操作

P操作:申请资源,S=S-1,若S≥0则执行P操作的进程继续执行;若S<0则置该进程为阻塞状态(因为无资源可用), 并将其插入阻塞队列

V操作:释放资源,S=S+1,若S>0则执行V操作的进程继续执行;若S≤0则从阻塞状态唤醒一个进程,并将其插入就绪队列,然后执行V操作的进程继续

⚠️ 进程和信号量要分清 前驱图中,两个进程之间的箭头线条才是释放的信号量,且信号量的计数S123与进程的计数P123毫无关系

1.7. 存储方式

1.7.1 页式存储

将进程空间分为一个个页,假设每个页大小为nK,同样的将系统的物理空间也分为一个个nK大小的物理块(页帧号),这样每次将需要运行的逻辑页装入物理块中,运行完再装入其他需要运行的页,就可以分批次运行完进程,而无需将整块逻辑空间全部装入物理内存中

  • 优点
    • 利用率高
    • 碎片小(只在最后一个页中有)
    • 分配及管理简单
  • 缺点
    • 增加了系统开销
    • 可能产生抖动现象
某计算机系统页面大小为4K,若进程的页面变换表如下所示,逻辑地址为十六进制1D16H。该地址经过变换后,其物理地址应为?
		页号 | 物理块号
			0    1
			1    3
			2    4
			3    6
解: 
	页地址是页号和页内地址组成的,页号在高位,页内地址在低位
	无论是物理地址还是逻辑地址,页内地址是不变的
	页内地址表示页有多大,题目给出页面大小为4K
		4K = 2^12B
	所以页内地址占12位,12位二进制刚好是3位十六进制数,所以页内地址对应的逻辑地址为D16
	那么页号便为1,页号1对应的物理块号为3
	此时就可以得到物理地址为3D16H

1.7.2 段式存储

将进程空间分位一个个段,每段有段号和段内地址,与页式存储不同的是,每段物理大小不同,分段是根据逻辑整体分段的(这会造成分段大小不一样)。

地址表示:段号,段内地址

  • 段内偏移不能超过该段号对应的段长,否则越界错误
  • 此地址对应的真正内存地址应该是:段号对应的基地址+段内偏移
  • 优点
    • 程序逻辑完整
    • 修改互不影响
  • 缺点
    • 内存利用率低
    • 内存碎片浪费大

1.7.3 段页式存储

对进程空间先分段后分页

  • 优点
    • 空间浪费小
    • 存储共享容易
    • 能动态连接
  • 缺点
    • 由于管理软件的增加,复杂性和开销也增加,执行速度下降

1.8. 文件结构

系统中通常 有13个索引节点,从0开始编号

0~9为直接索引,即每个索引节点存放的是内容

10号索引节点为一级节点,存放的并非直接数据,而是链接到直接物理盘块的地址

二级索引节点类似,存放一级地址,一级地址再存放物理盘块地址

假设每个物理盘大小为4KB
0~9节点可以存4*10=40KB数据
------------
假设每个地址占4B
一个一级节点4KB可以存放1024个地址,可以对应1024个物理盘,可存1024*4KB=4096KB数据
------------
那么一个二级节点类似,可存1024*1024*4KB数据

1.9. 空闲存储空间管理

  • 空闲区表法:将所有空闲空间整合成一张表,即空闲文件目录
  • 空闲链表法:将所有空间空间链接成一个链表,根据需要分配
  • 成组链接法:即分组,每组内又链接成链表,是上述两种方法的综合
  • 位试图法:对每个物理空间用一位标识,为1则使用,为0则空闲,形成一张位试图

1.10. 设备管理

设备分类如下

  • 按数据组织分类:块设备,字符设备
  • 资源分配角度分类:独占设备,共享设备,虚拟设备
  • 数据传输速率分类:低速设备,中速设备,高速设备

I/O软件(输入输出软件)层次结构

1.11 输入输出技术

  • 程序控制(查询)方式:CPU主动查询外设是否完成数据传输,效率极低。
  • 程序中断方式:外设完成数据传输后,向CPU发送中断,等待CPU处理数据,效率相对较高。适用于键盘等实时性较高的场景
    • 中断响应时间指的是从发出中断请求到进入中断处理程序;中断处理时间指的是从中断处理开始到中断处理结束
    • 中断向量提供中断服务程序的入口地址
    • 多级中断嵌套,使用堆栈保护断点和现场
  • DMA方式(直接主存存取):CPU只需完成必要的初始化等待操作,数据传输的整个过程都由DMA控制器来完成,在主存和外设之间建立直接的数据通路,效率很高。适用于硬盘等高速设备
    • 在一个总线周期结束后,CPU会响应DMA请求,开始读取数据
    • CPU响应程序中断方式请求是在一条指令执行结束

1.12 单/双缓冲区时间花费

  • 单缓冲区花费时间=(读入+送至+处理)+(读入+送至)*(磁盘数-1)
  • 双缓冲区花费时间=(读入+送至+处理)+读入 *(磁盘数-1)

2. 数据结构与算法

2.1. 线性结构

每个元素最多只有一个出度和一个入度,表现为一条线状。线性表按存储方式分为顺序表和链表

  • 顺序存储:用一组地址连续的存储单元一次存储线性表中的数据元素,使得逻辑上相邻的元素物理上也相邻
  • 链式存储:存储个数据元素的节点的地址并不要求是连续的,数据元素逻辑上相邻,物理上分开。

2.2 广义表

广义表是线性表的推广,是由0个或多个单元素或自表组成的有限序列

  • 表头:广义表的第一个表元素就是表头
  • 表尾:广义表中,除了第一个元素之外的其他所有元素构成的表称之为表尾

⚠️ 广义表和线性表的区别:线性表的元素都是结构上不可分的单元素,而广义表的元素既可以是单元素也可以是有结构的表

2.3 二叉树

是n个节点的有限集合,它或者是空树,或者是由一个跟节点及两个互不相交且分别称为左、右子树的二叉树所组成。与树的区别在于每个节点最多只有两个字节点。

  • 满二叉树:每层都是满节点的

  • 完全二叉树:k-1层全是满节点,第k层从左到右是满的

  • 最优二叉树(霍夫曼树):是一类带权,路径长度最短的树

    • 路径:树中一个节点到另一个节点之间的通路
    • 节点的路径长度:两节点路径上的分支数目
    • 树的路径长度:根节点到达每一个叶子节点之间的路径长度之和
    • 权:节点代表的值
    • 节点的带权路径长度:该节点到跟节点之间的路径长度乘以该节点的权
    • 树的带权路径长度(树的代价):树的所有叶子节点的带权路径长度之和
  • 查找二叉树:查找二叉树上每一个节点都存储一个值,且每个节点的所有左孩子节点值都小于父节点值,而所有右孩子节点值都大于父节点值

以根节点顺序遍历二叉树有三种方式

  • 先序:根左右
  • 中序:左根右
  • 后续:左右根

以层次遍历:按层次从上到下从左到右

2.4. 图

2.4.1 图的基本概念

  • 无向图:图的结点之间连线是没有箭头的,不分方向
  • 有向图:图的结点之间连线是箭头,区分A到B,和B到A是两条线
  • 完全图:无向完全图中,节点两两之间都有连线,有向完全图中两两节点之间都有互通的两个箭头

2.4.2 图的存储

  • 邻接矩阵:假设一个图中有n个节点,则使用n阶矩阵来存储这个图中各节点的关系,规则是若节点i到节点j有连线,则矩阵Rij=1否则为0

  • 邻接链表:用到了两个数据结构,先用一个一维数组将图中所有结点存储起来,而后对此一维数组的每个结点元素使用链表挂上和其有连接关系的结点的编号和权值

2.4.3 图的遍历

深度优先:从任一节点出发,遍历到底,直至返回,再选取任一其他节点出发,重复这个过程直至遍历完整个图

广度优先:先访问完一个顶点的所有邻接点,而后再依次访问其邻接点的所有邻接点

2.4.4 最小生成树

假设有n个结点,那么这个图的最小生成树有n-1条边

  • 克鲁斯卡尔算法:这个算法是从边出发,因为本质是选取权值最小的n-1条边,因此就将边按权值大小排序,依次选取权值最小的边,直至囊阔所有结点,注意选边时不能形成环路

  • 针对上图使用克鲁斯卡尔算法生成最小生成树步骤如下(题目源自:什么是最小生成树?

    1. 一共9个节点,因此我们最小生成树共8条边
    2. 选择权值最小的边V4-V7,没有形成环路,添加入树
    3. 选择权值最小的边V2-V8,没有形成环路,添加入树
    4. 选择权值最小的边V0-V1,没有形成环路,添加入树
    5. 选择权值最小的边V0-V5,没有形成环路,添加入树
    6. 选择权值最小的边V1-V6,没有形成环路,添加入树
    7. 选择权值最小的边V1-V6,没有形成环路,添加入树
    8. 选择权值最小的边V3-V7,没有形成环路,添加入树
    9. 选择权值最小的边V5-V6,形成环路,舍弃
    10. 选择权值最小的边V1-V2,形成环路,舍弃
    11. 选择权值最小的边V6-V7,没有形成环路,添加入树
    12. 到此我们已经有了8条边(n-1=9-1=8),最小生成树已经完成

2.5 算法复杂度

2.5.1 时间复杂度

是指程序运行从开始到结束的需要时间。通常分析时间复杂度的方法是从算法中选取一种对于所研究的问题来说是基本运算的操作,以该操作重复执行的次数作为算法的时间度量。一般来说,算法中原操作重复执行的次数是规模n的某个函数T(n)。由于许多情况下精确计算T(n)是困难的,因此引入渐进时间复杂度在数量上估计一个算法的执行时间。其定义如下:

如果存在两个常数c和m,对于所有的n,当n≥m时有f(n)≤cg(n), 则有f(n)=O(g(n))。也就是说,随着n的增大,f(n)逐渐地不大于g(n), 例如一个程序的实际执行时间为T(n)=3n^2+2n^2+n, 则T(n)=O(n^3)

  • 常见的对算法执行所需时间的度量:O(1)<O(log2n)<O(n)<O(nlog2n)<O(n^2)<O(n^3)<O(2^n)

2.5.1 空间复杂度

对一个算法在运行过程中临时占用存储空间大小的度量。一个算法的空间复杂度只考虑在运行过程中为局部变量分配的存储空间的大小

2.6 排序算法

  • 排序的分类:稳定排序与不稳定排序:依据是两个的值在一个待排序序列中的顺序在排序前后是不是相对不变的,若相对不变则为稳定排序,反之则为不稳定排序
  • 内排序和外排序:依据排序是在内存中进行的还是在外部进行的

排序的算法有很多,大致可以分为以下几类

  • 插入类排序:直接插入排序、shell排序
  • 选择类排序
    • 直接选择排序:假设待排序的元素有n个,在第一趟排序过程中,从n个元素序列中选择最小的元素,并将其放在元素序列的最前面,即第一个位置。在第二趟排序过程中,从剩余的n-1个元素中,选择最小的元素,将其放在第二位置。以此类推,直到没有待比较的元素,简单选择排序算法结束。
    • 堆排序:将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆。将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端。重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤直到整个序列有序
  • 交换类排序
    • 冒泡排序:重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
    • 快速排序:采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重复上述操作,直到将无序序列排列成有序序列。
  • 归并排序:归并是将两个或两个以上的有序表组合成一个新的有序表,假设初始序列含有n个记录,则可看成是n个子序列,每个子序列的长度为1,然后两两归并,得到[ n/2 ]个长度为2或为1的有序的子序列;再将子序列两两归并。如此重复,直到得到一个长度为n的有序序列为止
  • 基数排序

3. 计算机网络

3.1. OSI七层模型

由低层到高层排序如下

功能单位协议设备
物理层在链路上透明地传输位。需要完成的工作包括线路配置、确定数据传输模式、确定信号形式、对信号进行编码、连接传输介质。为此定义了建立、维护和拆除物理链路所具备的机械特性、电器特性、功能特性以及规程特性比特EIA/TIA RS-232中继器
RS-449集线器
V.35
RJ-45
FDDI
数据链路层把不可靠的信道变为可靠的信道。为此将比特组成帧,在链路上提供点到点的帧传输,并进行差错控制、流量控制等SDLC交换器
HDLC网桥
LAPB
PPP
STP
帧中继等
IEEE802.3
ATM
网络层在源节点-目的节点之间进行路由选择、拥塞控制、顺序控制、传送包,保证报文的正确性。网络层控制着通信子网的运行,因而它又称为通信子网IP分组IP路由器
ICMP
IGMP
ARP
RARP
传输层提供端-端间可靠透明的数据传输,保证报文顺序的正确性、数据的完整性报文段TCP网关
UDP
会话层建立通信进程的逻辑名字于物理名字之间的联系
提供进程之间建立、管理和终止会话的方式,处理同步与恢复问题
RPC网关
SQL
NFS
表示层实现数据转换(包括格式转换、压缩、加密等),提供标准的应用接口、公用的通信服务、公共数据表示方法JPEG网关
ASCII
GIF
MPEG
DES
应用层对用户不透明的提供各种服务如E-mail数据Telent网关
FTP
HTTP
SMTP
POP3
DNS
DHCP等

3.2. TCP/IP

3.2.1 网络层协议

  • IP:网络层最重要的核心协议,在源地址和目的地址之间传从数据报,面向无连接,不可靠
  • ICMP:因特网控制报文协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息
  • IGMP:网络组管理协议,允许因特网中的计算机参加多播,是计算机用作向相邻多目路由器报告多目组成成员的协议,支持组播
  • ARP和RARP:地址解析协议,ARP是将IP地址转换为物理地址,RARP是将物理地址转换为IP地址

3.2.2 传输层协议

  • TCP:整个TCP/IP协议族中最重要的协议之一,在IP协议提供的不可靠数据基础上,采用了重发技术,为应用程序提供了一个可靠的、面向全连接的,全双工的数据传输服务。一般用于传输数据量比较少,且对可靠性要求高的场合
  • UDP:是一种不可靠、无连接的协议,有助于提高传输速率,一般用于传输数据量大,第可靠性要求不高,但要求速度快的场合

3.2.3 应用层协议

基于TCP的FTP,HTTP等都是可靠传输。基于UDP的DHCP、DNS等都是不可靠传输

  • FTP:可靠的文本传输协议,用于因特网上的控制文件的双向传输
  • HTTP:超文本传输协议,用于从www服务器传输超文本到本地浏览器的传输协议。使用SSL加密后的安全网页协议为HTTPS
  • Telnet:远程连接协议,是因特网远程登录服务的标准协议和主要方式
  • TFTP:不可靠的、开销不大的小文件传输协议
  • SNMP:简单网络管理协议,由一组网络管理的标准协议,包含一个应用层协议、数据库模型和一组资源对象。该协议能够支持网络管理系统,用于监测连接到网络上的设备是否有引起管理师关注的情况,该协议封装在UDP中传送
  • DHCP:动态主机配置协议,基于UDP,基于C/S模型,为主机动态分配IP地址,有固定分配,动态分配,自动分配三种方式
    • 客户端可以从DHCP服务器获得本机IP地址,DNS服务器地址,DHCP服务器地址,默认网关地址
  • DNS:域名解析协议,通过域名解析出IP协议

3.2.4 邮件相关协议

  • SMTP:简单邮件传输协议,是一组用于由源地址到目的地址传送邮件的规则,邮件报文采用ASCII格式表示
  • POP3:用于邮件接收的协议。邮件客户端通过与服务器之间建立TCP链接,采用Client/Server计算模式来传送邮件
  • MIME:提供多格式邮件服务(附加多媒体)
  • PGP:安全邮件协议

3.3. 通信方式和交换方式

  • 通信方式
    • 单工:只能由设备A发送给设备B,即数据只能单向流动
    • 半双工:设备A和设备B可以相互通信,但同一时刻数据流只能单向流动
    • 全双工:设备A和设备B在任意时刻都能相互通信
  • 交换方式
    • 电路交换:通信一方进行呼叫,另一方接收后,在二者之间会建立一个专用电路,特点为面向连接、实时性高、链路利用率低,一般用于语音视频通信
    • 报文交换:以报文为单位,存储转发模式,接收到数据后先存储,进行差错校验,没有错误则转发,有错误则丢弃。因此会有延迟,但可靠性高,是面向无连接的
    • 分组交换:以分组为单位,也是存储转发模式。因为分组的长度比报文小,所以延时小于报文交换。又可以分为三种方式
      • 数据报:是现在主流的交换方式。各个分组携带地址信息,自由的选择不同的路由路径传送到接收方,接收方接收到分组后再根据地址信息重新组装成原数据,是面向无连接的,是不可靠的
      • 虚电路:发送方发送一个分组,接收方收到后二者之间就建立了一个虚拟的通信线路,二者之间的分组数据交互都通过这条线路传送,在空闲时间这条线路也可以传送其他数据,是面向连接的,是可靠的
      • 信元交换:异步传输模式ATM采用的交换方式。本质是按照虚电路方式进行转发,只不过信元是固定长度的分组(共53B,其中5B为头部,48B为数据域),是面向连接的,是可靠的

3.4. IPv4网络号

  • A类:8位
  • B类: 16位
  • C类: 24位

3.5. Internet网络服务

  • Gopher服务器:提供分类的文档查询及管理的计算机。他将网络中浩瀚如海的信息分门别类的整理成菜单形式,提供用户快捷查询并选择使用
  • Telnet服务器:提供远程登录服务,一般使用Telnet的协议。使用Telnet可以实现远程计算机资源共享,也就是指使用远程计算机就和使用本地计算机一样,很多BBS(电子公告牌)就是使用Telnet协议实现的
  • FTP服务器:提供文件的上传和下载服务。一般使用FTP协议。使用该协议可以实现文件的共享,可以远程传递较大的文件。同时,该服务器也提供存放文件或软件的磁盘空间
  • E-mail服务器:提供电子邮件服务。一般都支持SMTP和POP3协议。该服务器用来存放使用电子邮件用户的邮件并且维护邮件用户的邮件发送
  • Web服务器:提供www服务。一般使用http协议来实现。浏览器软件必须通过访问Web服务器才能获取信息

4. 数据库技术基础

4.1. 基本概念

  • 数据库系统DBS:是一个采用了数据库技术,有组织地、动态的存储大量相关数据,方便多用户访问的计算机系统,由下面四部分组成
    • 数据库:统一管理、长期存储在计算机内的,有组织的相关数据的集合
    • 硬件:构成计算机系统包括存储数据所需的外部设备
    • 软件:操作系统、数据管理系统及应用程序
    • 人员:系统分析和数据库设计人员、应用程序员、最终用户、数据库管理员DBA
  • 数据库管理系统DBMS的功能
    • 实现对共享数据有效的组织、管理和存取
    • 包括数据定义、数据库操作、数据库运行管理、数据的存储管理、数据库的建立和维护等

4.2 三级模式-两级映像

  • 内模式:管理如何存储物理的数据,对应具体物理存储文件
  • 模式-内模式映像(物理独立性):是表和数据物理存储之间的映像,存在于概念级和内部级之间,若修改了数据存储方式,只需要修改此映射而无需修改应用程序
  • 模式(概念模式):就是我们通常使用的基本表,根据应用、需求将物理数据划分成一张张表
  • 外模式-模式映像(数据逻辑独立性):是表和试图之间的映射,存在于概念级和外部级之间,若表中数据发生了修改,只需要修改此映射而不需修改应用程序
  • 外模式:对应数据库中的视图这个级别,将表进行一定的处理后再提供给用户使用

4.3 数据库设计

  • 需求分析:分析数据存储要求,产出物有数据流图、数据字典、需求说明书
  • 概念结构设计:设计E-R图(实体-属性图),与物理实现无关,说明有哪些实体,实体有哪些属性
    • E-R模型
      • E-R模型及实体-联系模型,使用椭圆表示属性、长方形表示实体、菱形表示联系、联系两端要标注联系类型
      • 属性分类
        • 简单属性和复合属性:属性是否可以分割
        • 单值属性和多值属性:属性有多少个取值
        • NULL属性:无意义
        • 派生属性:可由其他属性生成
      • 联系类型:一对一(1:1),一对多(1:n),多对多(n:n)
  • 逻辑结构设计:将E-R图转换成关系模型,即转换成实际的表和表中的列属性,这里要考虑很多规范化的东西
    • 关系模型

      • 关系模型也即数据库中常用的表,包括实体的属性,标识出实体的主键和外键。如下:

        • S(Sno,Sname,SD,Sage,Sex): 学生S关系模式,属性为学号、姓名、系、年龄和性别
          T(Tno,Tname,Age,Sex): 教师T关系模式,属性为教师号、姓名、年龄和性别
          C (Cno,Cname,Pcno): 课程C关系模式,属性为课程号、课程名和先修课程号
          SC (Sno,Cno,Grade): 学生选课SC关系模式,属性为学号、课程号和成绩.

    • 模式转换

      • E-R图转换为关系模型,每个实体都要对应一个关系模式,其中实体间联系需要如下操作
        • 1:1联系,联系可以放到任意的两端实体中作为一个属性(要保证1:1两端的关联)
        • 1:N联系,联系可以单独作为一个关系模式,也可以在N端中加入1端实体的主键
        • M:N联系,联系必须作为一个单独的关系模式,其主键是M和N端的联合主键
  • 物理设计:根据生成的表等概念,生成物理数据库

4.4 关系代数运算

并:两张表中所有记录数合并,相同记录只显示一次

交:结果是两张表中相同的记录

差:S1-S2,结果是S1表中有但S2中没有的记录

笛卡尔积:S1 x S2,产生的结果包括S1和S2的所有属性列,并且S1中的每条记录依次和S2中所有记录组合成一条记录,最终属性列为S1+S2属性列,记录数为S1 x S2

投影(π):实际是按条件选择某关系模式中某列,列也可以用数字表示

选择(σ):实际是按条件选择某关系模式中的某条记录

自然连接

  • 结果显示全部的属性列,但是相同属性列只显示一次

  • 显示两个关系模式中属性相同且值相同的记录

给定关系R(A, B, C, D)和关系S(C, D, E)

对其进行自然连接运算R⋈S后的属性列为几个?
与σR.B>S.E(R⋈S)等价的代数表达式为?
A. σ2>7(RXS)     B. π1,2,3,4,7(σ'2'>'7'^3=5^4=6(RXS))
C. σ'2'>'7'(RXS) D. π1,2,3,4,7(σ2>7^3=5^4=6(RXS)
解:
	首先我们应该明确R⋈S之后属性列分别为ABCDE, 因此可以解答第一个问题属性列为5个
	第二步我们需要将自然连接转换为笛卡尔积
		假设我们对R和S进行笛卡尔积,此时属性列为ABCDCDE
			- 对应列号为1234567
		那么当将RXS转换为R⋈S时我们选择的列号便为12347
			- 此时我们可以得到: π1,2,3,4,7(RXS)
		列处理完之后我们需要处理行,可以发现R和S相同的列为S.C=R.C, S.D=R.D, 这对应着笛卡尔积的3=5, 4=6
			- 此时我们可以得到: R⋈S = π1,2,3,4,7(σ3=5^4=6(RXS))
		接下来我们看题目中给到的投影条件σR.B>S.E, 其中R.B对应着笛卡尔积的2列, S.E对应着笛卡尔积的7列
			- 我们便可以得到最终的结果: σR.B>S.E(R⋈S) = π1,2,3,4,7(σ2>7^3=5^4=6(RXS)

4.5. 函数依赖

给定一个X,能唯一确定一个Y,就称X确定Y或者说Y依赖于X

函数依赖又可以扩展以下两种规则

  • 部分函数依赖:(A,B)可以确定C,(A,B)中的一部分(即A)可以确定C,称为部分函数依赖

  • 传递函数依赖

    • 当A和B不等价时,A可确定B,B可确定C,则A可确定C,是传递函数依赖
    • 若A和B等价,则不存在传递,直接就可以确定C

4.6. 键与依赖

超键:能唯一标识此表的属性的组合

候选键:超键中去掉冗余的属性,剩余的属性就是候选键

主属性:候选键内的属性为主属性,其他属性为非主属性

主键:任意一个候选键即可作为主键

外键:其他表中的主键

实体完整性约束(主键约束):主键值不能为空也不能重复

参照完整性约束(外键约束):外键必须是其他表中已经存在的主键的值,或者为空

用户自定义完整性约束(自定义表达式约束):如设定年龄属性的值必须在0~150之间

4.7. 范式

  • 第一范式(1NF):关系中的每一个分量必须是一个不可分隔的数据项。通俗的说,第一范式就是表中不允许有小表的存在
  • 第二范式(2NF):在满足1NF的基础上,且不存在非主属性对候选码的部分依赖则属于2NF。
  • 第三范式(3NF):在满足1NF的基础上,表中不存在非主属性对候选码的传递依赖
  • BC范式:在第三范式的基础上进一步消除主属性对与码的部分函数依赖和传递依赖。通俗来说就是在每一种情况下,每一个依赖的左边决定因素都必然包含候选键

4.8. 事务管理

事务提交commit,事务回滚rollback

事务:由一系列操作组成,这些操作要么全做,要么不做,拥有四种特性:

  • 原子性:要么全做,要么全不做
  • 一致性:事务发生后数据是一致的,例如银行转账,不会存在A账户转出但B账户没收到的情况
  • 隔离性:任一事务的更新操作直到其成功提交的整个过程对其他事务都是不可见的,不同事务之间是隔离的,互不干涉
  • 持续性:事务操作的结果是持续性的

4.8.1 数据控制

  • 安全性控制(security):保护数据库不受恶意访问,即防止不合法的使用所造成的数据泄漏、更改或破坏。例如可以为用户划分不同的权限
  • 完整性控制(integrality):是指数据库正确性和相容性,防止合法用户使用数据库时向数据库加入不符合语义的数据。保证数据正确,避免非法更新
  • 并发控制(concurrency control):事务是并发控制的前提条件,并发控制就是控制不同的事物并发执行,提高系统效率,但并发控制中存在三个问题
    • 丢失更新:事务1对数据A进行修改并写回,事务2也对A进行了修改并写回,此时事务2写回的数据会覆盖事务1写回的数据,就丢失了事务1对A的更新。即对数据A的更新会被覆盖
    • 不可重复读:事务2读A,而后事务1对数据A进行了修改并写回,此时若事务2再读A,发现数据不对,即一个事务重复读A两次,发现A数据有误
    • 读脏数据:事务1对数据A进行了修改后,事务2读取数据A。而后事务1回滚,数据A恢复了原来的值,那么事务2对数据A做的事是无效的,读到了脏数据
  • 故障恢复 (recovery from failure):数据库中的 4 类故障是事务内部故障、系统故障、介质故障及计算机病毒。故障恢复主要是指恢复数据库本身,即在故障引起数据库当前状态不一致后,将数据库恢复到某个正确状态或一致状态。恢复的原理非常简单,就是要建立冗余(redundancy) 数据。换句话说,确定数据库是否可恢复的方法就是其包含的每一条信息是否都可以利用冗余地存储在别处的信息重构。

4.8.2 封锁协议

X锁是排它锁(写锁)。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他事务都不能再对A加任何的锁,直到T释放A上的锁

S锁是共享锁(读锁)。若事务T对数据对象A加上S锁,则只允许T读取A,但不能修改A,其他事务只能再对A加S锁,直到T释放A上的S锁

  • 一级封锁协议:事务在修改数据R之前必须先对其加上X锁,直到事务结束才释放。可解决丢失更新问题
  • 二级封锁协议:一级封锁协议的基础上加上事务T在读数据R之前必须对其加上S锁,读完后即可释放S锁。可解决丢失更新、读脏数据问题
  • 三级封锁协议:一级封锁协议加上事务T在读数据R之前先对其加上S锁,直到事务结束才释放。可解决丢失更新、读脏数据、数据重复读问题

4.9. 分布式数据库

局部数据库位于不同的物理位置,使用一个全局DBMS将所有局部数据库联网管理

  • 分片模式
    • 水平分片:将表中水平的记录分别存放在不同的地方
    • 垂直分片:将表中的垂直列分别存放在不同地方
  • 分片透明性:用户或应用程序不需要知道逻辑上访问的表具体是如何分块存储的
  • 位置透明性:应用程序不关心数据存储物理位置
  • 逻辑透明性:用户或应用程序无需知道局部使用的是那种数据模型
  • 复制透明性:用户或应用程序不关心复制的数据从何而来

5. 程序设计语言基础知识

5.1. 程序设计语言概述

程序设计语言是为了书写计算机程序而人为设计的符号语言,用于对计算机过程进行描述、组织和推导

  • 低级语言:机器语言、汇编语言
  • 高级语言:功能更强,抽象级别更高,与人们使用的自然语言比较接近

⚠️ 高级语言和脚本语言是两个概念,没有任何关系

5.2. 编译和解释

5.2.1 编译程序

  • 生成独立可执行文件,直接运行
  • 运行时无法控制源程序
  • 效率高

5.2.2 解释程序

  • 不生成可执行文件。可以逐条解释执行,用于调试模式
  • 可以控制源程序
  • 因为还需要控制程序因此执行速度慢、效率低

⚠️ 无论是编译还是解释都需要依次进行词法分析,语法分析,语义分析

6. 软件工程基础知识

6.1. 信息系统生命周期

  • 系统规划阶段: 对组织的环境、目标及现行系统进行初步调查,根据组织目标和发展战略确定信息系统的发展战略,对建设新系统的需求做出分析和预测。同时考虑建设新系统所受各种约束,研究建设新系统的必要性和可能性。根据需要与可能,给出制建系统的备选方案 输出:可行性研究报告、系统设计任务书
  • 系统分析阶段: 系统分析阶段的任务是回答系统“做什么”的问题。根据系统设计任务书所确定的范围,对现行系统进行详细调查,描述现行系统的业务流程,指出现行系统的局限性和不足之处,确定新系统的基本目标和逻辑功能要求,即提出新系统的逻辑模型,分析阶段又称为逻辑设计阶段,这个阶段是整个系统建设的关键阶段,也是信息系统建设与一般工程项目的重要区别所在 输出:系统说明书
    • 结构化分析:
      • 结构化分析是一种建模技术,其建立的分析模型的核心是数据字典。围绕这个核心有数据流图、实体联系图和状态-迁移图
        • 数据字典(DD):描述了在目标系统中使用和生成的所有数据对象。
          • 数据字典下有四类条目:数据流、数据项、数据存储和基本加工
        • 数据流图(DFD):数据流图描述数据在系统中如何被传送或变换,以及描述如何对数据进行变换的功能(子功能),用于功能建模
          • 数据流:由一组固定成分的数据组成,表示数据的流向。在DFD中,数据流的流向必须经过加工
          • 加工:描述了输入数据流到输出数据流之间的变换,数据流图中常见的三种错误
            • 有输入但是没输出,成为黑洞
            • 有输出但是没输入,成为奇迹
            • 输入不足以产生输出,成为灰洞
          • 数据存储:用来存储数据
          • 外部实体:指存在于软件系统之外的人员或组织,它指出系统所需数据的源和系统所产生数据的归宿地
        • 实体联系图:描述数据对象及数据对象之间的关系,用于数据建模
        • 状态-迁移图:描述系统对外部事件如何响应以及如何动作,用于行为模型
  • 系统设计阶段: 系统设计阶段要回答的问题是“怎么做”。该阶段的任务是根据系统说明书中规定的功能要求,具体设计实现逻辑模型的技术方案,也就是设计新系统的物理模型。这个阶段又称为物理设计阶段,可分为总体设计(概要设计)和详细设计两个子阶段。 输出:系统设计说明书(该要设计、详细设计说明书)
    • 系统设计方法:结构化设计方法,面向对象设计方法
      • 体系化结构设计主要包括:体系结构设计、数据设计、接口设计、过程设计
        • 体系结构设计:定义软件的主要构造元素及其之间的关系。依据系统规格说明、数据流图进行
        • 数据设计:确定软件涉及的文件系统的结构及数据库的表结构。依据实体联系图进行
        • 接口设计:描述用户界面、软件和其他硬件设备、其他软件系统及使用人员的外部接口,以及各种结构之间的内部接口。依据数据流图进行
        • 过程设计:确定软件各个组成部分内的算法及内部数据结构,并选定某种过程的表达形式来描述各种算法。依据加工规格说明进行
      • 概要设计基本任务:又称为系统总体结构设计,是将系统的功能需求分配给软件模块,确定每个模块的功能和调用关系,形成软件的模块结构图(即系统结构图)
      • 详细设计基本任务:模块内详细算法设计、模块内数据结构设计、数据库的物理设计、其他设计(代码、输入/输出格式、用户界面)、编写详细设计说明书、评审
  • 系统实施阶段: 是将设计的系统付诸实施的阶段。这一阶段的任务包括计算机等设备的购置、安装和调试、程序的编写和调试、人员培训、数据文件转换、系统调试与转换等。这个阶段的特点是几个相互联系、相互制约的任务同时展开,必须精心安排、合理组织。系统实施是按实施计划分阶段完成的,每个阶段应写出实施进展报告。系统测试之后写出系统测试分析报告 输出:实施进展报告、系统测试分析报告
  • 系统运行和维护阶段: 系统投入运行后需要经常进行维护和评价,记录系统运行的情况,根据一定的规则对系统进行必要的修改,评价系统的工作质量和经济效益

6.2. 软件体系结构风格

6.2.1 管道过滤器

管道过滤器体系结构由一组称为过滤器的构件以及连接构件的管道组成,管道将数据从一个过滤器传送到另一个过滤器

优点:

  • 软件结构具有良好的隐蔽性和高内聚、低耦合的特点
  • 允许设计者将整个系统的输入输出行为看成是多个过滤器的行为的简单合成
  • 支持软件复用
  • 系统维护和增强系统性能简单
  • 允许对一些如吞吐量、死锁等属性的分析
  • 支持并行执行

6.2.2 分布式

缺点:

  • 额外的复杂性
  • 接口数量暴增
  • 容易出现强耦合导致可维护性差
  • 信息安全的风险

优点:

  • 支持大量并发用户
  • 容错和灾备能力
  • 可灵活扩展

6.3. 耦合与内聚

良好的设计模式:高内聚低耦合

内聚:模块内部关联程度

耦合:模块与模块之间的关联程度

内聚程度从低到高如下

  • 偶然内聚:一个模块内的各处理元素之间没有任何联系
  • 逻辑内聚:模块内执若干个逻辑上相似的功能,通过参数确定该模块完成那一个功能
  • 时间内聚:把需要同时执行的动作组合在一起形成的模块
  • 过程内聚:一个模块完成多个任务,这些任务必须按照指定的过程执行
  • 通信内聚:模块内的所有处理元素都在同一个数据结构上操作,或者各处理使用相同的输入数据或者产生相同的输出数据
  • 顺序内聚:一个模块中的各个处理元素都密切相关同一个功能且必须顺序执行,前一个功能元素的输出就是下一个功能元素的输入
  • 功能内聚:最强的内聚,模块内的所有元素共同作用完成一个功能,缺一不可

耦合程度从低到高如下表所示

  • 无直接耦合:两个模块之间没有直接的关系,他们分别从属于不同模块的控制与调用,不传递任何信息
  • 数据耦合:两个模块之间有调用关系,传递的是简单的数据值,相当于高级语言中的值传递
  • 标记耦合:两个模块之间传递的是数据结构
  • 控制耦合:一个模块调用另一个模块时,传递的是控制变量,被调用模块通过该控制变量的值有选择的执行模块内的某一功能
  • 外部耦合:模块之间通过软件之外的环境链接(如I/O将模块耦合到特定的设备、格式、通信协议上时)
  • 公共耦合:通过一个公共数据环境相互作用的那些模块之间的耦合
  • 内容耦合:当一个模块直接使用另一个模块的内部数据,或通过非正常入口转入另一个模块内部时

6.4. 开发模型

6.4.1 喷泉模型

喷泉模型以用户需求为动力,以应用对象为驱动,适合于面向对象的开发方法

6.4.2 基于构件开发

利用预先包装的构件来构造应用系统。构件可以是组织内部开发的构件,也可以是商品化成品软件构件。基于构件的开发模型具有许多螺旋模型的特点,它本质上是演化模型,需要以迭代方式构建软件。基于构件的开发,开发效率高,但是由于使用的构件有可能需要内部开发或者使用商品化的构件,所以成本较高。

6.5. 敏捷开发

6.5.1 极限编程(XP)

极限编程是敏捷方法中最普遍的一种,由价值观、原则、实践和行为四个部分组成。

是激发开发人员创造性、使得管理负担最小的一种技术

  • 四个价值观:沟通、简单性、反馈、勇气
  • 五大原则:简单性假设、快速反馈、逐步修改、提倡更改、优质工作
  • 十二个最佳实践:计划游戏,小型发布,系统隐喻,简单设计,测试驱动,重构,结对编程,集体所有权,持续集成,每周工作40小时,现场客户,编码标准
  • 鼓励行为:协作与沟通,自组织与责任,迭代与小步快速迭代,持续学习与改进,测试驱动开发,共享责任与集体拥有,勇于挑战和适应变化,注重可持续性与工作平衡

6.5.2 水晶法(Crystal)

每一个不同的项目都需要一套不同的策略、约定和方法论

6.5.3 并列争球法(Scrum)

使用迭代的方法,其中把每30天一次的迭代称为一个冲刺,并按需求的优先级来实现产品。多个自组织和自治小组并行地递增实现产品,协调是通过简短的日常情况会议进行

Scrum步骤:

  • 确定Product Backlog(按优先顺序排列一个产品需求列表)
  • 根据Product Backlog进行工作量预估和安排
  • 通过Sprint Planning Meeting从Product Backlog中挑选一个Story作为本次迭代完成的目标,这个目标的时间周期是1~4周,然后细化这个Story,形成一个Sprint Backlog
  • 每个成员根据Sprint Backlog再细化成更小的任务(细到每个任务的工作量在2天内能完成)
  • 在Scrum Team完成会议上选出的Sprint Backlog过程中,需要进行Daily Scrum Meeting,每次会议控制在15分钟左右,每个人都必须发言,向所有成员当面汇报前一天的工作,承诺今天要完成的任务,可以提出遇到不能解决的问题,并更新自己的Sprint Burn Down
  • 做到每日集成,也就是每天都要有一个可以成功编译并且可以演示的版本
  • 当一个Story完成,即Sprint Backlog完成,也就表示一次Sprint完成,此时要进行Sprint Review Meeting,即评审会议。产品负责人和客户都要参加,每一个Scrum的成员都要向他们演示自己完成的软件产品
  • Sprint Retrospective Meeting,也称总结会议,以轮流发言的方式进行,每个人都要发言,总结并讨论改进的地方,放入下一轮Sprint的产品需求中

6.5.4 自适应软件开发(ASD)

有一个使命为指导,它设立了项目的目标,但并不描述如何达到这个目标

6.6. 软件失效术语

  • 软件错误:在软件的生存期内不希望或不可接受的人为错误,其结果是导致软件缺陷
  • 软件缺陷:存在于软件(文档,数据,程序)之中不希望或不可接受的偏差
  • 软件故障:在软件运行过程中出现的一种不希望或不可接受的内部状态
  • 软件失效:在软件运行时产生的一种不希望或不可接受的外部行为

6.7. 软件工程的基本要素

  • 方法:完成软件开发的各项任务的技术方法
  • 工具:为运用方法而提供的软件工程支撑环境
  • 过程:获得高质量软件所需要完成的一系列任务

6.8. CMM(软件成熟度模型)

  1. 初始级别:该级别表示软件开发过程尚未被规范化。在这种状态下,软件开发项目极度依赖个别的英雄式人物。
  2. 可重复级:建立了基本的项目管理过程和实践来跟踪项目费用、进度和功能特性,有必要的过程准则来重复以前在同类项目中的成功
  3. 已定义级:管理和工程两方面的软件过程已经文档化、标准化,并综合成整个软件开发组织的标准软件过程
  4. 已管理级:制定了软件过程和产品质量的详细度量标准
  5. 优化级:加强了定量分析,通过来自过程质量反馈和来自新观念、新技术的反馈使过程能不断持续更新改进

7. 安全性知识

7.1. 信息安全含义及属性

保护信息的保密性、完整性、安全性,另外也包括其他属性,如:真实性、可核查性、不可抵赖性和可靠性

  • 保密性:信息不被泄露给未授权的个人、实体和过程或不被其使用的特征。保证保密性的方法包括:
    • 最小授权原则
    • 防暴露
    • 信息加密
    • 物理保密
  • 完整性:信息未授权不能改变的特征。影响完整性的主要因素有设备故障、误码、人为攻击和计算机病毒等。保证完整性的方法包括:
    • 协议:通过安全协议检测出被删除、失效、被修改的字段
    • 纠错编码方式:利用校验码完成检错和纠错功能
    • 密码校验和方法
    • 数字签名:能识别出发送方来源
    • 公证:请求系统管理或中介机构证明信息的真实性
  • 可用性:需要时,授权实体可以访问和使用的特征。一般用于系统正常使用时间和整个工作时间之比来度量
  • 真实性:对信息的来源进行判断,能对伪造来源的信息予以鉴别
  • 可核查性:系统实体的行为可以被独一无二的追溯到该实体的特性,这个特性就是要求该实体对其行为负责,为探测和调查安全违章事件提供可能性
  • 不可抵赖性:是指建立有效的责任机制,防止用户否认其行为
  • 可靠性:系统在规定的时间和给定的条件下,无故障的完成规定功能的概率

7.2. 对称加密技术

数据的加密和解密的密钥(密码)是相同的,属于不公开密钥算法

其缺点是加密强度不高(因为密钥位数少),且密钥分发困难(因为密钥还需要传输给接收方,也要考考虑保密性问题)。优点是加密速度快适合加密大数据

常见的对称密钥加密算法:

  • DES
  • 3DES
  • AES
  • RC-5
  • IDEA

7.3. 非对称加密技术

数据的加密和解密的密钥是不同的,分为公钥和私钥。是公开密钥加密算法

其缺点是加密速度慢。优点是安全性高,不容易破解

非对称技术的原理:发送者发送数据时,使用接收者的公钥作为加密密钥,私钥做解密密钥,这样只有接收者才能解密密文得到明文。安全性更高(无需传输密钥)。但无法保证完整性

常见非对称加密算法:

  • RSA
  • Elgamal
  • ECC(椭圆曲线算法)
  • 背包算法
  • Rabin
  • D-H

7.4. 数字信封原理

信是对称加密的密钥,数字信封就是对此密钥进行非对称加密。

数字信封运用了对称加密技术和非对称加密技术,本质是使用对称密钥加密数据,非对称密钥加密对称密钥,解决了对称密钥的传输问题

具体过程:发送方将数据用对称加密传输,而将对称密钥用接收方公钥加密发送给对方。接收方收到数字信封,用自己的私钥解密信封,取出对称密钥,便可以通过对称密钥得到明文

7.5. 网络攻击和威胁

被动攻击

  • 窃听(网络监听):用各种可能的合法的或非法的手段窃取系统中的信息资源和敏感信息
  • 业务流分析:通过对系统进行长期监听,利用系统分析方法对诸如通信频道、通信信息流向、通信总量的变化等参数进行研究,从而发现有价值的信息和规律
  • 非法登陆:有些资料将这种方式归为被动攻击

主动攻击

  • 假冒身份:通过欺骗通信系统(或用户)达到非法用户冒充为合法用户,或者特权小的用户冒充成为特权大的用户的目的。
  • 抵赖:这是一种来自用户的攻击,比如:否认自己曾经发布过某条消息、伪造一份对方来信等
  • 旁路控制:攻击者利用系统的安全缺陷或安全性上脆弱之处获得非授权的权利或特权
  • 重放攻击:所截获的某次合法的通信数据拷贝,出于非法的目的而被重新发送
  • 拒绝服务(DOS):对信息或其他资源的合法访问被无条件的阻止

7.6. 计算机病毒

7.6.1 常见计算机病毒

  • 宏病毒:宏病毒是一种寄存在文档或模板的宏中的计算机病毒。一旦打开这样的文档,其中的宏就会被执行,于是宏病毒就会被激活,转移到计算机上,并驻留在Normal模板上。从此以后,所有自动保存的文档都会“感染”上这种宏病毒,而且如果其他用户打开了感染病毒的文档,宏病毒又会转移到他的计算机上。
  • 熊猫病毒:是一款拥有自动传播、自动感染硬盘能力和强大的破坏能力的病毒

7.6.2 有效防治计算机病毒的策略

安装并及时升级防病毒软件,可以有效防治计算机病毒

7.7. 防火墙

防火墙对数据包信息的过滤是通过对数据包的IP头和TCP头或UDP头的检查来实现的,主要信息有IP源地址、IP目标地址、协议、数据包到达以及出去的端口等。

防火墙无法自主判断所有来自网络的URL地址是否存在安全隐患

8. 基于质量特性的测试与评价

8.1. 功能性测试

  • 完备性测试:评价软件产品提供的功能覆盖所有的具体任务或用户目标的程度
  • 正确性测试:评估产品或系统提供具有所需精度的正确结果的能力
  • 适合性测试:软件产品的功能是否是用户需求的功能

8.2. 性能效率测试

  • 时间特性测试:在特定条件下,其响应时间、处理时间及吞吐率满足需求的程度
  • 资源利用性测试:评估产品或系统执行功能时所使用资源数量和类型满足需求的程度
  • 容量测试:评估软件产品或系统参数的最大限度满足需求的程度

8.2.1 性能效率测试类型

  • 基准测试:对业务模型中涉及的每种业务做基准检测(常规性能测试)
  • 并发测试:测试系统在同时处理多个请求时的性能和稳定性,以确定系统的并发处理能力
  • 压力测试:在事先规定的饱和状态下,系统是否还预备处理业务的能力
  • 负载测试:不断加压,直到找到系统不可用临界点的过程
  • 稳定性测试:在特定的环境下,给系统加载一定业务压力,使系统运行一段比较长的时间,以此检测系统是否稳定。稳定性测试是概率性测试
  • 极限测试:过量用户下的压力测试。目的是确定系统的极限并发用户数
  • 场景测试:构造系统综合场景的测试模型,模拟不同用户执行不同操作,最大限度模拟系统真实场景
  • 吞吐量测试:模拟系统真实使用场景,每隔一定时间段并发不同数目的虚拟用户执行检查点操作,运行一段时间,计算每单位时间系统处理的能力(事务数/单位时间)。目的是计算系统的吞吐能力

8.3. 易用性测试

  • 可辨识性测试:用户对于产品的辨识度
  • 入口描述:引导页中能说明该网站目的的比例
  • 易学性测试
  • 易操作性测试
  • 易访问性测试
    • 特殊群体的易访问性
    • 支持语言的充分性
  • 演示覆盖率:有多少比例的任务为用户提供帮助演示
  • 用户差错防御测试
    • 抵御误操作
    • 用户输入差错纠正
  • 用户界面舒适性测试

8.4. 兼容性测试

  • 共存性测试:评估在与其他产品共享通用的环境和资源的条件下,产品能够有效执行其所需功能并且不会对其他产品造成负面影的程度
  • 互相操作性测试:评估两个或多个系统、产品或组件能够交换信息并使用自己交换的信息的程度
    • 数据格式可交换性
    • 数据传输的交换接口是否正常实现

8.5. 信息安全性测试

  • 保密性测试:评估确保数据只有在被授权时才能被访问的程度
    • 访问控制
    • 数据加密
  • 完整性测试:评估系统、产品或组件防止未授权访问、篡改计算机程序或数据的程度
  • 抗抵赖性测试:评估活动或事件可以被证实且不可被否认的程度
    • 数字签名
    • 安全审计
  • 可核查性测试:评估实体的活动可以被唯一地追溯到该实体的程度
    • 用户审计跟踪的完整性
    • 系统日志存储
  • 真实性测试:评估对象或资源的身份能够被证实符合其声明的程度
    • 鉴别机制的充分性

8.6. 可靠性测试

  • 成熟性测试:评估系统、产品、组件在正常运行时满足可靠性程度
    • 故障密度
    • 故障修复率
    • 平均失效间隔时间
    • 周期失效率
  • 可用性测试:需要使用时能够进行操作和访问的程度
    • 系统可用性:在计划时间内,系统实际可用时间比例
    • 平均宕机时间
  • 容错性测试:当存在硬件或者软件故障时,系统、产品或软件的运行符合预期的程度
    • 避免失效率:能控制多少种故障模式以避免关键或严重的失效
    • 组件的冗余度:为避免系统失效而安装冗余组件的比例
  • 易恢复性:评估发生中断或失效时,产品或系统能够恢复直接受影响的数据并重建期望的系统状态的程度
    • 平均回复时间
    • 数据备份完整性:数据能否完整地定期进行备份
    • 数据恢复能力

8.7. 可维护性测试

  • 模块化测试:评估多个独立组件组成的系统或计算机程序,其中一个组件的变更对其他组件的影响大小的程度
  • 可重用性测试:评估资产能够被用于多个系统或其他资产建设的程度
    • 资产的可重用性
    • 编码规则符合性
  • 易分析性测试:评估预期的变更,对产品或系统的影响,诊断产品的缺陷或失效原因、识别待修改部分的有效性和效率的程度
    • 日志完整性
    • 诊断功能有效性
  • 易修改性:评价产品或系统可以被有效地、有效率地修改,且不会引入缺陷或降低现有产品质量的程度
    • 扩充系统应用
    • 软件版本更新方式
    • 软件版本更新时的数据操作
    • 系统参数配置
    • 用户权限配置
  • 易测试性:评估能够为系统、产品或组件建立测试准则,并通过测试执行来确定测试准则被满足的有效性和效率的程度

8.8. 可移植性测试

  • 适应性测试:评估产品能够有效地、有效率地适应不同的或演变的硬件、软件或者其他运行(或使用)环境的程度
    • 硬件环境的适应性
    • 系统环境的适应性:包括但不限于操作环境、数据库、浏览器、支撑软件的适应性
  • 易安装性测试:评价在指定环境中,产品能够成功地安装和卸载的有效性和效率的程度
  • 易替换性测试:评价在相同环境,产品能够替换另一个相同用途的指定软件产品的程度(同产品软件覆盖安装)

8.9. 依从性测试

用与评估产品遵循八大质量特性(功能性、性能效率、易用性、可靠性、信息安全性、维护性、兼容性、可移植性)有关的标准、约定和法规以及类似规定的程度

8.10. 符合性测试(标准符合性测试)

测量产品的功能和性能指标,与相关国家标准或行业标准所规定的功能和性能指标之间符合程度的测试活动

  • 在标准符合性测试前需要获得的资源
    • 待测产品
    • 用户文档集中包含的所有文档
    • 产品说明中表示出的所有需求文档
    • 软件产品宣称符合的标准

10. 测试用例的设计方法

10.1. 等价类划分法

10.1.1 等价类划分6条原则

  • 在输入条件规定了取值范围或值的个数的情况下,可以确立一个有效等价类和两个无效等价类(例如:程序输入条件为1~10)
  • 在输入条件规定了输入值的集合或者规定了“必须如何”的条件的情况下,可以确立一个有效等价类和一个无效等价类(例如:输入条件规定x取值必须是偶数)
  • 在输入条件是一个布尔量的情况下,可确定一个有效等价类和一个无效等价类
  • 在规定了输入数据的一组值(假定n个), 并且程序要对每一个输入值分别处理的情况下,可以确立n个有效等价类和1个无效等价类(例如: 销售奖金对第1, 2, 3名分别奖励)
  • 在规定了数据必须遵守的规则的情况下, 可确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则). (例如: 输入规定必须为整数)
  • 在确定已划分的等价类中,各元素在程序处理中的方式不同的情况下,则应在将该等价类进一步划分为更小的等价类

10.1.2 等价类实现测试用例

  1. 划分输入条件
  2. 通过输入条件确定有效等价类
  3. 通过输入条件确定无效等价类
  4. 确定测试用例
    1. 为每一个等价类规定一个唯一的编号
    2. 设计一个新的测试用例,使其尽可能多的覆盖尚未覆盖的有效等价类。重复这一步,最后使得所有有效等价类都被覆盖
    3. 设计一个新的测试用例,使其只能覆盖一个无效等价类。重复这一步骤是所有无效等价类均被覆盖
一个软件中要求用户输入以年月表示的日期,假定日期的输入范围限定在2000年1月~2100年12月之间,
并且规定日期由6位数字字符组成,前4位表示年,后2位表示月。
那么请为“日期输入格式检查”这一功能通过等价类划分法设计测试用例

解:
1. 划分输入条件如下:
	日期的类型及长度
	年份范围
	月份范围
2. 依据输入条件确定有效等价类和无效等价类,并规定唯一编号,如下:
	输入条件          有效等价类。      无效等价类
	日期的类型及长度    (1)6位数字字符    (4)非数字字符 (5)小于6位数字字符 (6)大于6位数字字符
	年份范围          (2)2000~2100    (7)小于2000  (8)大于2100
	月份范围          (3)1~12         (9)小于1  (10)大于12
3. 设计一个新的测试用例尽可能多的覆盖有效等价类
	200001 输入有效(1,2,3)
4. 设计一个新的用例,覆盖一条无效等价类,重复直到无效等价类全部覆盖(注意测试数据要从全局考虑而不是单一的等价类),完整用例如下
	200001	输入有效	(1,2,3)
	20000a	输入无效	(4)
	2000011	输入无效	(5)
	20001	输入无效	(6)
	199901	输入无效	(7)
	210101	输入无效	(8)
	200000	输入无效	(9)
	200013	输入无效	(10)

⚠️ 注意测试数据要从全局考虑而不是单一的等价类 例如 我们想覆盖第7条等价类 测试数据应该位199901 而不是1999(这其实导致了我们一条用例覆盖了多个无效等价类)

10.2. 边界值法

边界值的选择可分为二值边界测试和三值边界测试

  • 二值边界值:如果有一个n变量的软件输入域,使其中一个变量取略小于最小值、最小值、正常值、最大值、略大于最大值这样五种选择,其余的所有变量取正常值。如此对每个变量都重负进行之后,该n变量软件输入域会产生4n+1个测试用例
  • 三值边界值:如果有一个n变量的软件输入域,使其中一个变量取略小于最小值、最小值、略大于最小值、正常值、略小于最大值、最大值、略大于最大值这样七种选择。其余的所有变量取正常值。如此对每个变量都重负进行之后,该n变量软件输入域会产生6n+1个测试用例

⚠️ 最小值和最大值就是边界的值无关是否包含 例如: 1<x<100 最小值取1,最大值取100 1≤x≤100 最小值取1,最大值取100

10.3. 因果图法

是一种简化的逻辑图,可以直观的表明输入条件和输出动作之间的因果关系

因果图的基本关系符号和约束如下(一般左侧为原因右侧为结果):

⚠️ 约束条件是为了表明原因和原因之间、结果和结果之间的关系

10.3.1 因果图实现步骤

  1. 分析程序规格说明的描述,那些是原因,哪些是结果
  2. 分析程序规格说明的描述中语义的内容,并将其表示成连接各个原因与各个结果的“因果图”
  3. 标明约束条件
  4. 把因果图转换成判定表
  5. 为判定表中每一列的情况设计成测试用例

10.3.2 示例

⚠️ 例子的题目并不严谨,主要理解过程

支票借记功能如下:

输入是借记金额、账户类型和当前金额;输出是新的金额和操作代码。

  • 账户类型是邮政(“p”)类型或柜台(“c”)类型
  • 操作代码是“D&L”,“D”,“S&L”,“L”,分别对应处理借记并发送信件,只处理借记,冻结账户和发送信件,只发送信件

如果账户中有足够的金额或者新的余额在授权透支的范围内,则处理借记。

如果新的余额超过了授权透支的范围,则不处理借记,如果是一个邮政帐户则进行冻结。

邮政帐户的所有交易都会发送信件,非邮政帐户如果有足够的资金(在授权透支范围内)也会发送信件

非邮政帐户,即没有足够的金额且新的余额超过了授权透支的范围时会发送信件

解:

  1. 根据规格说明我们首先要拆分找到原因和结果
  • 原因
    • C1:账户中有足够的金额
    • C2:新的余额在授权透支的范围内
    • C3:是邮政帐户
  • 结果
    • A1:处理借记
    • A2:冻结账户
    • A3:发送信件
  1. 针对规格说明将原因结果组合画出因果图

    1. C1、C2有一个发生则会造成A1

    2. C1、C2同时没有发生的情况下C3发生则会造成A2

    3. C3发生A3一定发生 C3不发生的情况下,C2发生也会造成A3 C3不发生的情况下,C1、C2也都不发生,则也会造成A3

  2. 判断因与因之间,果与果之间是否存在约束

    • 账户中有足够金额(C1)与新的余额在授权透支的范围内(C2)是互斥条件
  3. 将因果图转换为判定表

    ⚠️ 后面的步骤将会在判定表部分继续完成

10.4. 判定表法

判定表通常由四个部分组成

  • 条件桩:列出了问题的所有条件
  • 动作桩:列出了问题规定可能采取的操作
  • 条件项:列出针对它所列条件的取值
  • 动作项:列出在条件项的各种取值情况下应该采取的动作

10.4.1 建立判定表的步骤

  1. 确定规则个数,假如有n个条件,每个条件有两个取值(0, 1), 则有 2n 种规则
  2. 列出所有条件桩和动作桩
  3. 填入条件项
  4. 填入动作项,制定初始判定表
  5. 简化,合并相似规则或相同动作

10.4.2 示例

⚠️ 题目描述见因果图章节

  1. 我们需要把因果图中的因都作为条件桩,果都作为动作桩,写入表格如下

    判定规则
    1
    条件桩C1:账户中有足够的金额
    C2:新的余额在授权透支的范围内
    C3:是邮政帐户
    动作桩A1:处理借记
    A2:冻结账户
    A3:发送信件
  2. 组合条件桩的所有各种可能填入条件项

    判定规则
    12345678
    条件桩C1:账户中有足够的金额TTTTFFFF
    C2:新的余额在授权透支的范围内TTFFTTFF
    C3:是邮政帐户TFTFTFTF
    动作桩A1:处理借记
    A2:冻结账户
    A3:发送信件
  3. 根据因果图中的关系,判断每个条件项对应的动作项填入表格,并简化得到最终的判定表

    判定表中的每一有效列就是一条测试用例

    判定规则
    12345678
    条件桩C1:账户中有足够的金额TTTTFFFF
    C2:新的余额在授权透支的范围内TTFFTTFF
    C3:是邮政帐户TFTFTFTF
    动作桩A1:处理借记**TTTTFF
    A2:冻结账户**FFFFTF
    A3:发送信件**TFTTTT

10.5. 基本路径测试法

基本路径测试法是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法

10.5.1 控制流图

基础结构如下:

控制流图中的基本概念:

  • 节点:以标有编号的圆圈表示,表示基本的程序块,可以是一个单独的语句,也可以是多个顺序执行语句的语句块。
  • 判定节点:带有分支的节点,程序中的复合条件要分解为简单条件,构成多个判定节点
  • 控制流(边):用带箭头的线表示,连接相关的两个节点,每一个控制流必须终止于某一个节点。
  • 区域:一个区域由一组节点以及相关连接节点的控制流所共同构成。

10.5.2 圈复杂度V(G)

V(G) = e-n+2 = P+1 = A+1

  • e:控制流个数
  • n:节点个数
  • P:判定节点数
  • A:封闭区域数

⚠️ 圈复杂度越高错误的可能越高

10.6. 基于结构(白盒)的动态测试技术

基于结构的动态测试主要关注语句、分支、路径、调用等程序结构的覆盖。基于结构的动态测试的关键是用例设计

10.6.1 基于控制流

int functionl(bool a, bool b, bool c)
{
	int x;
	x = 0;
	if (a&&(b||c))
	{
		x = 1;
	}
	return x
}

⚠️ 我们将依据此段C语言程序实现不同程度覆盖

  • 语句测试

    • 选择足够多的测试数据,使被测程序中每条语句都要被经历到
    • 测试条件:每个可执行语句
    • 测试覆盖项:每个可执行语句
    为了使程序中的每条语句都能够至少执行一次,我们可以构造出以下用例
    输入a=T, b=T, c=T, 预计结果x=1
    
  • 分支测试

    • 使得程序中的每个分支都要被经历到,哪怕这个分支上没有语句
    • 测试条件:每个分支
    • 测试覆盖项:每个分支
    程序流程图中一共存在一个判定即两个分支,我们可以构造如下所示的测试用例实现分支覆盖
    1. 输入a=T,b=T,c=T,预计输出x=1
    2. 输入a=F,b=F,c=F,预计输出x=0
    
  • 判定测试

    • 使得程序中的每个判定语句的结果取值都要被经历到
    • 测试条件:每个判定语句
    • 测试覆盖项:每个判定语句的每个结果值
    该程序判定语句为 if (a&&(b||c)) 其结果有两个值 True 或 False,因此我们可以构造如下所示的测试用例实现判定覆盖
    1. 输入a=T,b=T,c=T,预计输出x=1
    2. 输入a=F,b=F,c=F,预计输出x=0
    
  • 分支条件测试

    ⚠️ 在判定语句中,只有 && 或者 || 两侧的变量才能算条件 例如 ((a||(b&c)||(c&&d)) 中,一共有 a, (b&c), cd 4个条件 例如 ((a||(b&&c)||(c&&d)) 中,一共有 a, b, c, cd 5个条件

    • 条件覆盖

      • 使得每一判定语句中每个判定条件的可能值至少满足一次
      该程序判定语句为 if (a&&(b||c)) ,其中有3个条件分别为a,b,c。我们可以构造如下的用例达到条件覆盖
      1. 输入a=F,b=T,c=T,预计输出x=1
      2. 输入a=T,b=F,c=F,预计输出x=0
      

      ⚠️ 满足条件覆盖不一定会满足判定覆盖也不一定会满足语句覆盖,因此我们通常不会单独使用条件覆盖,我们会使用分支条件测试

    • 使得每个判定语句的结果取值,以及每个判定条件的取值都能被覆盖到

    • 测试条件:每个判定语句

    • 测试覆盖项:每个判定语句中所有判定条件的取值

    该程序判定语句为 if (a&&(b||c)) ,其中有3个条件分别为a,b,c,其结果有两个值 True 或 False,因此我们可以构造如下所示的测试用例实现判定覆盖
    1. 输入a=T,b=T,c=F,判定语句取值=True,预计输出x=1
    2. 输入a=F,b=F,c=T,判定语句取值=False,预计输出x=0
    
  • 分支条件组合测试

    • 使每个判定语句中的所有判定条件的各种可能组合都至少出现一次
    • 测试条件:每个判定语句
    • 测试覆盖项:每个判定语句中所有判定条件的布尔值的每个唯一可行组合
    该程序判定语句为 if (a&&(b||c)) 其中有3个条件分别为a,b,c,那么一共会有2^3种组合,因此一共可以产生如下所示8条用例
    1. 输入a=T,b=T,c=T,预计输出x=1
    2. 输入a=T,b=T,c=F,预计输出x=1
    3. 输入a=T,b=F,c=T,预计输出x=1
    4. 输入a=T,b=F,c=F,预计输出x=0
    5. 输入a=F,b=T,c=T,预计输出x=0
    6. 输入a=F,b=T,c=F,预计输出x=0
    7. 输入a=F,b=F,c=T,预计输出x=0
    8. 输入a=F,b=F,c=F,预计输出x=0
    
  • 修正条件判定测试(MCDC)

    • 每个判定条件都要可以单独的影响整个测试结果,假如有n个判定条件则需要n+1个用例就可以做到MCDC的100%覆盖
    • 测试条件:每个判定语句
    • 测试覆盖项:单个布尔条件可以独立影响判定结果的判定条件,其布尔值的每个唯一可行组合
    想要满足MCDC覆盖,我们只需要保证每一个判定条件都能够单独影响测试结果,因此我们可以在分支条件组合测试的用例中将符合要求的用例提取出来即可
    对于 `if (a&&(b||c))` 中的判断条件 a 来说,当bc保持不变的情况下,a分别为T和F会造成不同的测试结果的组合有(1,5)(2,6)(3,7)
    对于 `if (a&&(b||c))` 中的判断条件 b 来说,当ac保持不变的情况下,b分别为T和F会造成不同的测试结果的组合有(2,4)
    对于 `if (a&&(b||c))` 中的判断条件 c 来说,当ab保持不变的情况下,c分别为T和F会造成不同的测试结果的组合有(3,4)
    
    此时我可便可以依据每个判定条件的组合尽可能少的提取出用例作为MCDC的测试用例
    如2,3,4,6 或者 2,3,4,7皆可
    

10.6.2 基于数据流

定义:是指给变量赋了新的值(有时赋值会保持与之前相同也算一次定义)

使用:是指变量出现,但没有为其赋新的值

  • P-use(谓词使用):将变量作为判定条件
  • C-use(计算使用):将变量用来作为计算输入

⚠️ 上述是一段Ada语言的代码,用于求解形如ax^2+bx+c=0的一元二次方程。当方程无实数解时,输出Is_Complex为真,如果有实数解则输出至R1/R2

我们将用这段代码实现基于数据流的各种覆盖效果

首先我们需要通过代码确定出所有变量的定义和使用(注意定义和使用的概念),通常函数的输入参数要作为第0行的定义,输出的变量作为最后一行的计算使用

定义计算使用谓词使用
0A, B, C
1DiscrimA, B, C
2
3
4Discrim
5Is_Complex
6
7Is_Complex
8
9Is_Complex
10R1A, B, Discrim
11R2A, B, Discrim
12
13R1, R2, Is_Complex

基于上表中我们找到的对于变量的定义和使用可以进一步确定每一个变量的定义-使用对(变量从一次定义到每一次使用的路径),每一个定义使用对便是一个测试条件

定义-使用对计算使用谓词使用测试条件
0 → 1AT1
BT2
CT3
0 → 10AT4
BT5
0 → 11AT6
BT7
1 → 4DiscrimT8
1 → 10DiscrimT9
1 → 11DiscrimT10
5 → 9Is_ComplexT11
5 → 13Is_ComplexT12
7 → 9Is_ComplexT13
7 → 13Is_ComplexT14
10 → 13R1T15
11 → 13R2T16

得到了定义-使用对之后我们便可以达到各种覆盖

  • 全定义测试
    • 从每一个变量的每一次定义到变量任意一次使用(P-use或C-use)的控制流子路径

    • 实现过程:

      测试条件变量定义-使用对
      T1A0 → 1
      T2B0 → 1
      T3C0 → 1
      T8Discrim1 → 4
      T11Is_Complex5 → 9
      T13Is_Complex7 → 9
      T15R110 → 13
      T16R211 → 13

      上述为我们从所有定义-使用对中挑出的每一个变量的每一次定义到任意一次使用的定义-使用对。

      我们完成测试用例时需要保证测试数据在执行过程中能够覆盖到我们挑出的每一条定义-使用对,整合之后测试用例如下

      输入预期结果
      ABCIs_ComplexR1R2
      121FALSE-1-1
      111TRUE未定义未定义
  • 全计算使用测试
    • 从变量定义到该定义所有计算使用的控制流子路径

    • 实现过程:

      测试条件变量定义-使用对
      T1A0 → 1
      T2B
      T3C
      T4A0 → 10
      T5B
      T6A0 → 11
      T7B
      T9Discrim1 → 10
      T10Discrim1 → 11
      T12Is_Complex5 → 13
      T14Is_Complex7 → 13
      T15R110 → 13
      T16R211 → 13

      上述是我们从所有定义-使用对中找到的所有从定义到计算使用的定义-使用对

      我们完成测试用例时需要保证测试数据在执行过程中能够覆盖到我们挑出的每一条定义-使用对,整合之后测试用例如下

      输入预期结果
      ABCIs_ComplexR1R2
      121FALSE-1-1
      111TRUE未定义未定义
  • 全谓词使用测试
    • 从变量定义到该定义所有谓词使用的控制流子路径

    • 实现过程:

      测试条件条件定义-使用对
      T8Discrim1 → 4
      T11Is_Complex5 → 9
      T13Is_Complex7 → 9

      上述是我们从所有定义-使用对中找到的所有从定义到谓词使用的定义-使用对

      我们完成测试用例时需要保证测试数据在执行过程中能够覆盖到我们挑出的每一条定义-使用对,整合之后测试用例如下

      输入预期结果
      ABCIs_ComplexR1R2
      121FALSE-1-1
      111TRUE未定义未定义
  • 全使用测试
    • 从变量定义到该定义所有使用(谓词使用和计算使用)的控制流子路径

    • 实现过程:

      满足全使用测试覆盖需要用到我们最初找到的所有定义-使用对,同样的我们完成测试用例时需要保证测试数据在执行过程中能够覆盖到我们挑出的每一条定义-使用对,整合之后测试用例如下

      输入预期结果
      ABCIs_ComplexR1R2
      121FALSE-1-1
      111TRUE未定义未定义
  • 全定义-使用路径测试
    • 从每个变量定义到该定义每次使用(谓词使用和计算使用)的控制流子路径

    • 实现过程:

      按照全使用测试导出的同一组测试用例,对于全定义-使用路径测试也可以达到最大的测试覆盖(即全使用测试用例等同于全定义-使用路径测试用例

11. 项目管理

11.1 进度管理

11.1.1 关键路径法

关键路径:是项目的最短工期(总时长),但却是项目从开始到结束工期和最长的路径。进度网络图中可能有多条关键路径,因为活动会变化,因此关键路径也会变化

关键活动:关键路径上的活动

  • 最早开始时间(ES):某项活动能够开始的最早时间
  • 最早结束时间(EF):某项活动能够完成的最早时间,EF=ES+工期
  • 最迟结束时间(LF):为了使项目按时完成,某项活动必须完成的最迟时间
  • 最迟开始时间(LS):为了使项目按时完成,某项活动必须开始的最迟时间,LS=LF-工期
  • 关键路径上的活动(关键活动)的ES=LS, EF=LF
  • 总浮动时间:在不延误项目完工时间且不违反制度制约因素的前提下,活动可以从最早开始时间推迟或拖延的时间量。正常情况下关键活动的总浮动时间为0。总浮动时间=LS-ES或LF-EF或关键路径时长-包含节点的最长工期非关键路径时长

这几个时间通常作为每个节点的组成部分

  • 顺推:最早开始时间ES=所有前置活动最早完成时间的最大值,最早完成时间EF=ES+工期
  • 逆推:最晚完成时间LF=所有后续活动最晚开始时间的最小值,最晚开始LS=LF-工期

12. 案例一:白盒测试

12.1. 注意事项

  • 一组顺序结构可以映射为一个单一的节点

  • 在选择或多分支结构中分支的汇集处,即使没有执行语句也应该添加一个汇聚节点

    • 如if分支应该画为

  • 复合条件表达式,需要改变为一系列只有单个条件的嵌套判断

    • 例如有以下代码段

      if (a&&b)
      	x1
      else
      	x2
      

      我们画图时需要将判断条件a和b分别作为节点画入控制流图

  • 线性无关路径的条数 = V(G)

12.2 案例真题

阅读程序并回答下列三个问题

【问题一】请针对C语言代码给出100%DC(判定覆盖)所需逻辑条件

【问题二】请画出程序的控制流图,并计算控制流图的环路复杂度V(G)

【问题三】请给出问题二中控制流图的线性无关路径


  • 首先需要确定代码段中一共有6个判定

    为了满足判定覆盖我们需要覆盖每个判定结果的T和F,因此我们会有以下的逻辑条件

    • //1, 2, 3
    • //4
    • //6
    • //7
    • //9, 10
    • //11
    • buf len > 512 以及 buf len <= 512
    • buf_len == 0 以及 buf_len != 0
    • i < total_bytes 以及 i>=total_bytes
    • buf c[i] ==0 以及 buf c[i] != 0
    • buf_c[i]<7||buf_c[i]>14 以及 buf_c[i]>=7&&buf_c[i]<=14
    • i >= 32 以及 i < 32
  • 画图时注意在上一节中提及的注意事项

    • 一组顺序结构可以映射为一个单一的节点
    • 在选择或多分支结构中分支的汇集处,即使没有执行语句也应该添加一个汇聚节点
    • 复合条件表达式,需要改变为一系列只有单个条件的嵌套判断

           代码对应的控制流图如下,V(G)=e-n+2/P+1/A+1=8

            

  • 注意线性无关路径的条数 = V(G),我们可以依据此来验证结果是否正确

    依据控制流图得出的无关线性路径如下:

    • 1,2,4,5,13
    • 1,3,4,5,13
    • 1,2,4,6,13
    • 1,2,4,6,7,8,13
    • 1,2,4,6,7,9,11,12,13
    • 1,2,4,6,7,9,10,11,12,13
    • 1,2,4,6,7,9,10,6..
    • 1,2,4,6,7,9,11,6...

13. 案例二:黑盒测试

13.1. 注意事项

  • 在输入条件规定了取值范围或值的个数的情况下,可以确定一个有效等价类和两个无效等价类
    • 例如:程序输入范围为1~10
  • 在输入条件规定了输入值的集合或者规定了“必须如何”的条件的情况下,可以确立一个有效等价类和一个无效等价类
    • 例如:输入值x必须是偶数
  • 在输入条件是一个布尔量的情况下,可确定一个有效等价类和一个无效等价类
  • 在规定了输入数据的一组值(假定n个),并且要求程序对每一个输入值分别处理的情况下,可以确立n个有效等价类和一个无效等价类
    • 例如:销售奖金对第1,2,3名分别奖励
  • 在规定了输入规则必须遵守的情况下,可确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)
    • 输入必须为整数
  • 在确定已知的等价类中,各元素在程序处理中的方式不同的情况下,则应再将等价类进一步划分为更小的等价类
  • 边界值需要注意是二值边界还是三值边界

13.2. 案例真题

某航空公司进行促销活动,会员在指定日期范围内搭乘航班将获得奖励,奖励分为4个档次,由乘机次数和点数共同决定,如表2-1所示。其中点数跟票面价格和购票渠道有关,规则如表2-2

航空公司开发一个程序来计算会员在该促销活动后的奖励,程序的输入包括会员在活动期间的乘机次数C,官网购票金额A(单位:元)和手机客户端购票金额B(单位:元)程序的输出为本次活动奖励档次L。其中C、A、B为非负整数,L为0~5之间的整数(0表示无奖励)

【问题一】采用等价类划分法对该程序进行测试(同时对输入输出进行等价类划分),等价类表如表2-3所示,请补充其中的空

【问题二】根据以上等价类表设计的测试用例如表2-4所示,请补充其中的空

【问题三】对于黑盒测试来说,以上测试方法有哪些不足


解:

问题一:

  • 题目中指出C、A、B为非负整数
  • 题目中指出L为0~5之间的整数(0表示无奖励),且通过表2-1我们发现奖励档次为1,2,3,4。因此L的实际可输入值为0,1,2,3,4
  1. 非负整数
  2. 4
  3. 0
  4. 负整数

问题二:

  1. 1,2,3,8
  2. 0
  3. 20
  4. 15000
  5. 10
  6. 7000
  7. 1,2,3,7
  8. 0.1
  9. N/A

问题三

  1. 没有考虑到奖励档次的无效等价类
  2. 没有考虑到C,A,B之间的关系,及满足A/B但不满足C的情况
  3. 没有考虑到手机客户端购票的情况

14. 案例三:综合测试

14.1. 注意事项

  • 兼容性测试矩阵

  • Apdex(应用性能指数)对用户使用该系统的性能满意度进行度量,系统需要满足的Apdex指数为0.85以上

    • Apdex=(满意的样本数+容忍的样本数/2)/总样本数
  • SQL注入

    • 直接在某输入原字符后面加 or '1'='1' 或者 or 1=1 (根据原输入字符的数据类型来觉得是 1 还是 '1'
  • XSS

    • 直接在输入原字符后加 <script>alert("测试信息")</script>

14.2. 案例真题一

某证券交易所为了方便提供证券交易服务,欲开发一个基于Web的证券交易平台。其主要功能包括客户开户,记录查询、存取款、股票交易等。客户信息包括姓名、Email(必填且唯一)、地址等;股票交易信息包括股票代码 (6位数字编码的字符串) 、交易数量(100的整数倍)、买/卖价格(单位:元,精确到分) 。系统要支持:

(1)在特定时朝内3000个用户并发时,主要功能的处理能力至少要达到128个请求/秒,平均数据量2KB/请求:

(2)页面中采用表单实现客户信息、交易信息等的提交与交互,系统前端采用HTML5实现。

【问题一】在对此平台进行非功能测试时,需要测试哪些方面?

【问题二】在满足系统要支持的(1) 时,计算系统的通信吞吐量。

【问题三】表单输入测试需要测试哪几个方面?

【问题四】

(1) 针对股票代码: 111111、数量: 10万、当前价格: 6.00,设计4个股票交易的测试输入。

(2) 设计2个客户开户的测试输入,以测试是否存在XSS、SQL注入。


解:

问题一

  1. 客户端功能以及股票交易功能
  2. 系统在信息方面的安全性
  3. 系统能够支持的性能是否符合需求
  4. 系统兼容性

问题二

吞吐量=事务数/单位时间 = 30001282KB/1s = 768000KB/s

问题三

输入数据类型合法时系统处理情况

输入数据不合法时系统处理情况

SQL注入和XSS攻击

问题四

(1)

  1. 111111, 10万, 6.00, 正常进行交易
  2. 11111, 10万, 6.00, 股票代码错误
  3. 111111, 10.1万, 6.00, 交易数量非100整数倍
  4. 111111,10万,6.0,买/卖价格未精确到分

(2)

  1. 姓名:张三 or ‘1’ = ‘1’,Email: 123@mail.com,地址:xxxxxx
  2. 姓名:张三,Email: 123@mail.com,地址:xxxxxx<script>alert(”测试数据”)</script>

14.3. 案例真题二

阅读下列说明,回答问题1至问题3

【说明】

某公司欲开发一款二手车物流系统,以有效提升物流成交效率。该系统的主要功能是:

(1) 订单管理,费买顾问看到有买车线索后,会打电话询问买家是不是需要物流,若需要,帮买顾问就将这个线索发起为订单,帮助买家来找承运商

(2)线路管理与推荐:对承运商的线路进行管理。根据运输方式的不同,线路分为三种,即包车线路、固定线路、竞价体系,其中包车线路和固定线路是合约制。接入订单系统会根据订单的内容选择合适的承运商。即: 有新订单时,若符合固定线路和包车线路,系统自动分配给合约承运商:若不符合合约,系统将订单需求信息推送给各承运商,承运商对订单进行竞拍出价。

(3) 合约管理: 根据公司与承运商确定的合约,对合约内容进行设置。

(4) 基础信息管理: 包括帮买顾问 (这部分缺失)

【问题一】系统前端APP需支持不同品牌的不同系统平台,设计兼容性测试矩阵以对系统的兼容性进行测试

【问题二】承运商进行竞价时,前端需提交竞拍价格(整数,单位:元)数和可接受浮动比例(整数),针对这一功能设计4个测试用例。

【问题三】承运商竟拍部分的性能要求最高。采用性能测试工具在以系统竞拍功能为主进行性能测试时,采用Apdex (应用性能指数)对用户使用该系统的性能满意度进行度量,系统需要满足Apdex指数为0.9以上。测试数据如表3-1所示,请计算本系统的Apdex指数,并说明本系统是否达到要求。


解:

问题一

平台/品牌小米华为三星
Andrio11
Andrio12
IOS

问题二

  1. 1000,1
  2. 1000.0,1
  3. 1000,1.0
  4. 1000 or 1=1,1

问题三

Apdex = (满意的样本数+容忍的样本数/2)/总样本数 = (185+20/2)/(185+20+10) = 0.906 >= 0.9

该产品达到要求

15. 案例四:面向对象测试

15.1. 注意事项

  • UML(统一建模语言):是一种可视化的建模语言,而非程序设计语言,支持从需求分析开始的软件开发的全过程

  • 从总体来看,UML的结构包括构造块,规则和公共机制三个部分

    • 构造块:UML有三种基本的构造块分别是事物、关系和图
      • 事物:UML的重要组成部分,分为结构事务,行为事务,分组事务,注释事务

  • 关系:把事物紧密联系在一起

    • 依赖:一个事物的语义随另一个事物的语义的变化而变化,例如人的生活依赖水和空气

    • 关联:分为组合和聚合,都是部分和整体的关系,两个类之间的关联实际上是两个类所扮演的角色的关联,因此两个类可以有多个由不同角色标识的关联

      • 其中组合事务之间的关系更强,组合关系的两事务有着共同的生命周期,即整体不存在部分也不存在,例如人和人的大脑。
      • 聚合关系的两事务没有共同的生命周期,即部分消失整体依然存在,例如大雁和雁群
    • 泛化:一般/特殊的关系,子类和父类之间的关系

    • 实现:一个类元指定了另一个类元保证执行的契约

  • 图:多个相互关联的事物的集合

    • 公共机制:达到特定目标的公共UML方法
    • 规则:构造块如何放在一起的规定
  • 类图:静态图,为系统的静态设计视图,展现一组对象,接口,协作和它们之间的关系,UML如下

  • 用例图: 静态图,展现了一组用例、参与者以及它们之间的关系。用例图中的参与者是人、硬件或其他系统可以扮演的角色;用例是参与者完成的一系列操作,用例之间的关系有扩展、包含、泛化。如下:

        ⚠️ 扩展、包含是用例图独有关系 扩展的操作之间是无任何直接关系的 包含的操作是必须要做的,例如上图在登记信息之前必须要先进行用户登录操作

  • 活动图:动态图,是一种特殊的状态图,展现了在系统内从一个活动到另一个活动的流程。活动的分岔和汇合线是一条水平粗线。牢记下图中并发分岔、并发汇合、监护表达式、分支、流等名词及含义。每个分岔的分支数代表了可同时运行的线程数。活动图中能够并行执行的是在一个分岔粗线下的分支上的活动

  • 对父类中已经测试过的成员函数,有两种情况需要在子类中重新测试

    • 继承的成员函数在子类中做了改动
    • 成员函数调用了改动过的成员函数
  • 测试序列原则

    • 类和方法的调用顺序和测试顺序是相反的,先明确其调用顺序,再逆向获取其测试序列
    • 当类之间存在泛化关系时,要先测父类再测子类
    • 如果基类有构造函数,需要先测构造函数

15.2. 设计模式

  • 创建型模式
    • 工厂方法(factory method)模式:定义一个创建对象的接口,但由子类决定需要实例化哪一个类
    • 抽象工厂(abstract factory)模式:提供一个接口,可以创建一系列相关或相互依赖的对象,而无需指定他们具体的类
    • 原型(prototype)模式:指定创建对象的类型,并通过拷贝这个原型来创建新的对象
    • 单例(singleton)模式:保证一个类只有一个实例,并提供一个访问他的全局访问点
    • 构建器(builden)模式:将一个复杂类的表示与其构造分开,似的相同的构建过程能得出不同的表示
  • 结构型模式
    • 适配器(adpater)模式:将一个类的接口转换成用户希望得到的另一种接口。他使原本不相容的接口得以协同工作
    • 桥接(bridge)模式:类的抽象部分和实现部分分离,使他们可以独立变化
    • 组合(composite)模式:将对象组合成树型结构以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性
    • 装饰(decorator)模式:动态的给一个对象添加一些额外的职责。它提供了用子类扩展功能的一个灵活的替代,比派生一个子类更加灵活
    • 外观(facade)慢式:定义一个高层接口,为子系统中的一组接口提供一个一致的外观,从而简化了该子系统的使用
    • 享元(flyweight)校式:提供支持大量细粒度对象共享的有效方法
    • 代理(proxy)模式:为其他对象提供一种代理以控制这个对象的访问
  • 行为型模式
    • 职责链(chain of responsibility)模式:通过给多个对象处理请求的机会,减少请求的发送者与接收者之间的耦合。将接收对象链接起来,在链中传递请求,直到有一个对象处理这个请求
    • 命令(command)模式:将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,将请求排队或记录请求日志,支持可撤销的操作
    • 解释器(interpreten)模式:给定一种语言,定义它的文法表示,并定义一个解释器,该解释器用来根据文法表示来解释语言中的句子
    • 迭代器(iterator)模式:提供一种方法来顺序访问一个聚合对象中的各个元素而不需要暴露该对象的内部表示
    • 中介者(mediator)模式:用一个中介对象来封装一系列的对象交互。它使各对象不需要显式地相互调用,从而达到低耦合,还可以独立的改变对象间的交互
    • 备忘录(memento)模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,从而可以在以后将该对象恢复到原先保存的状态
    • 观家专(observer)模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新
    • 状态(state)模式:允许一个对象在其内部状态改变时改变它的行为
    • 策略(strategy)模式:定义一系列算法,把它们一个个封装起来,并且使它们之间可互相替换,从而让算法可以独立于使用它的用户而变化
    • 模版方法(template method)模式:定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义算法的某些特定步骤
    • 访问者(visitor)模式:表示一个作用于某对象结构中的各元素的操作,使得在不改变各元素的类的前提下定义作用于这些元素的新操作。

15.3. 面向对象的机制

  • 封装
  • 继承

15.3.1 多态

多态允许不同的对象对同一个消息做出不同的响应。通过多态,可以基于对象的具体类型调用相应的方法,提供了灵活性和可扩展性。

  • 参数多态:实现对不同参数类型的适应和处理
  • 过载多态:实现对不同参数类型和参数数量的适应和处理
  • 包含多态:它是通过继承和方法重写的机制来实现的
  • 强制多态:将一个对象引用强制转换为另一个相关类型的对象引用,并调用该对象的方法

实现多态:

  • 绑定:方法的调用与方法所在的类关联起来
    • 静态绑定(前期绑定):在编译期间进行,编译器根据变量或表达式的声明类型来决定应该调用哪个方法实现。
    • 动态绑定(后期绑定):在运行期间进行,运行时系统根据变量或表达式的实际类型来决定应该调用哪个方法实现。

15.4. 面向对象测试阶段

  • 面向对象分析的测试
  • 面向对象设计的测试
  • 面向对象编程的测试
  • 面向对象单元测试
  • 面向对象集成测试
  • 面向对象系统和确认测试

15.5. 案例真题

某汽车维修公司的工时计算模块每天定时根据系统登记的维修信息统计维修工的工时工资。维修工分为学徒、普通维修工和高级维修工三种,三种维修工有不同的时薪标准。

图4-1是该模块的类图,图中属性和操作前的“+”,“#”和“一”分别表示公有成员、保护成员和私有成员。

(1)类Engineer表示普通维修工。

(2)类studentEngineer和seniorEngineer都重新实现了类Engineer的方法calReward()。

(3)方法calReward()根据每个维修工每天的工时数(workTime)、时薪(hourSalary)来计算当天的工时工资。

(4)方法getReward() 调用方法calReward() 获取工时工资并打印显示。

(5)类System中的方法statReward()中首先调用了该类的方法load(),获取本系统工程师列表,然后调用了类Engineer中的方法calReward()。现拟采用面向对象的方法进行测试。

【问题一】

(1)图4-1所示的类图中,类System和Engineer之间是什么关系?

(2)类seniorEngineer重新实现了类Engineer的方法calReward(),这是面向对象的什么机制?

【问题二】

(1)类seniorEngineer中的方法calReward()和类studentEngineer中的方法getReward()是否需要重新测试?

【问题三】

(1)请结合题干说明中的描述,给出测试类Engineer方法calReward() 时的测试序列。

(2)请给出图4-1中各个类的测试顺序。

(3)从面向对象特性考虑,测试类System中方法statReward() 时应注意什么?


问题一

  1. 类System和Engineer之间是关联关系
  2. 这是面向对象多态的机制

问题二

因为calReward()是重新实现的,因此类seniorEngineer中的方法calReward()需要重新测试

因为在使用getReward()时调用了calReward(),因此类studentEngineer中的方法getReward()需要重新测试

问题三

  • 注意构造函数,与类名相同的方法是构造函数
  1. Engineer() → setWorkTime() → calReward() → getReward()

  2. Engineer → studentEngineer → seniorEngineer → System

    ⚠️ 这里我们先测Engineer后测studentEngineer/seniorEngineer是因为我们需要先测试父类再测试子类 先测Engineer后测System是因为,System会调用Engineer类中的calReward()方法。我们的测试序列是逆向的调用顺序,因此先测Engineer后测System

  3. 我们可以发现有两种Engineer(基类:Engineer,子类:studentEngineer/seniorEngineer),因此需要对各类的calReward()方法进行测试

16. 案例五:嵌入式系统测试

16.1. 注意事项

  • 嵌入式软件一般要求扇出数不大于7;注释率不小于20%
    • 扇出数:当前模块调用的模块数
    • 注释率:注释行数/代码总行数

16.2. 案例真题

某飞行器供油阀控制软件通过控制左右两边的油箱BL、BR向左右发动机EL、ER供油,既要保证飞行器的安全飞行,又要保证飞行器的平衡,该软件主要完成的功能如下:

(1)无故障情况下,控制左油箱BL向左发动机EL供油,右油箱BR向右发动机ER供油,不上报故障

(2)当左油箱BL故障时,控制右油箱BR分别向左、右发动机EL和ER供油,并上报二级故障一一左油箱故障

(3)当右油箱BR故障时,控制左油箱BL分别向左、右发动机EL和ER供油,并上报二级故障一一右油箱故障

(4)当左发动机EL故障时,根据左右油箱的剩油量决定(如果左右油箱剩油量之差大于等于50升则使用剩油量多的油箱供油,否则同侧优先供油)左油箱BL还是右油箱BR向右发动机ER供油,并上报一级故障一一左发动机故障

(5)当右发动机ER故障时,根据左右油箱的剩油量决定(如果左右油箱剩油量之差大于等于50升则使用剩油量多的油箱供油,否则同侧优先供油)左油箱目还是右油箱BR向左发动机BL供油,井上报一级故障一右发动机故障

(6)当一个油箱和一个发动机同时故障时,则无故障的油箱为无故障发动机供油,并上报一级故故障油箱和发动机所处位置

(7)当两个油箱或两个发动机同时故障或存在更多故障时,则应进行双发断油控制,并上报特级故障一-两侧油箱或两侧发动机故障

(8)故障级别从低级到高级依次为二级故障、一级故障和特级故障,如果低级故障和高级故障同时发生,则只上报最高级别故障

【问题1】

覆盖率是度量测试完整性的一个手段,也是度量测试有效性的一个手段。在嵌入式软件白盒测试过程中,通常以语句覆盖率、条件覆盖率和MC/DC覆盖率作为度量指标。

在实现第6条功能时,设计人员采用了下列算法:

if ( (BL==故障) && (EL==故障))

[BR供油ER; BL断油; EL断油;]

if ( (BL=故障) && (ER=故障))

[BR供油EL; BL断油; ER断油;]

if ( (BR==故障) && (EL==故障))

[BL供油ER; BR断油; EL断油;]

if ( (BR=故障) && (ER==故障) )

(BL供油EL; BR断油; ER断油;]

请指出对上述算法达到100%语句覆盖、100%条件覆盖和100%MC/DC覆盖所需的最少测试用例数目填写表5-1中的空(1)~(3)

【问题二】

为了测试此软件功能,测试人员设计了表5-2所示的测试用例,请填写该表中的空(1)~(12)

【问题三】

常见的黑盒测试的测试用例设计方法包括等价类划分、决策表、因果图、边界值分析等测试人员在针对本题设计测试时,使用哪种测试用例设计方法最恰当?


解:

问题一:

  1. 4
  2. 8
  3. 12

问题二

  1. BR
  2. BL
  3. BR
  4. BL
  5. 120
  6. 100
  7. 断油
  8. BL
  9. BL
  10. BR
  11. 故障
  12. 特级故障

问题三

使用等价类划分法最恰当

17. 附录

  • 国人部发[2003]39号文件

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值