软件测试工程师面试题整理

Python元组和列表区别,应用场景,这两可不可以用来做字典的键值

元组:对象有序,对象不可变,通过索引取值
列表:对象有序,对象可变,通过索引取值
应用场景:

  1. 需要修改用列表
  2. 不需要修改使用元组
  3. 一些列举出来用于遍历的数据用元组,比如:方向 (up, down, left, right)
  4. 一些存储来只用来使用的数据用元组,比如:经纬度(longitude, latitude),数据库的字段值/列名
  5. 生成数据过程中的数据存储使用列表,比如:获取一组数中的满足某些条件的数,存储不断产生的程序日志等
#元组中,每个元素提取出来作为字典的键,和列表组成字典
   tup = ('1', '2', '3', '4')
    values = ['ha', 'll', '0', '你好哇']
    keys = list(tup)
    dic = dict(zip(keys, values))

元组只有在其元素是可散列的(不可变类型)情况下,才可以作为字典的key值

#可以当键的元组例子
d = {}
t1 = (1, 'a', (2, 3))
d[t1] = "test1"
print(d)
>>>{(1, 'a', (2, 3)): 'test1'}

#不可以当键的元组例子
d={}
t2 = (1,'a',(2,3),[1,2,3])
d[t2] = "test2"

d={}
t2 = (1,'a',(2,3),{})
d[t2] = "test3"

列表和字典本身,不能作为字典的键值
d = {}
d[[1,2,3]] = 3 #会报错
d[{‘a’:3}] = 4 #也会报错

为什么列表和字典类型的值不能作为字典的键值:
因为键是不可变的。列表和字典的值是可以变化的,一旦变化就再也找不到value了。

OSI七层模型

第一层: “物理层”如网卡、光钎、电缆等硬件
第二层:“数据链路层”相当于tcp/ip协议的链路层
第三层:“网络层”相当于tcp/ip协议的网络层
第四层:“传输层”相当于tcp/ip协议的传输层
第五层:“会话层”维护网络中的连接状态,保持通信
第六层:“表示层”把数据转换成可理解的数据
第七层:“应用层”与tcp/ip协议应用层一致

HTTP工作在哪四层?

第一层:“链路层”负责以太网、wifi这样的底层网络发送数据包,工作在网卡这个层次,使用mac地址来标记网络设备,有时候也叫mac层。
第二层:“网络层”负责将链路层中的mac地址转换成ip地址,把局域网和广域网虚拟成一个巨大的网络环境。
第三层:“传输层”也就是tcp协议层,负责在ip地址上传输数据,tcp协议保证数据可靠传输,另外还有udp数据传输。
tcp协议
是一种有状态的协议,发送数据时首先要建立连接,保证数据不丢失不重复。
udp
是一种无状态的协议,发送数据时不需要建立连接,不保证数据不丢失不重复
第四层:“应用层”这一层就是我们常见的协议了,如http、ssh、ftp、smtp、telnet

HTTP和HTTPS区别,SSL加密协议工作在哪两层?

http协议:超文本传输协议,信息是明文传输;

https协议:是由SSL+ http协议构建的加密传输协议。。

两者使用的端口不一样,http:80,https:443

SSL加密协议工作在传输层和应用层

get和post区别

都可以向服务器提交数据,并且会从服务器获取数据。

    区别:

     ① 传参方式不同:get通过地址栏的方式传参,post通过表单报文方式传参。

    ② 传参长度不同:get的参数有长度限制,post没有。

    ③ 一般情况下,get是获取数据,比如查询,post提交数据,比如:增删改。

    ④ Get只发送一个tcp数据报文(包含请求头和data),post发送两个报文(1.请求头,返回·100,2.data,返回200)

情景测试:Python多线程,处理列表里的10w+数据,插入到数据库**

import pymysql
import threading
def sfzh_sql_insert():
    conn = pymysql.connect(host='172.XX.XXX.11', user='root', password="xxx",
                           database='XXXX_db', port=3306,
                           charset='utf8')
    cus= conn.cursor()
    try:
        for i in range(1000):
            sql=("INSERT INTO `fk_test_db`.`test_table`  VALUES ('%s')")%i
            #tlock.acquire()
            ok = cus.execute(sql)
            conn.commit()
            print (ok)
            #tlock.release()
    except Exception as e:
        print ("one error happen",e)
    finally:
        pass


class myThread(threading.Thread):
    def __init__(self,id):
        threading.Thread.__init__(self)
        self.id = id
        pass
    def run(self):
        sfzh_sql_insert(id)
        #print ("开始操作%s"%i)


threads =[]
tlock=threading.Lock()
for  i in range(100):
    thread = myThread(i)
    threads.append(thread)

for i in range(len(threads)):
    threads[i].start()

web和APP测试的区别

  1. 功能层面,APP需要兼容老版本,做老版本回归
  2. 性能层面:APP需要考虑流量、电量、CPU、GPU、内存占用,web一般只关注响应时间
  3. 兼容性层面:APP需要考虑各个型号的手机兼容,web只需要考虑浏览器兼容
  4. APP需要弱网测试,主要考虑丢包
  5. APP测试存在卸载、安装、更新
  6. APP测试需要考虑界面操作,横竖屏切换,多点触控,事件触发区域测试等

Python迭代器、生成器

迭代器
原理:
是一个迭代取值的工具,通过next取值,是一个可以记住遍历位置的对象,取值来源是可迭代对象保存的集合
关键字:
iter、__next__方法
应用场景:
非序列类型取值,如:字典,集合

生成器:
原理:
关键字:yield,有__iter__、__next__方法
创建方法:
1. 使用(),将列表生成式的[]换成()就可以;
2. 使用yield关键字,将普通函数变成生成器函数
应用场景:
1. 数据规模巨大,内存消耗严重的时候,如:
while n<=1000000:
yield n
n+=1
上面的生成器,只需要一个元素,就可以生成100万的数据,而迭代器需要100万的元素

2. 生成器处理大文件
def read_file(file,chunk_size = 1024):
    while True:
        data = file.read(chunk_size)
        if not data:
            break
        yield data
f = open('your_big_file.dat')
for i in read_file(f):
    print(i)

Python装饰器

装饰器本质上是一个Python函数(其实就是闭包),它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。装饰器用于有以下场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。

#为函数添加一个统计运行时长的功能以及日志记录功能
import time
import threading
 
def how_much_time(func):
    print("how_much_time函数开始了")
    def inner():
        t_start = time.time()
        func()
        t_end = time.time()
        print("一共花费了{0}秒时间".format(t_end - t_start, ))
#装饰器实例
def zhuang_shi(fun):
    def size(*args,**kwargs):
        print("这是一个装饰器")
        fun(*args,**kwargs)
        print("运行结束")
    return size

@zhuang_shi
def zhuangshi2(name):
    print("hello",name)

测试计划

测试计划的内容会因不同的项目以及项目的大小而有所不同,一般而言在测试计划中应该清晰描述以下内容:
1、 测试目标:对测试目标进行简要的描述。
2、 测试概要:摘要说明所需测试的软件、名词解释、以及提及所参考的相关文档。
3、 测试范围:测试计划所包含的测试软件需测试的范围和优先级,哪些需要重点测试、哪些无需测试或无法测试或推迟测试。
4、 重点事项:列出需要测试的软件的所有的主要功能和测试重点,这部分应该能和测试案例设计相对应和互相检查。
5、 质量目标:制定测试软件的产品质量目标和软件测试目标。
6、 资源需求:进行测试所需要的软硬件、测试工具、必要的技术资源、培训、文档等。
7、 人员组织:需要多少人进行测试,各自的角色和责任,他们是否需要进行相关的学习和培训,什么时候他们需要开始,并将持续多长时间。
8、 测试策略:制定测试整体策略、所使用的测试技术和方法。
9、 发布提交:在按照测试计划进行测试发布后需要交付的软件产品、测试案例、测试数据及相关文档。
10、 测试进度和任务人员安排:将测试的计划合理的分配到不同的测试人员,并注意先后顺序.如果开发的
Release不确定,可以给出测试的时间段.对于长期大型的测试计划,可以使用里程碑来表示进度的变化。
11、 测试开始/完成/延迟/继续的标准:制定测试开始和完成的标准;某些时候,测试计划会因某种原因(过多阻塞性的Bug)而导致延迟,问题解决后测试继续。
12、 风险分析:需要考虑测试计划中可能的风险和解决方法。

学生表 user +成绩表score 查询排名前十的学生编号

select SUM(b.score_data) as total ,a.id from user as a left join score as b on a.id = b.uid group by a.name order by total limit 10

查询mysql数据库中所有表的方法:show tables

用户数据权限测试

功能测试:
用户权限测试: 确保系统正确地应用了用户角色和权限,以防止未经授权的用户访问数据。
数据访问测试: 针对不同用户角色,测试其是否只能访问其授权范围内的数据。

性能测试:
大规模数据测试: 在数据量较大的情况下测试系统的性能,确保在负载增加时数据隔离仍然有效。
并发用户测试: 模拟多个用户同时访问系统,验证数据隔离在高并发情况下的稳定性。
安全测试:
越权访问测试: 尝试通过不同的手段(例如URL直接访问、修改请求等)来尝试越权访问其他用户或租户的数据。
数据加密测试: 如果系统使用加密技术,确保数据在传输和存储时得到适当的加密保护。

跨浏览器和设备测试:
不同设备和浏览器测试: 确保数据隔离在不同设备和浏览器上一致,防止特定设备或浏览器存在漏洞。

异常情况测试:
错误处理测试: 引发系统错误或异常情况,检查系统是否能够正确地处理这些情况而不泄露敏感数据。
异常数据测试: 输入异常或不合法的数据,确保系统能够正确拒绝或处理这些数据。

审计和日志检查:
审计日志测试: 检查系统的审计日志,确保记录了数据访问的相关信息,以便在需要时进行审计。
日志脱敏测试: 确保系统中的日志在展示给管理员或开发人员时,不泄露敏感信息。

回归测试:
系统更新测试: 在系统升级或更新后,重新测试数据隔离,以确保新的变更没有破坏原有的数据隔离机制。

接口越权测试

  1. 接口请求根据用户ID获取用户详细信息
  2. 修改接口请求中的用户ID,确认响应体中的用户信息是否直接变为用户ID对应的用户信息
  3. 如果修改用户ID就可以获取到用户信息,那么就存在越权漏洞
    解决方法:对当前账号及user_id值进行匹配校验,防止越权查看其它账号信息

项目中service层主要是干什么的?

Controller
从字面上理解是控制器,所以它是负责业务调度的,所以在这一层应写一些业务的调度代码

Service
具体的业务处理应放在service中去写,而且service不单纯是对于dao的增删改查的调用,service是业务层,所以应该更切近于具体业务功能要求,所以在这一层,一个方法所体现的是一个可以对外提供的功能

实例
比如购物商城中的生成订单方法,这里面就不简单是增加个订单记录那么简单,我们需要查询库存,核对商品等一系列实际业务逻辑的处理

spring中bean的理解

举例:
我们都在微博上@过某某,对方会优先看到这条信息,并给你反馈,那么在Spring中,你标识一个@符号,那么Spring就会来看看,并且从这里拿到一个Bean或者给出一个Bean

注解分为两类:

#拿到一个bean
1、一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;

#给出一个bean
2、一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装

项目前后端通信用到了什么协议

http协议就是前端与后端之间相互通信所遵循的协议,协议定义了传输信息的格式,信息所表示的具体的含义。

前端和后端之间沟通的信息分为两种:

  1. 前端给后端发送的信息叫做请求报文,也就是HTTP request
  2. 后端回复前端的信息叫做响应报文,也就是HTTP response

http协议最主要的内容就是定义了请求报文和响应报文的格式以及各个字段的含义。

final关键字

常见四种用法:

  1. 可以用来修饰一个类:该类不允许被继承
  2. 可以用来修饰一个方法:该方法不允许被覆盖重写
  3. 可以用来修饰一个局部变量:
    1、变量在第一次初始化赋值后,不允许再次修改数据
    2、如果是引用类型,则不能再次修改引用地址值
    3、final 变量是引用类型时,引用类型的内部内容是可以修改的,不受final限制
  4. 可以用来修饰一个成员变量:
    1、由于成员变量具有默认值,所以final修饰成员变量时,必须进行手动赋值,不能使用默认值
    2、final修饰的成员变量,要么手动赋值,要么通过构造方法进行赋值,二选一
    3、必须保证类中所有的重载构造方法都有对final成员变量进行赋值

Redis使用

一、redis是什么
是一个高性能的 key-value 数据库数据库,是介于接口服务端和数据库的中间层

二、为什么使用redis

  1. 读取速度快。因为缓存是写入内存中的,普通数据库数据是写在磁盘中的,基于内存的相比于磁盘速度是快很多的,但是也缺点,比如断电之后,内存中的数据会消失,磁盘则不会。

  2. 高并发,减轻数据库压力。一旦涉及大数据量需求,比如一些商品抢购等,或者主页瞬间访问量大的时候,磁盘读写上千上万次,有性能弊端。容易造成数据库瘫痪,服务器宕机。数据库顶不住,需要缓存分担一部分压力。
    举例:
    比如一个查询接口,第一次查询从数据库查数据,查完之后我们把数据存入redis缓存中,第二次查就可以直接从缓存中读取数据,这就是它的用法。那么一般我们把什么数据存入redis缓存中呢?主要是一些复杂操作,耗费时间长的,比如数据库查询要600ms,但是redis只需要20ms。
    而且,在接下来的几个小时内,这个数据都不会变化,我们就可以存入缓存数据库,为什么对时间有要求呢?因为缓存中的数据一般都是有过期时间的,这个开发写代码可以设置。

三、redis的数据类型是什么
主要有五种,字符串,哈希,列表,集合,有序集合

四、redis的雪崩,缓存穿透,缓存击穿机制是什么?

  1. 雪崩机制
    假设数据库访问量是每秒5千请求,redis数据库可以抗住每秒4千请求。但是redis数据库因为意外宕机,那么这五千个请求就会全部打到数据库上。
    这个时候数据库就挂掉了,这个时候如果没有特别的方案来处理这个故障,DBA直接重启数据库,那么马上又会被新的流量打死,这个就是redis雪崩机制。

    1.1. 解决方案:
    服务熔断或请求限流机制
    构建Redis缓存高可靠集群

  2. 缓存穿透
    假设一个系统每秒5千请求,但是有4千是黑客恶意攻击发起的,缓存中差不到,数据库中也查不到。
    比如说,数据库id都是从1开始的,但是黑客发过来的请求id都是负数,所以缓存中查不到,就会直接打到数据库,数据库就会挂掉,这种就是缓存穿透。

    2.1. 解决方案:
    非法请求的限制
    缓存空值或者默认值
    使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在

  3. 缓存击穿
    某个缓存数据库的key值,访问非常频繁,一直处于高并发访问,但是因为一些原因这个key失效,那么数据流量就把缓存击穿,瞬间打到数据库上,就像在屏风上凿开一个洞

    3.1. 解决方案:
    互斥锁方案,保证同一时间只有一个业务线程更新缓存
    不给热点数据设置过期时间,由后台异步缓存

equals与==的区别:

  1. ==是判断两个变量或实例是不是指向同一个内存空间,equals是判断两个变量或实例所指向的内存空间的值是不是相同
  2. ==是指对内存地址进行比较 , equals()是对字符串的内容进行比较
  3. ==指引用是否相同, equals()指的是值是否相同

Python进程和线程

进程
是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础,通俗的讲,一个进程对应一个程序,而这个程序有它的运行空间和系统资源,在计算机内部,每个进程使用的数据和状态都是独立的,我们也可以称一个进程就是一个任务

线程
是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。我们来举个例子,当我们在影院看电影的时候,影院的影音系统会有一个线程去控制视频的播放,还有会有个线程去控制声音,这样的两个线程组合在一起构成影音播放程序,也就是对应了一个进程。

Python进程和线程的区别

  1. 地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享,某进程内的线程在其它进程不可见。

  2. 通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

  3. 调度和切换:线程上下文切换比进程上下文切换要快得多。

  4. 在多线程OS中,进程不是一个可执行的实体。

  5. 进程是资源分配的最小单位,线程是程序执行的最小单位。

Python僵尸进程和孤儿进程

僵尸进程
主进程在创建子进程的时候,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

孤儿进程
孤儿进程指的是在其父进程执行完成或被终止后仍继续运行的一类进程。一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

Python映射

一、什么是Python映射
map(function, iterable, …) //映射(函数,可迭代,…)
返回将函数应用于所有iterable元素的迭代器,并返回结果。如果传递了其他可迭代参数,则函数必须采用那么多参数,并将应用于所有可迭代对象并行获取的元素

二、映射的使用场景

def square(lis):
	return lis ** 2
lis = list(range(10))
#计算lis中所有元素的平方
data = map(square,lis)
print(data)
print(list(data))

#map函数返回的是一个迭代器
>>> <map object at 0x7f7d3d789450>
>>> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

APP crash原因

1. 内存管理错误:
内存泄漏,程序运行时间越长,占用内存越大,最终用尽内存,导致程序崩溃。也可能是手机可用内存太小,APP占用内存超出限制,导致崩溃
2. 程序逻辑错误:
数组越界,堆栈溢出
3. 设备兼容问题:
由于设备的多样性,在不同设备上可能有不同表现
4. 网络因素:
网络太差,无法达到APP所需的快速响应时间,导致崩溃

APP ANR原因

只有当应用程序的UI线程响应超时才会引起ANR,超时产生原因一般有2种。
● 当前的事件没有机会得到处理
● 当前的事件正在处理,但是由于耗时太长没能及时完成

深拷贝和浅拷贝

    a = [1, 2, 3, ['a', 'b']] #原始对象
    b = a #赋值
    c = copy.copy(a) #对象拷贝,浅拷贝
    d = copy.deepcopy(a) #对象拷贝,深拷贝
    a.append(4) #修改对象
    a[3].append('c') #修改对象a中的['a','b']
    print('a = ', a)
    print('b = ', b)
    print('c = ', c)
    print('d = ', d)
#输出
>>> a =  [1, 2, 3, ['a', 'b', 'c'], 4]
>>> b =  [1, 2, 3, ['a', 'b', 'c'], 4]
>>> c =  [1, 2, 3, ['a', 'b', 'c']] #浅拷贝结果
>>> d =  [1, 2, 3, ['a', 'b']]#深拷贝结果

浅拷贝:
改变原始对象中为可变类型的元素的值,会同时影响拷贝对象;改变原始对象中为不可变类型的元素的值,不会响拷贝对象。

通过浅拷贝来的对象c只是子对象的修改和a保持了一致,对象本身的修改并没有生效,说明浅拷贝是将对象本身的引用复制给新对象,但是包含的子对象还是和之前一致的

深拷贝:
除了顶层拷贝,还对子元素也进行了拷贝。经过深拷贝后,原始对象和拷贝对象所有的可变元素地址都没有相同的了

最后通过深拷贝来的对象完全没有变化,说明深拷贝来的对象本身以及包含的子对象都完完全全是新的,和原对象没有一点关系。

应用场景
从数据处理的角度来看,可以应用在以下场景:

1)我们处理中间结果时往往不想对原始数据进行修改,所以这个时候可以使用深拷贝;
2)如果我们只是想新增一个辅助列(只涉及对父对象的修改),那这时我们可以使用浅拷贝,节约系统内存。
详情见:

https://www.cnblogs.com/yingzili/archive/2022/09/04/16654884.html

支付功能测试点

支付流程
支付的测试流程:点击支付–> 选择支付方式 --> 确认金额–> 输入密码 --> 成功支付。需要针对支付流程中的每个阶段和步骤分别测试。
(1)支付:点击支付,然后取消订单,能否正常取消。
(2) 选择支付方式:可以从正常和异常角度考虑。
正常:可以支持的支付方式有:信用卡,储蓄卡,网银支付,余额,第三方支付(微信,支付宝,京东、百度、聚合支付、组合支付),找人代付,验证是否支持并且可以正常选择并支付;
异常:
① 支付时结合优惠券/折扣券/促销价抵扣进行相关的抵扣,验证规则正确,并且可以正常抵扣和支付。
② 手机上没有安装微信、支付宝等APP时,选择对应的支付方式,系统如何处理;
(3) 确认支付金额:
正常:正常金额里用黑盒测试中的边界值法去测试。
最大支付金额(单日最大,单笔最大,余额最大);
最小支付金额。
异常:同样也用边界值方法提取测试点。
超过支付方式单日最大消费金额/单笔最大/余额最大;
异常金额支付:非数字、负数、0,小数点超过 2 位、格式错误、余额小于实际需要支付的金额等。
(4) 支付密码:
正常:可以支持的支付密码类型有:指纹,人脸识别,账号密码,动态获取验证码,手势,信用卡和支付码,小额免密等,确认自己的产品所支持的密码类型,确认可以验证并支付成功;
异常:
①输入错误的密码,检查有无提示信息且正确;
②超过密码错误上限,检查是否冻结等。
(5) 其他场景测试点:
①多笔订单合并支付,是否可以成功;
②重复点击支付按钮,是否会出现多次购买,并同步检查数据库的数据账目是否正确;
③支付失败之后,如何补单和退单。
④支付中断:
主动中断:可以继续支付并成功;
被动中断:比如电话、低电量、闹钟,断网、切换后台、耳机插拔等,验证可以继续支付。
⑤使用 Fiddler 等抓包篡改价格:不允许抓包或者数据加密,篡改不成功。

                                                      退款流程

正常:验证正常的退款流程,也就是退款的冒烟测试。
点击退款可以退款成功,并且检查交易状态是退款,退款金额可以到账;
结合优惠券等抵扣,可以退款实际支付金额;
同步检查数据库的数据和账目是正确的;
异常:提交错误退款(退款订单号不对),或者退款金额错误,都能够退款失败(此处一般会借助工具进行测试,比如进行接口测试);

                                                  非功能测试点

(1) UI测试:
1、支付按钮是否足够明显;
2、支付的界面是否简洁、美观,符合大众审美;
3、支付页面的字体大小是否合理。
(2) 兼容性测试:
BS:如果是 BS 架构的产品,需要测试浏览器的兼容性,所以就需要根据浏览器的内核,选择一些主流的浏览器进行测试;
APP:测试手机移动端的兼容性,比如手机型号,系统版本和屏幕大小及分辨率等。
(3) 易用性测试:
1、是否支持快捷键功能;
2、点击付款按钮,是否有提示;
3、取消付款,是否有提示;
4、输入框是否对齐,大小是否适中等。
(4) 性能测试:
1、多次点击支付按钮时,是否会出现多次扣款;
2、如果发生多次扣款,如何通过原支付渠道退回;
3、如果在双十一、双十二这种支付高峰的时候,支付时是否会排队;
4、是否会响应超时;
5、如果响应超时,是否会返回友好提示。
(5) 安全测试:
验证敏感信息是否加密,是否可以篡改;
通过一些工具进行安全扫描,检查是否有安全漏洞或者采用一些其他的手段进行专门的安全测试;
支付请求的伪造,金额的恶意篡改,恶意模拟第三方接口来调用商家接口等,均是我们需要考虑清楚的问题。
(6) 网络测试:
1、验证各种网络类型:2G、3G, 4G,5G,wifi 下都可以正常支付;
2、进行网络切换,支付功能正常;
3、弱网测试下支付功能正常:不会重复支付多次,APP 不会闪退 崩溃,而且页面提示友好;

                                                          测试方法

(1) 小额支付:
让开发修改代码,不管支付多少钱,实际支付都是 1 分钱;不过这种方法只能测试小额支付,就有可能会出现产品小额支付没问题,但是大额支付就错误的漏测情况;
(2) 申请测试金额,走报销流程:
这种方式一般会作为小额支付的一种补充,比如测试完小额支付后,再测试一些大额支付,这就需要跟公司申请测试基金,走报销流程;
(3) 把收款方改成自己的收款账号:
这样就可以自己支付,自己收款,避免浪费自己的金钱做公司项目的支付测试。但是这也是有风险的。万一扣款成功,但是支付的金额没有到账可该怎么办?
(4) 沙箱支付:
沙箱支付是一种虚拟的支付,不是真实的金额;这种方法可以验证小额和大额的支付流程;目前支付宝沙箱比较成熟,推荐使用。

断点续传的原理

断点续传,也就是要从文件已经下载的地方开始继续下载。所以在客户端浏览器传给
Web服务器的时候要多加一条信息–从哪里开始

下面是用自己编的一个"浏览器"来传递请求信息给Web服务器,要求从2000070字节开始。
GET /down.zip HTTP/1.0
User-Agent: NetFox
RANGE: bytes=2000070-
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2

仔细看一下就会发现多了一行RANGE: bytes=2000070-
这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了。
服务器收到这个请求以后,返回的信息如下:
206
Content-Length=106786028
Content-Range=bytes 2000070-106786027/106786028
Date=Mon, 30 Apr 2001 12:55:20 GMT
ETag=W/“02ca57e173c11:95b”
Content-Type=application/octet-stream
Server=Microsoft-IIS/5.0
Last-Modified=Mon, 30 Apr 2001 12:55:20 GMT

和前面服务器返回的信息比较一下,就会发现增加了一行:
Content-Range=bytes 2000070-106786027/106786028
返回的代码也改为206了,而不再是200了。

HTTPS协议详解

https是在http的基础上,引入了一个加密层,SSL/TLS

  1. 对称加密:
    加密使用的密钥,和解密使用的密钥是同一个
    可以看做key是一个密钥,akey=b,a是明文的话,b就是密文,解密:bkey=a

  2. 非对称加密:
    为了使黑客拿不到密钥,就用公钥对密钥进行加密,最后只能拿到私钥才能解密拿到密钥。
    公钥:使用公钥加密;
    私钥:使用秘钥解密;

步骤:
1、首先服务器自己生成公钥私钥对;
 	公钥公布出去,私钥自己保留;
2、客服端拿到公钥后,使用公钥,进行加密;
   	对这个加密后的密钥密文 通过网络传输给服务器;
 	这样黑客只能拿到公钥,但是黑客没有私钥,所以就不能对密钥密文进行解密;
3、后续客户端和服务器之间就可以使用对称密钥进行加密解密了;

  1. 总结:
    1、对称加密:用于传输数据进行加密(请求,响应),需要一个密钥,客服端生成需要告诉给服务器;

    2、非对称加密:服务器自己生成公钥和私钥,私钥自己留着,客服端利用公钥对密钥进行加密,传输给服务器;

    3、中间人攻击,黑客利用自己生成的公钥和私钥,把公钥给客服端,从客服端生成的密文解密出密钥

    4、引入证书机制,为了防止中间人攻击,服务器需要在公正机构里面申请一个证书,客服端拿着这个证书去公正机构验证是否合法,合法说明这个证书和证书里面的公钥是可以信任的。

HTTPS的工作原理

  1. 用户通过浏览器请求https网站,服务器收到请求,选择浏览器支持的加密和hash算法,同时返回数字证书给浏览器,包含颁发机构、网址、公钥、证书有效期等信息。
  2. 浏览器对证书的内容进行校验,如果有问题,则会有一个提示警告。否则,就生成随机秘钥X,同时使用证书中的公钥进行加密,并且发送给服务器。
  3. 服务器收到之后,使用私钥解密,得到随机秘钥X,然后使用随机秘钥X对网页内容进行加密,返回给浏览器。
  4. 浏览器则使用随机秘钥X和之前约定的加密算法进行解密,得到最终的网页内容

Charles抓包原理

Charles需要做的事情是对客户端伪装服务端,对服务端伪装客户端,具体如下:

截获真实客户端的HTTPS请求,伪装客户端向真实服务端发送HTTPS请求
接受真实服务器响应,用Charles自己的证书伪装服务端向真实客户端发送数据内容
ps:参考

HTTP和socket

HTTP是短连接,Socket(基于TCP协议的)是长连接。尽管HTTP1.1开始支持持久连接,但仍无法保证始终连接。而Socket连接一旦建立TCP三次握手,除非一方主动断开,否则连接状态一直保持。

HTTP连接服务端无法主动发消息,Socket连接双方请求的发送先后限制。这点就比较重要了,因为它将决定二者分别适合应用在什么场景下。HTTP采用“请求-响应”机制,在客户端还没发送消息给服务端前,服务端无法推送消息给客户端。必须满足客户端发送消息在前,服务端回复在后。Socket连接双方类似peer2peer的关系,一方随时可以向另一方喊话

ps:参考

kafka

kafka应用场景:
请求异步处理模型:
在这里插入图片同步:描述
为了提升用户体验,用户下单后,将订购消息发送至消息队列(kafka的延迟可以做到毫秒级),之后生成订单,返回给用户一个订购成功的消息,用户直接跳转到支付页面。这里涉及到同步和异步

  1. 同步:
    推送消息和订单管理是同步的,因为订单生成不允许有延时操作,必须先有订单,用户才能进行支付操作
  2. 异步:
    库存管理和积分管理是异步操作,因为用户下单后,不会关心库存是否减少,对于下单后的积分是否增加,也不会关注时效性,所以采用异步的形式
  3. 总结:
    通过异步操作,减少了同步的操作步骤,缩短了用户浏览等待时间,提升了用户体验
    参考

kafka的缓冲和削峰
上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间可以起到缓冲作用,把消息暂存在kafka中,下游服务器就可以按照自己的节奏慢慢处理。(MQ:(Message Queue)消息队列)
在这里插入图片描述

TCP连接的三次握手和四次挥手

三次握手

  1. 第一次握手:建立连接时,客户端向服务器发送SYN包(seq=x),请求建立连接,等待确认
  2. 第二次握手:服务端收到客户端的SYN包,回一个ACK包(ACK=x+1)确认收到,同时发送一个SYN包(seq=y)给客户端
  3. 第三次握手:客户端收到SYN+ACK包,再回一个ACK包(ACK=y+1)告诉服务端已经收到
    三次握手完成,成功建立连接,开始传输数据
    在这里插入图片描述

为什么需要三次握手

  1. 第一次握手:客户端发送网络包,服务端收到了。
    这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
  2. 第二次握手:服务端发包,客户端收到了。
    这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
  3. 第三次握手:客户端发包,服务端收到了。
    这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。

四次挥手

  1. 客户端发送FIN包(FIN=1)给服务端,告诉它自己的数据已经发送完毕,请求终止连接,此时客户端不发送数据,但还能接收数据
  2. 服务端收到FIN包,回一个ACK包给客户端告诉它已经收到包了,此时还没有断开socket连接,而是等待剩下的数据传输完毕
  3. 服务端等待数据传输完毕后,向客户端发送FIN包,表明可以断开连接
  4. 客户端收到后,回一个ACK包表明确认收到,等待一段时间,确保服务端不再有数据发过来,然后彻底断开连接
    在这里插入图片描述
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值